From 87904e3527ca13065ebe1273273cb4ecfe0f578b Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Thu, 2 Nov 2023 15:37:55 -0300 Subject: [PATCH 01/12] feat: pathfinder multithreading (#1646) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This introduces multithreading capabilities to the pathfinder system, significantly improving performance for pathfinding operations. By enabling concurrent processing, the pathfinder can now handle multiple path calculations simultaneously, reducing latency and increasing efficiency in environments with high pathfinding demands. Benefits: • Enhanced pathfinding performance with parallel computation. • Reduced response times for path calculations. • Scalability in handling numerous pathfinding requests concurrently. Impact: This update is expected to bolster the responsiveness of applications that rely heavily on pathfinding, particularly in real-time scenarios or large, complex maps. With multithreading, the system's capacity to compute paths is now more robust and better equipped to maintain performance under load. --- src/creatures/combat/combat.cpp | 2 +- src/creatures/combat/condition.cpp | 6 +- src/creatures/combat/condition.hpp | 2 +- src/creatures/creature.cpp | 173 ++++++++------ src/creatures/creature.hpp | 31 ++- src/creatures/monsters/monster.cpp | 19 +- src/creatures/monsters/monster.hpp | 8 +- src/creatures/npcs/npc.cpp | 4 +- src/creatures/npcs/npc.hpp | 2 +- src/creatures/players/player.cpp | 18 +- src/creatures/players/player.hpp | 6 +- src/game/game.cpp | 84 +++---- src/game/game.hpp | 8 +- src/game/scheduling/dispatcher.cpp | 72 ++++-- src/game/scheduling/dispatcher.hpp | 14 +- src/items/items_definitions.hpp | 5 + src/items/tile.cpp | 110 +++++++-- src/items/tile.hpp | 17 +- .../creatures/creature_functions.cpp | 2 +- src/lua/functions/map/position_functions.cpp | 2 +- src/map/map.cpp | 224 +++--------------- src/map/map.hpp | 8 +- src/map/utils/astarnodes.cpp | 15 +- src/map/utils/astarnodes.hpp | 2 +- src/server/network/protocol/protocolgame.cpp | 4 +- src/utils/arraylist.hpp | 21 +- 26 files changed, 436 insertions(+), 423 deletions(-) diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp index c398f07a2b2..38f2c5de217 100644 --- a/src/creatures/combat/combat.cpp +++ b/src/creatures/combat/combat.cpp @@ -898,7 +898,7 @@ void Combat::addDistanceEffect(std::shared_ptr caster, const Position void Combat::doChainEffect(const Position &origin, const Position &dest, uint8_t effect) { if (effect > 0) { - std::forward_list dirList; + stdext::arraylist dirList(128); FindPathParams fpp; fpp.minTargetDist = 0; fpp.maxTargetDist = 1; diff --git a/src/creatures/combat/condition.cpp b/src/creatures/combat/condition.cpp index f69488175bd..4cf1834e1a4 100644 --- a/src/creatures/combat/condition.cpp +++ b/src/creatures/combat/condition.cpp @@ -1929,7 +1929,7 @@ bool ConditionFeared::getFleeDirection(std::shared_ptr creature) { return false; } -bool ConditionFeared::getFleePath(std::shared_ptr creature, const Position &pos, std::forward_list &dirList) { +bool ConditionFeared::getFleePath(std::shared_ptr creature, const Position &pos, stdext::arraylist &dirList) { const std::vector walkSize { 15, 9, 3, 1 }; bool found = false; std::ptrdiff_t found_size = 0; @@ -2030,7 +2030,7 @@ bool ConditionFeared::startCondition(std::shared_ptr creature) { bool ConditionFeared::executeCondition(std::shared_ptr creature, int32_t interval) { Position currentPos = creature->getPosition(); - std::forward_list listDir; + stdext::arraylist listDir(128); g_logger().debug("[ConditionFeared::executeCondition] Executing condition, current position is {}", currentPos.toString()); @@ -2040,7 +2040,7 @@ bool ConditionFeared::executeCondition(std::shared_ptr creature, int32 } if (getFleePath(creature, currentPos, listDir)) { - g_dispatcher().addEvent(std::bind(&Game::forcePlayerAutoWalk, &g_game(), creature->getID(), listDir), "ConditionFeared::executeCondition"); + g_dispatcher().addEvent(std::bind(&Game::forcePlayerAutoWalk, &g_game(), creature->getID(), listDir.data()), "ConditionFeared::executeCondition"); g_logger().debug("[ConditionFeared::executeCondition] Walking Scheduled"); } } diff --git a/src/creatures/combat/condition.hpp b/src/creatures/combat/condition.hpp index f8228e074ca..28d637b8b87 100644 --- a/src/creatures/combat/condition.hpp +++ b/src/creatures/combat/condition.hpp @@ -333,7 +333,7 @@ class ConditionFeared final : public Condition { private: bool canWalkTo(std::shared_ptr creature, Position pos, Direction moveDirection) const; bool getFleeDirection(std::shared_ptr creature); - bool getFleePath(std::shared_ptr creature, const Position &pos, std::forward_list &dirList); + bool getFleePath(std::shared_ptr creature, const Position &pos, stdext::arraylist &dirList); bool getRandomDirection(std::shared_ptr creature, Position pos); bool isStuck(std::shared_ptr creature, Position pos) const; diff --git a/src/creatures/creature.cpp b/src/creatures/creature.cpp index 980bab34155..7058753acf1 100644 --- a/src/creatures/creature.cpp +++ b/src/creatures/creature.cpp @@ -133,16 +133,23 @@ void Creature::onThink(uint32_t interval) { } } + auto onThink = [self = getCreature(), interval] { + // scripting event - onThink + const auto &thinkEvents = self->getCreatureEvents(CREATURE_EVENT_THINK); + for (const auto creatureEventPtr : thinkEvents) { + creatureEventPtr->executeOnThink(self->static_self_cast(), interval); + } + }; + if (isUpdatingPath) { - isUpdatingPath = false; - goToFollowCreature(); + g_dispatcher().asyncEvent([self = getCreature(), onThink = std::move(onThink)] { + self->isUpdatingPath = false; + self->goToFollowCreature_async(onThink); + }); + return; } - // scripting event - onThink - const CreatureEventList &thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK); - for (const auto creatureEventPtr : thinkEvents) { - creatureEventPtr->executeOnThink(static_self_cast(), interval); - } + onThink(); } void Creature::onAttacking(uint32_t interval) { @@ -224,18 +231,20 @@ bool Creature::getNextStep(Direction &dir, uint32_t &) { return true; } -void Creature::startAutoWalk(const std::forward_list &listDir, bool ignoreConditions /* = false*/) { +void Creature::startAutoWalk(const std::vector &listDir, bool ignoreConditions /* = false*/) { + listWalkDir.clear(); + if (!ignoreConditions && (hasCondition(CONDITION_ROOTED) || hasCondition(CONDITION_FEARED))) { return; } - listWalkDir = listDir; + listWalkDir = { listDir.begin(), listDir.end() }; - size_t size = 0; - for (auto it = listDir.begin(); it != listDir.end() && size <= 1; ++it) { - size++; + if (listWalkDir.empty()) { + return; } - addEventWalk(size == 1); + + addEventWalk(listWalkDir.size() == 1); } void Creature::addEventWalk(bool firstStep) { @@ -249,20 +258,22 @@ void Creature::addEventWalk(bool firstStep) { return; } - int64_t ticks = getEventStepTicks(firstStep); + const int64_t ticks = getEventStepTicks(firstStep); if (ticks <= 0) { return; } - // Take first step right away, but still queue the next - if (ticks == 1) { - g_game().checkCreatureWalk(getID()); - } + g_dispatcher().context().tryAddEvent([ticks, self = getCreature()]() { + // Take first step right away, but still queue the next + if (ticks == 1) { + g_game().checkCreatureWalk(self->getID()); + } - eventWalk = g_dispatcher().scheduleEvent( - static_cast(ticks), std::bind(&Game::checkCreatureWalk, &g_game(), getID()), - "Creature::checkCreatureWalk" - ); + self->eventWalk = g_dispatcher().scheduleEvent( + static_cast(ticks), std::bind(&Game::checkCreatureWalk, &g_game(), self->getID()), + "Creature::checkCreatureWalk" + ); + }); } void Creature::stopEventWalk() { @@ -320,11 +331,7 @@ int32_t Creature::getWalkCache(const Position &pos) { if (std::abs(dx) <= maxWalkCacheWidth) { int32_t dy = Position::getOffsetY(pos, myPos); if (std::abs(dy) <= maxWalkCacheHeight) { - if (localMapCache[maxWalkCacheHeight + dy][maxWalkCacheWidth + dx]) { - return 1; - } else { - return 0; - } + return localMapCache[maxWalkCacheHeight + dy][maxWalkCacheWidth + dx]; } } @@ -464,7 +471,7 @@ void Creature::checkSummonMove(const Position &newPos, bool teleportSummon) { } } -void Creature::onCreatureMove(std::shared_ptr creature, std::shared_ptr newTile, const Position &newPos, std::shared_ptr oldTile, const Position &oldPos, bool teleport) { +void Creature::onCreatureMove(const std::shared_ptr &creature, const std::shared_ptr &newTile, const Position &newPos, const std::shared_ptr &oldTile, const Position &oldPos, bool teleport) { if (creature == getCreature()) { lastStep = OTSYS_TIME(); lastStepCost = 1; @@ -512,7 +519,7 @@ void Creature::onCreatureMove(std::shared_ptr creature, std::shared_pt // update 0 for (int32_t x = -maxWalkCacheWidth; x <= maxWalkCacheWidth; ++x) { - std::shared_ptr cacheTile = g_game().map.getTile(static_cast(myPos.getX() + x), static_cast(myPos.getY() - maxWalkCacheHeight), myPos.z); + const auto &cacheTile = g_game().map.getTile(static_cast(myPos.getX() + x), static_cast(myPos.getY() - maxWalkCacheHeight), myPos.z); updateTileCache(cacheTile, x, -maxWalkCacheHeight); } } else if (oldPos.y < newPos.y) { // south @@ -523,7 +530,7 @@ void Creature::onCreatureMove(std::shared_ptr creature, std::shared_pt // update mapWalkHeight - 1 for (int32_t x = -maxWalkCacheWidth; x <= maxWalkCacheWidth; ++x) { - std::shared_ptr cacheTile = g_game().map.getTile(static_cast(myPos.getX() + x), static_cast(myPos.getY() + maxWalkCacheHeight), myPos.z); + const auto &cacheTile = g_game().map.getTile(static_cast(myPos.getX() + x), static_cast(myPos.getY() + maxWalkCacheHeight), myPos.z); updateTileCache(cacheTile, x, maxWalkCacheHeight); } } @@ -548,7 +555,7 @@ void Creature::onCreatureMove(std::shared_ptr creature, std::shared_pt // update mapWalkWidth - 1 for (int32_t y = -maxWalkCacheHeight; y <= maxWalkCacheHeight; ++y) { - std::shared_ptr cacheTile = g_game().map.getTile(myPos.x + maxWalkCacheWidth, static_cast(myPos.y + y), myPos.z); + const auto &cacheTile = g_game().map.getTile(myPos.x + maxWalkCacheWidth, static_cast(myPos.y + y), myPos.z); updateTileCache(cacheTile, maxWalkCacheWidth, y); } } else if (oldPos.x > newPos.x) { // west @@ -593,7 +600,7 @@ void Creature::onCreatureMove(std::shared_ptr creature, std::shared_pt } } - auto followCreature = getFollowCreature(); + const auto &followCreature = getFollowCreature(); if (followCreature && (creature == getCreature() || creature == followCreature)) { if (hasFollowPath) { isUpdatingPath = true; @@ -605,7 +612,7 @@ void Creature::onCreatureMove(std::shared_ptr creature, std::shared_pt } } - auto attackedCreature = getAttackedCreature(); + const auto &attackedCreature = getAttackedCreature(); if (attackedCreature && (creature == attackedCreature || creature == getCreature())) { if (newPos.z != oldPos.z || !canSee(attackedCreature->getPosition())) { onCreatureDisappear(attackedCreature, false); @@ -948,7 +955,7 @@ bool Creature::setAttackedCreature(std::shared_ptr creature) { return true; } -void Creature::getPathSearchParams(std::shared_ptr, FindPathParams &fpp) { +void Creature::getPathSearchParams(const std::shared_ptr &, FindPathParams &fpp) { fpp.fullPathSearch = !hasFollowPath; fpp.clearSight = true; fpp.maxSearchDist = 12; @@ -956,55 +963,64 @@ void Creature::getPathSearchParams(std::shared_ptr, FindPathParams &fp fpp.maxTargetDist = 1; } +void Creature::goToFollowCreature_async(std::function &&onComplete) { + if (pathfinderRunning.load()) { + return; + } + + pathfinderRunning.store(true); + g_dispatcher().asyncEvent([self = getCreature()] { + self->goToFollowCreature(); + self->pathfinderRunning.store(false); + }); + + if (onComplete) { + g_dispatcher().context().addEvent(std::move(onComplete)); + } +} + void Creature::goToFollowCreature() { - auto followCreature = getFollowCreature(); - if (followCreature) { - if (isSummon() && !getMonster()->isFamiliar() && !canFollowMaster()) { - hasFollowPath = false; - return; - } + const auto &followCreature = getFollowCreature(); + if (!followCreature) { + return; + } - FindPathParams fpp; - getPathSearchParams(followCreature, fpp); - std::shared_ptr monster = getMonster(); - if (monster && !monster->getMaster() && (monster->isFleeing() || fpp.maxTargetDist > 1)) { - Direction dir = DIRECTION_NONE; - - if (monster->isFleeing()) { - monster->getDistanceStep(followCreature->getPosition(), dir, true); - } else { // maxTargetDist > 1 - if (!monster->getDistanceStep(followCreature->getPosition(), dir)) { - // if we can't get anything then let the A* calculate - listWalkDir.clear(); - if (getPathTo(followCreature->getPosition(), listWalkDir, fpp)) { - hasFollowPath = true; - startAutoWalk(listWalkDir); - } else { - hasFollowPath = false; - } - return; - } - } + const auto &monster = getMonster(); - if (dir != DIRECTION_NONE) { - listWalkDir.clear(); - listWalkDir.push_front(dir); + if (isSummon() && !monster->isFamiliar() && !canFollowMaster()) { + listWalkDir.clear(); + return; + } - hasFollowPath = true; - startAutoWalk(listWalkDir); - } - } else { - listWalkDir.clear(); - if (getPathTo(followCreature->getPosition(), listWalkDir, fpp)) { - hasFollowPath = true; - startAutoWalk(listWalkDir); - } else { - hasFollowPath = false; - } + bool executeOnFollow = true; + stdext::arraylist listDir(128); + + FindPathParams fpp; + getPathSearchParams(followCreature, fpp); + + if (monster && !monster->getMaster() && (monster->isFleeing() || fpp.maxTargetDist > 1)) { + Direction dir = DIRECTION_NONE; + + if (monster->isFleeing()) { + monster->getDistanceStep(followCreature->getPosition(), dir, true); + } else if (!monster->getDistanceStep(followCreature->getPosition(), dir)) { // maxTargetDist > 1 + // if we can't get anything then let the A* calculate + executeOnFollow = false; + } else if (dir != DIRECTION_NONE) { + listDir.push_back(dir); + hasFollowPath = true; } } - onFollowCreatureComplete(followCreature); + if (listDir.empty()) { + hasFollowPath = getPathTo(getFollowCreature()->getPosition(), listDir, fpp); + } + + startAutoWalk(listDir.data()); + + if (executeOnFollow) { + onFollowCreatureComplete(getFollowCreature()); + } } bool Creature::canFollowMaster() { @@ -1248,7 +1264,6 @@ bool Creature::addCondition(std::shared_ptr condition) { std::shared_ptr prevCond = getCondition(condition->getType(), condition->getId(), condition->getSubId()); if (prevCond) { prevCond->addCondition(getCreature(), condition); - return true; } @@ -1638,11 +1653,11 @@ bool Creature::isInvisible() const { != conditions.end(); } -bool Creature::getPathTo(const Position &targetPos, std::forward_list &dirList, const FindPathParams &fpp) { +bool Creature::getPathTo(const Position &targetPos, stdext::arraylist &dirList, const FindPathParams &fpp) { return g_game().map.getPathMatching(getCreature(), dirList, FrozenPathingConditionCall(targetPos), fpp); } -bool Creature::getPathTo(const Position &targetPos, std::forward_list &dirList, int32_t minTargetDist, int32_t maxTargetDist, bool fullPathSearch /*= true*/, bool clearSight /*= true*/, int32_t maxSearchDist /*= 7*/) { +bool Creature::getPathTo(const Position &targetPos, stdext::arraylist &dirList, int32_t minTargetDist, int32_t maxTargetDist, bool fullPathSearch /*= true*/, bool clearSight /*= true*/, int32_t maxSearchDist /*= 7*/) { FindPathParams fpp; fpp.fullPathSearch = fullPathSearch; fpp.maxSearchDist = maxSearchDist; diff --git a/src/creatures/creature.hpp b/src/creatures/creature.hpp index 0195ec17c30..5e03e33d703 100644 --- a/src/creatures/creature.hpp +++ b/src/creatures/creature.hpp @@ -43,6 +43,10 @@ class FrozenPathingConditionCall { bool isInRange(const Position &startPos, const Position &testPos, const FindPathParams &fpp) const; + Position getTargetPos() const { + return targetPos; + } + private: Position targetPos; }; @@ -266,9 +270,11 @@ class Creature : virtual public Thing, public SharedObject { phmap::flat_hash_set> getZones(); // walk functions - void startAutoWalk(const std::forward_list &listDir, bool ignoreConditions = false); + void startAutoWalk(const std::vector &listDir, bool ignoreConditions = false); void addEventWalk(bool firstStep = false); void stopEventWalk(); + + void goToFollowCreature_async(std::function &&onComplete = nullptr); virtual void goToFollowCreature(); // walk events @@ -283,8 +289,12 @@ class Creature : virtual public Thing, public SharedObject { virtual bool setFollowCreature(std::shared_ptr creature); // follow events - virtual void onFollowCreature(std::shared_ptr) { } - virtual void onFollowCreatureComplete(std::shared_ptr) { } + virtual void onFollowCreature(const std::shared_ptr &) { + /* empty */ + } + virtual void onFollowCreatureComplete(const std::shared_ptr &) { + /* empty */ + } // combat functions std::shared_ptr getAttackedCreature() { @@ -446,7 +456,7 @@ class Creature : virtual public Thing, public SharedObject { * @return false */ void checkSummonMove(const Position &newPos, bool teleportSummon = false); - virtual void onCreatureMove(std::shared_ptr creature, std::shared_ptr newTile, const Position &newPos, std::shared_ptr oldTile, const Position &oldPos, bool teleport); + virtual void onCreatureMove(const std::shared_ptr &creature, const std::shared_ptr &newTile, const Position &newPos, const std::shared_ptr &oldTile, const Position &oldPos, bool teleport); virtual void onAttackedCreatureDisappear(bool) { } virtual void onFollowCreatureDisappear(bool) { } @@ -524,8 +534,8 @@ class Creature : virtual public Thing, public SharedObject { double getDamageRatio(std::shared_ptr attacker) const; - bool getPathTo(const Position &targetPos, std::forward_list &dirList, const FindPathParams &fpp); - bool getPathTo(const Position &targetPos, std::forward_list &dirList, int32_t minTargetDist, int32_t maxTargetDist, bool fullPathSearch = true, bool clearSight = true, int32_t maxSearchDist = 7); + bool getPathTo(const Position &targetPos, stdext::arraylist &dirList, const FindPathParams &fpp); + bool getPathTo(const Position &targetPos, stdext::arraylist &dirList, int32_t minTargetDist, int32_t maxTargetDist, bool fullPathSearch = true, bool clearSight = true, int32_t maxSearchDist = 7); struct CountBlock_t { int32_t total; @@ -660,7 +670,7 @@ class Creature : virtual public Thing, public SharedObject { CreatureEventList eventsList; ConditionList conditions; - std::forward_list listWalkDir; + std::deque listWalkDir; std::weak_ptr m_tile; std::weak_ptr m_attackedCreature; @@ -721,16 +731,18 @@ class Creature : virtual public Thing, public SharedObject { bool skillLoss = true; bool lootDrop = true; bool cancelNextWalk = false; - bool hasFollowPath = false; bool forceUpdateFollowPath = false; bool hiddenHealth = false; bool floorChange = false; bool canUseDefense = true; bool moveLocked = false; + bool hasFollowPath = false; int8_t charmChanceModifier = 0; uint8_t wheelOfDestinyDrainBodyDebuff = 0; + std::atomic_bool pathfinderRunning = false; + // use map here instead of phmap to keep the keys in a predictable order std::map creatureIcons = {}; @@ -756,7 +768,7 @@ class Creature : virtual public Thing, public SharedObject { virtual uint16_t getLookCorpse() const { return 0; } - virtual void getPathSearchParams(std::shared_ptr creature, FindPathParams &fpp); + virtual void getPathSearchParams(const std::shared_ptr &, FindPathParams &fpp); virtual void death(std::shared_ptr) { } virtual bool dropCorpse(std::shared_ptr lastHitCreature, std::shared_ptr mostDamageCreature, bool lastHitUnjustified, bool mostDamageUnjustified); virtual std::shared_ptr getCorpse(std::shared_ptr lastHitCreature, std::shared_ptr mostDamageCreature); @@ -769,4 +781,5 @@ class Creature : virtual public Thing, public SharedObject { bool canFollowMaster(); bool isLostSummon(); void handleLostSummon(bool teleportSummons); + void executeAsyncPathTo(bool executeOnFollow, FindPathParams &fpp, std::function &&onComplete); }; diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp index 9bef75a5ecb..97c18e6d855 100644 --- a/src/creatures/monsters/monster.cpp +++ b/src/creatures/monsters/monster.cpp @@ -178,7 +178,7 @@ void Monster::onRemoveCreature(std::shared_ptr creature, bool isLogout } } -void Monster::onCreatureMove(std::shared_ptr creature, std::shared_ptr newTile, const Position &newPos, std::shared_ptr oldTile, const Position &oldPos, bool teleport) { +void Monster::onCreatureMove(const std::shared_ptr &creature, const std::shared_ptr &newTile, const Position &newPos, const std::shared_ptr &oldTile, const Position &oldPos, bool teleport) { Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport); if (mType->info.creatureMoveEvent != -1) { @@ -596,16 +596,17 @@ bool Monster::searchTarget(TargetSearchType_t searchType /*= TARGETSEARCH_DEFAUL return false; } -void Monster::onFollowCreatureComplete(std::shared_ptr creature) { +void Monster::onFollowCreatureComplete(const std::shared_ptr &creature) { if (!creature) { return; } + auto it = std::find(targetIDList.begin(), targetIDList.end(), creature->getID()); - if (it != targetIDList.end()) { - auto target = targetListMap[*it].lock(); - if (!target) { - return; - } + if (it == targetIDList.end()) { + return; + } + + if (const auto &target = targetListMap[*it].lock()) { targetIDList.erase(it); if (hasFollowPath) { @@ -870,7 +871,7 @@ void Monster::doAttacking(uint32_t interval) { } } -bool Monster::canUseAttack(const Position &pos, std::shared_ptr target) const { +bool Monster::canUseAttack(const Position &pos, const std::shared_ptr &target) const { if (isHostile()) { const Position &targetPos = target->getPosition(); uint32_t distance = std::max(Position::getDistanceX(pos, targetPos), Position::getDistanceY(pos, targetPos)); @@ -2066,7 +2067,7 @@ bool Monster::isImmune(CombatType_t combatType) const { return mType->info.m_damageImmunities[combatTypeToIndex(combatType)]; } -void Monster::getPathSearchParams(std::shared_ptr creature, FindPathParams &fpp) { +void Monster::getPathSearchParams(const std::shared_ptr &creature, FindPathParams &fpp) { Creature::getPathSearchParams(creature, fpp); fpp.minTargetDist = 1; diff --git a/src/creatures/monsters/monster.hpp b/src/creatures/monsters/monster.hpp index adcb0258503..e6178a4f77c 100644 --- a/src/creatures/monsters/monster.hpp +++ b/src/creatures/monsters/monster.hpp @@ -147,13 +147,13 @@ class Monster final : public Creature { void onCreatureAppear(std::shared_ptr creature, bool isLogin) override; void onRemoveCreature(std::shared_ptr creature, bool isLogout) override; - void onCreatureMove(std::shared_ptr creature, std::shared_ptr newTile, const Position &newPos, std::shared_ptr oldTile, const Position &oldPos, bool teleport) override; + void onCreatureMove(const std::shared_ptr &creature, const std::shared_ptr &newTile, const Position &newPos, const std::shared_ptr &oldTile, const Position &oldPos, bool teleport) override; void onCreatureSay(std::shared_ptr creature, SpeakClasses type, const std::string &text) override; void drainHealth(std::shared_ptr attacker, int32_t damage) override; void changeHealth(int32_t healthChange, bool sendHealthChange = true) override; bool getNextStep(Direction &direction, uint32_t &flags) override; - void onFollowCreatureComplete(std::shared_ptr creature) override; + void onFollowCreatureComplete(const std::shared_ptr &creature) override; void onThink(uint32_t interval) override; @@ -407,7 +407,7 @@ class Monster final : public Creature { void onAddCondition(ConditionType_t type) override; void onEndCondition(ConditionType_t type) override; - bool canUseAttack(const Position &pos, std::shared_ptr target) const; + bool canUseAttack(const Position &pos, const std::shared_ptr &target) const; bool canUseSpell(const Position &pos, const Position &targetPos, const spellBlock_t &sb, uint32_t interval, bool &inRange, bool &resetTicks); bool getRandomStep(const Position &creaturePos, Direction &direction); bool getDanceStep(const Position &creaturePos, Direction &direction, bool keepAttack = true, bool keepDistance = true); @@ -434,7 +434,7 @@ class Monster final : public Creature { return mType->info.lookcorpse; } void dropLoot(std::shared_ptr corpse, std::shared_ptr lastHitCreature) override; - void getPathSearchParams(std::shared_ptr creature, FindPathParams &fpp) override; + void getPathSearchParams(const std::shared_ptr &creature, FindPathParams &fpp) override; bool useCacheMap() const override { return !randomStepping; } diff --git a/src/creatures/npcs/npc.cpp b/src/creatures/npcs/npc.cpp index 89eabdae28b..2df46c285cb 100644 --- a/src/creatures/npcs/npc.cpp +++ b/src/creatures/npcs/npc.cpp @@ -113,7 +113,7 @@ void Npc::onRemoveCreature(std::shared_ptr creature, bool isLogout) { shopPlayerMap.clear(); } -void Npc::onCreatureMove(std::shared_ptr creature, std::shared_ptr newTile, const Position &newPos, std::shared_ptr oldTile, const Position &oldPos, bool teleport) { +void Npc::onCreatureMove(const std::shared_ptr &creature, const std::shared_ptr &newTile, const Position &newPos, const std::shared_ptr &oldTile, const Position &oldPos, bool teleport) { Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport); // onCreatureMove(self, creature, oldPosition, newPosition) @@ -134,7 +134,7 @@ void Npc::onCreatureMove(std::shared_ptr creature, std::shared_ptrgetPlayer()) { + if (const auto &player = creature->getPlayer()) { handlePlayerMove(player, newPos); } } diff --git a/src/creatures/npcs/npc.hpp b/src/creatures/npcs/npc.hpp index 27f46cbeec6..38cd9840a17 100644 --- a/src/creatures/npcs/npc.hpp +++ b/src/creatures/npcs/npc.hpp @@ -137,7 +137,7 @@ class Npc final : public Creature { void onCreatureAppear(std::shared_ptr creature, bool isLogin) override; void onRemoveCreature(std::shared_ptr creature, bool isLogout) override; - void onCreatureMove(std::shared_ptr creature, std::shared_ptr newTile, const Position &newPos, std::shared_ptr oldTile, const Position &oldPos, bool teleport) override; + void onCreatureMove(const std::shared_ptr &creature, const std::shared_ptr &newTile, const Position &newPos, const std::shared_ptr &oldTile, const Position &oldPos, bool teleport) override; void onCreatureSay(std::shared_ptr creature, SpeakClasses type, const std::string &text) override; void onThink(uint32_t interval) override; void onPlayerBuyItem(std::shared_ptr player, uint16_t itemid, uint8_t count, uint16_t amount, bool ignore, bool inBackpacks); diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index aba77e44c60..1178a666e1c 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -1830,10 +1830,10 @@ void Player::onWalk(Direction &dir) { setNextAction(OTSYS_TIME() + getStepDuration(dir)); } -void Player::onCreatureMove(std::shared_ptr creature, std::shared_ptr newTile, const Position &newPos, std::shared_ptr oldTile, const Position &oldPos, bool teleport) { +void Player::onCreatureMove(const std::shared_ptr &creature, const std::shared_ptr &newTile, const Position &newPos, const std::shared_ptr &oldTile, const Position &oldPos, bool teleport) { Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport); - auto followCreature = getFollowCreature(); + const auto &followCreature = getFollowCreature(); if (hasFollowPath && (creature == followCreature || (creature.get() == this && followCreature))) { isUpdatingPath = false; g_dispatcher().addEvent(std::bind(&Game::updateCreatureWalk, &g_game(), getID()), "Game::updateCreatureWalk"); @@ -1850,7 +1850,7 @@ void Player::onCreatureMove(std::shared_ptr creature, std::shared_ptr< } if (tradePartner && !Position::areInRange<2, 2, 0>(tradePartner->getPosition(), getPosition())) { - g_game().internalCloseTrade(static_self_cast()); + g_game().internalCloseTrade(getPlayer()); } } @@ -1873,13 +1873,13 @@ void Player::onCreatureMove(std::shared_ptr creature, std::shared_ptr< if (party) { party->updateSharedExperience(); - party->updatePlayerStatus(static_self_cast(), oldPos, newPos); + party->updatePlayerStatus(getPlayer(), oldPos, newPos); } if (teleport || oldPos.z != newPos.z) { int32_t ticks = g_configManager().getNumber(STAIRHOP_DELAY); if (ticks > 0) { - if (std::shared_ptr condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_PACIFIED, ticks, 0)) { + if (const auto &condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_PACIFIED, ticks, 0)) { addCondition(condition); } } @@ -4223,7 +4223,7 @@ void Player::goToFollowCreature() { } } -void Player::getPathSearchParams(std::shared_ptr creature, FindPathParams &fpp) { +void Player::getPathSearchParams(const std::shared_ptr &creature, FindPathParams &fpp) { Creature::getPathSearchParams(creature, fpp); fpp.fullPathSearch = true; } @@ -4287,7 +4287,7 @@ uint64_t Player::getGainedExperience(std::shared_ptr attacker) const { return 0; } -void Player::onFollowCreature(std::shared_ptr creature) { +void Player::onFollowCreature(const std::shared_ptr &creature) { if (!creature) { stopWalk(); } @@ -7558,9 +7558,9 @@ SoundEffect_t Player::getAttackSoundEffect() const { bool Player::canAutoWalk(const Position &toPosition, const std::function &function, uint32_t delay /* = 500*/) { if (!Position::areInRange<1, 1>(getPosition(), toPosition)) { // Check if can walk to the toPosition and send event to use function - std::forward_list listDir; + stdext::arraylist listDir(128); if (getPathTo(toPosition, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, &g_game(), getID(), listDir), __FUNCTION__); + g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, &g_game(), getID(), listDir.data()), __FUNCTION__); std::shared_ptr task = createPlayerTask(delay, function, __FUNCTION__); setNextWalkActionTask(task); diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 83b28e88364..2a32a838c36 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -815,7 +815,7 @@ class Player final : public Creature, public Cylinder, public Bankable { void goToFollowCreature() override; // follow events - void onFollowCreature(std::shared_ptr creature) override; + void onFollowCreature(const std::shared_ptr &) override; // walk events void onWalk(Direction &dir) override; @@ -1230,7 +1230,7 @@ class Player final : public Creature, public Cylinder, public Bankable { void onCreatureAppear(std::shared_ptr creature, bool isLogin) override; void onRemoveCreature(std::shared_ptr creature, bool isLogout) override; - void onCreatureMove(std::shared_ptr creature, std::shared_ptr newTile, const Position &newPos, std::shared_ptr oldTile, const Position &oldPos, bool teleport) override; + void onCreatureMove(const std::shared_ptr &creature, const std::shared_ptr &newTile, const Position &newPos, const std::shared_ptr &oldTile, const Position &oldPos, bool teleport) override; void onAttackedCreatureDisappear(bool isLogout) override; void onFollowCreatureDisappear(bool isLogout) override; @@ -2888,7 +2888,7 @@ class Player final : public Creature, public Cylinder, public Bankable { void addConditionSuppression(const std::array &addConditions); uint16_t getLookCorpse() const override; - void getPathSearchParams(std::shared_ptr creature, FindPathParams &fpp) override; + void getPathSearchParams(const std::shared_ptr &creature, FindPathParams &fpp) override; void setDead(bool isDead) { dead = isDead; diff --git a/src/game/game.cpp b/src/game/game.cpp index 76c83737f60..417c89a8497 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -1144,9 +1144,9 @@ void Game::playerMoveCreature(std::shared_ptr player, std::shared_ptr(movingCreatureOrigPos, player->getPosition())) { // need to walk to the creature first before moving it - std::forward_list listDir; + stdext::arraylist listDir(128); if (player->getPathTo(movingCreatureOrigPos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task = createPlayerTask(600, std::bind(&Game::playerMoveCreatureByID, this, player->getID(), movingCreature->getID(), movingCreatureOrigPos, toTile->getPosition()), "Game::playerMoveCreatureByID"); @@ -1441,9 +1441,9 @@ void Game::playerMoveItem(std::shared_ptr player, const Position &fromPo if (!Position::areInRange<1, 1>(playerPos, mapFromPos)) { // need to walk to the item first before using it - std::forward_list listDir; + stdext::arraylist listDir(128); if (player->getPathTo(item->getPosition(), listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerMoveItemByPlayerID, this, player->getID(), fromPos, itemId, fromStackPos, toPos, count), "Game::playerMoveItemByPlayerID"); player->setNextWalkActionTask(task); @@ -1498,9 +1498,9 @@ void Game::playerMoveItem(std::shared_ptr player, const Position &fromPo internalGetPosition(moveItem, itemPos, itemStackPos); } - std::forward_list listDir; + stdext::arraylist listDir(128); if (player->getPathTo(walkPos, listDir, 0, 0, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerMoveItemByPlayerID, this, player->getID(), itemPos, itemId, itemStackPos, toPos, count), "Game::playerMoveItemByPlayerID"); player->setNextWalkActionTask(task); @@ -3020,7 +3020,7 @@ void Game::playerMove(uint32_t playerId, Direction direction) { player->setNextWalkActionTask(nullptr); player->cancelPush(); - player->startAutoWalk(std::forward_list { direction }, false); + player->startAutoWalk(std::vector { direction }, false); } void Game::forcePlayerMove(uint32_t playerId, Direction direction) { @@ -3033,7 +3033,7 @@ void Game::forcePlayerMove(uint32_t playerId, Direction direction) { player->setNextWalkActionTask(nullptr); player->cancelPush(); - player->startAutoWalk(std::forward_list { direction }, true); + player->startAutoWalk(std::vector { direction }, true); } bool Game::playerBroadcastMessage(std::shared_ptr player, const std::string &text) const { @@ -3198,7 +3198,7 @@ void Game::playerReceivePingBack(uint32_t playerId) { player->sendPingBack(); } -void Game::playerAutoWalk(uint32_t playerId, const std::forward_list &listDir) { +void Game::playerAutoWalk(uint32_t playerId, const std::vector &listDir) { std::shared_ptr player = getPlayerByID(playerId); if (!player) { return; @@ -3209,7 +3209,7 @@ void Game::playerAutoWalk(uint32_t playerId, const std::forward_list player->startAutoWalk(listDir, false); } -void Game::forcePlayerAutoWalk(uint32_t playerId, const std::forward_list &listDir) { +void Game::forcePlayerAutoWalk(uint32_t playerId, const std::vector &listDir) { std::shared_ptr player = getPlayerByID(playerId); if (!player) { return; @@ -3298,9 +3298,9 @@ void Game::playerUseItemEx(uint32_t playerId, const Position &fromPos, uint8_t f internalGetPosition(moveItem, itemPos, itemStackPos); } - std::forward_list listDir; + stdext::arraylist listDir(128); if (player->getPathTo(walkToPos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerUseItemEx, this, playerId, itemPos, itemStackPos, fromItemId, toPos, toStackPos, toItemId), "Game::playerUseItemEx"); if (it.isRune() || it.type == ITEM_TYPE_POTION) { @@ -3403,9 +3403,9 @@ void Game::playerUseItem(uint32_t playerId, const Position &pos, uint8_t stackPo ReturnValue ret = g_actions().canUse(player, pos); if (ret != RETURNVALUE_NOERROR) { if (ret == RETURNVALUE_TOOFARAWAY) { - std::forward_list listDir; + stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerUseItem, this, playerId, pos, stackPos, index, itemId), "Game::playerUseItem"); if (it.isRune() || it.type == ITEM_TYPE_POTION) { @@ -3537,9 +3537,9 @@ void Game::playerUseWithCreature(uint32_t playerId, const Position &fromPos, uin internalGetPosition(moveItem, itemPos, itemStackPos); } - std::forward_list listDir; + stdext::arraylist listDir(128); if (player->getPathTo(walkToPos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerUseWithCreature, this, playerId, itemPos, itemStackPos, creatureId, itemId), "Game::playerUseWithCreature"); if (it.isRune() || it.type == ITEM_TYPE_POTION) { @@ -3676,9 +3676,9 @@ void Game::playerRotateItem(uint32_t playerId, const Position &pos, uint8_t stac } if (pos.x != 0xFFFF && !Position::areInRange<1, 1, 0>(pos, player->getPosition())) { - std::forward_list listDir; + stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerRotateItem, this, playerId, pos, stackPos, itemId), "Game::playerRotateItem"); player->setNextWalkActionTask(task); @@ -3717,9 +3717,9 @@ void Game::playerConfigureShowOffSocket(uint32_t playerId, const Position &pos, bool isPodiumOfRenown = itemId == ITEM_PODIUM_OF_RENOWN1 || itemId == ITEM_PODIUM_OF_RENOWN2; if (!Position::areInRange<1, 1, 0>(pos, player->getPosition())) { - std::forward_list listDir; + stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, false)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task; if (isPodiumOfRenown) { task = createPlayerTask(400, std::bind_front(&Player::sendPodiumWindow, player, item, pos, itemId, stackPos), "Game::playerConfigureShowOffSocket"); @@ -3764,9 +3764,9 @@ void Game::playerSetShowOffSocket(uint32_t playerId, Outfit_t &outfit, const Pos } if (!Position::areInRange<1, 1, 0>(pos, player->getPosition())) { - std::forward_list listDir; + stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, false)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerBrowseField, this, playerId, pos), "Game::playerBrowseField"); player->setNextWalkActionTask(task); } else { @@ -3893,9 +3893,9 @@ void Game::playerWrapableItem(uint32_t playerId, const Position &pos, uint8_t st } if (pos.x != 0xFFFF && !Position::areInRange<1, 1, 0>(pos, player->getPosition())) { - std::forward_list listDir; + stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerWrapableItem, this, playerId, pos, stackPos, itemId), "Game::playerWrapableItem"); player->setNextWalkActionTask(task); @@ -4063,9 +4063,9 @@ void Game::playerBrowseField(uint32_t playerId, const Position &pos) { } if (!Position::areInRange<1, 1>(playerPos, pos)) { - std::forward_list listDir; + stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerBrowseField, this, playerId, pos), "Game::playerBrowseField"); player->setNextWalkActionTask(task); } else { @@ -4313,9 +4313,9 @@ void Game::playerRequestTrade(uint32_t playerId, const Position &pos, uint8_t st } if (!Position::areInRange<1, 1>(tradeItemPosition, playerPosition)) { - std::forward_list listDir; + stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerRequestTrade, this, playerId, pos, stackPos, tradePlayerId, itemId), "Game::playerRequestTrade"); player->setNextWalkActionTask(task); @@ -4862,9 +4862,9 @@ void Game::playerQuickLoot(uint32_t playerId, const Position &pos, uint16_t item if (!autoLoot && pos.x != 0xffff) { if (!Position::areInRange<1, 1, 0>(pos, player->getPosition())) { // need to walk to the corpse first before looting it - std::forward_list listDir; + stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task = createPlayerTask(0, std::bind(&Game::playerQuickLoot, this, player->getID(), pos, itemId, stackPos, defaultItem, lootAllCorpses, autoLoot), "Game::playerQuickLoot"); player->setNextWalkActionTask(task); } else { @@ -5747,7 +5747,7 @@ bool Game::internalCreatureSay(std::shared_ptr creature, SpeakClasses } void Game::checkCreatureWalk(uint32_t creatureId) { - std::shared_ptr creature = getCreatureByID(creatureId); + const auto &creature = getCreatureByID(creatureId); if (creature && creature->getHealth() > 0) { creature->onCreatureWalk(); cleanup(); @@ -5755,20 +5755,20 @@ void Game::checkCreatureWalk(uint32_t creatureId) { } void Game::updateCreatureWalk(uint32_t creatureId) { - std::shared_ptr creature = getCreatureByID(creatureId); + const auto &creature = getCreatureByID(creatureId); if (creature && creature->getHealth() > 0) { - creature->goToFollowCreature(); + creature->goToFollowCreature_async(); } } void Game::checkCreatureAttack(uint32_t creatureId) { - std::shared_ptr creature = getCreatureByID(creatureId); + const auto &creature = getCreatureByID(creatureId); if (creature && creature->getHealth() > 0) { creature->onAttacking(0); } } -void Game::addCreatureCheck(std::shared_ptr creature) { +void Game::addCreatureCheck(const std::shared_ptr &creature) { creature->creatureCheck = true; if (creature->inCheckCreaturesVector) { @@ -5777,10 +5777,10 @@ void Game::addCreatureCheck(std::shared_ptr creature) { } creature->inCheckCreaturesVector = true; - checkCreatureLists[uniform_random(0, EVENT_CREATURECOUNT - 1)].push_back(creature); + checkCreatureLists[uniform_random(0, EVENT_CREATURECOUNT - 1)].emplace_back(creature); } -void Game::removeCreatureCheck(std::shared_ptr creature) { +void Game::removeCreatureCheck(const std::shared_ptr &creature) { if (creature->inCheckCreaturesVector) { creature->creatureCheck = false; } @@ -5792,7 +5792,7 @@ void Game::checkCreatures() { auto &checkCreatureList = checkCreatureLists[index]; size_t it = 0, end = checkCreatureList.size(); while (it < end) { - std::shared_ptr creature = checkCreatureList[it]; + const auto &creature = checkCreatureList[it]; if (creature && creature->creatureCheck) { if (creature->getHealth() > 0) { creature->onThink(EVENT_CREATURE_THINK_INTERVAL); @@ -8995,9 +8995,9 @@ void Game::playerSetMonsterPodium(uint32_t playerId, uint32_t monsterRaceId, con } if (!Position::areInRange<1, 1, 0>(pos, player->getPosition())) { - if (std::forward_list listDir; + if (stdext::arraylist listDir(128); player->getPathTo(pos, listDir, 0, 1, true, false)) { - g_dispatcher().addEvent(std::bind_front(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind_front(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task = createPlayerTask(400, std::bind_front(&Game::playerBrowseField, this, playerId, pos), "Game::playerBrowseField"); player->setNextWalkActionTask(task); } else { @@ -9086,9 +9086,9 @@ void Game::playerRotatePodium(uint32_t playerId, const Position &pos, uint8_t st } if (pos.x != 0xFFFF && !Position::areInRange<1, 1, 0>(pos, player->getPosition())) { - if (std::forward_list listDir; + if (stdext::arraylist listDir(128); player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind_front(&Game::playerAutoWalk, this, player->getID(), listDir), "Game::playerAutoWalk"); + g_dispatcher().addEvent(std::bind_front(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); std::shared_ptr task = createPlayerTask(400, std::bind_front(&Game::playerRotatePodium, this, playerId, pos, stackPos, itemId), "Game::playerRotatePodium"); player->setNextWalkActionTask(task); diff --git a/src/game/game.hpp b/src/game/game.hpp index a5c7cd116c0..2b30a31d2f4 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -168,8 +168,8 @@ class Game { bool removeCreature(std::shared_ptr creature, bool isLogout = true); void executeDeath(uint32_t creatureId); - void addCreatureCheck(std::shared_ptr creature); - static void removeCreatureCheck(std::shared_ptr creature); + void addCreatureCheck(const std::shared_ptr &creature); + static void removeCreatureCheck(const std::shared_ptr &creature); size_t getPlayersOnline() const { return players.size(); @@ -320,8 +320,8 @@ class Game { void playerCloseNpcChannel(uint32_t playerId); void playerReceivePing(uint32_t playerId); void playerReceivePingBack(uint32_t playerId); - void playerAutoWalk(uint32_t playerId, const std::forward_list &listDir); - void forcePlayerAutoWalk(uint32_t playerId, const std::forward_list &listDir); + void playerAutoWalk(uint32_t playerId, const std::vector &listDir); + void forcePlayerAutoWalk(uint32_t playerId, const std::vector &listDir); void playerStopAutoWalk(uint32_t playerId); void playerUseItemEx(uint32_t playerId, const Position &fromPos, uint8_t fromStackPos, uint16_t fromItemId, const Position &toPos, uint8_t toStackPos, uint16_t toItemId); void playerUseItem(uint32_t playerId, const Position &pos, uint8_t stackPos, uint8_t index, uint16_t itemId); diff --git a/src/game/scheduling/dispatcher.cpp b/src/game/scheduling/dispatcher.cpp index 1bb7512f11d..a24ef770466 100644 --- a/src/game/scheduling/dispatcher.cpp +++ b/src/game/scheduling/dispatcher.cpp @@ -14,7 +14,6 @@ #include "lib/di/container.hpp" #include "utils/tools.hpp" -constexpr static auto ASYNC_TIME_OUT = std::chrono::seconds(15); thread_local DispatcherContext Dispatcher::dispacherContext; Dispatcher &Dispatcher::getInstance() { @@ -30,7 +29,7 @@ void Dispatcher::init() { while (!threadPool.getIoContext().stopped()) { updateClock(); - executeEvents(asyncLock); + executeEvents(); executeScheduledEvents(); mergeEvents(); @@ -56,12 +55,12 @@ void Dispatcher::executeSerialEvents(std::vector &tasks) { dispacherContext.reset(); } -void Dispatcher::executeParallelEvents(std::vector &tasks, const uint8_t groupId, std::unique_lock &asyncLock) { - const size_t totalTaskSize = tasks.size(); - std::atomic_uint_fast64_t executedTasks = 0; +void Dispatcher::executeParallelEvents(std::vector &tasks, const uint8_t groupId) { + std::atomic_uint_fast64_t totalTaskSize = tasks.size(); + std::atomic_bool isTasksCompleted = false; for (const auto &task : tasks) { - threadPool.addLoad([this, &task, &executedTasks, groupId, totalTaskSize] { + threadPool.addLoad([groupId, &task, &isTasksCompleted, &totalTaskSize] { dispacherContext.type = DispatcherType::AsyncEvent; dispacherContext.group = static_cast(groupId); dispacherContext.taskName = task.getContext(); @@ -70,21 +69,21 @@ void Dispatcher::executeParallelEvents(std::vector &tasks, const uint8_t g dispacherContext.reset(); - executedTasks.fetch_add(1); - if (executedTasks.load() >= totalTaskSize) { - signalAsync.notify_one(); + totalTaskSize.fetch_sub(1); + if (totalTaskSize.load() == 0) { + isTasksCompleted.store(true); + isTasksCompleted.notify_one(); } }); } - if (signalAsync.wait_for(asyncLock, ASYNC_TIME_OUT) == std::cv_status::timeout) { - g_logger().warn("A timeout occurred when executing the async dispatch in the context({}). Executed Tasks: {}/{}.", groupId, executedTasks.load(), totalTaskSize); - } + isTasksCompleted.wait(false); + tasks.clear(); } -void Dispatcher::executeEvents(std::unique_lock &asyncLock) { - for (uint_fast8_t groupId = 0; groupId < static_cast(TaskGroup::Last); ++groupId) { +void Dispatcher::executeEvents(const TaskGroup startGroup) { + for (uint_fast8_t groupId = static_cast(startGroup); groupId < static_cast(TaskGroup::Last); ++groupId) { auto &tasks = m_tasks[groupId]; if (tasks.empty()) { return; @@ -92,9 +91,9 @@ void Dispatcher::executeEvents(std::unique_lock &asyncLock) { if (groupId == static_cast(TaskGroup::Serial)) { executeSerialEvents(tasks); - mergeEvents(); // merge request, as there may be async event requests + mergeAsyncEvents(); } else { - executeParallelEvents(tasks, groupId, asyncLock); + executeParallelEvents(tasks, groupId); } } } @@ -128,18 +127,37 @@ void Dispatcher::executeScheduledEvents() { } dispacherContext.reset(); + + mergeAsyncEvents(); // merge async events requested by scheduled events + executeEvents(TaskGroup::GenericParallel); // execute async events requested by scheduled events } -// Merge thread events with main dispatch events -void Dispatcher::mergeEvents() { +// Merge only async thread events with main dispatch events +void Dispatcher::mergeAsyncEvents() { + constexpr uint8_t start = static_cast(TaskGroup::GenericParallel); + constexpr uint8_t end = static_cast(TaskGroup::Last); + for (const auto &thread : threads) { std::scoped_lock lock(thread->mutex); - for (uint_fast8_t i = 0; i < static_cast(TaskGroup::Last); ++i) { + for (uint_fast8_t i = start; i < end; ++i) { if (!thread->tasks[i].empty()) { m_tasks[i].insert(m_tasks[i].end(), make_move_iterator(thread->tasks[i].begin()), make_move_iterator(thread->tasks[i].end())); thread->tasks[i].clear(); } } + } +} + +// Merge thread events with main dispatch events +void Dispatcher::mergeEvents() { + constexpr uint8_t serial = static_cast(TaskGroup::Serial); + + for (const auto &thread : threads) { + std::scoped_lock lock(thread->mutex); + if (!thread->tasks[serial].empty()) { + m_tasks[serial].insert(m_tasks[serial].end(), make_move_iterator(thread->tasks[serial].begin()), make_move_iterator(thread->tasks[serial].end())); + thread->tasks[serial].clear(); + } if (!thread->scheduledTasks.empty()) { scheduledTasks.insert(make_move_iterator(thread->scheduledTasks.begin()), make_move_iterator(thread->scheduledTasks.end())); @@ -196,3 +214,19 @@ void Dispatcher::stopEvent(uint64_t eventId) { scheduledTasksRef.erase(it); } } + +void DispatcherContext::addEvent(std::function &&f) const { + g_dispatcher().addEvent(std::move(f), taskName); +} + +void DispatcherContext::tryAddEvent(std::function &&f) const { + if (!f) { + return; + } + + if (isAsync()) { + g_dispatcher().addEvent(std::move(f), taskName); + } else { + f(); + } +} diff --git a/src/game/scheduling/dispatcher.hpp b/src/game/scheduling/dispatcher.hpp index 73ba38ed224..9d0a5c51750 100644 --- a/src/game/scheduling/dispatcher.hpp +++ b/src/game/scheduling/dispatcher.hpp @@ -55,6 +55,12 @@ struct DispatcherContext { return type; } + // postpone the event + void addEvent(std::function &&f) const; + + // if the context is async, the event will be postponed, if not, it will be executed immediately. + void tryAddEvent(std::function &&f) const; + private: void reset() { group = TaskGroup::ThreadPool; @@ -143,15 +149,16 @@ class Dispatcher { void init(); void shutdown() { - signalAsync.notify_all(); + signalSchedule.notify_all(); } + inline void mergeAsyncEvents(); inline void mergeEvents(); - inline void executeEvents(std::unique_lock &asyncLock); + inline void executeEvents(const TaskGroup startGroup = TaskGroup::Serial); inline void executeScheduledEvents(); inline void executeSerialEvents(std::vector &tasks); - inline void executeParallelEvents(std::vector &tasks, const uint8_t groupId, std::unique_lock &asyncLock); + inline void executeParallelEvents(std::vector &tasks, const uint8_t groupId); inline std::chrono::nanoseconds timeUntilNextScheduledTask() const; inline void checkPendingTasks() { @@ -174,7 +181,6 @@ class Dispatcher { uint_fast64_t dispatcherCycle = 0; ThreadPool &threadPool; - std::condition_variable signalAsync; std::condition_variable signalSchedule; std::atomic_bool hasPendingTasks = false; std::mutex dummyMutex; // This is only used for signaling the condition variable and not as an actual lock. diff --git a/src/items/items_definitions.hpp b/src/items/items_definitions.hpp index 8b54fa679b5..c6326acd28b 100644 --- a/src/items/items_definitions.hpp +++ b/src/items/items_definitions.hpp @@ -431,6 +431,11 @@ enum TileFlags_t : uint32_t { TILESTATE_IMMOVABLENOFIELDBLOCKPATH = 1 << 21, TILESTATE_NOFIELDBLOCKPATH = 1 << 22, TILESTATE_SUPPORTS_HANGABLE = 1 << 23, + TILESTATE_MOVEABLE = 1 << 24, + TILESTATE_ISHORIZONTAL = 1 << 25, + TILESTATE_ISVERTICAL = 1 << 26, + TILESTATE_BLOCKPROJECTILE = 1 << 27, + TILESTATE_HASHEIGHT = 1 << 28, TILESTATE_FLOORCHANGE = TILESTATE_FLOORCHANGE_DOWN | TILESTATE_FLOORCHANGE_NORTH | TILESTATE_FLOORCHANGE_SOUTH | TILESTATE_FLOORCHANGE_EAST | TILESTATE_FLOORCHANGE_WEST | TILESTATE_FLOORCHANGE_SOUTH_ALT | TILESTATE_FLOORCHANGE_EAST_ALT, }; diff --git a/src/items/tile.cpp b/src/items/tile.cpp index 92beb20d52f..44631406fda 100644 --- a/src/items/tile.cpp +++ b/src/items/tile.cpp @@ -26,18 +26,34 @@ auto real_nullptr_tile = std::make_shared(0xFFFF, 0xFFFF, 0xFF); const std::shared_ptr &Tile::nullptr_tile = real_nullptr_tile; bool Tile::hasProperty(ItemProperty prop) const { - if (ground && ground->hasProperty(prop)) { - return true; - } - - if (const TileItemVector* items = getItemList()) { - for (auto &item : *items) { - if (item->hasProperty(prop)) { - return true; - } - } + switch (prop) { + case CONST_PROP_BLOCKSOLID: + return hasFlag(TILESTATE_BLOCKSOLID); + case CONST_PROP_HASHEIGHT: + return hasFlag(TILESTATE_HASHEIGHT); + case CONST_PROP_BLOCKPROJECTILE: + return hasFlag(TILESTATE_BLOCKPROJECTILE); + case CONST_PROP_BLOCKPATH: + return hasFlag(TILESTATE_BLOCKPATH); + case CONST_PROP_ISVERTICAL: + return hasFlag(TILESTATE_ISVERTICAL); + case CONST_PROP_ISHORIZONTAL: + return hasFlag(TILESTATE_ISHORIZONTAL); + case CONST_PROP_MOVEABLE: + return hasFlag(TILESTATE_MOVEABLE); + case CONST_PROP_IMMOVABLEBLOCKSOLID: + return hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID); + case CONST_PROP_IMMOVABLEBLOCKPATH: + return hasFlag(TILESTATE_IMMOVABLEBLOCKPATH); + case CONST_PROP_IMMOVABLENOFIELDBLOCKPATH: + return hasFlag(TILESTATE_IMMOVABLENOFIELDBLOCKPATH); + case CONST_PROP_NOFIELDBLOCKPATH: + return hasFlag(TILESTATE_NOFIELDBLOCKPATH); + case CONST_PROP_SUPPORTHANGABLE: + return hasFlag(TILESTATE_SUPPORTS_HANGABLE); + default: + return false; } - return false; } bool Tile::hasProperty(std::shared_ptr exclude, ItemProperty prop) const { @@ -943,6 +959,7 @@ void Tile::addThing(int32_t, std::shared_ptr thing) { if (creature) { Spectators::clearCache(); creature->setParent(static_self_cast()); + CreatureVector* creatures = makeCreatures(); creatures->insert(creatures->begin(), creature); } else { @@ -1530,6 +1547,7 @@ void Tile::internalAddThing(uint32_t, std::shared_ptr thing) { std::shared_ptr creature = thing->getCreature(); if (creature) { Spectators::clearCache(); + CreatureVector* creatures = makeCreatures(); creatures->insert(creatures->begin(), creature); } else { @@ -1574,14 +1592,14 @@ void Tile::internalAddThing(uint32_t, std::shared_ptr thing) { } } -void Tile::updateTileFlags(std::shared_ptr item) { +void Tile::updateTileFlags(const std::shared_ptr &item) { resetTileFlags(item); setTileFlags(item); } -void Tile::setTileFlags(std::shared_ptr item) { +void Tile::setTileFlags(const std::shared_ptr &item) { if (!hasFlag(TILESTATE_FLOORCHANGE)) { - const ItemType &it = Item::items[item->getID()]; + const auto &it = Item::items[item->getID()]; if (it.floorChange != 0) { setFlag(it.floorChange); } @@ -1603,6 +1621,10 @@ void Tile::setTileFlags(std::shared_ptr item) { setFlag(TILESTATE_IMMOVABLENOFIELDBLOCKPATH); } + if (item->hasProperty(CONST_PROP_SUPPORTHANGABLE)) { + setFlag(TILESTATE_SUPPORTS_HANGABLE); + } + if (item->getTeleport()) { setFlag(TILESTATE_TELEPORT); } @@ -1627,9 +1649,34 @@ void Tile::setTileFlags(std::shared_ptr item) { setFlag(TILESTATE_BED); } - std::shared_ptr container = item->getContainer(); - if (container && container->getDepotLocker()) { - setFlag(TILESTATE_DEPOT); + if (item->hasProperty(CONST_PROP_IMMOVABLEBLOCKPATH)) { + setFlag(TILESTATE_IMMOVABLEBLOCKPATH); + } + + if (item->hasProperty(CONST_PROP_MOVEABLE)) { + setFlag(TILESTATE_MOVEABLE); + } + + if (item->hasProperty(CONST_PROP_ISHORIZONTAL)) { + setFlag(TILESTATE_ISHORIZONTAL); + } + + if (item->hasProperty(CONST_PROP_ISVERTICAL)) { + setFlag(TILESTATE_ISVERTICAL); + } + + if (item->hasProperty(CONST_PROP_BLOCKPROJECTILE)) { + setFlag(TILESTATE_BLOCKPROJECTILE); + } + + if (item->hasProperty(CONST_PROP_HASHEIGHT)) { + setFlag(TILESTATE_HASHEIGHT); + } + + if (const auto &container = item->getContainer()) { + if (container->getDepotLocker()) { + setFlag(TILESTATE_DEPOT); + } } if (item->hasProperty(CONST_PROP_SUPPORTHANGABLE)) { @@ -1637,7 +1684,7 @@ void Tile::setTileFlags(std::shared_ptr item) { } } -void Tile::resetTileFlags(std::shared_ptr item) { +void Tile::resetTileFlags(const std::shared_ptr &item) { const ItemType &it = Item::items[item->getID()]; if (it.floorChange != 0) { resetFlag(TILESTATE_FLOORCHANGE); @@ -1667,6 +1714,26 @@ void Tile::resetTileFlags(std::shared_ptr item) { resetFlag(TILESTATE_IMMOVABLENOFIELDBLOCKPATH); } + if (item->hasProperty(CONST_PROP_MOVEABLE) && !hasProperty(item, CONST_PROP_MOVEABLE)) { + resetFlag(TILESTATE_MOVEABLE); + } + + if (item->hasProperty(CONST_PROP_ISHORIZONTAL) && !hasProperty(item, CONST_PROP_ISHORIZONTAL)) { + resetFlag(TILESTATE_ISHORIZONTAL); + } + + if (item->hasProperty(CONST_PROP_ISVERTICAL) && !hasProperty(item, CONST_PROP_ISVERTICAL)) { + resetFlag(TILESTATE_ISVERTICAL); + } + + if (item->hasProperty(CONST_PROP_BLOCKPROJECTILE) && !hasProperty(item, CONST_PROP_BLOCKPROJECTILE)) { + resetFlag(TILESTATE_BLOCKPROJECTILE); + } + + if (item->hasProperty(CONST_PROP_HASHEIGHT) && !hasProperty(item, CONST_PROP_HASHEIGHT)) { + resetFlag(TILESTATE_HASHEIGHT); + } + if (item->getTeleport()) { resetFlag(TILESTATE_TELEPORT); } @@ -1687,9 +1754,10 @@ void Tile::resetTileFlags(std::shared_ptr item) { resetFlag(TILESTATE_BED); } - std::shared_ptr container = item->getContainer(); - if (container && container->getDepotLocker()) { - resetFlag(TILESTATE_DEPOT); + if (const auto &container = item->getContainer()) { + if (container->getDepotLocker()) { + resetFlag(TILESTATE_DEPOT); + } } if (item->hasProperty(CONST_PROP_SUPPORTHANGABLE)) { diff --git a/src/items/tile.hpp b/src/items/tile.hpp index de5dd4f0e43..c5471756159 100644 --- a/src/items/tile.hpp +++ b/src/items/tile.hpp @@ -140,6 +140,7 @@ class Tile : public Cylinder, public SharedObject { std::shared_ptr getTopCreature() const; std::shared_ptr getBottomCreature() const; std::shared_ptr getTopVisibleCreature(std::shared_ptr creature) const; + std::shared_ptr getBottomVisibleCreature(std::shared_ptr creature) const; std::shared_ptr getTopTopItem() const; std::shared_ptr getTopDownItem() const; @@ -210,7 +211,7 @@ class Tile : public Cylinder, public SharedObject { void addThing(std::shared_ptr thing) override final; void addThing(int32_t index, std::shared_ptr thing) override; - void updateTileFlags(std::shared_ptr item); + void updateTileFlags(const std::shared_ptr &item); void updateThing(std::shared_ptr thing, uint16_t itemId, uint32_t count) override final; void replaceThing(uint32_t index, std::shared_ptr thing) override final; @@ -244,8 +245,14 @@ class Tile : public Cylinder, public SharedObject { std::shared_ptr getGround() const { return ground; } - void setGround(std::shared_ptr item) { - ground = item; + void setGround(const std::shared_ptr &item) { + if (ground) { + resetTileFlags(ground); + } + + if (ground = item) { + setTileFlags(item); + } } private: @@ -254,8 +261,8 @@ class Tile : public Cylinder, public SharedObject { void onRemoveTileItem(const CreatureVector &spectators, const std::vector &oldStackPosVector, std::shared_ptr item); void onUpdateTile(const CreatureVector &spectators); - void setTileFlags(std::shared_ptr item); - void resetTileFlags(std::shared_ptr item); + void setTileFlags(const std::shared_ptr &item); + void resetTileFlags(const std::shared_ptr &item); bool hasHarmfulField() const; ReturnValue checkNpcCanWalkIntoTile() const; diff --git a/src/lua/functions/creatures/creature_functions.cpp b/src/lua/functions/creatures/creature_functions.cpp index 14d86f1e291..c5221a9c3ad 100644 --- a/src/lua/functions/creatures/creature_functions.cpp +++ b/src/lua/functions/creatures/creature_functions.cpp @@ -911,7 +911,7 @@ int CreatureFunctions::luaCreatureGetPathTo(lua_State* L) { fpp.clearSight = getBoolean(L, 6, fpp.clearSight); fpp.maxSearchDist = getNumber(L, 7, fpp.maxSearchDist); - std::forward_list dirList; + stdext::arraylist dirList(128); if (creature->getPathTo(position, dirList, fpp)) { lua_newtable(L); diff --git a/src/lua/functions/map/position_functions.cpp b/src/lua/functions/map/position_functions.cpp index 5cee3f2d847..3e5582a1cd2 100644 --- a/src/lua/functions/map/position_functions.cpp +++ b/src/lua/functions/map/position_functions.cpp @@ -97,7 +97,7 @@ int PositionFunctions::luaPositionGetPathTo(lua_State* L) { fpp.clearSight = getBoolean(L, 6, fpp.clearSight); fpp.maxSearchDist = getNumber(L, 7, fpp.maxSearchDist); - std::forward_list dirList; + stdext::arraylist dirList(128); if (g_game().map.getPathMatching(pos, dirList, FrozenPathingConditionCall(position), fpp)) { lua_newtable(L); diff --git a/src/map/map.cpp b/src/map/map.cpp index 53f7c98db38..72e867551be 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -17,6 +17,7 @@ #include "game/zones/zone.hpp" #include "io/iomap.hpp" #include "io/iomapserialize.hpp" +#include "game/scheduling/dispatcher.hpp" #include "map/spectators.hpp" void Map::load(const std::string &identifier, const Position &pos) { @@ -484,30 +485,39 @@ bool Map::isSightClear(const Position &fromPos, const Position &toPos, bool floo } std::shared_ptr Map::canWalkTo(const std::shared_ptr &creature, const Position &pos) { - int32_t walkCache = creature->getWalkCache(pos); + if (!creature || creature->isRemoved()) { + return nullptr; + } + + const int32_t walkCache = creature->getWalkCache(pos); + if (walkCache == 0) { return nullptr; - } else if (walkCache == 1) { + } + + if (walkCache == 1) { return getTile(pos.x, pos.y, pos.z); } // used for non-cached tiles - std::shared_ptr tile = getTile(pos.x, pos.y, pos.z); + const auto &tile = getTile(pos.x, pos.y, pos.z); if (creature->getTile() != tile) { if (!tile || tile->queryAdd(0, creature, 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) != RETURNVALUE_NOERROR) { return nullptr; } } + return tile; } -bool Map::getPathMatching(const std::shared_ptr &creature, std::forward_list &dirList, const FrozenPathingConditionCall &pathCondition, const FindPathParams &fpp) { - Position pos = creature->getPosition(); - Position endPos; - - AStarNodes nodes(pos.x, pos.y); +bool Map::getPathMatching(const std::shared_ptr &creature, stdext::arraylist &dirList, const FrozenPathingConditionCall &pathCondition, const FindPathParams &fpp) { + return getPathMatching(creature, creature->getPosition(), dirList, pathCondition, fpp); +} - int32_t bestMatch = 0; +bool Map::getPathMatching(const std::shared_ptr &creature, const Position &startPos, stdext::arraylist &dirList, const FrozenPathingConditionCall &pathCondition, const FindPathParams &fpp) { + static int_fast32_t allNeighbors[8][2] = { + { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 } + }; static int_fast32_t dirNeighbors[8][5][2] = { { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 1, 1 }, { -1, 1 } }, @@ -519,186 +529,14 @@ bool Map::getPathMatching(const std::shared_ptr &creature, std::forwar { { 0, 1 }, { 1, 0 }, { 1, -1 }, { 1, 1 }, { -1, 1 } }, { { -1, 0 }, { 0, 1 }, { -1, -1 }, { 1, 1 }, { -1, 1 } } }; - static int_fast32_t allNeighbors[8][2] = { - { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 } - }; - const Position startPos = pos; - - AStarNode* found = nullptr; - while (fpp.maxSearchDist != 0 || nodes.getClosedNodes() < 100) { - AStarNode* n = nodes.getBestNode(); - if (!n) { - if (found) { - break; - } - return false; - } - - const int_fast32_t x = n->x; - const int_fast32_t y = n->y; - pos.x = x; - pos.y = y; - if (pathCondition(startPos, pos, fpp, bestMatch)) { - found = n; - endPos = pos; - if (bestMatch == 0) { - break; - } - } - - uint_fast32_t dirCount; - int_fast32_t* neighbors; - if (n->parent) { - const int_fast32_t offset_x = n->parent->x - x; - const int_fast32_t offset_y = n->parent->y - y; - if (offset_y == 0) { - if (offset_x == -1) { - neighbors = *dirNeighbors[DIRECTION_WEST]; - } else { - neighbors = *dirNeighbors[DIRECTION_EAST]; - } - } else if (!fpp.allowDiagonal || offset_x == 0) { - if (offset_y == -1) { - neighbors = *dirNeighbors[DIRECTION_NORTH]; - } else { - neighbors = *dirNeighbors[DIRECTION_SOUTH]; - } - } else if (offset_y == -1) { - if (offset_x == -1) { - neighbors = *dirNeighbors[DIRECTION_NORTHWEST]; - } else { - neighbors = *dirNeighbors[DIRECTION_NORTHEAST]; - } - } else if (offset_x == -1) { - neighbors = *dirNeighbors[DIRECTION_SOUTHWEST]; - } else { - neighbors = *dirNeighbors[DIRECTION_SOUTHEAST]; - } - dirCount = fpp.allowDiagonal ? 5 : 3; - } else { - dirCount = 8; - neighbors = *allNeighbors; - } - - const int_fast32_t f = n->f; - for (uint_fast32_t i = 0; i < dirCount; ++i) { - pos.x = x + *neighbors++; - pos.y = y + *neighbors++; - - if (fpp.maxSearchDist != 0 && (Position::getDistanceX(startPos, pos) > fpp.maxSearchDist || Position::getDistanceY(startPos, pos) > fpp.maxSearchDist)) { - continue; - } - - if (fpp.keepDistance && !pathCondition.isInRange(startPos, pos, fpp)) { - continue; - } - - std::shared_ptr tile; - AStarNode* neighborNode = nodes.getNodeByPosition(pos.x, pos.y); - if (neighborNode) { - tile = getTile(pos.x, pos.y, pos.z); - } else { - tile = canWalkTo(creature, pos); - if (!tile) { - continue; - } - } - - // The cost (g) for this neighbor - const int_fast32_t cost = AStarNodes::getMapWalkCost(n, pos); - const int_fast32_t extraCost = AStarNodes::getTileWalkCost(creature, tile); - const int_fast32_t newf = f + cost + extraCost; - - if (neighborNode) { - if (neighborNode->f <= newf) { - // The node on the closed/open list is cheaper than this one - continue; - } - - neighborNode->f = newf; - neighborNode->parent = n; - nodes.openNode(neighborNode); - } else { - // Does not exist in the open/closed list, create a std::make_shared - neighborNode = nodes.createOpenNode(n, pos.x, pos.y, newf); - if (!neighborNode) { - if (found) { - break; - } - return false; - } - } - } - - nodes.closeNode(n); - } - - if (!found) { - return false; - } - - int_fast32_t prevx = endPos.x; - int_fast32_t prevy = endPos.y; - - found = found->parent; - while (found) { - pos.x = found->x; - pos.y = found->y; - - int_fast32_t dx = pos.getX() - prevx; - int_fast32_t dy = pos.getY() - prevy; - - prevx = pos.x; - prevy = pos.y; - - if (dx == 1 && dy == 1) { - dirList.push_front(DIRECTION_NORTHWEST); - } else if (dx == -1 && dy == 1) { - dirList.push_front(DIRECTION_NORTHEAST); - } else if (dx == 1 && dy == -1) { - dirList.push_front(DIRECTION_SOUTHWEST); - } else if (dx == -1 && dy == -1) { - dirList.push_front(DIRECTION_SOUTHEAST); - } else if (dx == 1) { - dirList.push_front(DIRECTION_WEST); - } else if (dx == -1) { - dirList.push_front(DIRECTION_EAST); - } else if (dy == 1) { - dirList.push_front(DIRECTION_NORTH); - } else if (dy == -1) { - dirList.push_front(DIRECTION_SOUTH); - } - - found = found->parent; - } - return true; -} - -bool Map::getPathMatching(const Position &start, std::forward_list &dirList, const FrozenPathingConditionCall &pathCondition, const FindPathParams &fpp) { - Position pos = start; + Position pos = startPos; Position endPos; AStarNodes nodes(pos.x, pos.y); int32_t bestMatch = 0; - static int_fast32_t dirNeighbors[8][5][2] = { - { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 1, 1 }, { -1, 1 } }, - { { -1, 0 }, { 0, 1 }, { 0, -1 }, { -1, -1 }, { -1, 1 } }, - { { -1, 0 }, { 1, 0 }, { 0, -1 }, { -1, -1 }, { 1, -1 } }, - { { 0, 1 }, { 1, 0 }, { 0, -1 }, { 1, -1 }, { 1, 1 } }, - { { 1, 0 }, { 0, -1 }, { -1, -1 }, { 1, -1 }, { 1, 1 } }, - { { -1, 0 }, { 0, -1 }, { -1, -1 }, { 1, -1 }, { -1, 1 } }, - { { 0, 1 }, { 1, 0 }, { 1, -1 }, { 1, 1 }, { -1, 1 } }, - { { -1, 0 }, { 0, 1 }, { -1, -1 }, { 1, 1 }, { -1, 1 } } - }; - static int_fast32_t allNeighbors[8][2] = { - { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 } - }; - - const Position startPos = pos; - AStarNode* found = nullptr; while (fpp.maxSearchDist != 0 || nodes.getClosedNodes() < 100) { AStarNode* n = nodes.getBestNode(); @@ -768,20 +606,18 @@ bool Map::getPathMatching(const Position &start, std::forward_list &d continue; } - std::shared_ptr tile; AStarNode* neighborNode = nodes.getNodeByPosition(pos.x, pos.y); - if (neighborNode) { - tile = getTile(pos.x, pos.y, pos.z); - } else { - tile = getTile(pos.x, pos.y, pos.z); - if (!tile || tile->hasFlag(TILESTATE_BLOCKSOLID)) { - continue; - } + + const bool withoutCreature = creature == nullptr; + const auto &tile = neighborNode || withoutCreature ? getTile(pos.x, pos.y, pos.z) : canWalkTo(creature, pos); + + if (!tile || !neighborNode && withoutCreature && tile->hasFlag(TILESTATE_BLOCKSOLID)) { + continue; } // The cost (g) for this neighbor - const int_fast32_t cost = AStarNodes::getMapWalkCost(n, pos, true); - const int_fast32_t extraCost = 0; + const int_fast32_t cost = AStarNodes::getMapWalkCost(n, pos, withoutCreature); + const int_fast32_t extraCost = AStarNodes::getTileWalkCost(creature, tile); const int_fast32_t newf = f + cost + extraCost; if (neighborNode) { @@ -820,8 +656,8 @@ bool Map::getPathMatching(const Position &start, std::forward_list &d pos.x = found->x; pos.y = found->y; - int_fast32_t dx = pos.getX() - prevx; - int_fast32_t dy = pos.getY() - prevy; + const int_fast32_t dx = pos.getX() - prevx; + const int_fast32_t dy = pos.getY() - prevy; prevx = pos.x; prevy = pos.y; diff --git a/src/map/map.hpp b/src/map/map.hpp index ac0211c7daf..d5ca9b2af14 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -123,9 +123,11 @@ class Map : protected MapCache { std::shared_ptr canWalkTo(const std::shared_ptr &creature, const Position &pos); - bool getPathMatching(const std::shared_ptr &creature, std::forward_list &dirList, const FrozenPathingConditionCall &pathCondition, const FindPathParams &fpp); + bool getPathMatching(const std::shared_ptr &creature, stdext::arraylist &dirList, const FrozenPathingConditionCall &pathCondition, const FindPathParams &fpp); - bool getPathMatching(const Position &startPos, std::forward_list &dirList, const FrozenPathingConditionCall &pathCondition, const FindPathParams &fpp); + bool getPathMatching(const Position &startPos, stdext::arraylist &dirList, const FrozenPathingConditionCall &pathCondition, const FindPathParams &fpp) { + return getPathMatching(nullptr, startPos, dirList, pathCondition, fpp); + } std::map waypoints; @@ -145,6 +147,8 @@ class Map : protected MapCache { Houses housesCustomMaps[50]; private: + bool getPathMatching(const std::shared_ptr &creature, const Position &startPos, stdext::arraylist &dirList, const FrozenPathingConditionCall &pathCondition, const FindPathParams &fpp); + /** * Set a single tile. */ diff --git a/src/map/utils/astarnodes.cpp b/src/map/utils/astarnodes.cpp index 36265dd7f12..e4cccd4e694 100644 --- a/src/map/utils/astarnodes.cpp +++ b/src/map/utils/astarnodes.cpp @@ -104,23 +104,28 @@ int_fast32_t AStarNodes::getMapWalkCost(AStarNode* node, const Position &neighbo return MAP_NORMALWALKCOST; } -int_fast32_t AStarNodes::getTileWalkCost(const std::shared_ptr &creature, std::shared_ptr tile) { +int_fast32_t AStarNodes::getTileWalkCost(const std::shared_ptr &creature, const std::shared_ptr &tile) { + if (!creature || !tile) { + return 0; + } + int_fast32_t cost = 0; if (tile->getTopVisibleCreature(creature) != nullptr) { // destroy creature cost cost += MAP_NORMALWALKCOST * 3; } - if (std::shared_ptr field = tile->getFieldItem()) { - CombatType_t combatType = field->getCombatType(); - std::shared_ptr monster = creature->getMonster(); + if (const auto &field = tile->getFieldItem()) { + const CombatType_t combatType = field->getCombatType(); + const auto &monster = creature->getMonster(); + if (!creature->isImmune(combatType) && !creature->hasCondition(Combat::DamageToConditionType(combatType)) && (monster && !monster->canWalkOnFieldType(combatType))) { cost += MAP_NORMALWALKCOST * 18; } /** * Make player try to avoid magic fields, when calculating pathing */ - std::shared_ptr player = creature->getPlayer(); + const auto &player = creature->getPlayer(); if (player && !field->isBlocking() && field->getDamage() != 0) { cost += MAP_NORMALWALKCOST * 18; } diff --git a/src/map/utils/astarnodes.hpp b/src/map/utils/astarnodes.hpp index eba694de218..26f33cdfcc4 100644 --- a/src/map/utils/astarnodes.hpp +++ b/src/map/utils/astarnodes.hpp @@ -31,7 +31,7 @@ class AStarNodes { AStarNode* getNodeByPosition(uint32_t x, uint32_t y); static int_fast32_t getMapWalkCost(AStarNode* node, const Position &neighborPos, bool preferDiagonal = false); - static int_fast32_t getTileWalkCost(const std::shared_ptr &creature, std::shared_ptr tile); + static int_fast32_t getTileWalkCost(const std::shared_ptr &creature, const std::shared_ptr &tile); private: static constexpr int32_t MAX_NODES = 512; diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 6da9e94180e..e81933610a8 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -1555,7 +1555,7 @@ void ProtocolGame::parseAutoWalk(NetworkMessage &msg) { msg.skipBytes(numdirs); - std::forward_list path; + stdext::arraylist path; for (uint8_t i = 0; i < numdirs; ++i) { uint8_t rawdir = msg.getPreviousByte(); switch (rawdir) { @@ -1592,7 +1592,7 @@ void ProtocolGame::parseAutoWalk(NetworkMessage &msg) { return; } - addGameTask(&Game::playerAutoWalk, player->getID(), path); + addGameTask(&Game::playerAutoWalk, player->getID(), path.data()); } void ProtocolGame::parseSetOutfit(NetworkMessage &msg) { diff --git a/src/utils/arraylist.hpp b/src/utils/arraylist.hpp index ea803ab8cf0..94e05e2eb76 100644 --- a/src/utils/arraylist.hpp +++ b/src/utils/arraylist.hpp @@ -21,6 +21,25 @@ namespace stdext { template class arraylist { public: + arraylist() = default; + + explicit arraylist(size_t reserveSize) { + reserve(reserveSize); + } + + explicit arraylist(std::initializer_list _Ilist) { + backContainer.assign(_Ilist); + } + + arraylist &operator=(std::initializer_list _Ilist) { + backContainer.assign(_Ilist); + return *this; + } + + void assign(std::initializer_list _Ilist) { + backContainer.assign(_Ilist); + } + bool contains(const T &v) { update(); return std::ranges::find(backContainer, v) != backContainer.end(); @@ -128,7 +147,7 @@ namespace stdext { const auto &data() noexcept { update(); - return backContainer.data(); + return backContainer; } T &operator[](const size_t i) { From 57b4593b4029e9208bb0c5bcc3c0c9ec4d7236b2 Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Thu, 2 Nov 2023 16:16:08 -0300 Subject: [PATCH 02/12] improve: use modern implementations to manage threads (#1756) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This updates the thread management constructs within the codebase. It shifts from using std::lock_guard to std::scoped_lock for managing mutexes, providing a more modern and safer scope-based locking mechanism. Additionally, it replaces std::condition_variable with std::atomic::wait, leveraging the more efficient and scalable waiting and notification system provided by atomics. Benefits: • std::scoped_lock is more flexible than std::lock_guard, allowing for handling multiple mutexes without the risk of deadlock. • std::atomic::wait introduces potential performance gains by utilizing a more lightweight synchronization mechanism compared to traditional condition variables. Impact: • These improvements are expected to enhance the safety and efficiency of concurrent operations. They modernize the codebase, aligning it with current best practices for C++ concurrency. --- src/canary_server.cpp | 16 +++++++--------- src/canary_server.hpp | 15 +++++++-------- src/creatures/players/management/ban.cpp | 2 +- src/game/game.cpp | 2 +- src/kv/kv.cpp | 4 ++-- src/lib/di/shared.hpp | 8 ++++---- src/server/network/connection/connection.cpp | 14 +++++++------- 7 files changed, 29 insertions(+), 32 deletions(-) diff --git a/src/canary_server.cpp b/src/canary_server.cpp index 6d833e0ce0b..7facada14d5 100644 --- a/src/canary_server.cpp +++ b/src/canary_server.cpp @@ -40,8 +40,7 @@ CanaryServer::CanaryServer( ) : logger(logger), rsa(rsa), - serviceManager(serviceManager), - loaderUniqueLock(loaderLock) { + serviceManager(serviceManager) { logInfos(); toggleForceCloseButton(); g_game().setGameState(GAME_STATE_STARTUP); @@ -93,10 +92,9 @@ int CanaryServer::run() { g_webhook().sendMessage("Server is now online", "Server has successfully started.", WEBHOOK_COLOR_ONLINE); - loaderDone = true; - loaderSignal.notify_all(); + loaderStatus = LoaderStatus::LOADED; } catch (FailedToInitializeCanary &err) { - loadFailed = true; + loaderStatus = LoaderStatus::FAILED; logger.error(err.what()); logger.error("The program will close after pressing the enter key..."); @@ -104,16 +102,16 @@ int CanaryServer::run() { if (isatty(STDIN_FILENO)) { getchar(); } - - loaderSignal.notify_all(); } + + loaderStatus.notify_one(); }, "CanaryServer::run" ); - loaderSignal.wait(loaderUniqueLock, [this] { return loaderDone || loadFailed; }); + loaderStatus.wait(LoaderStatus::LOADING); - if (loadFailed || !serviceManager.is_running()) { + if (loaderStatus == LoaderStatus::FAILED || !serviceManager.is_running()) { logger.error("No services running. The server is NOT online!"); shutdown(); return EXIT_FAILURE; diff --git a/src/canary_server.hpp b/src/canary_server.hpp index 6d75f64dc16..d9374309c4a 100644 --- a/src/canary_server.hpp +++ b/src/canary_server.hpp @@ -40,18 +40,17 @@ class CanaryServer { int run(); private: + enum class LoaderStatus : uint8_t { + LOADING, + LOADED, + FAILED + }; + RSA &rsa; Logger &logger; ServiceManager &serviceManager; - std::mutex loaderLock; - std::condition_variable loaderSignal; - std::condition_variable mapSignal; - std::unique_lock loaderUniqueLock; - std::string threadFailMsg; - - bool loaderDone = false; - bool loadFailed = false; + std::atomic loaderStatus = LoaderStatus::LOADING; void logInfos(); static void toggleForceCloseButton(); diff --git a/src/creatures/players/management/ban.cpp b/src/creatures/players/management/ban.cpp index 0c08fdc6f1e..3315836ebea 100644 --- a/src/creatures/players/management/ban.cpp +++ b/src/creatures/players/management/ban.cpp @@ -15,7 +15,7 @@ #include "utils/tools.hpp" bool Ban::acceptConnection(uint32_t clientIP) { - std::lock_guard lockClass(lock); + std::scoped_lock lockClass(lock); uint64_t currentTime = OTSYS_TIME(); diff --git a/src/game/game.cpp b/src/game/game.cpp index 417c89a8497..a01ac60bff8 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -9864,7 +9864,7 @@ void Game::playerRewardChestCollect(uint32_t playerId, const Position &pos, uint reward->setParent(playerRewardChest); } - std::lock_guard lock(player->quickLootMutex); + std::scoped_lock lock(player->quickLootMutex); ReturnValue returnValue = collectRewardChestItems(player, maxMoveItems); if (returnValue != RETURNVALUE_NOERROR) { diff --git a/src/kv/kv.cpp b/src/kv/kv.cpp index e5dbc974b76..0e2f4b2f836 100644 --- a/src/kv/kv.cpp +++ b/src/kv/kv.cpp @@ -27,7 +27,7 @@ void KVStore::set(const std::string &key, const std::initializer_list KVStore::get(const std::string &key, bool forceLoad /*= false */) { logger.debug("KVStore::get({})", key); - std::lock_guard lock(mutex_); + std::scoped_lock lock(mutex_); if (forceLoad || !store_.contains(key)) { auto value = load(key); if (value) { diff --git a/src/lib/di/shared.hpp b/src/lib/di/shared.hpp index e206cbd4b4c..c1e2f0c6743 100644 --- a/src/lib/di/shared.hpp +++ b/src/lib/di/shared.hpp @@ -29,9 +29,9 @@ namespace extension { #if !defined(BOOST_DI_NOT_THREAD_SAFE) //<> explicit scope(scope &&other) noexcept : - scope(std::move(other), std::lock_guard(other.mutex_)) { } + scope(std::move(other), std::scoped_lock(other.mutex_)) { } //<> - scope(scope &&other, const std::lock_guard &) noexcept : + scope(scope &&other, const std::scoped_lock &) noexcept : object_(std::move(other.object_)) { } #endif @@ -49,7 +49,7 @@ namespace extension { wrappers::shared create(const TProvider &provider) & { if (!object_) { #if !defined(BOOST_DI_NOT_THREAD_SAFE) - std::lock_guard lock(mutex_); + std::scoped_lock lock(mutex_); if (!object_) #endif object_ = std::shared_ptr { provider.get() }; @@ -65,7 +65,7 @@ namespace extension { auto &object = provider.cfg().template data(); if (!object) { #if !defined(BOOST_DI_NOT_THREAD_SAFE) - std::lock_guard lock(mutex_); + std::scoped_lock lock(mutex_); if (!object) #endif object = std::shared_ptr { provider.get() }; diff --git a/src/server/network/connection/connection.cpp b/src/server/network/connection/connection.cpp index 8e637c053ee..d2937756cf0 100644 --- a/src/server/network/connection/connection.cpp +++ b/src/server/network/connection/connection.cpp @@ -53,7 +53,7 @@ void Connection::close(bool force) { // any thread ConnectionManager::getInstance().releaseConnection(shared_from_this()); - std::lock_guard lockClass(connectionLock); + std::scoped_lock lockClass(connectionLock); ip = 0; if (connectionState == CONNECTION_STATE_CLOSED) { return; @@ -114,7 +114,7 @@ void Connection::accept(bool toggleParseHeader /* = true */) { } void Connection::parseProxyIdentification(const std::error_code &error) { - std::lock_guard lockClass(connectionLock); + std::scoped_lock lockClass(connectionLock); readTimer.cancel(); if (error) { @@ -167,7 +167,7 @@ void Connection::parseProxyIdentification(const std::error_code &error) { } void Connection::parseHeader(const std::error_code &error) { - std::lock_guard lockClass(connectionLock); + std::scoped_lock lockClass(connectionLock); readTimer.cancel(); if (error) { @@ -209,7 +209,7 @@ void Connection::parseHeader(const std::error_code &error) { } void Connection::parsePacket(const std::error_code &error) { - std::lock_guard lockClass(connectionLock); + std::scoped_lock lockClass(connectionLock); readTimer.cancel(); if (error) { @@ -275,7 +275,7 @@ void Connection::parsePacket(const std::error_code &error) { } void Connection::resumeWork() { - std::lock_guard lockClass(connectionLock); + std::scoped_lock lockClass(connectionLock); try { // Wait to the next packet @@ -287,7 +287,7 @@ void Connection::resumeWork() { } void Connection::send(const OutputMessage_ptr &outputMessage) { - std::lock_guard lockClass(connectionLock); + std::scoped_lock lockClass(connectionLock); if (connectionState == CONNECTION_STATE_CLOSED) { return; } @@ -324,7 +324,7 @@ uint32_t Connection::getIP() { return ip; } - std::lock_guard lockClass(connectionLock); + std::scoped_lock lockClass(connectionLock); // IP-address is expressed in network byte order std::error_code error; From 436bcacc26a567e7c8fa1446df30e59109ef6065 Mon Sep 17 00:00:00 2001 From: Luan Santos Date: Thu, 2 Nov 2023 15:53:16 -0700 Subject: [PATCH 03/12] improve: move all onKill events to registed onDeath (#1759) Alternative implementation of #1665 This change deprecates `onKill` (you'll get a warning if you try to use `onKill`, but it'll keep working until we decide to delete the callback from the source. Taking advantage of registed `onDeath` events and the fact that mechanics often use either damage map or the party of the top damage dealer. It also fixes a lot of inconsistencies in how kill tasks work, making most systems match what they should do when doing quests in a group. Full credit to @duuh30 for finding the issue and exploring the fix, and @beats-dh for helping with that. ## (very basic) benchmarks ### With this change (note, also includes #1757) ``` Average (Mean): Approximately 0.353 ms Median: Approximately 0.509 ms 95th Percentile (P95): 0.675 ms ``` ### Before this change ``` Average (Mean): Approximately 2998.6 ms Median: Approximately 2012.4 ms 95th Percentile (P95): 5997.9 ms ``` --- .../monster/bosses/black_knight.lua | 4 + .../monster/bosses/diseased_bill.lua | 4 + .../monster/bosses/diseased_dan.lua | 4 + .../monster/bosses/diseased_fred.lua | 4 + .../monster/bosses/energized_raging_mage.lua | 4 + .../monster/bosses/kroazur.lua | 4 + .../monster/bosses/pythius_the_rotten.lua | 4 + .../monster/bosses/raging_mage.lua | 4 + .../monster/bosses/renegade_orc.lua | 4 + .../monster/bosses/splasher.lua | 4 + .../constructs/diamond_servant_replica.lua | 4 + .../constructs/golden_servant_replica.lua | 4 + .../monster/dawnport/mountain_troll.lua | 4 + .../monster/dawnport/muglex_clan_footman.lua | 4 + .../monster/dragons/dragon.lua | 5 + .../monster/dragons/dragon_lord.lua | 4 + .../monster/extra_dimensional/yielothax.lua | 4 + .../monster/humanoids/lost_exile.lua | 4 + .../monster/humanoids/minotaur_bruiser.lua | 4 + .../humanoids/minotaur_cult_follower.lua | 4 + .../humanoids/minotaur_cult_prophet.lua | 4 + .../humanoids/minotaur_cult_zealot.lua | 4 + .../monster/humans/burning_gladiator.lua | 4 + data-otservbr-global/monster/humans/nomad.lua | 4 + .../monster/humans/nomad_blue.lua | 4 + .../monster/humans/nomad_female.lua | 4 + .../humans/priestess_of_the_wild_sun.lua | 4 + .../monster/magicals/crystalcrusher.lua | 4 + .../monster/magicals/enfeebled_silencer.lua | 4 + .../monster/magicals/frazzlemaw.lua | 4 + .../monster/magicals/silencer.lua | 4 + .../monster/magicals/weakened_frazzlemaw.lua | 4 + .../monster/mammals/husky.lua | 4 + data-otservbr-global/monster/mammals/rat.lua | 4 + .../bigfoots_burden/bosses/abyssador.lua | 4 + .../bigfoots_burden/bosses/deathstrike.lua | 4 + .../bigfoots_burden/bosses/gnomevil.lua | 4 + .../quests/bigfoots_burden/versperoth.lua | 4 + .../bosses/dorokoll_the_mystic.lua | 4 + .../bosses/eliz_the_unyielding.lua | 4 + .../bosses/eshtaba_the_conjurer.lua | 4 + .../bosses/essence_of_malice.lua | 4 + .../bosses/malkhar_deathbringer.lua | 4 + .../bosses/mezlon_the_defiler.lua | 4 + .../bosses/pillars/pillar_of_death.lua | 4 + .../bosses/pillars/pillar_of_draining.lua | 4 + .../bosses/pillars/pillar_of_healing.lua | 4 + .../bosses/pillars/pillar_of_protection.lua | 4 + .../bosses/pillars/pillar_of_summoning.lua | 4 + .../cults_of_tibia/bosses/ravenous_hunger.lua | 9 +- .../bosses/the_corruptor_of_souls.lua | 4 + .../cults_of_tibia/bosses/the_false_god.lua | 4 + .../cults_of_tibia/bosses/the_sandking.lua | 4 + .../bosses/the_souldespoiler.lua | 4 + .../bosses/the_source_of_corruption.lua | 4 + .../bosses/the_unarmored_voidborn.lua | 4 + .../quests/cults_of_tibia/cult_believer.lua | 4 + .../quests/cults_of_tibia/cult_enforcer.lua | 4 + .../quests/cults_of_tibia/cult_scholar.lua | 4 + .../quests/cults_of_tibia/misguided_bully.lua | 4 + .../cults_of_tibia/misguided_shadow.lua | 4 + .../bosses/the_baron_from_below.lua | 5 + .../bosses/the_count_of_the_core.lua | 4 + .../bosses/the_duke_of_the_depths.lua | 4 + .../quests/dangerous_depth/makeshift_home.lua | 4 + .../quests/dangerous_depth/organic_matter.lua | 4 + .../quests/dangerous_depth/snail_slime.lua | 5 + .../dark_trails/death_priest_shargon.lua | 4 + .../quests/dark_trails/the_ravager.lua | 4 + .../feaster_of_souls/the_dread_maiden.lua | 4 + .../feaster_of_souls/the_fear_feaster.lua | 4 + .../quests/feaster_of_souls/the_pale_worm.lua | 1 + .../quests/feaster_of_souls/the_unwelcome.lua | 4 + .../bosses/ferumbras_mortal_shell.lua | 4 + .../ferumbras_ascendant/bosses/mazoran.lua | 4 + .../ferumbras_ascendant/bosses/plagirath.lua | 4 + .../ferumbras_ascendant/bosses/ragiaz.lua | 4 + .../ferumbras_ascendant/bosses/razzagorn.lua | 4 + .../ferumbras_ascendant/bosses/shulgrax.lua | 4 + .../ferumbras_ascendant/bosses/tarbaz.lua | 4 + .../bosses/the_lord_of_the_lice.lua | 4 + .../bosses/the_shatterer.lua | 4 + .../ferumbras_ascendant/bosses/zamulosh.lua | 4 + .../ferumbras_ascendant/bosses/zamulosh2.lua | 4 + .../ferumbras_ascendant/bosses/zamulosh3.lua | 9 +- .../bosses/lady_tenebris.lua | 9 +- .../forgotten_knowledge/bosses/lloyd.lua | 9 +- .../bosses/melting_frozen_horror.lua | 9 +- .../bosses/soul_of_dragonking_zyrtarch.lua | 4 + .../bosses/the_blazing_time_guardian.lua | 4 + .../bosses/the_enraged_thorn_knight.lua | 9 +- .../bosses/the_freezing_time_guardian.lua | 4 + .../bosses/the_last_lore_keeper.lua | 4 + .../bosses/the_time_guardian.lua | 4 + .../bound_astral_power.lua | 4 + .../cosmic_energy_prism_a.lua | 9 +- .../cosmic_energy_prism_b.lua | 9 +- .../cosmic_energy_prism_c.lua | 2 +- .../cosmic_energy_prism_d.lua | 9 +- .../grave_danger/bosses/count_vlarkorth.lua | 4 + .../quests/grave_danger/bosses/duke_krule.lua | 4 + .../quests/grave_danger/bosses/earl_osam.lua | 4 + .../quests/grave_danger/bosses/king_zelos.lua | 1 + .../grave_danger/bosses/lord_azaram.lua | 4 + .../quests/grave_danger/bosses/sir_baeloc.lua | 4 + .../quests/hero_of_rathleton/deep_terror.lua | 4 + .../empowered_glooth_horror.lua | 9 +- .../hero_of_rathleton/professor_maxxen.lua | 4 + .../quests/in_service_of_yalahar/azerus.lua | 4 + .../quests/in_service_of_yalahar/azerus2.lua | 4 + .../quests/in_service_of_yalahar/inky.lua | 4 + .../in_service_of_yalahar/sharptooth.lua | 4 + .../quests/kilmaresh/an_astral_glyph.lua | 9 +- .../monster/quests/kilmaresh/bragrumol.lua | 4 + .../monster/quests/kilmaresh/mozradek.lua | 4 + .../monster/quests/kilmaresh/xogixath.lua | 4 + .../monster/quests/liquid_black/jaul.lua | 4 + .../monster/quests/liquid_black/obujos.lua | 4 + .../monster/quests/liquid_black/tanjis.lua | 4 + .../primal_ordeal_quest/magma_bubble.lua | 1 + .../primal_ordeal_quest/the_primal_menace.lua | 1 + .../quests/soul_war/goshnars_cruelty.lua | 4 + .../quests/soul_war/goshnars_greed.lua | 4 + .../quests/soul_war/goshnars_malice.lua | 4 + .../quests/soul_war/goshnars_megalomania.lua | 4 + .../quests/soul_war/goshnars_spite.lua | 4 + .../the_dream_courts/bosses/alptramun.lua | 4 + .../bosses/izcandar_the_banished.lua | 4 + .../bosses/malofur_mangrinder.lua | 4 + .../the_dream_courts/bosses/maxxenius.lua | 4 + .../bosses/the_nightmare_beast.lua | 4 + .../the_elemental_spheres/earth_overlord.lua | 4 + .../the_elemental_spheres/energy_overlord.lua | 4 + .../the_elemental_spheres/fire_overlord.lua | 4 + .../the_elemental_spheres/ice_overlord.lua | 4 + .../lord_of_the_elements.lua | 4 + .../quests/the_inquisition/annihilon.lua | 4 + .../quests/the_inquisition/golgordan.lua | 4 + .../quests/the_inquisition/hellgorak.lua | 4 + .../quests/the_inquisition/latrivan.lua | 4 + .../quests/the_inquisition/madareth.lua | 4 + .../quests/the_inquisition/ungreez.lua | 4 + .../quests/the_inquisition/ushuriel.lua | 4 + .../quests/the_inquisition/zugurosh.lua | 4 + .../the_new_frontier/shard_of_corruption.lua | 4 + .../quests/the_new_frontier/tirecz.lua | 4 + .../the_secret_library/bosses/ghulosh.lua | 4 + .../the_secret_library/bosses/gorzindel.lua | 4 + .../bosses/the_scourge_of_oblivion.lua | 4 + .../quests/the_secret_library/lokathmor.lua | 4 + .../quests/the_secret_library/mazzinor.lua | 4 + .../fury_of_the_emperor.lua | 4 + .../lizard_abomination.lua | 4 + .../wrath_of_the_emperor/mutated_zalamon.lua | 4 + .../scorn_of_the_emperor.lua | 4 + .../snake_god_essence.lua | 4 + .../wrath_of_the_emperor/snake_thing.lua | 4 + .../spite_of_the_emperor.lua | 4 + .../wrath_of_the_emperor/the_keeper.lua | 4 + .../wrath_of_the_emperor.lua | 4 + .../monster/reptiles/lizard_magistratus.lua | 4 + .../monster/reptiles/lizard_noble.lua | 4 + .../monster/undeads/demon_skeleton.lua | 4 + .../monster/vermins/deepworm.lua | 4 + .../monster/vermins/diremaw.lua | 4 + .../monster/vermins/drillworm.lua | 4 + .../monster/vermins/parasite.lua | 4 + .../monster/vermins/wiggler.lua | 4 + .../quests/dangerous_depth/using_crystals.lua | 5 +- .../quests/feaster_of_souls/bosses_killed.lua | 17 +- .../quests/grave_danger/bosses_killed.lua | 31 ++-- .../quests/secret_library/bosses_killed.lua | 31 ++-- .../actions/quests/soul_war/bosses_killed.lua | 17 +- .../quests/the_dream_courts/bosses_killed.lua | 17 +- .../monster/lower_roshamuul.lua | 16 +- .../creaturescripts/others/login_events.lua | 108 ------------- .../the_great_dragon_hunt.lua | 27 ++-- .../an_uneasy_alliance/renegade_orc_kill.lua | 20 +-- .../quests/bigfoot_burden/bosses_warzone.lua | 31 ++-- .../quests/bigfoot_burden/parasite.lua | 20 +-- .../quests/bigfoot_burden/versperoth_kill.lua | 13 +- .../quests/bigfoot_burden/wiggler_kill.lua | 24 +-- .../cults_of_tibia/bosses_mission_cults.lua | 74 +++++---- .../cults_of_tibia/carlin_vortex_spawn.lua | 32 ++-- .../cults_of_tibia/destroyed_pillar.lua | 29 ++-- .../cults_of_tibia/essence_of_malice.lua | 9 +- .../cults_of_tibia/glowing_rubbish_amulet.lua | 60 ++++--- .../cults_of_tibia/minotaur_task_count.lua | 22 +-- .../bosses_mission_depths.lua | 49 +++--- .../dangerous_depths/lost_exile_task.lua | 79 +++++----- .../dangerous_depths/snail_slime_kill.lua | 34 ++-- .../dangerous_depths/the_baron_from_below.lua | 32 +--- .../dark_trails/kill_death_priest_shargon.lua | 20 ++- .../quests/dark_trails/kill_the_ravager.lua | 18 +-- .../quests/dawnport/goblin_kill.lua | 22 +-- .../quests/dawnport/minotaur_kill.lua | 22 +-- .../quests/dawnport/troll_kill.lua | 22 +-- .../elemental_spheres/overlord_kill.lua | 23 +-- .../ferumbras_ascendant/bosses_kill.lua | 28 ++-- .../the_shatterer_kill.lua | 27 ++-- .../pythius_the_rotten_kill.lua | 11 +- .../forgotten_knowledge/bosses_kill.lua | 48 +++--- .../bound_astral_power.lua | 26 +--- .../forgotten_knowledge/energy_prism.lua | 2 +- .../energy_prism_death.lua | 3 +- .../forgotten_knowledge/replica_servants.lua | 18 +-- .../quests/hero_of_rathleton/bosses_kill.lua | 8 +- .../in_service_of_yalahar/azerus_kill.lua | 9 +- .../diseased_trio_kill.lua | 26 ++-- .../quara_leader_kill.lua | 30 ++-- .../quests/inquisition/inquisition_boss.lua | 15 +- .../inquisition/inquisition_ungreez.lua | 14 +- .../killing_in_the_name_of/boss_kill.lua | 68 ++++++++ .../quests/killing_in_the_name_of/kill.lua | 121 --------------- .../killing_in_the_name_of/monster_kill.lua | 111 +++++++++++++ .../quests/kilmaresh/bragrumol.lua | 17 +- .../quests/kilmaresh/fafnar.lua | 27 ++-- .../quests/kilmaresh/mozradek.lua | 17 +- .../quests/kilmaresh/xogixath.lua | 17 +- .../liquid_black/deepling_boss_kill.lua | 24 +-- .../energized_raging_mage_kill.lua | 16 +- .../raging_mage_tower/raging_mage_kill.lua | 34 ++-- .../raging_mage_tower/yielothax_kill.lua | 10 +- .../secret_service/black_knight_kill.lua | 23 +-- .../quests/spike_tasks/lower_spike_kill.lua | 27 ++-- .../quests/spike_tasks/middle_spike_kill.lua | 26 ++-- .../quests/spike_tasks/upper_spike_kill.lua | 27 ++-- .../quests/svargrond_arena/arena_kill.lua | 30 +++- .../quests/the_first_dragon/kill_dragon.lua | 14 +- .../quests/the_ice_islands/husky_kill.lua | 15 +- .../the_primal_menace_killed.lua | 24 +-- .../quests/thieves_guild/nomad_kill.lua | 23 +-- .../wrath_of_the_emperor/bosses_kill.lua | 11 +- .../wrath_of_the_emperor/keeper_kill.lua | 13 +- .../lizard_magistratus_kill.lua | 25 +-- .../lizard_noble_kill.lua | 25 +-- .../wrath_of_the_emperor/zalamon_kill.lua | 21 ++- .../scripts/hazard/primal.lua | 12 +- .../primal_ordeal_quest/bosses_killed.lua | 18 +++ ...eaturescripts-shard_of_corruption_kill.lua | 22 --- .../shard_of_corruption_kill.lua | 14 ++ ...cripts-tirecz_kill.lua => tirecz_kill.lua} | 13 +- .../mission03_rational_request.lua | 22 ++- ...reaturescript-nightmare_monsters_kills.lua | 33 ---- .../nightmare_monsters_kills.lua | 31 ++++ data/libs/functions/set.lua | 146 ++++++++++++++++++ data/libs/kill_lib.lua | 21 +++ data/libs/libs.lua | 1 + src/lua/creature/creatureevent.cpp | 6 + .../monster/monster_type_functions.cpp | 9 +- 250 files changed, 1742 insertions(+), 1277 deletions(-) create mode 100644 data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/boss_kill.lua delete mode 100644 data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/kill.lua create mode 100644 data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/monster_kill.lua create mode 100644 data-otservbr-global/scripts/quests/primal_ordeal_quest/bosses_killed.lua delete mode 100644 data-otservbr-global/scripts/quests/the_new_frontier/creaturescripts-shard_of_corruption_kill.lua create mode 100644 data-otservbr-global/scripts/quests/the_new_frontier/shard_of_corruption_kill.lua rename data-otservbr-global/scripts/quests/the_new_frontier/{creaturescripts-tirecz_kill.lua => tirecz_kill.lua} (83%) delete mode 100644 data-otservbr-global/scripts/quests/threatened_dreams/creaturescript-nightmare_monsters_kills.lua create mode 100644 data-otservbr-global/scripts/quests/threatened_dreams/nightmare_monsters_kills.lua create mode 100644 data/libs/functions/set.lua create mode 100644 data/libs/kill_lib.lua diff --git a/data-otservbr-global/monster/bosses/black_knight.lua b/data-otservbr-global/monster/bosses/black_knight.lua index fe50d74af3f..2905e1a7814 100644 --- a/data-otservbr-global/monster/bosses/black_knight.lua +++ b/data-otservbr-global/monster/bosses/black_knight.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "BlackKnightDeath", +} + monster.bosstiary = { bossRaceId = 46, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/bosses/diseased_bill.lua b/data-otservbr-global/monster/bosses/diseased_bill.lua index b8982c4e259..c2524dd8267 100644 --- a/data-otservbr-global/monster/bosses/diseased_bill.lua +++ b/data-otservbr-global/monster/bosses/diseased_bill.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "DiseasedTrioDeath", +} + monster.bosstiary = { bossRaceId = 485, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/bosses/diseased_dan.lua b/data-otservbr-global/monster/bosses/diseased_dan.lua index 8eb9d3a1535..7ee84a080a1 100644 --- a/data-otservbr-global/monster/bosses/diseased_dan.lua +++ b/data-otservbr-global/monster/bosses/diseased_dan.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "DiseasedTrioDeath", +} + monster.bosstiary = { bossRaceId = 486, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/bosses/diseased_fred.lua b/data-otservbr-global/monster/bosses/diseased_fred.lua index e516fd9e2df..d2ab31a5578 100644 --- a/data-otservbr-global/monster/bosses/diseased_fred.lua +++ b/data-otservbr-global/monster/bosses/diseased_fred.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "DiseasedTrioDeath", +} + monster.bosstiary = { bossRaceId = 484, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/bosses/energized_raging_mage.lua b/data-otservbr-global/monster/bosses/energized_raging_mage.lua index d8d7d4809e8..0d3aea8aaf0 100644 --- a/data-otservbr-global/monster/bosses/energized_raging_mage.lua +++ b/data-otservbr-global/monster/bosses/energized_raging_mage.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "EnergizedRagingMageDeath", +} + monster.health = 3500 monster.maxHealth = 3500 monster.race = "blood" diff --git a/data-otservbr-global/monster/bosses/kroazur.lua b/data-otservbr-global/monster/bosses/kroazur.lua index 78357fbf8e7..14740f8f522 100644 --- a/data-otservbr-global/monster/bosses/kroazur.lua +++ b/data-otservbr-global/monster/bosses/kroazur.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ThreatenedDreamsNightmareMonstersDeath", +} + monster.bosstiary = { bossRaceId = 1515, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/bosses/pythius_the_rotten.lua b/data-otservbr-global/monster/bosses/pythius_the_rotten.lua index 3331d64e027..b635ea69133 100644 --- a/data-otservbr-global/monster/bosses/pythius_the_rotten.lua +++ b/data-otservbr-global/monster/bosses/pythius_the_rotten.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "PythiusTheRottenDeath", +} + monster.health = 9000 monster.maxHealth = 9000 monster.race = "undead" diff --git a/data-otservbr-global/monster/bosses/raging_mage.lua b/data-otservbr-global/monster/bosses/raging_mage.lua index 39518d5431a..5fd30131b8a 100644 --- a/data-otservbr-global/monster/bosses/raging_mage.lua +++ b/data-otservbr-global/monster/bosses/raging_mage.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "RagingMageDeath", +} + monster.health = 3500 monster.maxHealth = 3500 monster.race = "blood" diff --git a/data-otservbr-global/monster/bosses/renegade_orc.lua b/data-otservbr-global/monster/bosses/renegade_orc.lua index c12f3d73e39..53f075751ae 100644 --- a/data-otservbr-global/monster/bosses/renegade_orc.lua +++ b/data-otservbr-global/monster/bosses/renegade_orc.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "RenegadeOrcDeath", +} + monster.health = 450 monster.maxHealth = 450 monster.race = "blood" diff --git a/data-otservbr-global/monster/bosses/splasher.lua b/data-otservbr-global/monster/bosses/splasher.lua index 670c402c859..b579d921327 100644 --- a/data-otservbr-global/monster/bosses/splasher.lua +++ b/data-otservbr-global/monster/bosses/splasher.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "QuaraLeadersDeath", +} + monster.health = 1700 monster.maxHealth = 1700 monster.race = "blood" diff --git a/data-otservbr-global/monster/constructs/diamond_servant_replica.lua b/data-otservbr-global/monster/constructs/diamond_servant_replica.lua index 487811413e1..733ea51c2fe 100644 --- a/data-otservbr-global/monster/constructs/diamond_servant_replica.lua +++ b/data-otservbr-global/monster/constructs/diamond_servant_replica.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ReplicaServantDeath", +} + monster.raceId = 1326 monster.Bestiary = { class = "Construct", diff --git a/data-otservbr-global/monster/constructs/golden_servant_replica.lua b/data-otservbr-global/monster/constructs/golden_servant_replica.lua index dbf2b07dfeb..4a93d0d9635 100644 --- a/data-otservbr-global/monster/constructs/golden_servant_replica.lua +++ b/data-otservbr-global/monster/constructs/golden_servant_replica.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ReplicaServantDeath", +} + monster.raceId = 1327 monster.Bestiary = { class = "Construct", diff --git a/data-otservbr-global/monster/dawnport/mountain_troll.lua b/data-otservbr-global/monster/dawnport/mountain_troll.lua index 86e38adf4cd..fab1ebf82b5 100644 --- a/data-otservbr-global/monster/dawnport/mountain_troll.lua +++ b/data-otservbr-global/monster/dawnport/mountain_troll.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "MorrisTrollDeath", +} + monster.health = 30 monster.maxHealth = 30 monster.race = "blood" diff --git a/data-otservbr-global/monster/dawnport/muglex_clan_footman.lua b/data-otservbr-global/monster/dawnport/muglex_clan_footman.lua index 53bc52730f5..2695c29aea9 100644 --- a/data-otservbr-global/monster/dawnport/muglex_clan_footman.lua +++ b/data-otservbr-global/monster/dawnport/muglex_clan_footman.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "MorrisGoblinDeath", +} + monster.health = 50 monster.maxHealth = 50 monster.race = "blood" diff --git a/data-otservbr-global/monster/dragons/dragon.lua b/data-otservbr-global/monster/dragons/dragon.lua index 52ca6324429..16dd2aa26c7 100644 --- a/data-otservbr-global/monster/dragons/dragon.lua +++ b/data-otservbr-global/monster/dragons/dragon.lua @@ -13,6 +13,11 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "TheGreatDragonHuntDeath", + "TheFirstDragonDragonTaskDeath", +} + monster.raceId = 34 monster.Bestiary = { class = "Dragon", diff --git a/data-otservbr-global/monster/dragons/dragon_lord.lua b/data-otservbr-global/monster/dragons/dragon_lord.lua index 57ce3725109..65d7e225e47 100644 --- a/data-otservbr-global/monster/dragons/dragon_lord.lua +++ b/data-otservbr-global/monster/dragons/dragon_lord.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "TheGreatDragonHuntDeath", +} + monster.raceId = 39 monster.Bestiary = { class = "Dragon", diff --git a/data-otservbr-global/monster/extra_dimensional/yielothax.lua b/data-otservbr-global/monster/extra_dimensional/yielothax.lua index 76b1194cd07..487a8d5c30d 100644 --- a/data-otservbr-global/monster/extra_dimensional/yielothax.lua +++ b/data-otservbr-global/monster/extra_dimensional/yielothax.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "YielothaxDeath", +} + monster.raceId = 717 monster.Bestiary = { class = "Extra Dimensional", diff --git a/data-otservbr-global/monster/humanoids/lost_exile.lua b/data-otservbr-global/monster/humanoids/lost_exile.lua index 8fc53213306..d1bb52aaa09 100644 --- a/data-otservbr-global/monster/humanoids/lost_exile.lua +++ b/data-otservbr-global/monster/humanoids/lost_exile.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "LastExileDeath", +} + monster.raceId = 1529 monster.Bestiary = { class = "Humanoid", diff --git a/data-otservbr-global/monster/humanoids/minotaur_bruiser.lua b/data-otservbr-global/monster/humanoids/minotaur_bruiser.lua index b704e765d2c..51eb241298c 100644 --- a/data-otservbr-global/monster/humanoids/minotaur_bruiser.lua +++ b/data-otservbr-global/monster/humanoids/minotaur_bruiser.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "MorrisMinotaurDeath", +} + monster.health = 100 monster.maxHealth = 100 monster.race = "blood" diff --git a/data-otservbr-global/monster/humanoids/minotaur_cult_follower.lua b/data-otservbr-global/monster/humanoids/minotaur_cult_follower.lua index 1aff1c992c6..18883c46827 100644 --- a/data-otservbr-global/monster/humanoids/minotaur_cult_follower.lua +++ b/data-otservbr-global/monster/humanoids/minotaur_cult_follower.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "MinotaurCultTaskDeath", +} + monster.raceId = 1508 monster.Bestiary = { class = "Humanoid", diff --git a/data-otservbr-global/monster/humanoids/minotaur_cult_prophet.lua b/data-otservbr-global/monster/humanoids/minotaur_cult_prophet.lua index 13e823fa17a..5f86e2de209 100644 --- a/data-otservbr-global/monster/humanoids/minotaur_cult_prophet.lua +++ b/data-otservbr-global/monster/humanoids/minotaur_cult_prophet.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "MinotaurCultTaskDeath", +} + monster.raceId = 1509 monster.Bestiary = { class = "Humanoid", diff --git a/data-otservbr-global/monster/humanoids/minotaur_cult_zealot.lua b/data-otservbr-global/monster/humanoids/minotaur_cult_zealot.lua index be4fc8a4bdc..571d3faa060 100644 --- a/data-otservbr-global/monster/humanoids/minotaur_cult_zealot.lua +++ b/data-otservbr-global/monster/humanoids/minotaur_cult_zealot.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "MinotaurCultTaskDeath", +} + monster.raceId = 1510 monster.Bestiary = { class = "Humanoid", diff --git a/data-otservbr-global/monster/humans/burning_gladiator.lua b/data-otservbr-global/monster/humans/burning_gladiator.lua index 70f9f4f0c1d..8923d0928cb 100644 --- a/data-otservbr-global/monster/humans/burning_gladiator.lua +++ b/data-otservbr-global/monster/humans/burning_gladiator.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "FafnarMissionsDeath", +} + monster.raceId = 1798 monster.Bestiary = { class = "Human", diff --git a/data-otservbr-global/monster/humans/nomad.lua b/data-otservbr-global/monster/humans/nomad.lua index d656857b42f..9c34282bf80 100644 --- a/data-otservbr-global/monster/humans/nomad.lua +++ b/data-otservbr-global/monster/humans/nomad.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "NomadDeath", +} + monster.raceId = 310 monster.Bestiary = { class = "Human", diff --git a/data-otservbr-global/monster/humans/nomad_blue.lua b/data-otservbr-global/monster/humans/nomad_blue.lua index 02465d966f7..07ba7aff29a 100644 --- a/data-otservbr-global/monster/humans/nomad_blue.lua +++ b/data-otservbr-global/monster/humans/nomad_blue.lua @@ -14,6 +14,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "NomadDeath", +} + monster.raceId = 777 monster.Bestiary = { class = "Human", diff --git a/data-otservbr-global/monster/humans/nomad_female.lua b/data-otservbr-global/monster/humans/nomad_female.lua index 2703f84d4c6..9460aab59cf 100644 --- a/data-otservbr-global/monster/humans/nomad_female.lua +++ b/data-otservbr-global/monster/humans/nomad_female.lua @@ -14,6 +14,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "NomadDeath", +} + monster.raceId = 776 monster.Bestiary = { class = "Human", diff --git a/data-otservbr-global/monster/humans/priestess_of_the_wild_sun.lua b/data-otservbr-global/monster/humans/priestess_of_the_wild_sun.lua index 25eea0d8723..a97c9a3c56d 100644 --- a/data-otservbr-global/monster/humans/priestess_of_the_wild_sun.lua +++ b/data-otservbr-global/monster/humans/priestess_of_the_wild_sun.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "FafnarMissionsDeath", +} + monster.raceId = 1799 monster.Bestiary = { class = "Human", diff --git a/data-otservbr-global/monster/magicals/crystalcrusher.lua b/data-otservbr-global/monster/magicals/crystalcrusher.lua index c0698ab34b5..4da886c9df3 100644 --- a/data-otservbr-global/monster/magicals/crystalcrusher.lua +++ b/data-otservbr-global/monster/magicals/crystalcrusher.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "MiddleSpikeDeath", +} + monster.raceId = 869 monster.Bestiary = { class = "Magical", diff --git a/data-otservbr-global/monster/magicals/enfeebled_silencer.lua b/data-otservbr-global/monster/magicals/enfeebled_silencer.lua index 95bd1948831..c631f75d0cb 100644 --- a/data-otservbr-global/monster/magicals/enfeebled_silencer.lua +++ b/data-otservbr-global/monster/magicals/enfeebled_silencer.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ThreatenedDreamsNightmareMonstersDeath", +} + monster.raceId = 1443 monster.Bestiary = { class = "Magical", diff --git a/data-otservbr-global/monster/magicals/frazzlemaw.lua b/data-otservbr-global/monster/magicals/frazzlemaw.lua index 50927628608..32a053b1dcc 100644 --- a/data-otservbr-global/monster/magicals/frazzlemaw.lua +++ b/data-otservbr-global/monster/magicals/frazzlemaw.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "RoshamuulKillsDeath", +} + monster.raceId = 1022 monster.Bestiary = { class = "Magical", diff --git a/data-otservbr-global/monster/magicals/silencer.lua b/data-otservbr-global/monster/magicals/silencer.lua index e71ec572cef..b2399ce294d 100644 --- a/data-otservbr-global/monster/magicals/silencer.lua +++ b/data-otservbr-global/monster/magicals/silencer.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "RoshamuulKillsDeath", +} + monster.raceId = 1014 monster.Bestiary = { class = "Magical", diff --git a/data-otservbr-global/monster/magicals/weakened_frazzlemaw.lua b/data-otservbr-global/monster/magicals/weakened_frazzlemaw.lua index d44126f9518..d7e8eba093f 100644 --- a/data-otservbr-global/monster/magicals/weakened_frazzlemaw.lua +++ b/data-otservbr-global/monster/magicals/weakened_frazzlemaw.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ThreatenedDreamsNightmareMonstersDeath", +} + monster.raceId = 1442 monster.Bestiary = { class = "Magical", diff --git a/data-otservbr-global/monster/mammals/husky.lua b/data-otservbr-global/monster/mammals/husky.lua index 314d948e454..dae58bcc664 100644 --- a/data-otservbr-global/monster/mammals/husky.lua +++ b/data-otservbr-global/monster/mammals/husky.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "HuskyDeath", +} + monster.raceId = 325 monster.Bestiary = { class = "Mammal", diff --git a/data-otservbr-global/monster/mammals/rat.lua b/data-otservbr-global/monster/mammals/rat.lua index 17747658eea..205888f9a55 100644 --- a/data-otservbr-global/monster/mammals/rat.lua +++ b/data-otservbr-global/monster/mammals/rat.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "RationalRequestRatDeath", +} + monster.raceId = 21 monster.Bestiary = { class = "Mammal", 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 177700eedf9..24c993fda5b 100644 --- a/data-otservbr-global/monster/quests/bigfoots_burden/bosses/abyssador.lua +++ b/data-otservbr-global/monster/quests/bigfoots_burden/bosses/abyssador.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "BossesWarzoneDeath", +} + monster.bosstiary = { bossRaceId = 887, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/bigfoots_burden/bosses/deathstrike.lua b/data-otservbr-global/monster/quests/bigfoots_burden/bosses/deathstrike.lua index 9fef07f960d..b7e88ede791 100644 --- a/data-otservbr-global/monster/quests/bigfoots_burden/bosses/deathstrike.lua +++ b/data-otservbr-global/monster/quests/bigfoots_burden/bosses/deathstrike.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "BossesWarzoneDeath", +} + monster.bosstiary = { bossRaceId = 892, bossRace = RARITY_ARCHFOE, 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 b0d0a7487a1..cd287d83709 100644 --- a/data-otservbr-global/monster/quests/bigfoots_burden/bosses/gnomevil.lua +++ b/data-otservbr-global/monster/quests/bigfoots_burden/bosses/gnomevil.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "BossesWarzoneDeath", +} + monster.bosstiary = { bossRaceId = 893, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/bigfoots_burden/versperoth.lua b/data-otservbr-global/monster/quests/bigfoots_burden/versperoth.lua index d8e260236fd..c422f817bb2 100644 --- a/data-otservbr-global/monster/quests/bigfoots_burden/versperoth.lua +++ b/data-otservbr-global/monster/quests/bigfoots_burden/versperoth.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "VesperothDeath", +} + monster.health = 100000 monster.maxHealth = 100000 monster.race = "venom" diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/dorokoll_the_mystic.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/dorokoll_the_mystic.lua index 018dc2c092e..926fb0c79ac 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/dorokoll_the_mystic.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/dorokoll_the_mystic.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "EssenceOfMaliceSpawnsDeath", +} + monster.health = 30000 monster.maxHealth = 30000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/eliz_the_unyielding.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/eliz_the_unyielding.lua index bc6aa5b1741..41c7815e73c 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/eliz_the_unyielding.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/eliz_the_unyielding.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "EssenceOfMaliceSpawnsDeath", +} + monster.health = 30000 monster.maxHealth = 30000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/eshtaba_the_conjurer.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/eshtaba_the_conjurer.lua index 175b0df635e..b6190942dbc 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/eshtaba_the_conjurer.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/eshtaba_the_conjurer.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "EssenceOfMaliceSpawnsDeath", +} + monster.health = 30000 monster.maxHealth = 30000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/essence_of_malice.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/essence_of_malice.lua index e9b7c7d9105..ef49131374d 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/essence_of_malice.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/essence_of_malice.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "CultsOfTibiaBossDeath", +} + monster.bosstiary = { bossRaceId = 1487, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/malkhar_deathbringer.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/malkhar_deathbringer.lua index 14013f130ec..7b800bd8f22 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/malkhar_deathbringer.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/malkhar_deathbringer.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "EssenceOfMaliceSpawnsDeath", +} + monster.health = 30000 monster.maxHealth = 30000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/mezlon_the_defiler.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/mezlon_the_defiler.lua index 425ae3cc725..3576693ea0f 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/mezlon_the_defiler.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/mezlon_the_defiler.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "EssenceOfMaliceSpawnsDeath", +} + monster.health = 30000 monster.maxHealth = 30000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_death.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_death.lua index 9ef05c56c67..5ad9d82334b 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_death.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_death.lua @@ -14,6 +14,10 @@ monster.corpse = 0 monster.speed = 0 monster.manaCost = 0 +monster.events = { + "DestroyedPillar", +} + monster.changeTarget = { interval = 4000, chance = 20, diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_draining.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_draining.lua index ec8fb38d78e..c2bb501e3b6 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_draining.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_draining.lua @@ -14,6 +14,10 @@ monster.corpse = 0 monster.speed = 0 monster.manaCost = 0 +monster.events = { + "DestroyedPillar", +} + monster.changeTarget = { interval = 4000, chance = 20, diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_healing.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_healing.lua index fff5544ece4..95c185f7d4c 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_healing.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_healing.lua @@ -14,6 +14,10 @@ monster.corpse = 0 monster.speed = 0 monster.manaCost = 0 +monster.events = { + "DestroyedPillar", +} + monster.changeTarget = { interval = 4000, chance = 20, diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_protection.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_protection.lua index d8d103b22f3..5729390a4d8 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_protection.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_protection.lua @@ -14,6 +14,10 @@ monster.corpse = 0 monster.speed = 0 monster.manaCost = 0 +monster.events = { + "DestroyedPillar", +} + monster.changeTarget = { interval = 4000, chance = 20, diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_summoning.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_summoning.lua index a6e02db4fbc..27937b85537 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_summoning.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/pillars/pillar_of_summoning.lua @@ -14,6 +14,10 @@ monster.corpse = 0 monster.speed = 0 monster.manaCost = 0 +monster.events = { + "DestroyedPillar", +} + monster.changeTarget = { interval = 4000, chance = 20, diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/ravenous_hunger.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/ravenous_hunger.lua index cee0dd32fc6..ee9b5d37a66 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/ravenous_hunger.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/ravenous_hunger.lua @@ -13,6 +13,11 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "LeidenHeal", + "CultsOfTibiaBossDeath", +} + monster.bosstiary = { bossRaceId = 1427, bossRace = RARITY_ARCHFOE, @@ -57,10 +62,6 @@ monster.flags = { canWalkOnPoison = true, } -monster.events = { - "LeidenHeal", -} - monster.light = { level = 0, color = 0, diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_corruptor_of_souls.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_corruptor_of_souls.lua index dfcc46ab6d7..adc1b89d393 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_corruptor_of_souls.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_corruptor_of_souls.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "CultsOfTibiaBossDeath", +} + monster.health = 290000 monster.maxHealth = 290000 monster.race = "venom" diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_false_god.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_false_god.lua index 888f068159b..a1ec678bdf0 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_false_god.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_false_god.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "CultsOfTibiaBossDeath", +} + monster.bosstiary = { bossRaceId = 1409, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_sandking.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_sandking.lua index 89ef694e51a..3e0914007db 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_sandking.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_sandking.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "CultsOfTibiaBossDeath", +} + monster.bosstiary = { bossRaceId = 1444, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_souldespoiler.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_souldespoiler.lua index abcf4d8fc27..35878eae9bf 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_souldespoiler.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_souldespoiler.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "CultsOfTibiaBossDeath", +} + monster.bosstiary = { bossRaceId = 1422, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_source_of_corruption.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_source_of_corruption.lua index ef660075883..83f14ead593 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_source_of_corruption.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_source_of_corruption.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "CultsOfTibiaBossDeath", +} + monster.bosstiary = { bossRaceId = 1500, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_unarmored_voidborn.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_unarmored_voidborn.lua index 40c70d77fb7..0dbf6743e2d 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_unarmored_voidborn.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_unarmored_voidborn.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "CultsOfTibiaBossDeath", +} + monster.bosstiary = { bossRaceId = 1406, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/cult_believer.lua b/data-otservbr-global/monster/quests/cults_of_tibia/cult_believer.lua index 71a717df8f3..18c727b1eab 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/cult_believer.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/cult_believer.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "CarlinVortexDeath", +} + monster.raceId = 1512 monster.Bestiary = { class = "Human", diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/cult_enforcer.lua b/data-otservbr-global/monster/quests/cults_of_tibia/cult_enforcer.lua index 27b33840d4c..abe7c8d4a9a 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/cult_enforcer.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/cult_enforcer.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "CarlinVortexDeath", +} + monster.raceId = 1513 monster.Bestiary = { class = "Human", diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/cult_scholar.lua b/data-otservbr-global/monster/quests/cults_of_tibia/cult_scholar.lua index e4d9b02ada5..bd743a11076 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/cult_scholar.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/cult_scholar.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "CarlinVortexDeath", +} + monster.raceId = 1514 monster.Bestiary = { class = "Human", diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/misguided_bully.lua b/data-otservbr-global/monster/quests/cults_of_tibia/misguided_bully.lua index 8f653d2f2dd..5cf1c3b8582 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/misguided_bully.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/misguided_bully.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "GlowingRubbishAmuletDeath", +} + monster.raceId = 1412 monster.Bestiary = { class = "Humanoid", diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/misguided_shadow.lua b/data-otservbr-global/monster/quests/cults_of_tibia/misguided_shadow.lua index 5886f068e97..547c67f7cf1 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/misguided_shadow.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/misguided_shadow.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "GlowingRubbishAmuletDeath", +} + monster.health = 3000 monster.maxHealth = 3000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/dangerous_depth/bosses/the_baron_from_below.lua b/data-otservbr-global/monster/quests/dangerous_depth/bosses/the_baron_from_below.lua index 12c461e44a3..e780ac65c8b 100644 --- a/data-otservbr-global/monster/quests/dangerous_depth/bosses/the_baron_from_below.lua +++ b/data-otservbr-global/monster/quests/dangerous_depth/bosses/the_baron_from_below.lua @@ -13,6 +13,11 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "DepthWarzoneBossDeath", + "TheBaronFromBelowThink", +} + monster.health = 350000 monster.maxHealth = 350000 monster.race = "blood" 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 3a9b1726e29..80878aaa360 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 @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "DepthWarzoneBossDeath", +} + monster.health = 350000 monster.maxHealth = 350000 monster.race = "blood" 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 eb960a171e0..31c354f7667 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 @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "DepthWarzoneBossDeath", +} + monster.health = 350000 monster.maxHealth = 350000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/dangerous_depth/makeshift_home.lua b/data-otservbr-global/monster/quests/dangerous_depth/makeshift_home.lua index fc70f937f66..0b64ccee736 100644 --- a/data-otservbr-global/monster/quests/dangerous_depth/makeshift_home.lua +++ b/data-otservbr-global/monster/quests/dangerous_depth/makeshift_home.lua @@ -14,6 +14,10 @@ monster.corpse = 0 monster.speed = 0 monster.manaCost = 0 +monster.events = { + "MakeshiftHomeDeath", +} + monster.changeTarget = { interval = 5000, chance = 10, diff --git a/data-otservbr-global/monster/quests/dangerous_depth/organic_matter.lua b/data-otservbr-global/monster/quests/dangerous_depth/organic_matter.lua index a7d5ec477be..bf292570fb8 100644 --- a/data-otservbr-global/monster/quests/dangerous_depth/organic_matter.lua +++ b/data-otservbr-global/monster/quests/dangerous_depth/organic_matter.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "OrganicMatterDeath", +} + monster.health = 10000 monster.maxHealth = 10000 monster.race = "venom" diff --git a/data-otservbr-global/monster/quests/dangerous_depth/snail_slime.lua b/data-otservbr-global/monster/quests/dangerous_depth/snail_slime.lua index e5e4942e6d4..2bfa943c47a 100644 --- a/data-otservbr-global/monster/quests/dangerous_depth/snail_slime.lua +++ b/data-otservbr-global/monster/quests/dangerous_depth/snail_slime.lua @@ -13,6 +13,11 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "SnailSlimeDeath", + "SnailSlimeThink", +} + monster.health = 4500 monster.maxHealth = 4500 monster.race = "venom" diff --git a/data-otservbr-global/monster/quests/dark_trails/death_priest_shargon.lua b/data-otservbr-global/monster/quests/dark_trails/death_priest_shargon.lua index 13fd2f07c51..c64a01061b9 100644 --- a/data-otservbr-global/monster/quests/dark_trails/death_priest_shargon.lua +++ b/data-otservbr-global/monster/quests/dark_trails/death_priest_shargon.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ShargonDeath", +} + monster.bosstiary = { bossRaceId = 1047, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/quests/dark_trails/the_ravager.lua b/data-otservbr-global/monster/quests/dark_trails/the_ravager.lua index 1c10ace0db9..a8683a6f92e 100644 --- a/data-otservbr-global/monster/quests/dark_trails/the_ravager.lua +++ b/data-otservbr-global/monster/quests/dark_trails/the_ravager.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "TheRavagerDeath", +} + monster.bosstiary = { bossRaceId = 1035, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/quests/feaster_of_souls/the_dread_maiden.lua b/data-otservbr-global/monster/quests/feaster_of_souls/the_dread_maiden.lua index 9ca5ba11862..83308c9c2fc 100644 --- a/data-otservbr-global/monster/quests/feaster_of_souls/the_dread_maiden.lua +++ b/data-otservbr-global/monster/quests/feaster_of_souls/the_dread_maiden.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "FeasterOfSoulsBossDeath", +} + monster.bosstiary = { bossRaceId = 1872, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/feaster_of_souls/the_fear_feaster.lua b/data-otservbr-global/monster/quests/feaster_of_souls/the_fear_feaster.lua index 058842c7089..b5f69b05e3f 100644 --- a/data-otservbr-global/monster/quests/feaster_of_souls/the_fear_feaster.lua +++ b/data-otservbr-global/monster/quests/feaster_of_souls/the_fear_feaster.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "FeasterOfSoulsBossDeath", +} + monster.health = 300000 monster.maxHealth = 300000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/feaster_of_souls/the_pale_worm.lua b/data-otservbr-global/monster/quests/feaster_of_souls/the_pale_worm.lua index 41bf63ad767..bde610ee680 100644 --- a/data-otservbr-global/monster/quests/feaster_of_souls/the_pale_worm.lua +++ b/data-otservbr-global/monster/quests/feaster_of_souls/the_pale_worm.lua @@ -22,6 +22,7 @@ monster.manaCost = 0 monster.events = { "paleWormDeath", + "FeasterOfSoulsBossDeath", } monster.changeTarget = { diff --git a/data-otservbr-global/monster/quests/feaster_of_souls/the_unwelcome.lua b/data-otservbr-global/monster/quests/feaster_of_souls/the_unwelcome.lua index 383795d8bbe..7c0cd052961 100644 --- a/data-otservbr-global/monster/quests/feaster_of_souls/the_unwelcome.lua +++ b/data-otservbr-global/monster/quests/feaster_of_souls/the_unwelcome.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "FeasterOfSoulsBossDeath", +} + monster.health = 300000 monster.maxHealth = 300000 monster.race = "undead" 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 0d1cb775768..27160109571 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 @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "AscendantBossesDeath", +} + monster.health = 300000 monster.maxHealth = 300000 monster.race = "venom" 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 e412a2af7c3..1a25d435223 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/mazoran.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/mazoran.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "AscendantBossesDeath", +} + monster.bosstiary = { bossRaceId = 1186, bossRace = RARITY_ARCHFOE, 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 e0cb0b883ff..b86ac1a47bd 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/plagirath.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/plagirath.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "AscendantBossesDeath", +} + monster.bosstiary = { bossRaceId = 1199, bossRace = RARITY_ARCHFOE, 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 0f196297f4a..e9f97824c97 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ragiaz.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ragiaz.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "AscendantBossesDeath", +} + monster.bosstiary = { bossRaceId = 1180, bossRace = RARITY_ARCHFOE, 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 480df7868fa..07d2a55b07b 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/razzagorn.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/razzagorn.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "AscendantBossesDeath", +} + monster.bosstiary = { bossRaceId = 1177, bossRace = RARITY_ARCHFOE, 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 2ad81b631c7..69eae8f369b 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/shulgrax.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/shulgrax.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "AscendantBossesDeath", +} + monster.health = 40000 monster.maxHealth = 40000 monster.race = "undead" 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 9b6bf3492f0..16fd12f63e8 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/tarbaz.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/tarbaz.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "AscendantBossesDeath", +} + monster.health = 290000 monster.maxHealth = 290000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/the_lord_of_the_lice.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/the_lord_of_the_lice.lua index 1a9d2504c4d..08b0fd0a836 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/the_lord_of_the_lice.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/the_lord_of_the_lice.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "AscendantBossesDeath", +} + monster.bosstiary = { bossRaceId = 1179, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/the_shatterer.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/the_shatterer.lua index 76a70e53189..eb414a427f3 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/the_shatterer.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/the_shatterer.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "TheShattererDeath", +} + monster.health = 220000 monster.maxHealth = 220000 monster.race = "fire" 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 00d02c7c38d..f3bbd04efd4 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "AscendantBossesDeath", +} + monster.health = 300000 monster.maxHealth = 300000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh2.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh2.lua index e3f7a2cfceb..5adb3a046bc 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh2.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh2.lua @@ -14,6 +14,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "AscendantBossesDeath", +} + monster.health = 300000 monster.maxHealth = 300000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh3.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh3.lua index 3d8b71189eb..ec8cb0ade3a 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh3.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh3.lua @@ -14,6 +14,11 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "AscendantBossesDeath", + "ZamuloshClone", +} + monster.health = 1000 monster.maxHealth = 1000 monster.race = "undead" @@ -53,10 +58,6 @@ monster.flags = { canWalkOnPoison = true, } -monster.events = { - "ZamuloshClone", -} - monster.light = { level = 0, color = 0, diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/lady_tenebris.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/lady_tenebris.lua index 40452abcabe..c7087a421ba 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/lady_tenebris.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/lady_tenebris.lua @@ -13,6 +13,11 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ForgottenKnowledgeBossDeath", + "HealthForgotten", +} + monster.bosstiary = { bossRaceId = 1315, bossRace = RARITY_ARCHFOE, @@ -57,10 +62,6 @@ monster.flags = { canWalkOnPoison = true, } -monster.events = { - "HealthForgotten", -} - monster.light = { level = 0, color = 0, diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/lloyd.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/lloyd.lua index 4cb143dd933..2cd9bdcd5b0 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/lloyd.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/lloyd.lua @@ -13,6 +13,11 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ForgottenKnowledgeBossDeath", + "LloydPrepareDeath", +} + monster.bosstiary = { bossRaceId = 1329, bossRace = RARITY_ARCHFOE, @@ -57,10 +62,6 @@ monster.flags = { canWalkOnPoison = true, } -monster.events = { - "LloydPrepareDeath", -} - monster.light = { level = 0, color = 0, diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/melting_frozen_horror.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/melting_frozen_horror.lua index d856af4495c..6fa44fff690 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/melting_frozen_horror.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/melting_frozen_horror.lua @@ -13,6 +13,11 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ForgottenKnowledgeBossDeath", + "MeltingDeath", +} + monster.health = 70000 monster.maxHealth = 70000 monster.race = "undead" @@ -57,10 +62,6 @@ monster.flags = { canWalkOnPoison = true, } -monster.events = { - "MeltingDeath", -} - monster.light = { level = 0, color = 0, diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/soul_of_dragonking_zyrtarch.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/soul_of_dragonking_zyrtarch.lua index 030838fa5d5..2def55d9283 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/soul_of_dragonking_zyrtarch.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/soul_of_dragonking_zyrtarch.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ForgottenKnowledgeBossDeath", +} + monster.bosstiary = { bossRaceId = 1289, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_blazing_time_guardian.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_blazing_time_guardian.lua index 736c3233d4e..dd4144c4aad 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_blazing_time_guardian.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_blazing_time_guardian.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ForgottenKnowledgeBossDeath", +} + monster.health = 150000 monster.maxHealth = 150000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_enraged_thorn_knight.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_enraged_thorn_knight.lua index 6e74ec8281e..38d27e009af 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_enraged_thorn_knight.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_enraged_thorn_knight.lua @@ -13,6 +13,11 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ForgottenKnowledgeBossDeath", + "HealthForgotten", +} + monster.bosstiary = { bossRaceId = 1297, bossRace = RARITY_ARCHFOE, @@ -57,10 +62,6 @@ monster.flags = { canWalkOnPoison = true, } -monster.events = { - "HealthForgotten", -} - monster.light = { level = 0, color = 0, diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_freezing_time_guardian.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_freezing_time_guardian.lua index e43d501838b..ec4aac0f9fa 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_freezing_time_guardian.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_freezing_time_guardian.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ForgottenKnowledgeBossDeath", +} + monster.health = 150000 monster.maxHealth = 150000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_last_lore_keeper.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_last_lore_keeper.lua index 893cade4723..a875379d558 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_last_lore_keeper.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_last_lore_keeper.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ForgottenKnowledgeBossDeath", +} + monster.health = 750000 monster.maxHealth = 750000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_time_guardian.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_time_guardian.lua index 86d45d2d7ff..53d7eee517a 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_time_guardian.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_time_guardian.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ForgottenKnowledgeBossDeath", +} + monster.health = 150000 monster.maxHealth = 150000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/bound_astral_power.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bound_astral_power.lua index f012b1c1185..42be68d8ebe 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bound_astral_power.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bound_astral_power.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "BoundAstralPowerDeath", +} + monster.health = 70000 monster.maxHealth = 70000 monster.race = "venom" diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_a.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_a.lua index c85eda464fe..7dde9b15691 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_a.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_a.lua @@ -14,6 +14,11 @@ monster.corpse = 0 monster.speed = 0 monster.manaCost = 0 +monster.events = { + "EnergyPrismDeath", + "EnergyPrismHealthChange", +} + monster.changeTarget = { interval = 2000, chance = 0, @@ -43,10 +48,6 @@ monster.flags = { canWalkOnPoison = true, } -monster.events = { - "EnergyPrism", -} - monster.light = { level = 0, color = 0, diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_b.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_b.lua index eb90930545e..cfd5dd674a3 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_b.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_b.lua @@ -14,6 +14,11 @@ monster.corpse = 0 monster.speed = 0 monster.manaCost = 0 +monster.events = { + "EnergyPrismHealthChange", + "EnergyPrismDeath", +} + monster.changeTarget = { interval = 2000, chance = 0, @@ -43,10 +48,6 @@ monster.flags = { canWalkOnPoison = true, } -monster.events = { - "EnergyPrism", -} - monster.light = { level = 0, color = 0, diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_c.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_c.lua index b8de11033d7..92045bac1b9 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_c.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_c.lua @@ -44,7 +44,7 @@ monster.flags = { } monster.events = { - "EnergyPrism", + "EnergyPrismHealthChange", } monster.light = { diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_d.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_d.lua index cf53e32a384..ec58b3ead68 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_d.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/cosmic_energy_prism_d.lua @@ -14,6 +14,11 @@ monster.corpse = 0 monster.speed = 0 monster.manaCost = 0 +monster.events = { + "EnergyPrismHealthChange", + "EnergyPrismDeath", +} + monster.changeTarget = { interval = 2000, chance = 0, @@ -43,10 +48,6 @@ monster.flags = { canWalkOnPoison = true, } -monster.events = { - "EnergyPrism", -} - monster.light = { level = 0, color = 0, diff --git a/data-otservbr-global/monster/quests/grave_danger/bosses/count_vlarkorth.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/count_vlarkorth.lua index 929bd2f90b6..ebe04c8ec92 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/count_vlarkorth.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/count_vlarkorth.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "GraveDangerBossDeath", +} + monster.health = 75000 monster.maxHealth = 75000 monster.race = "venom" diff --git a/data-otservbr-global/monster/quests/grave_danger/bosses/duke_krule.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/duke_krule.lua index 121f09f2d4b..0760491d1bc 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/duke_krule.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/duke_krule.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "GraveDangerBossDeath", +} + monster.health = 75000 monster.maxHealth = 75000 monster.race = "venom" diff --git a/data-otservbr-global/monster/quests/grave_danger/bosses/earl_osam.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/earl_osam.lua index ccc260d201e..c996116a336 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/earl_osam.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/earl_osam.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "GraveDangerBossDeath", +} + monster.health = 75000 monster.maxHealth = 75000 monster.race = "venom" diff --git a/data-otservbr-global/monster/quests/grave_danger/bosses/king_zelos.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/king_zelos.lua index 7b3adde7c04..0201e821448 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/king_zelos.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/king_zelos.lua @@ -14,6 +14,7 @@ monster.outfit = { } monster.events = { + "GraveDangerBossDeath", "zelosDeath", } diff --git a/data-otservbr-global/monster/quests/grave_danger/bosses/lord_azaram.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/lord_azaram.lua index 8e47689c9e5..701a0b6f92b 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/lord_azaram.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/lord_azaram.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "GraveDangerBossDeath", +} + monster.health = 75000 monster.maxHealth = 75000 monster.race = "venom" diff --git a/data-otservbr-global/monster/quests/grave_danger/bosses/sir_baeloc.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/sir_baeloc.lua index d9a43a7dc01..042ce32e981 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/sir_baeloc.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/sir_baeloc.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "GraveDangerBossDeath", +} + monster.health = 75000 monster.maxHealth = 75000 monster.race = "venom" diff --git a/data-otservbr-global/monster/quests/hero_of_rathleton/deep_terror.lua b/data-otservbr-global/monster/quests/hero_of_rathleton/deep_terror.lua index d5715452efa..534175a881a 100644 --- a/data-otservbr-global/monster/quests/hero_of_rathleton/deep_terror.lua +++ b/data-otservbr-global/monster/quests/hero_of_rathleton/deep_terror.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "RathletonBossDeath", +} + monster.bosstiary = { bossRaceId = 1087, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/quests/hero_of_rathleton/empowered_glooth_horror.lua b/data-otservbr-global/monster/quests/hero_of_rathleton/empowered_glooth_horror.lua index 8f3e9d0e482..b99cd1f87d7 100644 --- a/data-otservbr-global/monster/quests/hero_of_rathleton/empowered_glooth_horror.lua +++ b/data-otservbr-global/monster/quests/hero_of_rathleton/empowered_glooth_horror.lua @@ -13,6 +13,11 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "RathletonBossDeath", + "GloothHorror", +} + monster.health = 25000 monster.maxHealth = 25000 monster.race = "venom" @@ -52,10 +57,6 @@ monster.flags = { canWalkOnPoison = true, } -monster.events = { - "GloothHorror", -} - monster.light = { level = 0, color = 0, diff --git a/data-otservbr-global/monster/quests/hero_of_rathleton/professor_maxxen.lua b/data-otservbr-global/monster/quests/hero_of_rathleton/professor_maxxen.lua index 8bb03ae7631..8a1ec35e913 100644 --- a/data-otservbr-global/monster/quests/hero_of_rathleton/professor_maxxen.lua +++ b/data-otservbr-global/monster/quests/hero_of_rathleton/professor_maxxen.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "RathletonBossDeath", +} + monster.health = 90000 monster.maxHealth = 90000 monster.race = "venom" diff --git a/data-otservbr-global/monster/quests/in_service_of_yalahar/azerus.lua b/data-otservbr-global/monster/quests/in_service_of_yalahar/azerus.lua index cd5ad5ae043..87329f07738 100644 --- a/data-otservbr-global/monster/quests/in_service_of_yalahar/azerus.lua +++ b/data-otservbr-global/monster/quests/in_service_of_yalahar/azerus.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "AzerusDeath", +} + monster.health = 26000 monster.maxHealth = 26000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/in_service_of_yalahar/azerus2.lua b/data-otservbr-global/monster/quests/in_service_of_yalahar/azerus2.lua index ef0b7d49807..19f074c17eb 100644 --- a/data-otservbr-global/monster/quests/in_service_of_yalahar/azerus2.lua +++ b/data-otservbr-global/monster/quests/in_service_of_yalahar/azerus2.lua @@ -14,6 +14,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "AzerusDeath", +} + monster.health = 26000 monster.maxHealth = 26000 monster.race = "blood" 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 7326ed59abc..bcb266254fe 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 @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "QuaraLeadersDeath", +} + monster.health = 750 monster.maxHealth = 750 monster.race = "blood" 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 d707fc89581..583df08b8b5 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 @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "QuaraLeadersDeath", +} + monster.health = 3100 monster.maxHealth = 3100 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/kilmaresh/an_astral_glyph.lua b/data-otservbr-global/monster/quests/kilmaresh/an_astral_glyph.lua index 5b76352b45d..a9c8792332a 100644 --- a/data-otservbr-global/monster/quests/kilmaresh/an_astral_glyph.lua +++ b/data-otservbr-global/monster/quests/kilmaresh/an_astral_glyph.lua @@ -14,6 +14,11 @@ monster.corpse = 0 monster.speed = 235 monster.manaCost = 0 +monster.events = { + "ForgottenKnowledgeBossDeath", + "AstralGlyphDeath", +} + monster.changeTarget = { interval = 2000, chance = 0, @@ -46,10 +51,6 @@ monster.flags = { canWalkOnPoison = true, } -monster.events = { - "AstralGlyphDeath", -} - monster.light = { level = 0, color = 0, diff --git a/data-otservbr-global/monster/quests/kilmaresh/bragrumol.lua b/data-otservbr-global/monster/quests/kilmaresh/bragrumol.lua index b653df68c89..bb7ef950744 100644 --- a/data-otservbr-global/monster/quests/kilmaresh/bragrumol.lua +++ b/data-otservbr-global/monster/quests/kilmaresh/bragrumol.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "BragrumolDeath", +} + monster.health = 38000 monster.maxHealth = 38000 monster.race = "fire" diff --git a/data-otservbr-global/monster/quests/kilmaresh/mozradek.lua b/data-otservbr-global/monster/quests/kilmaresh/mozradek.lua index 093b8d7ceeb..8602923a08b 100644 --- a/data-otservbr-global/monster/quests/kilmaresh/mozradek.lua +++ b/data-otservbr-global/monster/quests/kilmaresh/mozradek.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "MozradekDeath", +} + monster.bosstiary = { bossRaceId = 1829, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/quests/kilmaresh/xogixath.lua b/data-otservbr-global/monster/quests/kilmaresh/xogixath.lua index 886b7632944..3c77465e1ab 100644 --- a/data-otservbr-global/monster/quests/kilmaresh/xogixath.lua +++ b/data-otservbr-global/monster/quests/kilmaresh/xogixath.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "XogixathDeath", +} + monster.health = 28000 monster.maxHealth = 28000 monster.race = "fire" diff --git a/data-otservbr-global/monster/quests/liquid_black/jaul.lua b/data-otservbr-global/monster/quests/liquid_black/jaul.lua index c9fa8b2c7fe..965bbacb14c 100644 --- a/data-otservbr-global/monster/quests/liquid_black/jaul.lua +++ b/data-otservbr-global/monster/quests/liquid_black/jaul.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "DeeplingBossDeath", +} + monster.bosstiary = { bossRaceId = 773, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/quests/liquid_black/obujos.lua b/data-otservbr-global/monster/quests/liquid_black/obujos.lua index b8c84b54c61..1f32fd54f1c 100644 --- a/data-otservbr-global/monster/quests/liquid_black/obujos.lua +++ b/data-otservbr-global/monster/quests/liquid_black/obujos.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "DeeplingBossDeath", +} + monster.bosstiary = { bossRaceId = 774, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/quests/liquid_black/tanjis.lua b/data-otservbr-global/monster/quests/liquid_black/tanjis.lua index 4313a4a74ab..586af950be3 100644 --- a/data-otservbr-global/monster/quests/liquid_black/tanjis.lua +++ b/data-otservbr-global/monster/quests/liquid_black/tanjis.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "DeeplingBossDeath", +} + monster.bosstiary = { bossRaceId = 775, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua index eb7d9a7aeff..8f3bf7f6166 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua @@ -15,6 +15,7 @@ monster.outfit = { monster.events = { "MagmaBubbleDeath", + "ThePrimeOrdealBossDeath", } monster.bosstiary = { diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua index c6a7eb46164..b81e83f7af7 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua @@ -66,6 +66,7 @@ monster.outfit = { monster.events = { "ThePrimalMenaceDeath", + "ThePrimeOrdealBossDeath", } monster.health = 400000 diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua index 502c11e7db8..40957e0bde4 100644 --- a/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua +++ b/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "SoulwarsBossDeath", +} + monster.health = 300000 monster.maxHealth = 300000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua index 834edccf59f..0c8ddbbac42 100644 --- a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua +++ b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "SoulwarsBossDeath", +} + monster.health = 300000 monster.maxHealth = 300000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua index ce6699ea39a..5e79dcccbdd 100644 --- a/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua +++ b/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "SoulwarsBossDeath", +} + monster.health = 300000 monster.maxHealth = 300000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_megalomania.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_megalomania.lua index 1c871919b87..18cfdeacd90 100644 --- a/data-otservbr-global/monster/quests/soul_war/goshnars_megalomania.lua +++ b/data-otservbr-global/monster/quests/soul_war/goshnars_megalomania.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "SoulwarsBossDeath", +} + monster.health = 500000 monster.maxHealth = 500000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua index f6180e7ff6d..cf46b89a76d 100644 --- a/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua +++ b/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "SoulwarsBossDeath", +} + monster.health = 300000 monster.maxHealth = 300000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/the_dream_courts/bosses/alptramun.lua b/data-otservbr-global/monster/quests/the_dream_courts/bosses/alptramun.lua index a46b6610aff..76275c2cd0f 100644 --- a/data-otservbr-global/monster/quests/the_dream_courts/bosses/alptramun.lua +++ b/data-otservbr-global/monster/quests/the_dream_courts/bosses/alptramun.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "DreamCourtsBossDeath", +} + monster.health = 320000 monster.maxHealth = 320000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/the_dream_courts/bosses/izcandar_the_banished.lua b/data-otservbr-global/monster/quests/the_dream_courts/bosses/izcandar_the_banished.lua index 26b2c837282..9c693024899 100644 --- a/data-otservbr-global/monster/quests/the_dream_courts/bosses/izcandar_the_banished.lua +++ b/data-otservbr-global/monster/quests/the_dream_courts/bosses/izcandar_the_banished.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "DreamCourtsBossDeath", +} + monster.bosstiary = { bossRaceId = 1699, bossRace = RARITY_NEMESIS, diff --git a/data-otservbr-global/monster/quests/the_dream_courts/bosses/malofur_mangrinder.lua b/data-otservbr-global/monster/quests/the_dream_courts/bosses/malofur_mangrinder.lua index 4e85ee19d95..2bd63f042be 100644 --- a/data-otservbr-global/monster/quests/the_dream_courts/bosses/malofur_mangrinder.lua +++ b/data-otservbr-global/monster/quests/the_dream_courts/bosses/malofur_mangrinder.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "DreamCourtsBossDeath", +} + monster.health = 320000 monster.maxHealth = 320000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/the_dream_courts/bosses/maxxenius.lua b/data-otservbr-global/monster/quests/the_dream_courts/bosses/maxxenius.lua index d5dd3890976..8db50108f56 100644 --- a/data-otservbr-global/monster/quests/the_dream_courts/bosses/maxxenius.lua +++ b/data-otservbr-global/monster/quests/the_dream_courts/bosses/maxxenius.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "DreamCourtsBossDeath", +} + monster.health = 320000 monster.maxHealth = 320000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/the_dream_courts/bosses/the_nightmare_beast.lua b/data-otservbr-global/monster/quests/the_dream_courts/bosses/the_nightmare_beast.lua index c8c3f8da275..d0520193aad 100644 --- a/data-otservbr-global/monster/quests/the_dream_courts/bosses/the_nightmare_beast.lua +++ b/data-otservbr-global/monster/quests/the_dream_courts/bosses/the_nightmare_beast.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "DreamCourtsBossDeath", +} + monster.health = 850000 monster.maxHealth = 850000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/the_elemental_spheres/earth_overlord.lua b/data-otservbr-global/monster/quests/the_elemental_spheres/earth_overlord.lua index c651694c21e..33251b292d5 100644 --- a/data-otservbr-global/monster/quests/the_elemental_spheres/earth_overlord.lua +++ b/data-otservbr-global/monster/quests/the_elemental_spheres/earth_overlord.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ElementalOverlordDeath", +} + monster.health = 4000 monster.maxHealth = 4000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/the_elemental_spheres/energy_overlord.lua b/data-otservbr-global/monster/quests/the_elemental_spheres/energy_overlord.lua index 10846df7c35..844a6504d33 100644 --- a/data-otservbr-global/monster/quests/the_elemental_spheres/energy_overlord.lua +++ b/data-otservbr-global/monster/quests/the_elemental_spheres/energy_overlord.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ElementalOverlordDeath", +} + monster.health = 4000 monster.maxHealth = 4000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/the_elemental_spheres/fire_overlord.lua b/data-otservbr-global/monster/quests/the_elemental_spheres/fire_overlord.lua index c3b7d152a96..7364324263d 100644 --- a/data-otservbr-global/monster/quests/the_elemental_spheres/fire_overlord.lua +++ b/data-otservbr-global/monster/quests/the_elemental_spheres/fire_overlord.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ElementalOverlordDeath", +} + monster.health = 4000 monster.maxHealth = 4000 monster.race = "fire" diff --git a/data-otservbr-global/monster/quests/the_elemental_spheres/ice_overlord.lua b/data-otservbr-global/monster/quests/the_elemental_spheres/ice_overlord.lua index 7da731c90ab..9a65a1c8ef2 100644 --- a/data-otservbr-global/monster/quests/the_elemental_spheres/ice_overlord.lua +++ b/data-otservbr-global/monster/quests/the_elemental_spheres/ice_overlord.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ElementalOverlordDeath", +} + monster.health = 4000 monster.maxHealth = 4000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/the_elemental_spheres/lord_of_the_elements.lua b/data-otservbr-global/monster/quests/the_elemental_spheres/lord_of_the_elements.lua index eba6b1c9412..7bdc28f7421 100644 --- a/data-otservbr-global/monster/quests/the_elemental_spheres/lord_of_the_elements.lua +++ b/data-otservbr-global/monster/quests/the_elemental_spheres/lord_of_the_elements.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ElementalOverlordDeath", +} + monster.bosstiary = { bossRaceId = 454, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/the_inquisition/annihilon.lua b/data-otservbr-global/monster/quests/the_inquisition/annihilon.lua index e35249ea832..26013b74ece 100644 --- a/data-otservbr-global/monster/quests/the_inquisition/annihilon.lua +++ b/data-otservbr-global/monster/quests/the_inquisition/annihilon.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "InquisitionBossDeath", +} + monster.bosstiary = { bossRaceId = 418, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/quests/the_inquisition/golgordan.lua b/data-otservbr-global/monster/quests/the_inquisition/golgordan.lua index 7da1ca0e093..59a74148ed6 100644 --- a/data-otservbr-global/monster/quests/the_inquisition/golgordan.lua +++ b/data-otservbr-global/monster/quests/the_inquisition/golgordan.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "InquisitionBossDeath", +} + monster.bosstiary = { bossRaceId = 416, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/quests/the_inquisition/hellgorak.lua b/data-otservbr-global/monster/quests/the_inquisition/hellgorak.lua index 2fcb10ece1f..79209cb8560 100644 --- a/data-otservbr-global/monster/quests/the_inquisition/hellgorak.lua +++ b/data-otservbr-global/monster/quests/the_inquisition/hellgorak.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "InquisitionBossDeath", +} + monster.bosstiary = { bossRaceId = 403, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/quests/the_inquisition/latrivan.lua b/data-otservbr-global/monster/quests/the_inquisition/latrivan.lua index 9854d2060b4..be2d46288fa 100644 --- a/data-otservbr-global/monster/quests/the_inquisition/latrivan.lua +++ b/data-otservbr-global/monster/quests/the_inquisition/latrivan.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "InquisitionBossDeath", +} + monster.health = 25000 monster.maxHealth = 25000 monster.race = "fire" diff --git a/data-otservbr-global/monster/quests/the_inquisition/madareth.lua b/data-otservbr-global/monster/quests/the_inquisition/madareth.lua index 344609d71bf..66caf4329f5 100644 --- a/data-otservbr-global/monster/quests/the_inquisition/madareth.lua +++ b/data-otservbr-global/monster/quests/the_inquisition/madareth.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "InquisitionBossDeath", +} + monster.bosstiary = { bossRaceId = 414, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/quests/the_inquisition/ungreez.lua b/data-otservbr-global/monster/quests/the_inquisition/ungreez.lua index be3f10a6e37..c19b2199920 100644 --- a/data-otservbr-global/monster/quests/the_inquisition/ungreez.lua +++ b/data-otservbr-global/monster/quests/the_inquisition/ungreez.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "UngreezDeath", +} + monster.health = 8200 monster.maxHealth = 8200 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/the_inquisition/ushuriel.lua b/data-otservbr-global/monster/quests/the_inquisition/ushuriel.lua index 25b14bd6298..35c7d81b030 100644 --- a/data-otservbr-global/monster/quests/the_inquisition/ushuriel.lua +++ b/data-otservbr-global/monster/quests/the_inquisition/ushuriel.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "InquisitionBossDeath", +} + monster.health = 31500 monster.maxHealth = 31500 monster.race = "fire" diff --git a/data-otservbr-global/monster/quests/the_inquisition/zugurosh.lua b/data-otservbr-global/monster/quests/the_inquisition/zugurosh.lua index 796346d7a31..fedf47e5fe1 100644 --- a/data-otservbr-global/monster/quests/the_inquisition/zugurosh.lua +++ b/data-otservbr-global/monster/quests/the_inquisition/zugurosh.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "InquisitionBossDeath", +} + monster.bosstiary = { bossRaceId = 434, bossRace = RARITY_BANE, diff --git a/data-otservbr-global/monster/quests/the_new_frontier/shard_of_corruption.lua b/data-otservbr-global/monster/quests/the_new_frontier/shard_of_corruption.lua index a818d413269..c7ba3fa0e02 100644 --- a/data-otservbr-global/monster/quests/the_new_frontier/shard_of_corruption.lua +++ b/data-otservbr-global/monster/quests/the_new_frontier/shard_of_corruption.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ShardOfCorruptionDeath", +} + monster.health = 600 monster.maxHealth = 600 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/the_new_frontier/tirecz.lua b/data-otservbr-global/monster/quests/the_new_frontier/tirecz.lua index 8bd994210c8..42cbd1f2b9f 100644 --- a/data-otservbr-global/monster/quests/the_new_frontier/tirecz.lua +++ b/data-otservbr-global/monster/quests/the_new_frontier/tirecz.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "TireczDeath", +} + monster.health = 25000 monster.maxHealth = 25000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/the_secret_library/bosses/ghulosh.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/ghulosh.lua index 789d59fc8fd..4324a573ec4 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/bosses/ghulosh.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/ghulosh.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "SecretLibraryBossDeath", +} + monster.bosstiary = { bossRaceId = 1608, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/the_secret_library/bosses/gorzindel.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/gorzindel.lua index bd05efbfc7c..b00bffd6d60 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/bosses/gorzindel.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/gorzindel.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "SecretLibraryBossDeath", +} + monster.bosstiary = { bossRaceId = 1591, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/the_secret_library/bosses/the_scourge_of_oblivion.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/the_scourge_of_oblivion.lua index 9529a00cedb..5965afef0a3 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/bosses/the_scourge_of_oblivion.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/the_scourge_of_oblivion.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "SecretLibraryBossDeath", +} + monster.bosstiary = { bossRaceId = 1642, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/the_secret_library/lokathmor.lua b/data-otservbr-global/monster/quests/the_secret_library/lokathmor.lua index 47484e5dc22..537b2584d82 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/lokathmor.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/lokathmor.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "SecretLibraryBossDeath", +} + monster.bosstiary = { bossRaceId = 1574, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/the_secret_library/mazzinor.lua b/data-otservbr-global/monster/quests/the_secret_library/mazzinor.lua index bbf93c31425..a9be1bc3221 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/mazzinor.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/mazzinor.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "SecretLibraryBossDeath", +} + monster.bosstiary = { bossRaceId = 1605, bossRace = RARITY_ARCHFOE, diff --git a/data-otservbr-global/monster/quests/wrath_of_the_emperor/fury_of_the_emperor.lua b/data-otservbr-global/monster/quests/wrath_of_the_emperor/fury_of_the_emperor.lua index 463d57908da..46f365304c3 100644 --- a/data-otservbr-global/monster/quests/wrath_of_the_emperor/fury_of_the_emperor.lua +++ b/data-otservbr-global/monster/quests/wrath_of_the_emperor/fury_of_the_emperor.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "WrathOfTheEmperorBossDeath", +} + monster.health = 51000 monster.maxHealth = 51000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/wrath_of_the_emperor/lizard_abomination.lua b/data-otservbr-global/monster/quests/wrath_of_the_emperor/lizard_abomination.lua index eab957f402d..9b0e18c6cc3 100644 --- a/data-otservbr-global/monster/quests/wrath_of_the_emperor/lizard_abomination.lua +++ b/data-otservbr-global/monster/quests/wrath_of_the_emperor/lizard_abomination.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ZalamonDeath", +} + monster.health = 95000 monster.maxHealth = 95000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/wrath_of_the_emperor/mutated_zalamon.lua b/data-otservbr-global/monster/quests/wrath_of_the_emperor/mutated_zalamon.lua index ad7c98a1abe..39aa68ae966 100644 --- a/data-otservbr-global/monster/quests/wrath_of_the_emperor/mutated_zalamon.lua +++ b/data-otservbr-global/monster/quests/wrath_of_the_emperor/mutated_zalamon.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ZalamonDeath", +} + monster.health = 155000 monster.maxHealth = 155000 monster.race = "venom" diff --git a/data-otservbr-global/monster/quests/wrath_of_the_emperor/scorn_of_the_emperor.lua b/data-otservbr-global/monster/quests/wrath_of_the_emperor/scorn_of_the_emperor.lua index bbb474fa652..7b0b97c6354 100644 --- a/data-otservbr-global/monster/quests/wrath_of_the_emperor/scorn_of_the_emperor.lua +++ b/data-otservbr-global/monster/quests/wrath_of_the_emperor/scorn_of_the_emperor.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "WrathOfTheEmperorBossDeath", +} + monster.health = 45000 monster.maxHealth = 45000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/wrath_of_the_emperor/snake_god_essence.lua b/data-otservbr-global/monster/quests/wrath_of_the_emperor/snake_god_essence.lua index 9d7e4f4fbaa..8479eeba806 100644 --- a/data-otservbr-global/monster/quests/wrath_of_the_emperor/snake_god_essence.lua +++ b/data-otservbr-global/monster/quests/wrath_of_the_emperor/snake_god_essence.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ZalamonDeath", +} + monster.health = 65000 monster.maxHealth = 65000 monster.race = "blood" diff --git a/data-otservbr-global/monster/quests/wrath_of_the_emperor/snake_thing.lua b/data-otservbr-global/monster/quests/wrath_of_the_emperor/snake_thing.lua index 272ef668f54..0085b08ca09 100644 --- a/data-otservbr-global/monster/quests/wrath_of_the_emperor/snake_thing.lua +++ b/data-otservbr-global/monster/quests/wrath_of_the_emperor/snake_thing.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ZalamonDeath", +} + monster.health = 70000 monster.maxHealth = 70000 monster.race = "venom" diff --git a/data-otservbr-global/monster/quests/wrath_of_the_emperor/spite_of_the_emperor.lua b/data-otservbr-global/monster/quests/wrath_of_the_emperor/spite_of_the_emperor.lua index f0951ea2dbc..2ab41632582 100644 --- a/data-otservbr-global/monster/quests/wrath_of_the_emperor/spite_of_the_emperor.lua +++ b/data-otservbr-global/monster/quests/wrath_of_the_emperor/spite_of_the_emperor.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "WrathOfTheEmperorBossDeath", +} + monster.health = 48000 monster.maxHealth = 48000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/wrath_of_the_emperor/the_keeper.lua b/data-otservbr-global/monster/quests/wrath_of_the_emperor/the_keeper.lua index 43d731d6bdd..3062b6f2f5e 100644 --- a/data-otservbr-global/monster/quests/wrath_of_the_emperor/the_keeper.lua +++ b/data-otservbr-global/monster/quests/wrath_of_the_emperor/the_keeper.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "TheKeeperDeath", +} + monster.health = 40000 monster.maxHealth = 40000 monster.race = "venom" diff --git a/data-otservbr-global/monster/quests/wrath_of_the_emperor/wrath_of_the_emperor.lua b/data-otservbr-global/monster/quests/wrath_of_the_emperor/wrath_of_the_emperor.lua index 70494aee5f9..99ad2361003 100644 --- a/data-otservbr-global/monster/quests/wrath_of_the_emperor/wrath_of_the_emperor.lua +++ b/data-otservbr-global/monster/quests/wrath_of_the_emperor/wrath_of_the_emperor.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "WrathOfTheEmperorBossDeath", +} + monster.health = 55000 monster.maxHealth = 55000 monster.race = "undead" diff --git a/data-otservbr-global/monster/reptiles/lizard_magistratus.lua b/data-otservbr-global/monster/reptiles/lizard_magistratus.lua index 410adcacc4b..cce60cb8d2d 100644 --- a/data-otservbr-global/monster/reptiles/lizard_magistratus.lua +++ b/data-otservbr-global/monster/reptiles/lizard_magistratus.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "LizardMagistratusDeath", +} + monster.raceId = 655 monster.Bestiary = { class = "Reptile", diff --git a/data-otservbr-global/monster/reptiles/lizard_noble.lua b/data-otservbr-global/monster/reptiles/lizard_noble.lua index 18847211c0a..1dcfe3d2873 100644 --- a/data-otservbr-global/monster/reptiles/lizard_noble.lua +++ b/data-otservbr-global/monster/reptiles/lizard_noble.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "LizardNobleDeath", +} + monster.raceId = 656 monster.Bestiary = { class = "Reptile", diff --git a/data-otservbr-global/monster/undeads/demon_skeleton.lua b/data-otservbr-global/monster/undeads/demon_skeleton.lua index 7e133b866cc..c40806e299b 100644 --- a/data-otservbr-global/monster/undeads/demon_skeleton.lua +++ b/data-otservbr-global/monster/undeads/demon_skeleton.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "UpperSpikeDeath", +} + monster.raceId = 37 monster.Bestiary = { class = "Undead", diff --git a/data-otservbr-global/monster/vermins/deepworm.lua b/data-otservbr-global/monster/vermins/deepworm.lua index 1127359392b..91b2ded8752 100644 --- a/data-otservbr-global/monster/vermins/deepworm.lua +++ b/data-otservbr-global/monster/vermins/deepworm.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "WarzoneWormDeath", +} + monster.raceId = 1531 monster.Bestiary = { class = "Vermin", diff --git a/data-otservbr-global/monster/vermins/diremaw.lua b/data-otservbr-global/monster/vermins/diremaw.lua index 530c3203922..1e3accb0fd3 100644 --- a/data-otservbr-global/monster/vermins/diremaw.lua +++ b/data-otservbr-global/monster/vermins/diremaw.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "WarzoneWormDeath", +} + monster.raceId = 1532 monster.Bestiary = { class = "Vermin", diff --git a/data-otservbr-global/monster/vermins/drillworm.lua b/data-otservbr-global/monster/vermins/drillworm.lua index f1ae51b1df4..3cf92fce18a 100644 --- a/data-otservbr-global/monster/vermins/drillworm.lua +++ b/data-otservbr-global/monster/vermins/drillworm.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "LowerSpikeDeath", +} + monster.raceId = 878 monster.Bestiary = { class = "Vermin", diff --git a/data-otservbr-global/monster/vermins/parasite.lua b/data-otservbr-global/monster/vermins/parasite.lua index da981020291..65e83dbb7f2 100644 --- a/data-otservbr-global/monster/vermins/parasite.lua +++ b/data-otservbr-global/monster/vermins/parasite.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "ParasiteDeath", +} + monster.health = 550 monster.maxHealth = 550 monster.race = "venom" diff --git a/data-otservbr-global/monster/vermins/wiggler.lua b/data-otservbr-global/monster/vermins/wiggler.lua index 3c438edb4bc..76c994cdff5 100644 --- a/data-otservbr-global/monster/vermins/wiggler.lua +++ b/data-otservbr-global/monster/vermins/wiggler.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0, } +monster.events = { + "WigglerDeath", +} + monster.raceId = 899 monster.Bestiary = { class = "Vermin", diff --git a/data-otservbr-global/scripts/actions/quests/dangerous_depth/using_crystals.lua b/data-otservbr-global/scripts/actions/quests/dangerous_depth/using_crystals.lua index ca95fa99bc9..68a348fc08f 100644 --- a/data-otservbr-global/scripts/actions/quests/dangerous_depth/using_crystals.lua +++ b/data-otservbr-global/scripts/actions/quests/dangerous_depth/using_crystals.lua @@ -370,10 +370,7 @@ end local function startWarzoneIV() addEvent(function() - local monstro = Game.createMonster("The Baron From Below", Position(33648, 32303, 15)) - if monstro then - monstro:registerEvent("TheBaronFromBelowThink") - end + Game.createMonster("The Baron From Below", Position(33648, 32303, 15)) addEvent(sumonarLavasIV, 15 * 1000, 5) addEvent(lavaHoles, 15 * 1000, 1) end, 10 * 1000) diff --git a/data-otservbr-global/scripts/actions/quests/feaster_of_souls/bosses_killed.lua b/data-otservbr-global/scripts/actions/quests/feaster_of_souls/bosses_killed.lua index b77304f5627..b08abd9a2d2 100644 --- a/data-otservbr-global/scripts/actions/quests/feaster_of_souls/bosses_killed.lua +++ b/data-otservbr-global/scripts/actions/quests/feaster_of_souls/bosses_killed.lua @@ -5,9 +5,9 @@ local bosses = { ["the pale worm"] = { storage = Storage.Quest.U12_30.FeasterOfSouls.PaleWormKilled }, } -local bossesFeasterOfSouls = CreatureEvent("FeasterOfSoulsKill") -function bossesFeasterOfSouls.onKill(creature, target) - local targetMonster = target:getMonster() +local bossesFeasterOfSouls = CreatureEvent("FeasterOfSoulsBossDeath") +function bossesFeasterOfSouls.onDeath(creature) + local targetMonster = creature:getMonster() if not targetMonster or targetMonster:getMaster() then return true end @@ -15,14 +15,11 @@ function bossesFeasterOfSouls.onKill(creature, target) if not bossConfig then return true end - for key, value in pairs(targetMonster:getDamageMap()) do - local attackerPlayer = Player(key) - if attackerPlayer then - if bossConfig.storage then - attackerPlayer:setStorageValue(bossConfig.storage, 1) - end + onDeathForDamagingPlayers(creature, function(creature, player) + if bossConfig.storage then + player:setStorageValue(bossConfig.storage, 1) end - end + end) return true end diff --git a/data-otservbr-global/scripts/actions/quests/grave_danger/bosses_killed.lua b/data-otservbr-global/scripts/actions/quests/grave_danger/bosses_killed.lua index 60716e7ab6b..3142f9e1a04 100644 --- a/data-otservbr-global/scripts/actions/quests/grave_danger/bosses_killed.lua +++ b/data-otservbr-global/scripts/actions/quests/grave_danger/bosses_killed.lua @@ -7,9 +7,9 @@ local bosses = { ["king zelos"] = { storage = Storage.Quest.U12_20.GraveDanger.Bosses.KingZelosKilled }, } -local bossesGraveDanger = CreatureEvent("GraveDangerKill") -function bossesGraveDanger.onKill(creature, target) - local targetMonster = target:getMonster() +local bossesGraveDanger = CreatureEvent("GraveDangerKillGraveDangerBossDeath") +function bossesGraveDanger.onDeath(creature) + local targetMonster = creature:getMonster() if not targetMonster or targetMonster:getMaster() then return true end @@ -17,23 +17,20 @@ function bossesGraveDanger.onKill(creature, target) if not bossConfig then return true end - for key, value in pairs(targetMonster:getDamageMap()) do - local attackerPlayer = Player(key) - if attackerPlayer then - if bossConfig.storage then - attackerPlayer:setStorageValue(bossConfig.storage, 1) + onDeathForDamagingPlayers(creature, function(creature, player) + if bossConfig.storage then + player:setStorageValue(bossConfig.storage, 1) + end + local bossesKilled = 0 + for value in pairs(bosses) do + if player:getStorageValue(bosses[value].storage) > 0 then + bossesKilled = bossesKilled + 1 end end - end - local bossesKilled = 0 - for value in pairs(bosses) do - if creature:getStorageValue(bosses[value].storage) > 0 then - bossesKilled = bossesKilled + 1 + if bossesKilled >= 5 then -- number of mini bosses + player:setStorageValue(Storage.Quest.U12_20.GraveDanger.Bosses.KingZelosDoor, 1) end - end - if bossesKilled >= 5 then -- number of mini bosses - creature:setStorageValue(Storage.Quest.U12_20.GraveDanger.Bosses.KingZelosDoor, 1) - end + end) return true end diff --git a/data-otservbr-global/scripts/actions/quests/secret_library/bosses_killed.lua b/data-otservbr-global/scripts/actions/quests/secret_library/bosses_killed.lua index a825983987c..b7154ec9f0f 100644 --- a/data-otservbr-global/scripts/actions/quests/secret_library/bosses_killed.lua +++ b/data-otservbr-global/scripts/actions/quests/secret_library/bosses_killed.lua @@ -6,9 +6,9 @@ local bosses = { ["scourge of oblivion"] = { storage = Storage.Quest.U11_80.TheSecretLibrary.ScourgeOfOblivionKilled }, } -local bossesSecretLibrary = CreatureEvent("SecretLibraryKill") -function bossesSecretLibrary.onKill(player, target) - local targetMonster = target:getMonster() +local bossesSecretLibrary = CreatureEvent("SecretLibraryBossDeath") +function bossesSecretLibrary.onDeath(creature) + local targetMonster = creature:getMonster() if not targetMonster or targetMonster:getMaster() then return true end @@ -16,23 +16,20 @@ function bossesSecretLibrary.onKill(player, target) if not bossConfig then return true end - for key, value in pairs(targetMonster:getDamageMap()) do - local attackerPlayer = Player(key) - if attackerPlayer then - if bossConfig.storage then - attackerPlayer:setStorageValue(bossConfig.storage, 1) + onDeathForDamagingPlayers(creature, function(creature, player) + if bossConfig.storage then + player:setStorageValue(bossConfig.storage, 1) + end + local bossesKilled = 0 + for value in pairs(bosses) do + if player:getStorageValue(bosses[value].storage) > 0 then + bossesKilled = bossesKilled + 1 end end - end - local bossesKilled = 0 - for value in pairs(bosses) do - if player:getStorageValue(bosses[value].storage) > 0 then - bossesKilled = bossesKilled + 1 + if bossesKilled >= 4 then -- number of mini bosses + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.ScourgeOfOblivionDoor, 1) end - end - if bossesKilled >= 4 then -- number of mini bosses - player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.ScourgeOfOblivionDoor, 1) - end + end) return true end diff --git a/data-otservbr-global/scripts/actions/quests/soul_war/bosses_killed.lua b/data-otservbr-global/scripts/actions/quests/soul_war/bosses_killed.lua index 06aeff3c652..ea8612cc7e8 100644 --- a/data-otservbr-global/scripts/actions/quests/soul_war/bosses_killed.lua +++ b/data-otservbr-global/scripts/actions/quests/soul_war/bosses_killed.lua @@ -7,9 +7,9 @@ local bosses = { ["goshnar's megalomania"] = { storage = Storage.Quest.U12_40.SoulWar.GoshnarMegalomaniaKilled }, } -local bossesSoulWar = CreatureEvent("SoulWarKill") -function bossesSoulWar.onKill(creature, target) - local targetMonster = target:getMonster() +local bossesSoulWar = CreatureEvent("SoulwarsBossDeath") +function bossesSoulWar.onDeath(creature) + local targetMonster = creature:getMonster() if not targetMonster or targetMonster:getMaster() then return true end @@ -17,14 +17,11 @@ function bossesSoulWar.onKill(creature, target) if not bossConfig then return true end - for key, value in pairs(targetMonster:getDamageMap()) do - local attackerPlayer = Player(key) - if attackerPlayer then - if bossConfig.storage then - attackerPlayer:setStorageValue(bossConfig.storage, 1) - end + onDeathForDamagingPlayers(creature, function(creature, player) + if bossConfig.storage then + player:setStorageValue(bossConfig.storage, 1) end - end + end) return true end diff --git a/data-otservbr-global/scripts/actions/quests/the_dream_courts/bosses_killed.lua b/data-otservbr-global/scripts/actions/quests/the_dream_courts/bosses_killed.lua index cd6eb327972..c296a419741 100644 --- a/data-otservbr-global/scripts/actions/quests/the_dream_courts/bosses_killed.lua +++ b/data-otservbr-global/scripts/actions/quests/the_dream_courts/bosses_killed.lua @@ -7,9 +7,9 @@ local bosses = { ["the nightmare beast"] = { storage = Storage.Quest.U12_00.TheDreamCourts.NightmareBeastKilled }, } -local bossesDreamCourts = CreatureEvent("DreamCourtsKill") -function bossesDreamCourts.onKill(creature, target) - local targetMonster = target:getMonster() +local bossesDreamCourts = CreatureEvent("DreamCourtsBossDeath") +function bossesDreamCourts.onDeath(creature) + local targetMonster = creature:getMonster() if not targetMonster or targetMonster:getMaster() then return true end @@ -17,14 +17,11 @@ function bossesDreamCourts.onKill(creature, target) if not bossConfig then return true end - for key, value in pairs(targetMonster:getDamageMap()) do - local attackerPlayer = Player(key) - if attackerPlayer then - if bossConfig.storage then - attackerPlayer:setStorageValue(bossConfig.storage, 1) - end + onDeathForDamagingPlayers(creature, function(creature, player) + if bossConfig.storage then + player:setStorageValue(bossConfig.storage, 1) end - end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/monster/lower_roshamuul.lua b/data-otservbr-global/scripts/creaturescripts/monster/lower_roshamuul.lua index c27c83a21b1..a7a6ef8f1f0 100644 --- a/data-otservbr-global/scripts/creaturescripts/monster/lower_roshamuul.lua +++ b/data-otservbr-global/scripts/creaturescripts/monster/lower_roshamuul.lua @@ -1,14 +1,18 @@ local setting = { - ["frazzlemaw"] = roshamuul_killed_frazzlemaws, + ["frazzlemaw"] = ROSHAMUUL_KILLED_FRAZZLEMAWS, ["silencer"] = ROSHAMUUL_KILLED_SILENCERS, } -local lowerRoshamuul = CreatureEvent("LowerRoshamuul") -function lowerRoshamuul.onKill(creature, target) - local monster = setting[target:getName():lower()] - if monster then - creature:setStorageValue(monster, math.max(0, creature:getStorageValue(monster)) + 1) +local lowerRoshamuul = CreatureEvent("RoshamuulKillsDeath") +function lowerRoshamuul.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + local monster = setting[creature:getName():lower()] + if not monster then + return true end + + onDeathForParty(creature, mostDamageKiller, function(creature, player) + player:setStorageValue(monster, math.max(0, player:getStorageValue(monster)) + 1) + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/others/login_events.lua b/data-otservbr-global/scripts/creaturescripts/others/login_events.lua index f61182bea3f..7adef4c07a1 100644 --- a/data-otservbr-global/scripts/creaturescripts/others/login_events.lua +++ b/data-otservbr-global/scripts/creaturescripts/others/login_events.lua @@ -1,12 +1,8 @@ local loginEvents = CreatureEvent("LoginEvents") function loginEvents.onLogin(player) local events = { - --Monster - "LowerRoshamuul", --Others "AdvanceSave", - "BestiaryOnKill", - "BosstiaryOnKill", "BossParticipation", "DropLoot", "PlayerDeath", @@ -14,114 +10,10 @@ function loginEvents.onLogin(player) "FamiliarLogin", "FamiliarAdvance", --Quests - --Adventurers Guild Quest - "Thegreatdragonhuntkill", - --Bigfoot Burden Quest - "BossesWarzone", - "ParasiteWarzone", - "VersperothKill", - "WigglerKill", --Cults Of Tibia Quest - "BossesCults", - "MinotaurTask", - "VortexCarlin", "LeidenHeal", - "GlowingRubbishAmulet", - "DestroyedPillar", "HealthPillar", "YalahariHealth", - "EssenceOfMalice", - --Dangerous Depths Quest - "LostExileKill", - "SnailSlimeKill", - "TheBaronFromBelowKill", - --Dawnport Quest - "MorrisMinotaurKill", - "MorrisGoblinKill", - "MorrisTrollKill", - --Elemental Spheres Quest - "OverlordKill", - --Ferumbras Ascendant Quest - "AscendantBossesKill", - "TheShattererKill", - --Firewalker Boots - "PythiusTheRottenKill", - --Forgotten Knowledge Quest - "BossesForgottenKill", - "AstralPower", - "EnergyPrismDeath", - "ReplicaServant", - --Hero Of Rathleton - "RathletonBossKill", - --Secret Service - "BlackKnightKill", - --Service Of Yalahar - "DiseasedTrio", - "Azerus", - "QuaraLeaders", - --Inquisition - "InquisitionBossKill", - "UngreezKill", - --Killing In The Name Of - "KillingInTheNameOfKill", - "KillingInTheNameOfMinotaurKill", - "TiquandasRevengeKill", - "DemodrasKill", - --Kilmaresh - "BragrumolKill", - "MozradekKill", - "XogixathKill", - "FafnarKill", - --Liquid Black - "DeeplingBosses", - --Raging Mage Worldchange - "EnergizedRagingMageKill", - "RagingMageKill", - "YielothaxKill", - --Spike Tasks - "LowerSpikeKill", - "UpperSpikeKill", - "MiddleSpikeKill", - --Svargrond Arena - "SvargrondArenaKill", - --The Ice Islands Quest - "HuskyKill", - --The First Dragon - "KillDragon", - "SomewhatBeatableDeath", - --The New Frontier - "ShardOfCorruptionKill", - "TireczKill", - --Thieves Guild - "NomadKill", - --Threatened Dreams - Nightmare Intruders - "ThreatenedDreamsNightmareMonstersKills", - --Wrath of the Emperor - "LizardMagistratusKill", - "LizardNobleKill", - "KeeperKill", - "BossesKill", - "ZalamonKill", - -- The Rookie Guard - "VascalirRatKills", - -- An Uneasy Alliance - "RenegadeOrcKill", - -- Grave Danger - "GraveDangerKill", - -- Feaster of Souls - "FeasterOfSoulsKill", - -- Soul War - "SoulWarKill", - -- Secret Library - "SecretLibraryKill", - -- The Dream Courts - "DreamCourtsKill", - -- Prime Ordeal - "PrimeOrdealKill", - -- Concoctions - "ConcoctionsOnLogin", - -- Hazard System - "PrimalHazardKill", } for i = 1, #events do diff --git a/data-otservbr-global/scripts/creaturescripts/quests/adventurers_guild/the_great_dragon_hunt.lua b/data-otservbr-global/scripts/creaturescripts/quests/adventurers_guild/the_great_dragon_hunt.lua index d4011bbfc8a..75cd6f92366 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/adventurers_guild/the_great_dragon_hunt.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/adventurers_guild/the_great_dragon_hunt.lua @@ -8,24 +8,21 @@ local areas = { { from = Position(32993, 32632, 7), to = Position(33042, 32688, 7) }, } -local adventurersGuildHunt = CreatureEvent("TheGreatDragonHuntKill") -function adventurersGuildHunt.onKill(creature, target) - if not creature or not creature:isPlayer() then - return true +local adventurersGuildHunt = CreatureEvent("TheGreatDragonHuntDeath") +function adventurersGuildHunt.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + local valid = false + for _, area in ipairs(areas) do + if creature:getPosition():isInRange(area.from, area.to) then + valid = true + break + end end - - if not target or not target:isMonster() then + if not valid then return true end - - if table.contains({ "dragon lord", "dragon" }, target:getName():lower()) then - for _, area in ipairs(areas) do - if creature:getPosition():isInRange(area.from, area.to) then - creature:setStorageValue(Storage.AdventurersGuild.GreatDragonHunt.DragonCounter, creature:getStorageValue(Storage.AdventurersGuild.GreatDragonHunt.DragonCounter) + 1) - break - end - end - end + onDeathForParty(creature, mostDamageKiller, function(creature, player) + player:setStorageValue(Storage.AdventurersGuild.GreatDragonHunt.DragonCounter, math.max(0, player:getStorageValue(Storage.AdventurersGuild.GreatDragonHunt.DragonCounter)) + 1) + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/an_uneasy_alliance/renegade_orc_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/an_uneasy_alliance/renegade_orc_kill.lua index 90fcb9c5ae0..dbff7a11b45 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/an_uneasy_alliance/renegade_orc_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/an_uneasy_alliance/renegade_orc_kill.lua @@ -1,16 +1,10 @@ -local renegadeOrcKill = CreatureEvent("RenegadeOrcKill") -function renegadeOrcKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - if targetMonster:getName():lower() ~= "renegade orc" then - return true - end - local player = creature:getPlayer() - if player:getStorageValue(Storage.Quest.U8_54.AnUneasyAlliance.QuestDoor) == 0 then - player:setStorageValue(Storage.Quest.U8_54.AnUneasyAlliance.QuestDoor, 1) - end +local renegadeOrcKill = CreatureEvent("RenegadeOrcDeath") +function renegadeOrcKill.onDeath(creature, _corpse, _lastHitKiller, player, mostDamageKiller) + onDeathForParty(creature, mostDamageKiller, function(creature, player) + if player:getStorageValue(Storage.Quest.U8_54.AnUneasyAlliance.QuestDoor) == 0 then + player:setStorageValue(Storage.Quest.U8_54.AnUneasyAlliance.QuestDoor, 1) + end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/bosses_warzone.lua b/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/bosses_warzone.lua index b123a941a37..f526f67b171 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/bosses_warzone.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/bosses_warzone.lua @@ -5,31 +5,24 @@ local bosses = { } -- This will set the status of warzone (killing 1, 2 and 3 wz bosses in order you can open the chest and get "some golden fruits") and the reward chest storages -local bossesWarzone = CreatureEvent("BossesWarzone") -function bossesWarzone.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - local bossConfig = bosses[targetMonster:getName():lower()] +local bossesWarzone = CreatureEvent("BossesWarzoneDeath") +function bossesWarzone.onDeath(target) + local bossConfig = bosses[creature:getName():lower()] if not bossConfig then return true end - for index, value in pairs(targetMonster:getDamageMap()) do - local attackerPlayer = Player(index) - if attackerPlayer then - if (attackerPlayer:getStorageValue(Storage.BigfootBurden.WarzoneStatus) + 1) == bossConfig.status then - attackerPlayer:setStorageValue(Storage.BigfootBurden.WarzoneStatus, bossConfig.status) - if bossConfig.status == 4 then - attackerPlayer:setStorageValue(Storage.BigfootBurden.DoorGoldenFruits, 1) - end + onDeathForDamagingPlayers(creature, function(creature, player) + if (player:getStorageValue(Storage.BigfootBurden.WarzoneStatus) + 1) == bossConfig.status then + player:setStorageValue(Storage.BigfootBurden.WarzoneStatus, bossConfig.status) + if bossConfig.status == 4 then + player:setStorageValue(Storage.BigfootBurden.DoorGoldenFruits, 1) end - attackerPlayer:setStorageValue(bossConfig.storage, 1) - attackerPlayer:setStorageValue(Storage.BigfootBurden.BossKills, attackerPlayer:getStorageValue(Storage.BigfootBurden.BossKills) + 1) end - end + player:setStorageValue(bossConfig.storage, 1) + player:setStorageValue(Storage.BigfootBurden.BossKills, player:getStorageValue(Storage.BigfootBurden.BossKills) + 1) + end) + return true end bossesWarzone:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/parasite.lua b/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/parasite.lua index 912e6704225..35cd862a602 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/parasite.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/parasite.lua @@ -25,31 +25,21 @@ local function recreateCrystals(c) end end -local parasiteWarzone = CreatureEvent("ParasiteWarzone") -function parasiteWarzone.onKill(player, target) - local targetMonster = target:getMonster() - if not targetMonster then - return false - end - - local targetName = targetMonster:getName():lower() - if targetName ~= "parasite" then - return false - end - - local master = targetMonster:getMaster() +local parasiteWarzone = CreatureEvent("ParasiteDeath") +function parasiteWarzone.onDeath(creature) + local master = creature:getMaster() if not master or master:isPlayer() then return false end - local pos = targetMonster:getPosition() + local pos = creature:getPosition() if pos.x ~= 33097 or pos.y > 31979 or pos.y < 31976 or pos.z ~= 11 then return false end local config = warzoneConfig.findByName("Gnomevil") if config.locked then - targetMonster:say("It seems that someone has already destroyed the walls in the last 30 minutes.", TALKTYPE_MONSTER_SAY) + creature:say("It seems that someone has already destroyed the walls in the last 30 minutes.", TALKTYPE_MONSTER_SAY) return false end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/versperoth_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/versperoth_kill.lua index 4c7df5f6f43..c736981bd4d 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/versperoth_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/versperoth_kill.lua @@ -15,18 +15,9 @@ local function transformTeleport(open) end end -local versperothKill = CreatureEvent("VersperothKill") -function versperothKill.onKill(creature, target) +local versperothKill = CreatureEvent("VersperothDeath") +function versperothKill.onDeath(creature) local config = warzoneConfig.findByName("Abyssador") - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - if targetMonster:getName():lower() ~= "versperoth" then - return true - end - Game.setStorageValue(GlobalStorage.BigfootBurden.Versperoth.Battle, 2) addEvent(Game.setStorageValue, 30 * 60 * 1000, GlobalStorage.BigfootBurden.Versperoth.Battle, 0) diff --git a/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/wiggler_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/wiggler_kill.lua index 72421a59925..41e41ca1e66 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/wiggler_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/bigfoot_burden/wiggler_kill.lua @@ -1,19 +1,11 @@ -local wigglerKill = CreatureEvent("WigglerKill") -function wigglerKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - if targetMonster:getName():lower() ~= "wiggler" then - return true - end - - local player = creature:getPlayer() - local value = player:getStorageValue(Storage.BigfootBurden.ExterminatedCount) - if value < 10 and player:getStorageValue(Storage.BigfootBurden.MissionExterminators) == 1 then - player:setStorageValue(Storage.BigfootBurden.ExterminatedCount, value + 1) - end +local wigglerKill = CreatureEvent("WigglerDeath") +function wigglerKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + onDeathForParty(creature, mostDamageKiller, function(creature, player) + local value = player:getStorageValue(Storage.BigfootBurden.ExterminatedCount) + if value < 10 and player:getStorageValue(Storage.BigfootBurden.MissionExterminators) == 1 then + player:setStorageValue(Storage.BigfootBurden.ExterminatedCount, value + 1) + end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/bosses_mission_cults.lua b/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/bosses_mission_cults.lua index a0186fa664d..54e4511eb47 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/bosses_mission_cults.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/bosses_mission_cults.lua @@ -1,16 +1,16 @@ -local bossesCults = CreatureEvent("BossesCults") -function bossesCults.onKill(player, creature) - local bosses = { - ["ravenous hunger"] = { storage = Storage.CultsOfTibia.Barkless.Mission, value = 6 }, - ["the souldespoiler"] = { storage = Storage.CultsOfTibia.Misguided.Mission, value = 4 }, - ["essence of malice"] = { storage = Storage.CultsOfTibia.Humans.Mission, value = 2 }, - ["the unarmored voidborn"] = { storage = Storage.CultsOfTibia.Orcs.Mission, value = 2 }, - ["the false god"] = { storage = Storage.CultsOfTibia.Minotaurs.Mission, value = 4 }, - ["the sandking"] = { storage = Storage.CultsOfTibia.Life.Mission, value = 8, global = "sandking", g_value = 5 }, - ["the corruptor of souls"] = { createNew = "The Source Of Corruption", pos = Position(33039, 31922, 15), removeMonster = "zarcorix of yalahar", area1 = Position(33073, 31885, 15), area2 = Position(33075, 31887, 15) }, - ["the source of corruption"] = { storage = Storage.CultsOfTibia.FinalBoss.Mission, value = 2 }, - } +local bosses = { + ["ravenous hunger"] = { storage = Storage.CultsOfTibia.Barkless.Mission, value = 6 }, + ["the souldespoiler"] = { storage = Storage.CultsOfTibia.Misguided.Mission, value = 4 }, + ["essence of malice"] = { storage = Storage.CultsOfTibia.Humans.Mission, value = 2 }, + ["the unarmored voidborn"] = { storage = Storage.CultsOfTibia.Orcs.Mission, value = 2 }, + ["the false god"] = { storage = Storage.CultsOfTibia.Minotaurs.Mission, value = 4 }, + ["the sandking"] = { storage = Storage.CultsOfTibia.Life.Mission, value = 8, global = "sandking", g_value = 5 }, + ["the corruptor of souls"] = { createNew = "The Source Of Corruption", pos = Position(33039, 31922, 15), removeMonster = "zarcorix of yalahar", area1 = Position(33073, 31885, 15), area2 = Position(33075, 31887, 15) }, + ["the source of corruption"] = { storage = Storage.CultsOfTibia.FinalBoss.Mission, value = 2 }, +} +local bossesCults = CreatureEvent("CultsOfTibiaBossDeath") +function bossesCults.onDeath(creature) if not player:isPlayer() then return true end @@ -21,40 +21,36 @@ function bossesCults.onKill(player, creature) local monsterName = creature:getName():lower() local boss = bosses[monsterName] - if boss then - if boss.global and Game.getStorageValue(boss.global) < boss.g_value then - return true - end - if boss.createNew then - Game.setStorageValue("CheckTile", -1) - Game.createMonster(boss.createNew, boss.pos) - if removeMonster then - for _x = boss.area1.x, boss.area2.x, 1 do - for _y = boss.area1.y, boss.area2.y, 1 do - for _z = boss.area1.z, boss.area2.z, 1 do - if Tile(Position(_x, _y, _z)) then - local monster = Tile(Position(_x, _y, _z)):getTopCreature() - if monster and monster:isMonster() and monster:getName():lower() == string.lower(boss.removeMonster) then - monster:remove() - end + if not boss then + return true + end + if boss.global and Game.getStorageValue(boss.global) < boss.g_value then + return true + end + if boss.createNew then + Game.setStorageValue("CheckTile", -1) + Game.createMonster(boss.createNew, boss.pos) + if removeMonster then + for _x = boss.area1.x, boss.area2.x, 1 do + for _y = boss.area1.y, boss.area2.y, 1 do + for _z = boss.area1.z, boss.area2.z, 1 do + if Tile(Position(_x, _y, _z)) then + local monster = Tile(Position(_x, _y, _z)):getTopCreature() + if monster and monster:isMonster() and monster:getName():lower() == string.lower(boss.removeMonster) then + monster:remove() end end end end end - return true - end - for playerid, damage in pairs(creature:getDamageMap()) do - -- broadcastMessage(playerid.." damage:"..damage.total) - local p = Player(playerid) - if p then - -- broadcastMessage(p:getName()) - if p:getStorageValue(boss.storage) < boss.value then - p:setStorageValue(boss.storage, boss.value) - end - end end + return true end + onDeathForDamagingPlayers(creature, function(creature, player) + if player:getStorageValue(boss.storage) < boss.value then + player:setStorageValue(boss.storage, boss.value) + end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/carlin_vortex_spawn.lua b/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/carlin_vortex_spawn.lua index 9b4037c31e3..43c0b4332f0 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/carlin_vortex_spawn.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/carlin_vortex_spawn.lua @@ -1,24 +1,14 @@ -local vortexCarlin = CreatureEvent("VortexCarlin") -function vortexCarlin.onKill(creature, target, item) - if not creature or not creature:isPlayer() then - return true - end - - if not target or not target:isMonster() then - return true - end - - if table.contains({ "cult enforcer", "cult believer", "cult scholar" }, target:getName():lower()) then - local corpsePosition = target:getPosition() - local rand = math.random(32414, 32415) - Game.createItem(rand, 1, corpsePosition):setActionId(5580) - addEvent(function() - local teleport1 = Tile(corpsePosition):getItemById(rand) - if teleport1 then - teleport1:remove(1) - end - end, (1 * 60 * 1000), rand, 1, corpsePosition) - end +local vortexCarlin = CreatureEvent("CarlinVortexDeath") +function vortexCarlin.onDeath(creature) + local corpsePosition = creature:getPosition() + local rand = math.random(32414, 32415) + Game.createItem(rand, 1, corpsePosition):setActionId(5580) + addEvent(function() + local teleport = Tile(corpsePosition):getItemById(rand) + if teleport then + teleport:remove(1) + end + end, (1 * 60 * 1000), rand, 1, corpsePosition) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/destroyed_pillar.lua b/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/destroyed_pillar.lua index 2c2bd08dfc8..a727a877b23 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/destroyed_pillar.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/destroyed_pillar.lua @@ -1,28 +1,21 @@ -local destroyedPillar = CreatureEvent("DestroyedPillar") -function destroyedPillar.onKill(creature, target) - if not creature or not creature:isPlayer() then - return true - end - if not target or not target:isMonster() then - return true - end +local pillar = { + [1] = "pillar of summoning", + [2] = "pillar of death", + [3] = "pillar of protection", + [4] = "pillar of healing", + [5] = "pillar of draining", +} - local pillar = { - [1] = "pillar of summoning", - [2] = "pillar of death", - [3] = "pillar of protection", - [4] = "pillar of healing", - [5] = "pillar of draining", - } - - local monsterName = target:getName():lower() +local destroyedPillar = CreatureEvent("DestroyedPillar") +function destroyedPillar.onDeath(creature) + local monsterName = creature:getName():lower() local summoning = "summoning" local death = "death" local healing = "healing" local protection = "protection" local draining = "draining" for i = 1, #pillar do - local position = target:getPosition() + local position = creature:getPosition() local pilar = "" local newpos = {} pilar = pillar[i] diff --git a/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/essence_of_malice.lua b/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/essence_of_malice.lua index c107bd7957b..207b64345a6 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/essence_of_malice.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/essence_of_malice.lua @@ -1,6 +1,7 @@ -local essenceOfMalice = CreatureEvent("EssenceOfMalice") -function essenceOfMalice.onKill(creature, target) - local boss = { "eshtaba the conjurer", "mezlon the defiler", "eliz the unyielding", "malkhar deathbringer", "dorokoll the mystic" } +local boss = { "eshtaba the conjurer", "mezlon the defiler", "eliz the unyielding", "malkhar deathbringer", "dorokoll the mystic" } + +local essenceOfMalice = CreatureEvent("EssenceOfMaliceSpawnsDeath") +function essenceOfMalice.onDeath(creature) local newBoss = 0 local fromPos = Position(33087, 31909, 15) local toPos = Position(33112, 31932, 15) @@ -19,7 +20,7 @@ function essenceOfMalice.onKill(creature, target) end end end - if table.contains(boss, target:getName():lower()) and newBoss == 1 then + if table.contains(boss, creature:getName():lower()) and newBoss == 1 then Game.createMonster("Essence Of Malice", Position(33098, 31920, 15)) end return true diff --git a/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/glowing_rubbish_amulet.lua b/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/glowing_rubbish_amulet.lua index bdedfae09bb..55a16295bb3 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/glowing_rubbish_amulet.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/glowing_rubbish_amulet.lua @@ -1,43 +1,35 @@ -local glowingRubbishAmulet = CreatureEvent("GlowingRubbishAmulet") -function glowingRubbishAmulet.onKill(creature, killed) - local player = Player(creature) - if not player then - return true - end - - local monster = Monster(killed) - if not monster then - return true - end - - local amulet = player:getSlotItem(CONST_SLOT_NECKLACE) - if not amulet or amulet:getId() ~= 25296 then - return true - end +local glowingRubbishAmulet = CreatureEvent("GlowingRubbishAmuletDeath") +function glowingRubbishAmulet.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + onDeathForParty(creature, mostDamageKiller, function(creature, player) + local amulet = player:getSlotItem(CONST_SLOT_NECKLACE) + if not amulet or amulet:getId() ~= 25296 then + return true + end - if player:getStorageValue(Storage.CultsOfTibia.Misguided.Mission) ~= 3 then - return true - end + if player:getStorageValue(Storage.CultsOfTibia.Misguided.Mission) ~= 3 then + return true + end - local mStg = math.max(player:getStorageValue(Storage.CultsOfTibia.Misguided.Monsters), 0) - local eStg = math.max(player:getStorageValue(Storage.CultsOfTibia.Misguided.Exorcisms), 0) - if monster:getName():lower() == "misguided shadow" then - if eStg < 5 then - player:setStorageValue(Storage.CultsOfTibia.Misguided.Exorcisms, eStg + 1) + local mStg = math.max(player:getStorageValue(Storage.CultsOfTibia.Misguided.Monsters), 0) + local eStg = math.max(player:getStorageValue(Storage.CultsOfTibia.Misguided.Exorcisms), 0) + if monster:getName():lower() == "misguided shadow" then + if eStg < 5 then + player:setStorageValue(Storage.CultsOfTibia.Misguided.Exorcisms, eStg + 1) + end + return true end - return true - end - if monster:getName():lower() == "misguided bully" or monster:getName():lower() == "misguided thief" then - player:setStorageValue(Storage.CultsOfTibia.Misguided.Monsters, mStg + 1) - if player:getStorageValue(Storage.CultsOfTibia.Misguided.Monsters) >= 10 then - amulet:remove() - local it = player:addItem(25297, 1) - if it then - it:decay() + if monster:getName():lower() == "misguided bully" or monster:getName():lower() == "misguided thief" then + player:setStorageValue(Storage.CultsOfTibia.Misguided.Monsters, mStg + 1) + if player:getStorageValue(Storage.CultsOfTibia.Misguided.Monsters) >= 10 then + amulet:remove() + local it = player:addItem(25297, 1) + if it then + it:decay() + end end end - end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/minotaur_task_count.lua b/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/minotaur_task_count.lua index 83c5e2000cc..68f3a0f93a1 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/minotaur_task_count.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/cults_of_tibia/minotaur_task_count.lua @@ -1,17 +1,11 @@ -local minotaurTask = CreatureEvent("MinotaurTask") -function minotaurTask.onKill(creature, target) - if not creature or not creature:isPlayer() then - return true - end - - if not target or not target:isMonster() then - return true - end - - local storage = creature:getStorageValue(Storage.CultsOfTibia.Minotaurs.JamesfrancisTask) - if table.contains({ "minotaur cult follower", "minotaur cult zealot", "minotaur cult prophet" }, target:getName():lower()) and storage >= 0 and storage < 50 then - creature:setStorageValue(Storage.CultsOfTibia.Minotaurs.JamesfrancisTask, storage + 1) - end +local minotaurTask = CreatureEvent("MinotaurCultTaskDeath") +function minotaurTask.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + onDeathForParty(creature, mostDamageKiller, function(creature, player) + local storage = player:getStorageValue(Storage.CultsOfTibia.Minotaurs.JamesfrancisTask) + if storage >= 0 and storage < 50 then + player:setStorageValue(Storage.CultsOfTibia.Minotaurs.JamesfrancisTask, storage + 1) + end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/bosses_mission_depths.lua b/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/bosses_mission_depths.lua index 15d23787b7a..63ffa3c6ffd 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/bosses_mission_depths.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/bosses_mission_depths.lua @@ -1,3 +1,9 @@ +local bosses = { + ["the count of the core"] = { storage = Storage.DangerousDepths.Bosses.TheCountOfTheCore, value = os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN), teleportPosition = Position(33681, 32340, 15), toPosition = Position(33682, 32315, 15), toPositionBack = Position(33324, 32111, 15) }, + ["the duke of the depths"] = { storage = Storage.DangerousDepths.Bosses.TheDukeOfTheDepths, value = os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN), teleportPosition = Position(33719, 32302, 15), toPosition = Position(33691, 32301, 15), toPositionBack = Position(33275, 32318, 15) }, + ["the baron from below"] = { storage = Storage.DangerousDepths.Bosses.TheBaronFromBelow, value = os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN), teleportPosition = Position(33650, 32312, 15), toPosition = Position(33668, 32301, 15), toPositionBack = Position(33462, 32267, 15) }, +} + local function revert(position, toPosition) local teleport = Tile(position):getItemById(22761) if teleport then @@ -6,38 +12,23 @@ local function revert(position, toPosition) end end -local bossesMissionDepth = CreatureEvent("BossesMissionDepth") -function bossesMissionDepth.onKill(creature, creature) - if not creature or not creature:isPlayer() then +local bossesMissionDepth = CreatureEvent("DepthWarzoneBossDeath") +function bossesMissionDepth.onDeath(creature) + local boss = bosses[player:getName():lower()] + if not boss then return true end - - if not target or not target:isMonster() then - return true - end - - local bosses = { - ["the count of the core"] = { stg = Storage.DangerousDepths.Bosses.TheCountOfTheCore, value = os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN), teleportPosition = Position(33681, 32340, 15), toPosition = Position(33682, 32315, 15), toPositionBack = Position(33324, 32111, 15) }, - ["the duke of the depths"] = { stg = Storage.DangerousDepths.Bosses.TheDukeOfTheDepths, value = os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN), teleportPosition = Position(33719, 32302, 15), toPosition = Position(33691, 32301, 15), toPositionBack = Position(33275, 32318, 15) }, - ["the baron from below"] = { stg = Storage.DangerousDepths.Bosses.TheBaronFromBelow, value = os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN), teleportPosition = Position(33650, 32312, 15), toPosition = Position(33668, 32301, 15), toPositionBack = Position(33462, 32267, 15) }, - } - - local boss = bosses[creature:getName():lower()] - if boss then - for playerid, damage in pairs(creature:getDamageMap()) do - local player = Player(playerid) - if player then - if player:getStorageValue(boss.stg) < boss.value then - player:setStorageValue(boss.stg, boss.value) - end - end - end - local teleport = Tile(boss.teleportPosition):getItemById(1949) - if teleport then - teleport:transform(22761) - teleport:setDestination(boss.toPosition) - addEvent(revert, 20 * 60 * 1000, boss.teleportPosition, boss.toPositionBack) + onDeathForDamagingPlayers(creature, function(player, _value) + if player:getStorageValue(boss.storage) < boss.value then + player:setStorageValue(boss.storage, boss.value) end + end) + + local teleport = Tile(boss.teleportPosition):getItemById(1949) + if teleport then + teleport:transform(22761) + teleport:setDestination(boss.toPosition) + addEvent(revert, 20 * 60 * 1000, boss.teleportPosition, boss.toPositionBack) end return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/lost_exile_task.lua b/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/lost_exile_task.lua index ce1062785e0..de627fc2229 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/lost_exile_task.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/lost_exile_task.lua @@ -1,44 +1,53 @@ -local lostExileKill = CreatureEvent("LostExileKill") -function lostExileKill.onKill(creature, target) - if not creature or not creature:isPlayer() then - return true - end +local fromPos = Position(33768, 32227, 14) +local toPos = Position(33781, 32249, 14) - if not target or not target:isMonster() then - return true - end +local lostExileKill = CreatureEvent("LastExileDeath") +function lostExileKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + onDeathForParty(creature, mostDamageKiller, function(creature, player) + if player:getStorageValue(Storage.DangerousDepths.Dwarves.Home) ~= 1 then + return + end + if not creature:getPosition():isInRange(fromPos, toPos) then + return + end + local storage = player:getStorageValue(Storage.DangerousDepths.Dwarves.LostExiles) + if storage < 20 then + if storage < 0 then + player:setStorageValue(Storage.DangerousDepths.Dwarves.LostExiles, 1) + end + player:setStorageValue(Storage.DangerousDepths.Dwarves.LostExiles, storage + 1) + end + end) + return true +end - local fromPos = Position(33768, 32227, 14) - local toPos = Position(33781, 32249, 14) - local monsterName = target:getName():lower() +lostExileKill:register() - local storage = creature:getStorageValue(Storage.DangerousDepths.Dwarves.LostExiles) - local storage2 = creature:getStorageValue(Storage.DangerousDepths.Dwarves.Organisms) - if table.contains({ "lost exile" }, monsterName) then - if creature:getStorageValue(Storage.DangerousDepths.Dwarves.Home) == 1 then - if target:getPosition():isInRange(fromPos, toPos) then - if storage < 20 then - if storage < 0 then - creature:setStorageValue(Storage.DangerousDepths.Dwarves.LostExiles, 1) - end - creature:setStorageValue(Storage.DangerousDepths.Dwarves.LostExiles, storage + 1) - end - end +local wormKill = CreatureEvent("WarzoneWormDeath") +function wormKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + local storage = player:getStorageValue(Storage.DangerousDepths.Dwarves.Organisms) + onDeathForParty(creature, mostDamageKiller, function(creature, player) + if player:getStorageValue(Storage.DangerousDepths.Dwarves.Subterranean) ~= 1 then + return end - elseif table.contains({ "deepworm", "diremaw" }, monsterName) then - if creature:getStorageValue(Storage.DangerousDepths.Dwarves.Subterranean) == 1 then - if storage2 < 50 then - if storage2 < 0 then - creature:setStorageValue(Storage.DangerousDepths.Dwarves.Organisms, 1) - end - creature:setStorageValue(Storage.DangerousDepths.Dwarves.Organisms, storage2 + 1) + if storage < 50 then + if storage < 0 then + player:setStorageValue(Storage.DangerousDepths.Dwarves.Organisms, 1) end + player:setStorageValue(Storage.DangerousDepths.Dwarves.Organisms, storage + 1) end - elseif table.contains({ "makeshift home" }, monsterName) then - local woodenTrash = Game.createItem(398, 1, target:getPosition()) - woodenTrash:setActionId(57233) - end + end) + return true end -lostExileKill:register() +wormKill:register() + +local makeshiftKill = CreatureEvent("MakeshiftHomeDeath") +function makeshiftKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + local woodenTrash = Game.createItem(398, 1, creature:getPosition()) + woodenTrash:setActionId(57233) + return true +end + +makeshiftKill:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/snail_slime_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/snail_slime_kill.lua index c6886b27128..2134758a8e5 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/snail_slime_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/snail_slime_kill.lua @@ -27,20 +27,17 @@ end combat:setCallback(CALLBACK_PARAM_TARGETTILE, "onTargetTile") local function summonSlimes(master) - local contador = 0 + local count = 0 local slimeCheck = Game.getSpectators(master:getPosition(), false, false, 20, 20, 20, 20) for _, slime in pairs(slimeCheck) do if slime:isMonster() then if slime:getName():lower() == "snail slime" then - contador = contador + 1 + count = count + 1 end end end - if contador < 3 then - local summon = Game.createMonster("Snail Slime", master:getPosition(), true) - if summon then - summon:registerEvent("SnailSlimeKill") - end + if count < 3 then + Game.createMonster("Snail Slime", master:getPosition(), true) end end @@ -60,24 +57,11 @@ end snailSlimeThink:register() -local snailSlimeKill = CreatureEvent("SnailSlimeKill") -function snailSlimeKill.onKill(player, creature) - if not player:isPlayer() then - return true - end - if not creature:isMonster() or creature:getMaster() then - return true - end - - local monsterName = creature:getName():lower() - if monsterName == "snail slime" then - if not creature then - return - end - creature:say("!!", TALKTYPE_ORANGE_2) - local var = { type = 1, number = creature:getId() } - combat:execute(creature, var) - end +local snailSlimeKill = CreatureEvent("SnailSlimeDeath") +function snailSlimeKill.onDeath(creature) + creature:say("!!", TALKTYPE_ORANGE_2) + local var = { type = 1, number = creature:getId() } + combat:execute(creature, var) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/the_baron_from_below.lua b/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/the_baron_from_below.lua index be3bcca38cd..22963bfb56b 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/the_baron_from_below.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/dangerous_depths/the_baron_from_below.lua @@ -9,8 +9,8 @@ local function summonHungry(creature) monster:addHealth(-(monster:getHealth() - oldBossHealth)) monster:teleportTo(Position(33648, 32300, 15)) local organicMatter = Game.createMonster("organic matter", Position(33647, 32300, 15), true, true) - if organicMatter then - organicMatter:registerEvent("OrganicMatterKill") + if not organicMatter then + return false end if monster and monster:getName():lower() == "the hungry baron from below" then monster:addHealth(-(monster:getHealth() - oldBossHealth)) @@ -52,34 +52,18 @@ end local theBaronFromBelowThink = CreatureEvent("TheBaronFromBelowThink") function theBaronFromBelowThink.onThink(creature) - if not creature:isMonster() then - return true - end - - if creature:getName():lower() == "the baron from below" then - if not timers[creature:getId()] then - timers[creature:getId()] = addEvent(summonHungry, 30 * 1000, creature:getId()) - end + if not timers[creature:getId()] then + timers[creature:getId()] = addEvent(summonHungry, 30 * 1000, creature:getId()) end return true end theBaronFromBelowThink:register() -local organicMatterKill = CreatureEvent("OrganicMatterKill") -function organicMatterKill.onKill(player, creature) - if not player:isPlayer() then - return true - end - - if not creature:isMonster() then - return true - end - - if creature:getName():lower() == "organic matter" then - for i = 1, 4 do - Game.createMonster("aggressive matter", creature:getPosition(), true, false) - end +local organicMatterKill = CreatureEvent("OrganicMatterDeath") +function organicMatterKill.onDeath(creature) + for i = 1, 4 do + Game.createMonster("aggressive matter", creature:getPosition(), true, false) end end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/dark_trails/kill_death_priest_shargon.lua b/data-otservbr-global/scripts/creaturescripts/quests/dark_trails/kill_death_priest_shargon.lua index 489c033bc33..1cd88f5243c 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/dark_trails/kill_death_priest_shargon.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/dark_trails/kill_death_priest_shargon.lua @@ -15,23 +15,21 @@ local function removeTeleport(position) end end -local deathPriestShargon = CreatureEvent("ShargonKill") -function deathPriestShargon.onKill(creature, target) - if target:isPlayer() or target:getMaster() or target:getName():lower() ~= "death priest shargon" then - return true - end - - local position = target:getPosition() +local deathPriestShargon = CreatureEvent("ShargonDeath") +function deathPriestShargon.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + local position = creature:getPosition() position:sendMagicEffect(CONST_ME_TELEPORT) local item = Game.createItem(config.teleportId, 1, config.teleportPosition) if item:isTeleport() then item:setDestination(config.destinationPosition) end - if config.storageKey ~= nil then - if creature:getStorageValue(config.storageKey) < config.getStorageValue then - creature:setStorageValue(config.storageKey, config.setStorageValue) + onDeathForParty(creature, mostDamageKiller, function(creature, player) + if config.storageKey ~= nil then + if player:getStorageValue(config.storageKey) < config.getStorageValue then + player:setStorageValue(config.storageKey, config.setStorageValue) + end end - end + end) addEvent(removeTeleport, 5 * 60 * 1000, position) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/dark_trails/kill_the_ravager.lua b/data-otservbr-global/scripts/creaturescripts/quests/dark_trails/kill_the_ravager.lua index 0cc355f90c9..97798dadfeb 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/dark_trails/kill_the_ravager.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/dark_trails/kill_the_ravager.lua @@ -6,21 +6,19 @@ local function removeTeleport(position) end end -local theRavager = CreatureEvent("TheRavager") -function theRavager.onKill(creature, target) - if target:isPlayer() or target:getMaster() or target:getName():lower() ~= "the ravager" then - return true - end - - local position = target:getPosition() +local theRavager = CreatureEvent("TheRavagerDeath") +function theRavager.onDeath(player, creature) + local position = creature:getPosition() position:sendMagicEffect(CONST_ME_TELEPORT) local item = Game.createItem(1949, 1, { x = 33496, y = 32070, z = 8 }) if item:isTeleport() then item:setDestination(Position(33459, 32083, 8)) end - if creature:getStorageValue(Storage.DarkTrails.Mission11) < 1 then - creature:setStorageValue(Storage.DarkTrails.Mission11, 1) - end + onDeathForDamagingPlayers(creature, function(creature, player) + if player:getStorageValue(Storage.DarkTrails.Mission11) < 1 then + player:setStorageValue(Storage.DarkTrails.Mission11, 1) + end + end) addEvent(removeTeleport, 5 * 60 * 1000, position) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/dawnport/goblin_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/dawnport/goblin_kill.lua index 9d847279991..3464d10e90e 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/dawnport/goblin_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/dawnport/goblin_kill.lua @@ -1,17 +1,11 @@ -local goblinKill = CreatureEvent("MorrisGoblinKill") -function goblinKill.onKill(player, target) - if target:isPlayer() or target:getMaster() then - return true - end - - if target:getName():lower() ~= "muglex clan footman" then - return true - end - - local killAmount = player:getStorageValue(Storage.Quest.U10_55.Dawnport.MorrisGoblinCount) - if player:getStorageValue(Storage.Quest.U10_55.Dawnport.MorrisGoblin) == 1 and killAmount < 20 then - player:setStorageValue(Storage.Quest.U10_55.Dawnport.MorrisGoblinCount, killAmount + 1) - end +local goblinKill = CreatureEvent("MorrisGoblinDeath") +function goblinKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + onDeathForParty(creature, mostDamageKiller, function(creature, player) + local killAmount = player:getStorageValue(Storage.Quest.U10_55.Dawnport.MorrisGoblinCount) + if player:getStorageValue(Storage.Quest.U10_55.Dawnport.MorrisGoblin) == 1 and killAmount < 20 then + player:setStorageValue(Storage.Quest.U10_55.Dawnport.MorrisGoblinCount, killAmount + 1) + end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/dawnport/minotaur_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/dawnport/minotaur_kill.lua index f1b11b45895..dd8718aa0ee 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/dawnport/minotaur_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/dawnport/minotaur_kill.lua @@ -1,17 +1,11 @@ -local minotaurKill = CreatureEvent("MorrisMinotaurKill") -function minotaurKill.onKill(player, target) - if target:isPlayer() or target:getMaster() then - return true - end - - if target:getName():lower() ~= "minotaur bruiser" then - return true - end - - local killAmount = player:getStorageValue(Storage.Quest.U10_55.Dawnport.MorrisMinosCount) - if player:getStorageValue(Storage.Quest.U10_55.Dawnport.MorrisMinos) == 1 and killAmount < 20 then - player:setStorageValue(Storage.Quest.U10_55.Dawnport.MorrisMinosCount, killAmount + 1) - end +local minotaurKill = CreatureEvent("MorrisMinotaurDeath") +function minotaurKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + onDeathForParty(creature, mostDamageKiller, function(creature, player) + local killAmount = player:getStorageValue(Storage.Quest.U10_55.Dawnport.MorrisMinosCount) + if player:getStorageValue(Storage.Quest.U10_55.Dawnport.MorrisMinos) == 1 and killAmount < 20 then + player:setStorageValue(Storage.Quest.U10_55.Dawnport.MorrisMinosCount, killAmount + 1) + end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/dawnport/troll_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/dawnport/troll_kill.lua index 6e43a8a5e79..ce7fbeeb252 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/dawnport/troll_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/dawnport/troll_kill.lua @@ -1,17 +1,11 @@ -local trollKill = CreatureEvent("MorrisTrollKill") -function trollKill.onKill(player, target) - if target:isPlayer() or target:getMaster() then - return true - end - - if target:getName():lower() ~= "mountain troll" then - return true - end - - local killAmount = player:getStorageValue(Storage.Quest.U10_55.Dawnport.MorrisTrollCount) - if player:getStorageValue(Storage.Quest.U10_55.Dawnport.MorriskTroll) == 1 and killAmount < 20 then - player:setStorageValue(Storage.Quest.U10_55.Dawnport.MorrisTrollCount, killAmount + 1) - end +local trollKill = CreatureEvent("MorrisTrollDeath") +function trollKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + onDeathForParty(creature, mostDamageKiller, function(creature, player) + local killAmount = player:getStorageValue(Storage.Quest.U10_55.Dawnport.MorrisTrollCount) + if player:getStorageValue(Storage.Quest.U10_55.Dawnport.MorriskTroll) == 1 and killAmount < 20 then + player:setStorageValue(Storage.Quest.U10_55.Dawnport.MorrisTrollCount, killAmount + 1) + end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/elemental_spheres/overlord_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/elemental_spheres/overlord_kill.lua index 206923c3328..2d5b7b98f91 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/elemental_spheres/overlord_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/elemental_spheres/overlord_kill.lua @@ -6,13 +6,9 @@ local overlords = { ["lord of the elements"] = {}, } -local elementalSpheresOver = CreatureEvent("OverlordKill") -function elementalSpheresOver.onKill(creature, target) - if not target:isMonster() then - return true - end - - local bossName = target:getName() +local elementalSpheresOver = CreatureEvent("ElementalOverlordDeath") +function elementalSpheresOver.onDeath(creature) + local bossName = creature:getName() local bossConfig = overlords[bossName:lower()] if not bossConfig then return true @@ -21,12 +17,17 @@ function elementalSpheresOver.onKill(creature, target) if bossConfig.globalStorage then Game.setStorageValue(bossConfig.globalStorage, 0) end - - if bossConfig.storage and creature:getStorageValue(bossConfig.storage) < 1 then - creature:setStorageValue(bossConfig.storage, 1) + if not bossConfig.storage then + return true end - creature:say("You slayed " .. bossName .. ".", TALKTYPE_MONSTER_SAY) + onDeathForDamagingPlayers(creature, function(creature, player) + if player:getStorageValue(bossConfig.storage) < 1 then + player:setStorageValue(bossConfig.storage, 1) + end + player:say("You slayed " .. bossName .. ".", TALKTYPE_MONSTER_SAY) + end) + return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/bosses_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/bosses_kill.lua index b0a2f27aba5..9babbd3a0ed 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/bosses_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/bosses_kill.lua @@ -41,27 +41,19 @@ local function revertTeleport(position, itemId, transformId, destination) end local ascendantBossesKill = CreatureEvent("AscendantBossesKill") -function ascendantBossesKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster or targetMonster:getMaster() then - return true - end - - local bossConfig = bosses[targetMonster:getName():lower()] +function ascendantBossesKill.onDeath(creature) + local bossConfig = bosses[creature:getName():lower()] if not bossConfig then return true end - for player, _ in pairs(targetMonster:getDamageMap()) do - local attackerPlayer = Player(player) - if attackerPlayer then - if targetMonster:getName():lower() == "ferumbras mortal shell" then - attackerPlayer:setBossCooldown(targetMonster:getName(), os.time() + 60 * 60 * 14 * 24) - elseif targetMonster:getName():lower() == "the lord of the lice" then - attackerPlayer:setStorageValue(Storage.FerumbrasAscension.TheLordOfTheLiceAccess, 1) - end + onDeathForDamagingPlayers(creature, function(creature, player) + if creature:getName():lower() == "ferumbras mortal shell" then + player:setBossCooldown(creature:getName(), os.time() + 60 * 60 * 14 * 24) + elseif creature:getName():lower() == "the lord of the lice" then + player:setStorageValue(Storage.FerumbrasAscension.TheLordOfTheLiceAccess, 1) end - end + end) local teleport = Tile(bossConfig.teleportPos):getItemById(1949) if not teleport then @@ -70,12 +62,12 @@ function ascendantBossesKill.onKill(creature, target) if teleport then teleport:transform(22761) - targetMonster:getPosition():sendMagicEffect(CONST_ME_THUNDER) + creature:getPosition():sendMagicEffect(CONST_ME_THUNDER) teleport:setDestination(bossConfig.godbreakerPos) addEvent(revertTeleport, 2 * 60 * 1000, bossConfig.teleportPos, 22761, 1949, Position(33319, 32318, 13)) end - if targetMonster:getName():lower() == "ferumbras mortal shell" then + if creature:getName():lower() == "ferumbras mortal shell" then addEvent(transformCrystal, 2 * 60 * 1000) end return true diff --git a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/the_shatterer_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/the_shatterer_kill.lua index 3267107d8f5..a132bf68f17 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/the_shatterer_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/the_shatterer_kill.lua @@ -45,12 +45,14 @@ local chains = { [7] = { itemid = 2126, position = Position(33406, 32421, 14) }, }, } + local levers = { [1] = { position = Position(33385, 32410, 14) }, [2] = { position = Position(33403, 32391, 14) }, [3] = { position = Position(33430, 32418, 14) }, [4] = { position = Position(33410, 32441, 14) }, } + local function revert() for i = 1, #chains.West do local chainWest = chains.West[i] @@ -77,27 +79,20 @@ local function revert() end end -local theShattererKill = CreatureEvent("TheShattererKill") -function theShattererKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster or targetMonster:getMaster() or targetMonster:getName():lower() ~= "the shatterer" then - return true - end - for pid, _ in pairs(targetMonster:getDamageMap()) do - local attackerPlayer = Player(pid) - if attackerPlayer then - if targetMonster:getName():lower() == "the shatterer" then - attackerPlayer:setStorageValue(Storage.FerumbrasAscension.TheShatterer, 1) - end - end - end +local teleportPos = Position(33393, 32438, 14) +local newPos = Position(33436, 32443, 15) + +local theShattererKill = CreatureEvent("TheShattererDeath") +function theShattererKill.onDeath(creature) + onDeathForDamagingPlayers(creature, function(creature, player) + player:setStorageValue(Storage.FerumbrasAscension.TheShatterer, 1) + end) + local teleport = Tile(Position(33393, 32438, 14)):getItemById(1949) if not teleport then return true end local oldPos = teleport:getDestination() - local teleportPos = Position(33393, 32438, 14) - local newPos = Position(33436, 32443, 15) if teleport then teleport:transform(22761) targetMonster:getPosition():sendMagicEffect(CONST_ME_THUNDER) diff --git a/data-otservbr-global/scripts/creaturescripts/quests/firewalker_boots/pythius_the_rotten_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/firewalker_boots/pythius_the_rotten_kill.lua index 43543a8cbd7..d1c3f1e7232 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/firewalker_boots/pythius_the_rotten_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/firewalker_boots/pythius_the_rotten_kill.lua @@ -1,11 +1,8 @@ -local firewalkerBootsKill = CreatureEvent("PythiusTheRottenKill") -function firewalkerBootsKill.onKill(player, target) - if not target:isMonster() or target:getName():lower() ~= "pythius the rotten" then - return true - end - - target:say("NICE FIGHTING LITTLE WORM, YOUR VICTORY SHALL BE REWARDED!", TALKTYPE_MONSTER_SAY, false, player, Position(32572, 31405, 15)) +local firewalkerBootsKill = CreatureEvent("PythiusTheRottenDeath") +function firewalkerBootsKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + creature:say("NICE FIGHTING LITTLE WORM, YOUR VICTORY SHALL BE REWARDED!", TALKTYPE_MONSTER_SAY, false, player, Position(32572, 31405, 15)) + local player = Player(mostDamageKiller) player:teleportTo(Position(32577, 31403, 15)) player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) return true diff --git a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/bosses_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/bosses_kill.lua index 047da278310..cf573ea81d7 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/bosses_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/bosses_kill.lua @@ -13,38 +13,32 @@ local bosses = { ["an astral glyph"] = {}, } -local bossesForgottenKill = CreatureEvent("BossesForgottenKill") -function bossesForgottenKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster or targetMonster:getMaster() then - return true - end - +local bossesForgottenKill = CreatureEvent("ForgottenKnowledgeBossDeath") +function bossesForgottenKill.onDeath(creature) local bossConfig = bosses[targetMonster:getName():lower()] if not bossConfig then return true end - for key, value in pairs(targetMonster:getDamageMap()) do - local attackerPlayer = Player(key) - if attackerPlayer then - if bossConfig.storage then - attackerPlayer:setStorageValue(bossConfig.storage, os.time() + 20 * 3600) - elseif targetMonster:getName():lower() == "the enraged thorn knight" then - attackerPlayer:setStorageValue(Storage.ForgottenKnowledge.PlantCounter, 0) - attackerPlayer:setStorageValue(Storage.ForgottenKnowledge.BirdCounter, 0) - elseif targetMonster:getName():lower() == "melting frozen horror" then - local egg = Tile(Position(32269, 31084, 14)):getTopCreature() - if egg then - local pos = egg:getPosition() - egg:remove() - Game.createMonster("baby dragon", pos, true, true) - end - local horror = Tile(Position(32267, 31071, 14)):getTopCreature() - if horror then - horror:remove() - end - end + onDeathForDamagingPlayers(creature, function(creature, player) + if bossConfig.storage then + player:setStorageValue(bossConfig.storage, os.time() + 20 * 3600) + elseif targetMonster:getName():lower() == "the enraged thorn knight" then + player:setStorageValue(Storage.ForgottenKnowledge.PlantCounter, 0) + player:setStorageValue(Storage.ForgottenKnowledge.BirdCounter, 0) + end + end) + + if targetMonster:getName():lower() == "melting frozen horror" then + local egg = Tile(Position(32269, 31084, 14)):getTopCreature() + if egg then + local pos = egg:getPosition() + egg:remove() + Game.createMonster("baby dragon", pos, true, true) + end + local horror = Tile(Position(32267, 31071, 14)):getTopCreature() + if horror then + horror:remove() end end return true diff --git a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/bound_astral_power.lua b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/bound_astral_power.lua index c0c327f92ab..3709d5c559a 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/bound_astral_power.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/bound_astral_power.lua @@ -5,31 +5,21 @@ local positions = { [4] = { pos = Position(31995, 32856, 15), nextPos = Position(31975, 32856, 15) }, } -local astralPower = CreatureEvent("AstralPower") -function astralPower.onKill(creature, target) - local player = creature:getPlayer() - if not player then - return true - end - - local targetMonster = target:getMonster() - if not targetMonster or targetMonster:getMaster() then - return true - end - - local bossConfig = targetMonster:getName():lower() == "bound astral power" - if not bossConfig then - return true - end +local astralPower = CreatureEvent("BoundAstralPowerDeath") +function astralPower.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) Game.setStorageValue(GlobalStorage.ForgottenKnowledge.AstralPowerCounter, Game.getStorageValue(GlobalStorage.ForgottenKnowledge.AstralPowerCounter) + 1) if Game.getStorageValue(GlobalStorage.ForgottenKnowledge.AstralPowerCounter) >= 4 then Game.setStorageValue(GlobalStorage.ForgottenKnowledge.AstralPowerCounter, 1) end local msg = "The destruction of the power source gained you more time until the glyph is powered up!" + local player = Player(mostDamageKiller) + if not player then + return true + end for i = 1, #positions do - if creature:getPosition():getDistance(positions[i].pos) < 7 then - target:say(msg, TALKTYPE_MONSTER_SAY, false, nil, positions[i].pos) + if player:getPosition():getDistance(positions[i].pos) < 7 then + creature:say(msg, TALKTYPE_MONSTER_SAY, false, nil, positions[i].pos) Game.createMonster("bound astral power", positions[i].nextPos, true, true) Game.setStorageValue(GlobalStorage.ForgottenKnowledge.AstralGlyph, 1) addEvent(Game.setStorageValue, 1 * 60 * 1000, GlobalStorage.ForgottenKnowledge.AstralGlyph, 0) diff --git a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/energy_prism.lua b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/energy_prism.lua index 52ac5e0dc7f..c6611448f83 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/energy_prism.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/energy_prism.lua @@ -1,4 +1,4 @@ -local energyPrism = CreatureEvent("EnergyPrism") +local energyPrism = CreatureEvent("EnergyPrismHealthChange") function energyPrism.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) if not Tile(Position(32799, 32826, 14)):getTopCreature() then if creature:getHealth() < creature:getMaxHealth() then diff --git a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/energy_prism_death.lua b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/energy_prism_death.lua index ecdc212f69a..140362d92b3 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/energy_prism_death.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/energy_prism_death.lua @@ -1,6 +1,5 @@ local energyPrismDeath = CreatureEvent("EnergyPrismDeath") - -function energyPrismDeath.onKill(creature, target) +function energyPrismDeath.onDeath(creature) stopEvent(Storage.ForgottenKnowledge.LloydEvent) local tile = Tile(Position(32799, 32826, 14)) if not tile then diff --git a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/replica_servants.lua b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/replica_servants.lua index 6c8811a29fc..f15ee99f3a1 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/replica_servants.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/replica_servants.lua @@ -8,18 +8,8 @@ local servants = { playerStorage = Storage.ForgottenKnowledge.DiamondServantCounter, }, } -local replicaServant = CreatureEvent("ReplicaServant") -function replicaServant.onKill(creature, target) - local player = creature:getPlayer() - if not player then - return true - end - - local targetMonster = target:getMonster() - if not targetMonster or targetMonster:getMaster() then - return true - end - +local replicaServant = CreatureEvent("ReplicaServantDeath") +function replicaServant.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) local bossConfig = servants[targetMonster:getName():lower()] if not bossConfig then return true @@ -36,6 +26,10 @@ function replicaServant.onKill(creature, target) end end end + local player = Player(mostDamageKiller) + if not player then + return true + end if player:getStorageValue(bossConfig.playerStorage) < 0 then player:setStorageValue(bossConfig.playerStorage, 0) end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/hero_of_rathleton/bosses_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/hero_of_rathleton/bosses_kill.lua index 99478b3b603..db11a05fd13 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/hero_of_rathleton/bosses_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/hero_of_rathleton/bosses_kill.lua @@ -45,12 +45,8 @@ local function revertTeleport(position, itemId, transformId, destination) end end -local rathletonBossKill = CreatureEvent("RathletonBossKill") -function rathletonBossKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not target or not targetMonster or targetMonster:getMaster() then - return true - end +local rathletonBossKill = CreatureEvent("RathletonBossDeath") +function rathletonBossKill.onDeath(creature) local bossConfig = bosses[targetMonster:getName():lower()] if not bossConfig then return true diff --git a/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/azerus_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/azerus_kill.lua index d150950da65..478dafc6e68 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/azerus_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/azerus_kill.lua @@ -6,13 +6,8 @@ local function removeTeleport(position) end end -local azerus = CreatureEvent("Azerus") -function azerus.onKill(creature, target) - local targetMonster = target:getMonster() - if not target or not targetMonster or targetMonster:getName():lower() ~= "azerus" then - return true - end - +local azerus = CreatureEvent("AzerusDeath") +function azerus.onDeath(creature) local position = targetMonster:getPosition() position:sendMagicEffect(CONST_ME_TELEPORT) local item = Game.createItem(1949, 1, position) diff --git a/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/diseased_trio_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/diseased_trio_kill.lua index d0d92ac7c08..7c020aec611 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/diseased_trio_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/diseased_trio_kill.lua @@ -4,27 +4,23 @@ local diseasedTrio = { ["diseased fred"] = Storage.InServiceofYalahar.DiseasedFred, } -local diseasedTrioKill = CreatureEvent("DiseasedTrio") -function diseasedTrioKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - +local diseasedTrioKill = CreatureEvent("DiseasedTrioDeath") +function diseasedTrioKill.onDeath(creature) local bossStorage = diseasedTrio[targetMonster:getName():lower()] if not bossStorage then return true end - local player = creature:getPlayer() - if player:getStorageValue(bossStorage) < 1 then - player:setStorageValue(bossStorage, 1) - player:say("You slayed " .. targetMonster:getName() .. ".", TALKTYPE_MONSTER_SAY) - end + onDeathForDamagingPlayers(creature, function(creature, player) + if player:getStorageValue(bossStorage) < 1 then + player:setStorageValue(bossStorage, 1) + player:say("You slayed " .. targetMonster:getName() .. ".", TALKTYPE_MONSTER_SAY) + end - if player:getStorageValue(Storage.InServiceofYalahar.DiseasedDan) == 1 and player:getStorageValue(Storage.InServiceofYalahar.DiseasedBill) == 1 and player:getStorageValue(Storage.InServiceofYalahar.DiseasedFred) == 1 and player:getStorageValue(Storage.InServiceofYalahar.AlchemistFormula) ~= 1 then - player:setStorageValue(Storage.InServiceofYalahar.AlchemistFormula, 0) - end + if player:getStorageValue(Storage.InServiceofYalahar.DiseasedDan) == 1 and player:getStorageValue(Storage.InServiceofYalahar.DiseasedBill) == 1 and player:getStorageValue(Storage.InServiceofYalahar.DiseasedFred) == 1 and player:getStorageValue(Storage.InServiceofYalahar.AlchemistFormula) ~= 1 then + player:setStorageValue(Storage.InServiceofYalahar.AlchemistFormula, 0) + end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/quara_leader_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/quara_leader_kill.lua index 51eb420a80f..91f2faeb951 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/quara_leader_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/quara_leader_kill.lua @@ -4,27 +4,23 @@ local quaraLeaders = { ["splasher"] = Storage.InServiceofYalahar.QuaraSplasher, } -local quaraLeadersKill = CreatureEvent("QuaraLeaders") -function quaraLeadersKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - local bossStorage = quaraLeaders[targetMonster:getName():lower()] +local quaraLeadersKill = CreatureEvent("QuaraLeadersDeath") +function quaraLeadersKill.onDeath(creature) + local bossStorage = quaraLeaders[creature:getName():lower()] if not bossStorage then return true end - local player = creature:getPlayer() - if player:getStorageValue(bossStorage) < 1 then - player:setStorageValue(bossStorage, 1) - player:say("You slayed " .. targetMonster:getName() .. ".", TALKTYPE_MONSTER_SAY) - player:setStorageValue(Storage.InServiceofYalahar.QuaraState, 2) - player:setStorageValue(Storage.InServiceofYalahar.Questline, 41) - -- StorageValue for Questlog 'Mission 07: A Fishy Mission' - player:setStorageValue(Storage.InServiceofYalahar.Mission07, 4) - end + onDeathForDamagingPlayers(creature, function(creature, player) + if player:getStorageValue(bossStorage) < 1 then + player:setStorageValue(bossStorage, 1) + player:say("You slayed " .. creature:getName() .. ".", TALKTYPE_MONSTER_SAY) + player:setStorageValue(Storage.InServiceofYalahar.QuaraState, 2) + player:setStorageValue(Storage.InServiceofYalahar.Questline, 41) + -- StorageValue for Questlog 'Mission 07: A Fishy Mission' + player:setStorageValue(Storage.InServiceofYalahar.Mission07, 4) + end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/inquisition/inquisition_boss.lua b/data-otservbr-global/scripts/creaturescripts/quests/inquisition/inquisition_boss.lua index e2b15b60137..21546e005ad 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/inquisition/inquisition_boss.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/inquisition/inquisition_boss.lua @@ -8,14 +8,9 @@ local bosses = { ["hellgorak"] = 205, } -local inquisitionBossKill = CreatureEvent("InquisitionBossKill") -function inquisitionBossKill.onKill(player, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - local targetName = targetMonster:getName():lower() +local inquisitionBossKill = CreatureEvent("InquisitionBossDeath") +function inquisitionBossKill.onDeath(creature) + local targetName = creature:getName():lower() local bossStorage = bosses[targetName] if not bossStorage then return true @@ -28,7 +23,9 @@ function inquisitionBossKill.onKill(player, target) Game.setStorageValue(bossStorage, newValue) if newValue == 2 then - player:say("You now have 10 minutes to exit this room through the teleporter. It will bring you to the next room.", TALKTYPE_MONSTER_SAY) + onDeathForDamagingPlayers(creature, function(creature, player) + player:say("You now have 10 minutes to exit this room through the teleporter. It will bring you to the next room.", TALKTYPE_MONSTER_SAY) + end) addEvent(Game.setStorageValue, 10 * 60 * 1000, bossStorage, 0) end return true diff --git a/data-otservbr-global/scripts/creaturescripts/quests/inquisition/inquisition_ungreez.lua b/data-otservbr-global/scripts/creaturescripts/quests/inquisition/inquisition_ungreez.lua index 22cdf8b76fb..6859446d9d4 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/inquisition/inquisition_ungreez.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/inquisition/inquisition_ungreez.lua @@ -1,15 +1,9 @@ -local ungreezKill = CreatureEvent("UngreezKill") -function ungreezKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then +local ungreezKill = CreatureEvent("UngreezDeath") +function ungreezKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + local player = Player(mostDamageKiller) + if not player then return true end - - if targetMonster:getName():lower() ~= "ungreez" then - return true - end - - local player = creature:getPlayer() if player:getStorageValue(Storage.TheInquisition.Questline) == 18 then -- The Inquisition Questlog- 'Mission 6: The Demon Ungreez' player:setStorageValue(Storage.TheInquisition.Mission06, 2) diff --git a/data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/boss_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/boss_kill.lua new file mode 100644 index 00000000000..9fa65883199 --- /dev/null +++ b/data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/boss_kill.lua @@ -0,0 +1,68 @@ +local taskBoss = { + [0] = "the snapper", + [1] = "hide", + [2] = "deathbine", + [3] = "the bloodtusk", + [4] = "shardhead", + [5] = "esmeralda", + [6] = "fleshcrawler", + [7] = "ribstride", + [8] = "the bloodweb", + [9] = "thul", + [10] = "the old widow", + [11] = "hemming", + [12] = "tormentor", + [13] = "flameborn", + [14] = "fazzrah", + [15] = "tromphonyte", + [16] = "sulphur scuttler", + [17] = "bruise payne", + [18] = "the many", + [19] = "the noxious spawn", + [20] = "gorgo", + [21] = "stonecracker", + [22] = "leviathan", + [23] = "kerberos", + [24] = "ethershreck", + [25] = "paiz the pauperizer", + [26] = "bretzecutioner", + [27] = "zanakeph", + [28] = "tiquandas revenge", + [29] = "demodras", + [30] = "necropharus", + [31] = "the horned fox", +} + +local bossKillCount = Storage.Quest.U8_5.KillingInTheNameOf.BossKillCount.SnapperCount + +local deathEvent = CreatureEvent("KillingInTheNameOfBossDeath") +function deathEvent.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + local targetName = creature:getName():lower() + + onDeathForParty(creature, mostDamageKiller, function(creature, player) + for i, bossName in ipairs(taskBoss) do + if targetName == bossName then + if player:getStorageValue(bossKillCount + i) == 0 then + player:setStorageValue(bossKillCount + i, 1) + end + return true + end + end + end) + return true +end + +deathEvent:register() + +local serverstartup = GlobalEvent("KillingInTheNameOfBossDeathStartup") +function serverstartup.onStartup() + for _, bossName in pairs(taskBoss) do + local mType = MonsterType(bossName) + if not mType then + logger.error("[KillingInTheNameOfBossDeathStartup] boss with name {} is not a valid MonsterType", bossName) + else + mType:registerEvent("KillingInTheNameOfBossDeath") + end + end +end +serverstartup:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/kill.lua deleted file mode 100644 index 254e72273d4..00000000000 --- a/data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/kill.lua +++ /dev/null @@ -1,121 +0,0 @@ -local taskBoss = { - [0] = "the snapper", - [1] = "hide", - [2] = "deathbine", - [3] = "the bloodtusk", - [4] = "shardhead", - [5] = "esmeralda", - [6] = "fleshcrawler", - [7] = "ribstride", - [8] = "the bloodweb", - [9] = "thul", - [10] = "the old widow", - [11] = "hemming", - [12] = "tormentor", - [13] = "flameborn", - [14] = "fazzrah", - [15] = "tromphonyte", - [16] = "sulphur scuttler", - [17] = "bruise payne", - [18] = "the many", - [19] = "the noxious spawn", - [20] = "gorgo", - [21] = "stonecracker", - [22] = "leviathan", - [23] = "kerberos", - [24] = "ethershreck", - [25] = "paiz the pauperizer", - [26] = "bretzecutioner", - [27] = "zanakeph", - [28] = "tiquandas revenge", - [29] = "demodras", - [30] = "necropharus", - [31] = "the horned fox", -} -local function killCheck(player, targetName, taskName, taskStage, taskInfo, taskAltKillCount, taskkillCount) - if player:getStorageValue(taskName) == taskStage then - if table.contains(taskInfo, targetName) then - for k = 1, #taskInfo do - if taskAltKillCount ~= nil and targetName == taskInfo[k] then - player:setStorageValue(taskAltKillCount + k - 1, player:getStorageValue(taskAltKillCount + k - 1) + 1) - end - end - player:setStorageValue(taskkillCount, player:getStorageValue(taskkillCount) + 1) - player:setStorageValue(taskName, player:getStorageValue(taskName)) -- fake update quest tracker - end - end -end -local killCounter = Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.KillCount -local BossKillCount = Storage.Quest.U8_5.KillingInTheNameOf.BossKillCount.SnapperCount -local killingInTheNameOfKill = CreatureEvent("KillingInTheNameOfKill") -function killingInTheNameOfKill.onKill(player, target) - if target:isPlayer() or target:getMaster() then - return true - end - local targetName, startedTasks, taskId = target:getName():lower(), player:getStartedTasks() - for i = 1, #startedTasks do - taskId = startedTasks[i] - if table.contains(tasks.GrizzlyAdams[taskId].creatures, targetName) then - if #tasks.GrizzlyAdams[taskId].creatures > 1 then - for a = 1, #tasks.GrizzlyAdams[taskId].creatures do - if targetName == tasks.GrizzlyAdams[taskId].creatures[a] then - if tasks.GrizzlyAdams[taskId].raceName == "Apes" then - local apes = Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.KongraCount + a - 1 - player:setStorageValue(apes, player:getStorageValue(apes) + 1) - elseif tasks.GrizzlyAdams[taskId].raceName == "Quara Scouts" then - local scouts = Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.QuaraConstrictorScoutCount + a - 1 - player:setStorageValue(scouts, player:getStorageValue(scouts) + 1) - elseif tasks.GrizzlyAdams[taskId].raceName == "Underwater Quara" then - local underwater = Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.QuaraConstrictorCount + a - 1 - player:setStorageValue(underwater, player:getStorageValue(underwater) + 1) - elseif tasks.GrizzlyAdams[taskId].raceName == "Nightmares" then - local nightmares = Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.NightmareCount + a - 1 - player:setStorageValue(nightmares, player:getStorageValue(nightmares) + 1) - elseif tasks.GrizzlyAdams[taskId].raceName == "High Class Lizards" then - local lizards = Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.LizardChosenCount + a - 1 - player:setStorageValue(lizards, player:getStorageValue(lizards) + 1) - elseif tasks.GrizzlyAdams[taskId].raceName == "Sea Serpents" then - local serpents = Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.SeaSerpentCount + a - 1 - player:setStorageValue(serpents, player:getStorageValue(serpents) + 1) - elseif tasks.GrizzlyAdams[taskId].raceName == "Drakens" then - local drakens = Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.DrakenAbominationCount + a - 1 - player:setStorageValue(drakens, player:getStorageValue(drakens) + 1) - end - end - end - end - local killAmount = player:getStorageValue(killCounter + taskId) - player:setStorageValue(killCounter + taskId, killAmount + 1) - player:setStorageValue(KILLSSTORAGE_BASE + taskId, player:getStorageValue(KILLSSTORAGE_BASE + taskId)) -- fake update quest tracker - end - end - for j = 0, #taskBoss do - if targetName == taskBoss[j] then - if player:getStorageValue(BossKillCount + j) == 0 then - player:setStorageValue(BossKillCount + j, 1) - end - end - end - -- Minotaurs - killCheck(player, targetName, Storage.KillingInTheNameOf.BudrikMinos, 0, tasks.Budrik[1].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.MinotaurCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.MinotaurCount) - -- Necromancers and Priestesses - killCheck(player, targetName, Storage.KillingInTheNameOf.LugriNecromancers, 0, tasks.Lugri[1].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.NecromancerCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.NecromancerCount) - killCheck(player, targetName, Storage.KillingInTheNameOf.LugriNecromancers, 3, tasks.Lugri[1].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.NecromancerCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.NecromancerCount) - -- Green Djinns or Efreets - killCheck(player, targetName, Storage.KillingInTheNameOf.GreenDjinnTask, 0, tasks.Gabel[1].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.GreenDjinnCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.GreenDjinnCount) - -- Blue Djinns or Marids - killCheck(player, targetName, Storage.KillingInTheNameOf.BlueDjinnTask, 0, tasks.Malor[1].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.BlueDjinnCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.BlueDjinnCount) - -- Pirates - killCheck(player, targetName, Storage.KillingInTheNameOf.PirateTask, 0, tasks.RaymondStriker[1].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.PirateMarauderCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.PirateCount) - -- Trolls - killCheck(player, targetName, Storage.KillingInTheNameOf.TrollTask, 0, tasks.DanielSteelsoul[1].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.TrollCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.TrollCount) - -- Goblins - killCheck(player, targetName, Storage.KillingInTheNameOf.GoblinTask, 0, tasks.DanielSteelsoul[2].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.GoblinCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.GoblinCount) - -- Rotworms - killCheck(player, targetName, Storage.KillingInTheNameOf.RotwormTask, 0, tasks.DanielSteelsoul[3].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.RotwormCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.RotwormCount) - -- Cyclops - killCheck(player, targetName, Storage.KillingInTheNameOf.CyclopsTask, 0, tasks.DanielSteelsoul[4].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.CyclopsCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.CyclopsCount) - return true -end - -killingInTheNameOfKill:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/monster_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/monster_kill.lua new file mode 100644 index 00000000000..01b1648c25b --- /dev/null +++ b/data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/monster_kill.lua @@ -0,0 +1,111 @@ +local function killCheck(player, targetName, taskName, taskStage, taskInfo, taskAltKillCount, taskkillCount) + if player:getStorageValue(taskName) == taskStage then + if table.contains(taskInfo, targetName) then + for k = 1, #taskInfo do + if taskAltKillCount ~= nil and targetName == taskInfo[k] then + player:setStorageValue(taskAltKillCount + k - 1, player:getStorageValue(taskAltKillCount + k - 1) + 1) + end + end + player:setStorageValue(taskkillCount, player:getStorageValue(taskkillCount) + 1) + player:setStorageValue(taskName, player:getStorageValue(taskName)) -- fake update quest tracker + end + end +end + +local killCounter = Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.KillCount + +local deathEvent = CreatureEvent("KillingInTheNameOfMonsterDeath") +function deathEvent.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + local targetName = creature:getName():lower() + + onDeathForParty(creature, mostDamageKiller, function(creature, player) + local startedTasks, taskId = player:getStartedTasks() + for i = 1, #startedTasks do + taskId = startedTasks[i] + if table.contains(tasks.GrizzlyAdams[taskId].creatures, targetName) then + if #tasks.GrizzlyAdams[taskId].creatures > 1 then + for a = 1, #tasks.GrizzlyAdams[taskId].creatures do + if targetName == tasks.GrizzlyAdams[taskId].creatures[a] then + if tasks.GrizzlyAdams[taskId].raceName == "Apes" then + local apes = Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.KongraCount + a - 1 + player:setStorageValue(apes, player:getStorageValue(apes) + 1) + elseif tasks.GrizzlyAdams[taskId].raceName == "Quara Scouts" then + local scouts = Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.QuaraConstrictorScoutCount + a - 1 + player:setStorageValue(scouts, player:getStorageValue(scouts) + 1) + elseif tasks.GrizzlyAdams[taskId].raceName == "Underwater Quara" then + local underwater = Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.QuaraConstrictorCount + a - 1 + player:setStorageValue(underwater, player:getStorageValue(underwater) + 1) + elseif tasks.GrizzlyAdams[taskId].raceName == "Nightmares" then + local nightmares = Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.NightmareCount + a - 1 + player:setStorageValue(nightmares, player:getStorageValue(nightmares) + 1) + elseif tasks.GrizzlyAdams[taskId].raceName == "High Class Lizards" then + local lizards = Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.LizardChosenCount + a - 1 + player:setStorageValue(lizards, player:getStorageValue(lizards) + 1) + elseif tasks.GrizzlyAdams[taskId].raceName == "Sea Serpents" then + local serpents = Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.SeaSerpentCount + a - 1 + player:setStorageValue(serpents, player:getStorageValue(serpents) + 1) + elseif tasks.GrizzlyAdams[taskId].raceName == "Drakens" then + local drakens = Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.DrakenAbominationCount + a - 1 + player:setStorageValue(drakens, player:getStorageValue(drakens) + 1) + end + end + end + end + local killAmount = player:getStorageValue(killCounter + taskId) + player:setStorageValue(killCounter + taskId, killAmount + 1) + player:setStorageValue(KILLSSTORAGE_BASE + taskId, player:getStorageValue(KILLSSTORAGE_BASE + taskId)) -- fake update quest tracker + end + end + -- Minotaurs + killCheck(player, targetName, Storage.KillingInTheNameOf.BudrikMinos, 0, tasks.Budrik[1].creatures, nil, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.MinotaurCount) + -- Necromancers and Priestesses + killCheck(player, targetName, Storage.KillingInTheNameOf.LugriNecromancers, 0, tasks.Lugri[1].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.NecromancerCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.NecromancerCount) + killCheck(player, targetName, Storage.KillingInTheNameOf.LugriNecromancers, 3, tasks.Lugri[1].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.NecromancerCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.NecromancerCount) + -- Green Djinns or Efreets + killCheck(player, targetName, Storage.KillingInTheNameOf.GreenDjinnTask, 0, tasks.Gabel[1].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.GreenDjinnCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.GreenDjinnCount) + -- Blue Djinns or Marids + killCheck(player, targetName, Storage.KillingInTheNameOf.BlueDjinnTask, 0, tasks.Malor[1].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.BlueDjinnCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.BlueDjinnCount) + -- Pirates + killCheck(player, targetName, Storage.KillingInTheNameOf.PirateTask, 0, tasks.RaymondStriker[1].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.PirateMarauderCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.PirateCount) + -- Trolls + killCheck(player, targetName, Storage.KillingInTheNameOf.TrollTask, 0, tasks.DanielSteelsoul[1].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.TrollCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.TrollCount) + -- Goblins + killCheck(player, targetName, Storage.KillingInTheNameOf.GoblinTask, 0, tasks.DanielSteelsoul[2].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.GoblinCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.GoblinCount) + -- Rotworms + killCheck(player, targetName, Storage.KillingInTheNameOf.RotwormTask, 0, tasks.DanielSteelsoul[3].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.RotwormCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.RotwormCount) + -- Cyclops + killCheck(player, targetName, Storage.KillingInTheNameOf.CyclopsTask, 0, tasks.DanielSteelsoul[4].creatures, Storage.Quest.U8_5.KillingInTheNameOf.AltKillCount.CyclopsCount, Storage.Quest.U8_5.KillingInTheNameOf.MonsterKillCount.CyclopsCount) + end) + return true +end + +deathEvent:register() + +local serverstartup = GlobalEvent("KillingInTheNameOfMonsterDeathStartup") +function serverstartup.onStartup() + logger.info("[KillingInTheNameOfMonsterDeathStartup] registering monsters") + local monsters = Set({}, { insensitive = true }) + for _, task in pairs(tasks.GrizzlyAdams) do + monsters = monsters:union(task.creatures) + end + + monsters = monsters:union(tasks.Budrik[1].creatures) + monsters = monsters:union(tasks.Lugri[1].creatures) + monsters = monsters:union(tasks.Gabel[1].creatures) + monsters = monsters:union(tasks.Malor[1].creatures) + monsters = monsters:union(tasks.RaymondStriker[1].creatures) + monsters = monsters:union(tasks.DanielSteelsoul[1].creatures) + monsters = monsters:union(tasks.DanielSteelsoul[2].creatures) + monsters = monsters:union(tasks.DanielSteelsoul[3].creatures) + monsters = monsters:union(tasks.DanielSteelsoul[4].creatures) + + for monster in monsters:iter() do + local mType = MonsterType(monster) + if not mType then + logger.error("[KillingInTheNameOfMonsterDeathStartup] monster with name {} is not a valid MonsterType", monster) + else + mType:registerEvent("KillingInTheNameOfMonsterDeath") + end + end +end +serverstartup:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/bragrumol.lua b/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/bragrumol.lua index 9310a34737c..02846ec6cfd 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/bragrumol.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/bragrumol.lua @@ -1,16 +1,11 @@ -local bragrumol = CreatureEvent("BragrumolKill") +local bragrumol = CreatureEvent("BragrumolDeath") -function bragrumol.onKill(cid, target, damage, flags, corpse) - if isMonster(target) then - if string.lower(getCreatureName(target)) == "bragrumol" then - for attackerUid, damage in pairs(target:getDamageMap()) do - local player = Player(attackerUid) - if player and player:getStorageValue(Storage.Kilmaresh.Twelve.Bragrumol) == 1 then - player:setStorageValue(Storage.Kilmaresh.Twelve.Bragrumol, 2) - end - end +function bragrumol.onDeath(creature) + onDeathForDamagingPlayers(creature, function(creature, player) + if player:getStorageValue(Storage.Kilmaresh.Twelve.Bragrumol) == 1 then + player:setStorageValue(Storage.Kilmaresh.Twelve.Bragrumol, 2) end - end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/fafnar.lua b/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/fafnar.lua index 157b2302848..4d94f0e6d3b 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/fafnar.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/fafnar.lua @@ -3,22 +3,25 @@ local monster = { ["priestess of the wild sun"] = Storage.Kilmaresh.Thirteen.Fafnar, } -local fafnar = CreatureEvent("FafnarKill") +local fafnar = CreatureEvent("FafnarMissionsDeath") -function fafnar.onKill(creature, target) - local storage = monster[target:getName():lower()] - if target:isPlayer() or target:getMaster() or not storage then +function fafnar.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + local storage = monster[creature:getName():lower()] + if not storage then return false end - local kills = creature:getStorageValue(storage) - if kills == 300 and creature:getStorageValue(storage) == 1 then - creature:say("You slayed " .. target:getName() .. ".", TALKTYPE_MONSTER_SAY) - else - kills = kills + 1 - creature:say("You have slayed " .. target:getName() .. " " .. kills .. " times!", TALKTYPE_MONSTER_SAY) - creature:setStorageValue(storage, kills) - end + onDeathForParty(creature, mostDamageKiller, function(creature, player) + local kills = player:getStorageValue(storage) + if kills == 300 and player:getStorageValue(storage) == 1 then + player:say("You slayed " .. creature:getName() .. ".", TALKTYPE_MONSTER_SAY) + else + kills = kills + 1 + player:say("You have slayed " .. creature:getName() .. " " .. kills .. " times!", TALKTYPE_MONSTER_SAY) + player:setStorageValue(storage, kills) + end + end) + return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/mozradek.lua b/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/mozradek.lua index e87fef037eb..23507b878b0 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/mozradek.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/mozradek.lua @@ -1,16 +1,11 @@ -local mozradek = CreatureEvent("MozradekKill") +local mozradek = CreatureEvent("MozradekDeath") -function mozradek.onKill(cid, target, damage, flags, corpse) - if isMonster(target) then - if string.lower(getCreatureName(target)) == "mozradek" then - for attackerUid, damage in pairs(target:getDamageMap()) do - local player = Player(attackerUid) - if player and player:getStorageValue(Storage.Kilmaresh.Twelve.Mozradek) == 1 then - player:setStorageValue(Storage.Kilmaresh.Twelve.Mozradek, 2) - end - end +function mozradek.onDeath(creature) + onDeathForDamagingPlayers(creature, function(creature, player) + if player:getStorageValue(Storage.Kilmaresh.Twelve.Mozradek) == 1 then + player:setStorageValue(Storage.Kilmaresh.Twelve.Mozradek, 2) end - end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/xogixath.lua b/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/xogixath.lua index d9e2dba2e5e..cbfe0daeb3b 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/xogixath.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/kilmaresh/xogixath.lua @@ -1,16 +1,11 @@ -local xogixath = CreatureEvent("XogixathKill") +local xogixath = CreatureEvent("XogixathDeath") -function xogixath.onKill(cid, target, damage, flags, corpse) - if isMonster(target) then - if string.lower(getCreatureName(target)) == "xogixath" then - for attackerUid, damage in pairs(target:getDamageMap()) do - local player = Player(attackerUid) - if player and player:getStorageValue(Storage.Kilmaresh.Twelve.Xogixath) == 1 then - player:setStorageValue(Storage.Kilmaresh.Twelve.Xogixath, 2) - end - end +function xogixath.onDeath(creature) + onDeathForDamagingPlayers(creature, function(creature, player) + if player:getStorageValue(Storage.Kilmaresh.Twelve.Xogixath) == 1 then + player:setStorageValue(Storage.Kilmaresh.Twelve.Xogixath, 2) end - end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/liquid_black/deepling_boss_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/liquid_black/deepling_boss_kill.lua index 369d57155ca..6916f3dfa5a 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/liquid_black/deepling_boss_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/liquid_black/deepling_boss_kill.lua @@ -4,27 +4,19 @@ local bosses = { ["obujos"] = { status = 4, storage = Storage.DeeplingBosses.Obujos }, } -local deeplingBosses = CreatureEvent("DeeplingBosses") -function deeplingBosses.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - local bossConfig = bosses[targetMonster:getName():lower()] +local deeplingBosses = CreatureEvent("DeeplingBossDeath") +function deeplingBosses.onDeath(player, creature) + local bossConfig = bosses[creature:getName():lower()] if not bossConfig then return true end - for pid, _ in pairs(targetMonster:getDamageMap()) do - local attackerPlayer = Player(pid) - if attackerPlayer then - if attackerPlayer:getStorageValue(Storage.DeeplingBosses.DeeplingStatus) < bossConfig.status then - attackerPlayer:setStorageValue(Storage.DeeplingBosses.DeeplingStatus, bossConfig.status) - end - attackerPlayer:setStorageValue(bossConfig.storage, 1) + onDeathForDamagingPlayers(creature, function(creature, player) + if player:getStorageValue(Storage.DeeplingBosses.DeeplingStatus) < bossConfig.status then + player:setStorageValue(Storage.DeeplingBosses.DeeplingStatus, bossConfig.status) end - end + player:setStorageValue(bossConfig.storage, 1) + end) end deeplingBosses:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/energized_raging_mage_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/energized_raging_mage_kill.lua index 95cf707a712..d04b37bf6ee 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/energized_raging_mage_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/energized_raging_mage_kill.lua @@ -1,13 +1,5 @@ -local energizedRagingMageKill = CreatureEvent("EnergizedRagingMageKill") -function energizedRagingMageKill.onKill(player, creature, damage, flags) - if not creature or not creature:isMonster() then - return true - end - - if creature:getName():lower() ~= "energized raging mage" then - return true - end - +local deathEvent = CreatureEvent("EnergizedRagingMageDeath") +function deathEvent.onDeath(creature) if getGlobalStorageValue(673003) < 2000 then return true end @@ -15,10 +7,10 @@ function energizedRagingMageKill.onKill(player, creature, damage, flags) local monster = Game.createMonster("Raging Mage", creature:getPosition()) monster:setReward(true) - doCreatureSayWithRadius(player, "GNAAAAAHRRRG!! WHAT? WHAT DID YOU DO TO ME!! I... I feel the energies crawling away... from me... DIE!!!", TALKTYPE_ORANGE_1, 35, 71) + doCreatureSayWithRadius(creature, "GNAAAAAHRRRG!! WHAT? WHAT DID YOU DO TO ME!! I... I feel the energies crawling away... from me... DIE!!!", TALKTYPE_ORANGE_1, 35, 71) setGlobalStorageValue(673003, 0) return true end -energizedRagingMageKill:register() +deathEvent:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/raging_mage_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/raging_mage_kill.lua index a99341b7eaa..a24f174f5e7 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/raging_mage_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/raging_mage_kill.lua @@ -1,26 +1,20 @@ -local ragingMageKill = CreatureEvent("ragingMageKill") +local deathEvent = CreatureEvent("RagingMageDeath") -function ragingMageKill.onKill(cid, target, damage, flags, corpse) - if not target or type(target) ~= "userdata" or not target:isMonster() then - return true - end +function deathEvent.onDeath(creature) + broadcastMessage("The remains of the Raging Mage are scattered on the floor of his Tower. The dimensional portal quakes.", MESSAGE_EVENT_ADVANCE) + doCreatureSay(creature, "I WILL RETURN!! My death will just be a door to await my homecoming, my physical hull will be... my... argh...", TALKTYPE_ORANGE_1) - if target:getName():lower() == "raging mage" then - broadcastMessage("The remains of the Raging Mage are scattered on the floor of his Tower. The dimensional portal quakes.", MESSAGE_EVENT_ADVANCE) - doCreatureSay(target, "I WILL RETURN!! My death will just be a door to await my homecoming, my physical hull will be... my... argh...", TALKTYPE_ORANGE_1) - - addEvent(function() - broadcastMessage("With a great bang the dimensional portal in Zao collapsed and with it the connection to the other dimension shattered.", MESSAGE_EVENT_ADVANCE) - local tile = Tile(Position({ x = 33143, y = 31527, z = 2 })) - if tile then - local item = tile:getItemById(11796) - if item then - item:remove(1) - end + addEvent(function() + broadcastMessage("With a great bang the dimensional portal in Zao collapsed and with it the connection to the other dimension shattered.", MESSAGE_EVENT_ADVANCE) + local tile = Tile(Position({ x = 33143, y = 31527, z = 2 })) + if tile then + local item = tile:getItemById(11796) + if item then + item:remove(1) end - end, 5 * 60 * 1000) - end + end + end, 5 * 60 * 1000) return true end -ragingMageKill:register() +deathEvent:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/yielothax_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/yielothax_kill.lua index c22332db7a2..8ff28ceb824 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/yielothax_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/yielothax_kill.lua @@ -1,10 +1,6 @@ -local yielothaxKill = CreatureEvent("YielothaxKill") -function yielothaxKill.onKill(cid, target, damage, flags) - if isMonster(target) then - if string.lower(getCreatureName(target)) == "yielothax" then - setGlobalStorageValue(673003, getGlobalStorageValue(673003) + 1) - end - end +local yielothaxKill = CreatureEvent("YielothaxDeath") +function yielothaxKill.onDeath(creature) + setGlobalStorageValue(673003, getGlobalStorageValue(673003) + 1) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/secret_service/black_knight_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/secret_service/black_knight_kill.lua index 611de73ce09..d63dac6a194 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/secret_service/black_knight_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/secret_service/black_knight_kill.lua @@ -1,19 +1,10 @@ -local blackKnightKill = CreatureEvent("BlackKnightKill") -function blackKnightKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - if targetMonster:getName():lower() ~= "black knight" then - return true - end - - local player = creature:getPlayer() - if player:getStorageValue(Storage.SecretService.AVINMission04) == 1 then - player:setStorageValue(Storage.SecretService.AVINMission04, 2) - end - +local blackKnightKill = CreatureEvent("BlackKnightDeath") +function blackKnightKill.onDeath(creature) + onDeathForDamagingPlayers(creature, function(creature, player) + if player:getStorageValue(Storage.SecretService.AVINMission04) == 1 then + player:setStorageValue(Storage.SecretService.AVINMission04, 2) + end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/spike_tasks/lower_spike_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/spike_tasks/lower_spike_kill.lua index 02282ff3f37..16c79963c42 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/spike_tasks/lower_spike_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/spike_tasks/lower_spike_kill.lua @@ -4,20 +4,23 @@ local range = { to = Position(32345, 32710, 15), } -local lowerSpikeKill = CreatureEvent("LowerSpikeKill") -function lowerSpikeKill.onKill(creature, target) - if not table.contains({ -1, 7 }, creature:getStorageValue(SPIKE_LOWER_KILL_MAIN)) then - if creature:getPosition():isInRange(range.from, range.to) then - if target:isMonster() and (target:getMaster() == nil) and (target:getName():lower() == "drillworm") then - local sum = creature:getStorageValue(SPIKE_LOWER_KILL_MAIN) + 1 - creature:setStorageValue(SPIKE_LOWER_KILL_MAIN, sum) - creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have slayed " .. sum .. " out of 7 Drillworms.") - if sum == 7 then - creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Report the task to Gnomargery.") - end +local lowerSpikeKill = CreatureEvent("LowerSpikeDeath") +function lowerSpikeKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + if not creature:getPosition():isInRange(range.from, range.to) then + return true + end + + onDeathForParty(creature, mostDamageKiller, function(creature, player) + if not table.contains({ -1, 7 }, player:getStorageValue(SPIKE_LOWER_KILL_MAIN)) then + local sum = player:getStorageValue(SPIKE_LOWER_KILL_MAIN) + 1 + player:setStorageValue(SPIKE_LOWER_KILL_MAIN, sum) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have slayed " .. sum .. " out of 7 Drillworms.") + if sum == 7 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Report the task to Gnomargery.") end end - end + end) + return true end lowerSpikeKill:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/spike_tasks/middle_spike_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/spike_tasks/middle_spike_kill.lua index f5f8e0b673f..2dd6017d106 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/spike_tasks/middle_spike_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/spike_tasks/middle_spike_kill.lua @@ -4,20 +4,22 @@ local range = { to = Position(32380, 32725, 12), } -local middleSpikeKill = CreatureEvent("MiddleSpikeKill") -function middleSpikeKill.onKill(creature, target) - if not table.contains({ -1, 7 }, creature:getStorageValue(SPIKE_MIDDLE_KILL_MAIN)) then - if creature:getPosition():isInRange(range.from, range.to) then - if target:isMonster() and (target:getMaster() == nil) and (target:getName():lower() == "crystalcrusher") then - local sum = creature:getStorageValue(SPIKE_MIDDLE_KILL_MAIN) + 1 - creature:setStorageValue(SPIKE_MIDDLE_KILL_MAIN, sum) - creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have slayed " .. sum .. " out of 7 Crystalcrushers.") - if sum == 7 then - creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Report the task to Gnombold.") - end +local middleSpikeKill = CreatureEvent("MiddleSpikeDeath") +function middleSpikeKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + if not creature:getPosition():isInRange(range.from, range.to) then + return true + end + onDeathForParty(creature, mostDamageKiller, function(creature, player) + if not table.contains({ -1, 7 }, player:getStorageValue(SPIKE_MIDDLE_KILL_MAIN)) then + local sum = player:getStorageValue(SPIKE_MIDDLE_KILL_MAIN) + 1 + player:setStorageValue(SPIKE_MIDDLE_KILL_MAIN, sum) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have slayed " .. sum .. " out of 7 Crystalcrushers.") + if sum == 7 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Report the task to Gnombold.") end end - end + end) + return true end middleSpikeKill:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/spike_tasks/upper_spike_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/spike_tasks/upper_spike_kill.lua index d06f4e2c94f..96f9dc6b397 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/spike_tasks/upper_spike_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/spike_tasks/upper_spike_kill.lua @@ -4,20 +4,23 @@ local range = { to = Position(32365, 32759, 10), } -local upperSpikeKill = CreatureEvent("UpperSpikeKill") -function upperSpikeKill.onKill(creature, target) - if not table.contains({ -1, 7 }, creature:getStorageValue(SPIKE_UPPER_KILL_MAIN)) then - if creature:getPosition():isInRange(range.from, range.to) then - if target:isMonster() and (target:getMaster() == nil) and (target:getName():lower() == "demon skeleton") then - local sum = creature:getStorageValue(SPIKE_UPPER_KILL_MAIN) + 1 - creature:setStorageValue(SPIKE_UPPER_KILL_MAIN, sum) - creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have slayed " .. sum .. " out of 7 Demon Skeletons.") - if sum == 7 then - creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Report the task to Gnomilly.") - end +local upperSpikeKill = CreatureEvent("UpperSpikeDeath") +function upperSpikeKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + if not creature:getPosition():isInRange(range.from, range.to) then + return false + end + + onDeathForParty(creature, mostDamageKiller, function(creature, player) + if not table.contains({ -1, 7 }, player:getStorageValue(SPIKE_UPPER_KILL_MAIN)) then + local sum = player:getStorageValue(SPIKE_UPPER_KILL_MAIN) + 1 + player:setStorageValue(SPIKE_UPPER_KILL_MAIN, sum) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have slayed " .. sum .. " out of 7 Demon Skeletons.") + if sum == 7 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Report the task to Gnomilly.") end end - end + end) + return true end upperSpikeKill:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/svargrond_arena/arena_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/svargrond_arena/arena_kill.lua index 7798c4b3738..674dc5d27d5 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/svargrond_arena/arena_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/svargrond_arena/arena_kill.lua @@ -1,11 +1,10 @@ -local svargrondArenaKill = CreatureEvent("SvargrondArenaKill") -function svargrondArenaKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return +local deathEvent = CreatureEvent("SvargrondArenaBossDeath") +function deathEvent.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + local player = Player(mostDamageKiller) + if not player then + return true end - local player = creature:getPlayer() local pit = player:getStorageValue(Storage.SvargrondArena.PitDoor) if pit < 1 or pit > 10 then return @@ -16,7 +15,7 @@ function svargrondArenaKill.onKill(creature, target) return end - if not table.contains(ARENA[arena].creatures, targetMonster:getName():lower()) then + if not table.contains(ARENA[arena].creatures, creature:getName():lower()) then return end @@ -40,4 +39,19 @@ function svargrondArenaKill.onKill(creature, target) return true end -svargrondArenaKill:register() +deathEvent:register() + +local serverstartup = GlobalEvent("SvargrondArenaBossDeathStartup") +function serverstartup.onStartup() + for _, arena in pairs(ARENA) do + for _, bossName in pairs(arena.creatures) do + local mType = MonsterType(bossName) + if not mType then + logger.error("[SvargrondArenaBossDeathStartup] boss with name {} is not a valid MonsterType", bossName) + else + mType:registerEvent("SvargrondArenaBossDeath") + end + end + end +end +serverstartup:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_first_dragon/kill_dragon.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_first_dragon/kill_dragon.lua index eae77dc5437..55045c65e9d 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_first_dragon/kill_dragon.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_first_dragon/kill_dragon.lua @@ -1,18 +1,12 @@ -local killDragon = CreatureEvent("KillDragon") +local killDragon = CreatureEvent("TheFirstDragonDragonTaskDeath") -function killDragon.onKill(player, target) - if target:isPlayer() or target:getMaster() then - return true - end - if target:getName():lower() == "dragon" then +function killDragon.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + onDeathForParty(creature, mostDamageKiller, function(creature, player) local storage = player:getStorageValue(Storage.FirstDragon.DragonCounter) if storage >= 0 and storage < 200 then player:setStorageValue(Storage.FirstDragon.DragonCounter, player:getStorageValue(Storage.FirstDragon.DragonCounter) + 1) end - end - if player:getStorageValue(Storage.FirstDragon.TazhadurTimer) >= os.time() then - return true - end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_ice_islands/husky_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_ice_islands/husky_kill.lua index 3103f924e44..b5a3f4c4dff 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_ice_islands/husky_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_ice_islands/husky_kill.lua @@ -1,13 +1,10 @@ -local huskyKill = CreatureEvent("HuskyKill") +local huskyKill = CreatureEvent("HuskyDeath") -function huskyKill.onKill(player, target) - if target:isPlayer() or target:getMaster() then - return true - end - - if target:getName():lower() == "husky" then - player:setStorageValue(Storage.TheIceIslands.HuskyKill, player:getStorageValue(Storage.TheIceIslands.HuskyKill) + 1) - end +function huskyKill.onDeath(creature) + onDeathForDamagingPlayers(creature, function(creature, player) + local value = player:getStorageValue(Storage.TheIceIslands.HuskyKill) or 0 + player:setStorageValue(Storage.TheIceIslands.HuskyKill, value + 1) + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua index 2f5af644afa..3cafb041e31 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua @@ -1,29 +1,21 @@ local thePrimalMenaceDeath = CreatureEvent("ThePrimalMenaceDeath") -function thePrimalMenaceDeath.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) - if not creature then - return - end - +function thePrimalMenaceDeath.onDeath(creature) local damageMap = creature:getMonster():getDamageMap() local hazard = Hazard.getByName("hazard.gnomprona-gardens") if not hazard then return end local _, hazardPoints = hazard:getHazardPlayerAndPoints(damageMap) + onDeathForDamagingPlayers(creature, function(creature, player) + if player:getStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled) < 1 then + player:setStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled, 1) + end - for key, value in pairs(damageMap) do - local player = Player(key) - if player then - if player:getStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled) < 1 then - player:setStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled, 1) - end - - if hazard:getPlayerMaxLevel(player) == hazardPoints then - hazard:levelUp(player) - end + if hazard:getPlayerMaxLevel(player) == hazardPoints then + hazard:levelUp(player) end - end + end) end thePrimalMenaceDeath:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/thieves_guild/nomad_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/thieves_guild/nomad_kill.lua index 1bf05869998..6f9c3d32547 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/thieves_guild/nomad_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/thieves_guild/nomad_kill.lua @@ -1,19 +1,10 @@ -local nomadKill = CreatureEvent("NomadKill") -function nomadKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - if targetMonster:getName():lower() ~= "nomad" then - return true - end - - local player = creature:getPlayer() - if player:getStorageValue(Storage.ThievesGuild.Mission04) == 3 then - player:setStorageValue(Storage.ThievesGuild.Mission04, 4) - end - +local nomadKill = CreatureEvent("NomadDeath") +function nomadKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + onDeathForParty(creature, mostDamageKiller, function(creature, player) + if player:getStorageValue(Storage.ThievesGuild.Mission04) == 3 then + player:setStorageValue(Storage.ThievesGuild.Mission04, 4) + end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/bosses_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/bosses_kill.lua index 2cb2db29438..37a823a67ac 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/bosses_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/bosses_kill.lua @@ -17,14 +17,9 @@ local bosses = { }, } -local bossesKill = CreatureEvent("BossesKill") -function bossesKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - local bossConfig = bosses[targetMonster:getName():lower()] +local bossesKill = CreatureEvent("WrathOfTheEmperorBossDeat") +function bossesKill.onDeath(creature) + local bossConfig = bosses[creature:getName():lower()] if not bossConfig then return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/keeper_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/keeper_kill.lua index f43204ce59c..5be3f6f6dbe 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/keeper_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/keeper_kill.lua @@ -1,13 +1,6 @@ -local keeperKill = CreatureEvent("KeeperKill") -function keeperKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - if targetMonster:getName():lower() == "the keeper" then - Game.setStorageValue(Storage.WrathoftheEmperor.Mission03, 0) - end +local keeperKill = CreatureEvent("TheKeeperDeath") +function keeperKill.onDeath(creature) + Game.setStorageValue(Storage.WrathoftheEmperor.Mission03, 0) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/lizard_magistratus_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/lizard_magistratus_kill.lua index e526a699b20..8be99184fda 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/lizard_magistratus_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/lizard_magistratus_kill.lua @@ -1,20 +1,11 @@ -local lizardMagistratusKill = CreatureEvent("LizardMagistratusKill") -function lizardMagistratusKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - if targetMonster:getName():lower() ~= "lizard magistratus" then - return true - end - - local player = creature:getPlayer() - local storage = player:getStorageValue(Storage.WrathoftheEmperor.Mission06) - if storage >= 0 and storage < 4 then - player:setStorageValue(Storage.WrathoftheEmperor.Mission06, math.max(1, storage) + 1) - end - +local lizardMagistratusKill = CreatureEvent("LizardMagistratusDeath") +function lizardMagistratusKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + onDeathForParty(creature, mostDamageKiller, function(creature, player) + local storage = player:getStorageValue(Storage.WrathoftheEmperor.Mission06) + if storage >= 0 and storage < 4 then + player:setStorageValue(Storage.WrathoftheEmperor.Mission06, math.max(1, storage) + 1) + end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/lizard_noble_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/lizard_noble_kill.lua index ab45524fba1..112feffa73f 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/lizard_noble_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/lizard_noble_kill.lua @@ -1,20 +1,11 @@ -local lizardNobleKill = CreatureEvent("LizardNobleKill") -function lizardNobleKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - if targetMonster:getName():lower() ~= "lizard noble" then - return true - end - - local player = creature:getPlayer() - local storage = player:getStorageValue(Storage.WrathoftheEmperor.Mission07) - if storage >= 0 and storage < 6 then - player:setStorageValue(Storage.WrathoftheEmperor.Mission07, math.max(1, storage) + 1) - end - +local lizardNobleKill = CreatureEvent("LizardNobleDeath") +function lizardNobleKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + onDeathForParty(creature, mostDamageKiller, function(creature, player) + local storage = player:getStorageValue(Storage.WrathoftheEmperor.Mission07) + if storage >= 0 and storage < 6 then + player:setStorageValue(Storage.WrathoftheEmperor.Mission07, math.max(1, storage) + 1) + end + end) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/zalamon_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/zalamon_kill.lua index 143049aaece..349c704ca64 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/zalamon_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/wrath_of_the_emperor/zalamon_kill.lua @@ -13,26 +13,21 @@ local bossForms = { }, } -local zalamonKill = CreatureEvent("ZalamonKill") -function zalamonKill.onKill(player, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - if targetMonster:getName():lower() == "mutated zalamon" then +local zalamonKill = CreatureEvent("ZalamonDeath") +function zalamonKill.onDeath(creature) + if creature:getName():lower() == "mutated zalamon" then Game.setStorageValue(Storage.WrathoftheEmperor.Mission11, -1) return true end - local name = targetMonster:getName():lower() + local name = creature:getName():lower() local bossConfig = bossForms[name] if not bossConfig then return true end local found = false - for k, v in ipairs(Game.getSpectators(targetMonster:getPosition())) do + for k, v in ipairs(Game.getSpectators(creature:getPosition())) do if v:getName():lower() == bossConfig.newForm then found = true break @@ -40,8 +35,10 @@ function zalamonKill.onKill(player, target) end if not found then - Game.createMonster(bossConfig.newForm, targetMonster:getPosition(), false, true) - player:say(bossConfig.text, TALKTYPE_MONSTER_SAY) + local monster = Game.createMonster(bossConfig.newForm, creature:getPosition(), false, true) + if monster then + monster:say(bossConfig.text, TALKTYPE_MONSTER_SAY) + end end return true end diff --git a/data-otservbr-global/scripts/hazard/primal.lua b/data-otservbr-global/scripts/hazard/primal.lua index 8aeb80a555c..e4309b78f67 100644 --- a/data-otservbr-global/scripts/hazard/primal.lua +++ b/data-otservbr-global/scripts/hazard/primal.lua @@ -82,8 +82,14 @@ function createPrimalPod(position) end end -local primalKill = CreatureEvent("PrimalHazardKill") -function primalKill.onKill(_player, creature) +local spawnEvent = ZoneEvent(hazardZone) +function spawnEvent.onSpawn(monster, position) + monster:registerEvent("PrimalHazardDeath") +end +spawnEvent:register() + +local deathEvent = CreatureEvent("PrimalHazardDeath") +function deathEvent.onDeath(creature) if not configManager.getBoolean(configKeys.TOGGLE_HAZARDSYSTEM) then return true end @@ -123,4 +129,4 @@ function primalKill.onKill(_player, creature) return true end -primalKill:register() +deathEvent:register() diff --git a/data-otservbr-global/scripts/quests/primal_ordeal_quest/bosses_killed.lua b/data-otservbr-global/scripts/quests/primal_ordeal_quest/bosses_killed.lua new file mode 100644 index 00000000000..cb0c34b6401 --- /dev/null +++ b/data-otservbr-global/scripts/quests/primal_ordeal_quest/bosses_killed.lua @@ -0,0 +1,18 @@ +local bosses = { + ["magma bubble"] = { storage = Storage.Quest.U12_90.PrimalOrdeal.Bosses.MagmaBubbleKilled }, + ["the primal menace"] = { storage = Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled }, +} + +local bossesPrimeOrdeal = CreatureEvent("ThePrimeOrdealBossDeath") +function bossesPrimeOrdeal.onDeath(creature) + local bossConfig = bosses[creature:getName():lower()] + if not bossConfig or not bossConfig.storage then + return true + end + onDeathForDamagingPlayers(creature, function(creature, player) + player:setStorageValue(bossConfig.storage, 1) + end) + return true +end + +bossesPrimeOrdeal:register() diff --git a/data-otservbr-global/scripts/quests/the_new_frontier/creaturescripts-shard_of_corruption_kill.lua b/data-otservbr-global/scripts/quests/the_new_frontier/creaturescripts-shard_of_corruption_kill.lua deleted file mode 100644 index 4d97191766a..00000000000 --- a/data-otservbr-global/scripts/quests/the_new_frontier/creaturescripts-shard_of_corruption_kill.lua +++ /dev/null @@ -1,22 +0,0 @@ -local TheNewFrontier = Storage.Quest.U8_54.TheNewFrontier - -local shardOfCorruptionKill = CreatureEvent("ShardOfCorruptionKill") - -function shardOfCorruptionKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - if targetMonster:getName():lower() ~= "shard of corruption" then - return true - end - - local player = creature:getPlayer() - if player:getStorageValue(TheNewFrontier.Questline) == 11 then - player:setStorageValue(TheNewFrontier.Questline, 12) - end - return true -end - -shardOfCorruptionKill:register() diff --git a/data-otservbr-global/scripts/quests/the_new_frontier/shard_of_corruption_kill.lua b/data-otservbr-global/scripts/quests/the_new_frontier/shard_of_corruption_kill.lua new file mode 100644 index 00000000000..24d4a02922c --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_new_frontier/shard_of_corruption_kill.lua @@ -0,0 +1,14 @@ +local TheNewFrontier = Storage.Quest.U8_54.TheNewFrontier + +local shardOfCorruptionKill = CreatureEvent("ShardOfCorruptionDeath") + +function shardOfCorruptionKill.onDeath(creature) + onDeathForDamagingPlayers(creature, function(creature, player) + if player:getStorageValue(TheNewFrontier.Questline) == 11 then + player:setStorageValue(TheNewFrontier.Questline, 12) + end + end) + return true +end + +shardOfCorruptionKill:register() diff --git a/data-otservbr-global/scripts/quests/the_new_frontier/creaturescripts-tirecz_kill.lua b/data-otservbr-global/scripts/quests/the_new_frontier/tirecz_kill.lua similarity index 83% rename from data-otservbr-global/scripts/quests/the_new_frontier/creaturescripts-tirecz_kill.lua rename to data-otservbr-global/scripts/quests/the_new_frontier/tirecz_kill.lua index 3bd59a34450..5de50bf0eb1 100644 --- a/data-otservbr-global/scripts/quests/the_new_frontier/creaturescripts-tirecz_kill.lua +++ b/data-otservbr-global/scripts/quests/the_new_frontier/tirecz_kill.lua @@ -14,18 +14,9 @@ local function clearArena() end end -local tireczKill = CreatureEvent("TireczKill") - -function tireczKill.onKill(creature, target) - local targetMonster = target:getMonster() - if not targetMonster then - return true - end - - if targetMonster:getName():lower() ~= "tirecz" then - return true - end +local tireczKill = CreatureEvent("TireczDeath") +function tireczKill.onDeath(creature) local spectators, spectator = Game.getSpectators(Position({ x = 33063, y = 31034, z = 3 }), false, true, 10, 10, 10, 10) for i = 1, #spectators do spectator = spectators[i] diff --git a/data-otservbr-global/scripts/quests/the_rookie_guard/mission03_rational_request.lua b/data-otservbr-global/scripts/quests/the_rookie_guard/mission03_rational_request.lua index 7bd56fbd633..ee2e814656e 100644 --- a/data-otservbr-global/scripts/quests/the_rookie_guard/mission03_rational_request.lua +++ b/data-otservbr-global/scripts/quests/the_rookie_guard/mission03_rational_request.lua @@ -2,21 +2,17 @@ -- Mission Kills -local ratKill = CreatureEvent("VascalirRatKills") +local ratKill = CreatureEvent("RationalRequestRatDeath") -function ratKill.onKill(player, target) - if target:isPlayer() or target:getMaster() then - return true - end - if not target:getName():lower() == "rat" then - return true - end - if player:getStorageValue(Storage.TheRookieGuard.Mission03) == 1 then - local counter = player:getStorageValue(Storage.TheRookieGuard.RatKills) - if counter < 5 then - player:setStorageValue(Storage.TheRookieGuard.RatKills, counter + 1) +function ratKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + onDeathForParty(creature, mostDamageKiller, function(creature, player) + if player:getStorageValue(Storage.TheRookieGuard.Mission03) == 1 then + local counter = player:getStorageValue(Storage.TheRookieGuard.RatKills) + if counter < 5 then + player:setStorageValue(Storage.TheRookieGuard.RatKills, counter + 1) + end end - end + end) return true end diff --git a/data-otservbr-global/scripts/quests/threatened_dreams/creaturescript-nightmare_monsters_kills.lua b/data-otservbr-global/scripts/quests/threatened_dreams/creaturescript-nightmare_monsters_kills.lua deleted file mode 100644 index 42aa18e5471..00000000000 --- a/data-otservbr-global/scripts/quests/threatened_dreams/creaturescript-nightmare_monsters_kills.lua +++ /dev/null @@ -1,33 +0,0 @@ -local nightmareMonsters = { - "enfeebled silencer", - "weakened frazzlemaw", - "kroazur", -} -local ThreatenedDreams = Storage.Quest.U11_40.ThreatenedDreams - -local threatenedDreamsNightmareMonstersKills = CreatureEvent("ThreatenedDreamsNightmareMonstersKills") -function threatenedDreamsNightmareMonstersKills.onKill(player, target) - if target:isPlayer() or target:getMaster() then - return true - end - - if not table.contains(nightmareMonsters, target:getName():lower()) then - return true - end - - local enfeebledKills = player:getStorageValue(ThreatenedDreams.Mission02.EnfeebledCount) - local frazzlemawsKills = player:getStorageValue(ThreatenedDreams.Mission02.FrazzlemawsCount) - if player:getStorageValue(ThreatenedDreams.Mission02[1]) == 1 then - player:setStorageValue(ThreatenedDreams.Mission02[1], 1) - if target:getName():lower() == nightmareMonsters[1] then - player:setStorageValue(ThreatenedDreams.Mission02.EnfeebledCount, enfeebledKills + 1) - elseif target:getName():lower() == nightmareMonsters[2] then - player:setStorageValue(ThreatenedDreams.Mission02.FrazzlemawsCount, frazzlemawsKills + 1) - elseif target:getName():lower() == nightmareMonsters[3] then - player:setStorageValue(ThreatenedDreams.Mission02.KroazurKill, 1) - end - end - return true -end - -threatenedDreamsNightmareMonstersKills:register() diff --git a/data-otservbr-global/scripts/quests/threatened_dreams/nightmare_monsters_kills.lua b/data-otservbr-global/scripts/quests/threatened_dreams/nightmare_monsters_kills.lua new file mode 100644 index 00000000000..2b66a2c1eb7 --- /dev/null +++ b/data-otservbr-global/scripts/quests/threatened_dreams/nightmare_monsters_kills.lua @@ -0,0 +1,31 @@ +local nightmareMonsters = { + "enfeebled silencer", + "weakened frazzlemaw", + "kroazur", +} +local ThreatenedDreams = Storage.Quest.U11_40.ThreatenedDreams + +local deathEvent = CreatureEvent("ThreatenedDreamsNightmareMonstersDeath") +function deathEvent.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + if not table.contains(nightmareMonsters, creature:getName():lower()) then + return true + end + + onDeathForParty(creature, mostDamageKiller, function(creature, player) + local enfeebledKills = player:getStorageValue(ThreatenedDreams.Mission02.EnfeebledCount) + local frazzlemawsKills = player:getStorageValue(ThreatenedDreams.Mission02.FrazzlemawsCount) + if player:getStorageValue(ThreatenedDreams.Mission02[1]) == 1 then + player:setStorageValue(ThreatenedDreams.Mission02[1], 1) + if creature:getName():lower() == nightmareMonsters[1] then + player:setStorageValue(ThreatenedDreams.Mission02.EnfeebledCount, enfeebledKills + 1) + elseif creature:getName():lower() == nightmareMonsters[2] then + player:setStorageValue(ThreatenedDreams.Mission02.FrazzlemawsCount, frazzlemawsKills + 1) + elseif creature:getName():lower() == nightmareMonsters[3] then + player:setStorageValue(ThreatenedDreams.Mission02.KroazurKill, 1) + end + end + end) + return true +end + +deathEvent:register() diff --git a/data/libs/functions/set.lua b/data/libs/functions/set.lua new file mode 100644 index 00000000000..e3e6b6f921d --- /dev/null +++ b/data/libs/functions/set.lua @@ -0,0 +1,146 @@ +---@class Set +---@field values table +---@field options table +---@field options.insensitive boolean +---@method contains(key: any): boolean +---@method insert(key: any): void +---@method remove(key: any): void +---@method union(other: Set): Set +---@method intersection(other: Set): Set +---@method iter(): function +---@method __eq(other: Set): boolean +---@method __key(k: any): any +---@method __len(): number +---@method __tostring(): string +Set = {} + +---@param initial table|Set +---@param options table +---@return Set +setmetatable(Set, { + __call = function(self, initial, options) + local set = setmetatable({ + values = {}, + options = options or {}, + }, { __index = Set }) + if Set.isSet(initial) then + for k in initial:iter() do + set:insert(k) + end + elseif type(initial) == "table" then + for _, k in ipairs(initial) do + set:insert(k) + end + end + return set + end, +}) + +function Set.isSet(t) + local meta = getmetatable(t) + return meta and (meta == Set or meta.__index == Set) +end + +function Set:contains(key) + key = self:__key(key) + return self.values[key] ~= nil +end + +function Set:insert(key) + key = self:__key(key) + self.values[key] = true +end + +function Set:remove(key) + key = self:__key(key) + self.values[key] = nil +end + +function Set:union(other) + local set = Set(self, self.options) + for k in Set(other, self.options):iter() do + set:insert(k) + end + return set +end + +function Set:intersection(other) + local set = Set({}, self.options) + for k in Set(other, self.options):iter() do + if self:contains(k) then + set:insert(k) + end + end + return set +end + +function Set:__eq(other) + if #self ~= #other then + return false + end + for k in pairs(self.values) do + if not other:contains(k) then + return false + end + end + return true +end + +function Set:__key(k) + if self.options.insensitive then + if type(k) ~= "string" then + logger.error("key must be a string when insensitive option is enabled") + end + k = k:lower() + end + return k +end + +function Set:iter() + return pairs(self.values) +end + +function Set:__len() + return #self.values +end + +function Set:__tostring() + local t = {} + for k in self:iter() do + table.insert(t, k) + end + return "{ " .. table.concat(t, ", ") .. " }" +end + +function Set:tostring() + return self:__tostring() +end + +-- Usage: +-- local s = Set({ 1, 2, 3 }) +-- s:insert(4) +-- s:remove(2) +-- print(s:contains(1)) -- true +-- print(s:contains(2)) -- false +-- print(s:contains(3)) -- true +-- print(s:contains(4)) -- true +-- print(s:contains(5)) -- false +-- print(#s) -- 3 +-- print(s) -- { 1, 3, 4 } +-- for k in s:iter() do +-- print(k) +-- end +-- local s2 = Set({ 3, 4, 5 }) +-- print(s:union(s2)) -- { 1, 3, 4, 5 } +-- print(s2:union(s)) -- { 3, 4, 5, 1 } +-- print(s:union(s2) == s2:union(s)) -- true +-- +-- Strings +-- local s = Set({}, { insensitive = true }) +-- s:insert("a") +-- s:insert("B") +-- s:insert("c") +-- print(s) -- { a, b, c } +-- print(s:contains("a")) -- true +-- print(s:contains("A")) -- true +-- print(s:contains("b")) -- true diff --git a/data/libs/kill_lib.lua b/data/libs/kill_lib.lua new file mode 100644 index 00000000000..257be4722de --- /dev/null +++ b/data/libs/kill_lib.lua @@ -0,0 +1,21 @@ +-- Utility to combine onDeath event with a "kill" event for a player with a party (or not). + +function onDeathForParty(creature, player, func) + if not player or not player:isPlayer() then + return + end + + local participants = Participants(player, true) + for _, participant in ipairs(participants) do + func(creature, participant) + end +end + +function onDeathForDamagingPlayers(creature, func) + for key, value in pairs(creature:getDamageMap()) do + local player = Player(key) + if player then + func(creature, player) + end + end +end diff --git a/data/libs/libs.lua b/data/libs/libs.lua index ccc71dc8961..bd6164111de 100644 --- a/data/libs/libs.lua +++ b/data/libs/libs.lua @@ -32,3 +32,4 @@ dofile(CORE_DIRECTORY .. "/libs/loyalty_lib.lua") dofile(CORE_DIRECTORY .. "/libs/encounters_lib.lua") dofile(CORE_DIRECTORY .. "/libs/raids_lib.lua") dofile(CORE_DIRECTORY .. "/libs/concoctions_lib.lua") +dofile(CORE_DIRECTORY .. "/libs/kill_lib.lua") diff --git a/src/lua/creature/creatureevent.cpp b/src/lua/creature/creatureevent.cpp index b1984be2fd6..29feb652036 100644 --- a/src/lua/creature/creatureevent.cpp +++ b/src/lua/creature/creatureevent.cpp @@ -326,8 +326,14 @@ bool CreatureEvent::executeAdvance(std::shared_ptr player, skills_t skil return getScriptInterface()->callFunction(4); } +/** + * @deprecated Prefer using registered onDeath events instead for better performance. + */ void CreatureEvent::executeOnKill(std::shared_ptr creature, std::shared_ptr target, bool lastHit) const { // onKill(creature, target, lastHit) + g_logger().warn("[CreatureEvent::executeOnKill - Creature {} target {} event {}] " + "Deprecated use of onKill event. Use registered onDeath events instead for better performance.", + creature->getName(), target->getName(), getName()); if (!getScriptInterface()->reserveScriptEnv()) { g_logger().error("[CreatureEvent::executeOnKill - Creature {} target {} event {}] " "Call stack overflow. Too many lua script calls being nested.", diff --git a/src/lua/functions/creatures/monster/monster_type_functions.cpp b/src/lua/functions/creatures/monster/monster_type_functions.cpp index e08d322189c..0db51998ea7 100644 --- a/src/lua/functions/creatures/monster/monster_type_functions.cpp +++ b/src/lua/functions/creatures/monster/monster_type_functions.cpp @@ -13,6 +13,7 @@ #include "io/io_bosstiary.hpp" #include "creatures/combat/spells.hpp" #include "creatures/monsters/monsters.hpp" +#include "creatures/monsters/monster.hpp" #include "lua/functions/creatures/monster/monster_type_functions.hpp" #include "lua/scripts/scripts.hpp" @@ -1002,7 +1003,13 @@ int MonsterTypeFunctions::luaMonsterTypeRegisterEvent(lua_State* L) { // monsterType:registerEvent(name) const auto monsterType = getUserdataShared(L, 1); if (monsterType) { - monsterType->info.scripts.push_back(getString(L, 2)); + auto eventName = getString(L, 2); + monsterType->info.scripts.push_back(eventName); + for (const auto &[_, monster] : g_game().getMonsters()) { + if (monster->getMonsterType() == monsterType) { + monster->registerCreatureEvent(eventName); + } + } pushBoolean(L, true); } else { lua_pushnil(L); From c07792138640a445802bc5b53462f12e773673f0 Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Fri, 3 Nov 2023 10:35:32 -0300 Subject: [PATCH 04/12] improve: pathfinder mt (#1769) It is not necessary to call g_dispatcher().asyncEvent, the goToFollowCreature_async method is already in charge of doing this --- src/creatures/creature.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/creatures/creature.cpp b/src/creatures/creature.cpp index 7058753acf1..a001e9087a5 100644 --- a/src/creatures/creature.cpp +++ b/src/creatures/creature.cpp @@ -142,10 +142,8 @@ void Creature::onThink(uint32_t interval) { }; if (isUpdatingPath) { - g_dispatcher().asyncEvent([self = getCreature(), onThink = std::move(onThink)] { - self->isUpdatingPath = false; - self->goToFollowCreature_async(onThink); - }); + isUpdatingPath = false; + goToFollowCreature_async(onThink); return; } From 397a95c197cc323fe382f25e756449dd23a1f953 Mon Sep 17 00:00:00 2001 From: Daanyx <62149991+daanyx@users.noreply.github.com> Date: Fri, 3 Nov 2023 11:55:18 -0300 Subject: [PATCH 05/12] fix: improve imbuement assistant npc (#1750) Small fixes to pull request #1590 --- data-otservbr-global/npc/battlemart.lua | 2 +- data-otservbr-global/npc/imbuement_assistant.lua | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/data-otservbr-global/npc/battlemart.lua b/data-otservbr-global/npc/battlemart.lua index ec668947aa9..2461fc91129 100644 --- a/data-otservbr-global/npc/battlemart.lua +++ b/data-otservbr-global/npc/battlemart.lua @@ -7,7 +7,7 @@ npcConfig.description = internalNpcName npcConfig.health = 100 npcConfig.maxHealth = npcConfig.health -npcConfig.walkInterval = 0 +npcConfig.walkInterval = 2000 npcConfig.walkRadius = 2 npcConfig.outfit = { diff --git a/data-otservbr-global/npc/imbuement_assistant.lua b/data-otservbr-global/npc/imbuement_assistant.lua index a4f1228ecd6..38cf813408e 100644 --- a/data-otservbr-global/npc/imbuement_assistant.lua +++ b/data-otservbr-global/npc/imbuement_assistant.lua @@ -106,18 +106,18 @@ local imbuementPackagesData = { text = "skill club", moneyRequired = 6250, itemList = { - { itemId = 9657, count = 20 }, - { itemId = 22189, count = 15 }, - { itemId = 10405, count = 10 }, + { itemId = 9657, count = 20 }, -- cyclops toe + { itemId = 22189, count = 15 }, -- ogre nose ring + { itemId = 10405, count = 10 }, -- warmaster's wristguards }, }, ["blockade"] = { text = "skill shield", moneyRequired = 16150, itemList = { - { itemId = 9641, count = 20 }, - { itemId = 11703, count = 25 }, - { itemId = 20199, count = 25 }, + { itemId = 9641, count = 20 }, -- piece of scarab shell + { itemId = 11703, count = 25 }, -- brimstone shell + { itemId = 20199, count = 25 }, -- frazzle skin }, }, ["chop"] = { @@ -333,7 +333,8 @@ local function creatureSayCallback(npc, creature, type, message) return false end - local imbuementPackages = "Available imbuement packages: {bash}, {blockade}, {chop}, {epiphany}, {precision}, {slash}. additional attributes: {featherweight}, {strike}, {swiftness}, {vampirism}, {vibrancy}, {void}. elemental damage: {electrify}, {frost}, {reap}, {scorch}, {venom}. elemental protection: {cloud fabric}, {demon presence}, {dragon hide}, {lich shroud}, {quara scale}, {snake skin}." + local imbuementPackages = + "These are the available imbuement packages, Skill increase: {bash}, {blockade}, {chop}, {epiphany}, {precision}, {slash}. Additional attributes: {featherweight}, {strike}, {swiftness}, {vampirism}, {vibrancy}, {void}. Elemental damage: {electrify}, {frost}, {reap}, {scorch}, {venom}. Elemental protection: {cloud fabric}, {demon presence}, {dragon hide}, {lich shroud}, {quara scale}, {snake skin}." if MsgContains(message, "imbuement packages") then npcHandler:setTopic(playerId, 1) npcHandler:say(imbuementPackages, npc, creature) From 9df5f27e545f685dc32a2f2f4141e0c4278da302 Mon Sep 17 00:00:00 2001 From: Luan Santos Date: Fri, 3 Nov 2023 15:00:34 -0700 Subject: [PATCH 06/12] fix: add missing set.lua import (#1773) --- .../quests/feaster_of_souls/bosses_killed.lua | 6 +----- .../quests/grave_danger/bosses_killed.lua | 8 ++------ .../quests/secret_library/bosses_killed.lua | 6 +----- .../actions/quests/soul_war/bosses_killed.lua | 6 +----- .../quests/the_dream_courts/bosses_killed.lua | 6 +----- .../ferumbras_ascendant/bone_capsule.lua | 5 ++--- .../ferumbras_ascendant/death_dragon.lua | 5 ++--- .../disgusting_ooze_death.lua | 9 ++++----- .../ferumbras_mortal_shell_death.lua | 3 +-- .../ferumbras_soul_splinter.lua | 7 +------ .../rift_invader_death.lua | 10 ++++------ .../ferumbras_ascendant/zamulosh_clone.lua | 7 +------ .../astral_glyph_death.lua | 9 +-------- .../forgotten_knowledge/bosses_kill.lua | 6 +++--- .../lloyd_preparedeath.lua | 10 ++++++++-- .../forgotten_knowledge/replica_servants.lua | 2 +- .../thorn_knight_death.lua | 20 ++++++++----------- .../quests/hero_of_rathleton/bosses_kill.lua | 6 +++--- .../hero_of_rathleton/glooth_horror.lua | 7 +------ .../diseased_trio_kill.lua | 4 ++-- .../raging_mage_tower/raging_mage_2.lua | 7 +------ data/libs/functions/load.lua | 1 + data/libs/functions/party.lua | 13 ++++++++++++ 23 files changed, 63 insertions(+), 100 deletions(-) diff --git a/data-otservbr-global/scripts/actions/quests/feaster_of_souls/bosses_killed.lua b/data-otservbr-global/scripts/actions/quests/feaster_of_souls/bosses_killed.lua index b08abd9a2d2..5d021a9659d 100644 --- a/data-otservbr-global/scripts/actions/quests/feaster_of_souls/bosses_killed.lua +++ b/data-otservbr-global/scripts/actions/quests/feaster_of_souls/bosses_killed.lua @@ -7,11 +7,7 @@ local bosses = { local bossesFeasterOfSouls = CreatureEvent("FeasterOfSoulsBossDeath") function bossesFeasterOfSouls.onDeath(creature) - local targetMonster = creature:getMonster() - if not targetMonster or targetMonster:getMaster() then - return true - end - local bossConfig = bosses[targetMonster:getName():lower()] + local bossConfig = bosses[creature:getName():lower()] if not bossConfig then return true end diff --git a/data-otservbr-global/scripts/actions/quests/grave_danger/bosses_killed.lua b/data-otservbr-global/scripts/actions/quests/grave_danger/bosses_killed.lua index 3142f9e1a04..8b1ed5b2c89 100644 --- a/data-otservbr-global/scripts/actions/quests/grave_danger/bosses_killed.lua +++ b/data-otservbr-global/scripts/actions/quests/grave_danger/bosses_killed.lua @@ -7,13 +7,9 @@ local bosses = { ["king zelos"] = { storage = Storage.Quest.U12_20.GraveDanger.Bosses.KingZelosKilled }, } -local bossesGraveDanger = CreatureEvent("GraveDangerKillGraveDangerBossDeath") +local bossesGraveDanger = CreatureEvent("GraveDangerBossDeath") function bossesGraveDanger.onDeath(creature) - local targetMonster = creature:getMonster() - if not targetMonster or targetMonster:getMaster() then - return true - end - local bossConfig = bosses[targetMonster:getName():lower()] + local bossConfig = bosses[creature:getName():lower()] if not bossConfig then return true end diff --git a/data-otservbr-global/scripts/actions/quests/secret_library/bosses_killed.lua b/data-otservbr-global/scripts/actions/quests/secret_library/bosses_killed.lua index b7154ec9f0f..a62b922469e 100644 --- a/data-otservbr-global/scripts/actions/quests/secret_library/bosses_killed.lua +++ b/data-otservbr-global/scripts/actions/quests/secret_library/bosses_killed.lua @@ -8,11 +8,7 @@ local bosses = { local bossesSecretLibrary = CreatureEvent("SecretLibraryBossDeath") function bossesSecretLibrary.onDeath(creature) - local targetMonster = creature:getMonster() - if not targetMonster or targetMonster:getMaster() then - return true - end - local bossConfig = bosses[targetMonster:getName():lower()] + local bossConfig = bosses[creature:getName():lower()] if not bossConfig then return true end diff --git a/data-otservbr-global/scripts/actions/quests/soul_war/bosses_killed.lua b/data-otservbr-global/scripts/actions/quests/soul_war/bosses_killed.lua index ea8612cc7e8..de4b8ae182f 100644 --- a/data-otservbr-global/scripts/actions/quests/soul_war/bosses_killed.lua +++ b/data-otservbr-global/scripts/actions/quests/soul_war/bosses_killed.lua @@ -9,11 +9,7 @@ local bosses = { local bossesSoulWar = CreatureEvent("SoulwarsBossDeath") function bossesSoulWar.onDeath(creature) - local targetMonster = creature:getMonster() - if not targetMonster or targetMonster:getMaster() then - return true - end - local bossConfig = bosses[targetMonster:getName():lower()] + local bossConfig = bosses[creature:getName():lower()] if not bossConfig then return true end diff --git a/data-otservbr-global/scripts/actions/quests/the_dream_courts/bosses_killed.lua b/data-otservbr-global/scripts/actions/quests/the_dream_courts/bosses_killed.lua index c296a419741..ebbff0713ef 100644 --- a/data-otservbr-global/scripts/actions/quests/the_dream_courts/bosses_killed.lua +++ b/data-otservbr-global/scripts/actions/quests/the_dream_courts/bosses_killed.lua @@ -9,11 +9,7 @@ local bosses = { local bossesDreamCourts = CreatureEvent("DreamCourtsBossDeath") function bossesDreamCourts.onDeath(creature) - local targetMonster = creature:getMonster() - if not targetMonster or targetMonster:getMaster() then - return true - end - local bossConfig = bosses[targetMonster:getName():lower()] + local bossConfig = bosses[creature:getName():lower()] if not bossConfig then return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/bone_capsule.lua b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/bone_capsule.lua index 2d6e90036c4..36a9e3272c9 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/bone_capsule.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/bone_capsule.lua @@ -1,9 +1,8 @@ local boneCapsule = CreatureEvent("BoneCapsule") function boneCapsule.onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified) - local targetMonster = creature:getMonster() - local position = targetMonster:getPosition() + local position = creature:getPosition() position:sendMagicEffect(CONST_ME_POFF) - if not targetMonster or targetMonster:getName():lower() ~= "bone capsule" then + if creature:getName():lower() ~= "bone capsule" then return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/death_dragon.lua b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/death_dragon.lua index ad1a355a5b2..2f952dd81d8 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/death_dragon.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/death_dragon.lua @@ -1,7 +1,6 @@ local deathDragon = CreatureEvent("DeathDragon") function deathDragon.onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified) - local targetMonster = creature:getMonster() - if not targetMonster or targetMonster:getName():lower() ~= "death dragon" then + if not targetMonster or creature:getName():lower() ~= "death dragon" then return true end @@ -10,7 +9,7 @@ function deathDragon.onDeath(creature, corpse, lasthitkiller, mostdamagekiller, return true end - local spectators = Game.getSpectators(targetMonster:getPosition(), false, false, 10, 10, 10, 10) + local spectators = Game.getSpectators(creature:getPosition(), false, false, 10, 10, 10, 10) for i = 1, #spectators do local spectator = spectators[i] if spectator:isMonster() and spectator:getName():lower() == "ragiaz" then diff --git a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/disgusting_ooze_death.lua b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/disgusting_ooze_death.lua index 691b3c2c145..6231122703c 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/disgusting_ooze_death.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/disgusting_ooze_death.lua @@ -1,19 +1,18 @@ local disgustingOozeDeath = CreatureEvent("DisgustingOozeDeath") function disgustingOozeDeath.onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified) - local targetMonster = creature:getMonster() - if not targetMonster or targetMonster:getName():lower() ~= "disgusting ooze" then + if creature:getName():lower() ~= "disgusting ooze" then return true end if math.random(20) < 3 then for i = 1, 2 do - local monster = Game.createMonster("disgusting ooze", targetMonster:getPosition(), false, true) + local monster = Game.createMonster("disgusting ooze", creature:getPosition(), false, true) if not monster then return true end - monster:setMaster(targetMonster:getMaster()) + monster:setMaster(creature:getMaster()) end - targetMonster:say("The ooze splits and regenerates.", TALKTYPE_MONSTER_SAY) + creature:say("The ooze splits and regenerates.", TALKTYPE_MONSTER_SAY) end return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/ferumbras_mortal_shell_death.lua b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/ferumbras_mortal_shell_death.lua index 32f3216c48e..9add0b883ff 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/ferumbras_mortal_shell_death.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/ferumbras_mortal_shell_death.lua @@ -1,7 +1,6 @@ local ferumbrasMortalShell = CreatureEvent("FerumbrasMortalShell") function ferumbrasMortalShell.onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified) - local targetMonster = creature:getMonster() - if not targetMonster or targetMonster:getName():lower() ~= "destabilized ferumbras" then + if creature:getName():lower() ~= "destabilized ferumbras" then return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/ferumbras_soul_splinter.lua b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/ferumbras_soul_splinter.lua index b259d727fe6..73238b09b03 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/ferumbras_soul_splinter.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/ferumbras_soul_splinter.lua @@ -1,11 +1,6 @@ local ferumbrasSoulSplinter = CreatureEvent("FerumbrasSoulSplinter") function ferumbrasSoulSplinter.onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified) - local targetMonster = creature:getMonster() - if not targetMonster or targetMonster:getName():lower() ~= "ferumbras soul splinter" then - return true - end - - local monster = Game.createMonster("ferumbras essence", targetMonster:getPosition(), true, true) + local monster = Game.createMonster("ferumbras essence", creature:getPosition(), true, true) if not monster then return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/rift_invader_death.lua b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/rift_invader_death.lua index 73109373b8d..29eb15c99df 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/rift_invader_death.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/rift_invader_death.lua @@ -11,18 +11,16 @@ local crystals = { local riftInvaderDeath = CreatureEvent("RiftInvaderDeath") function riftInvaderDeath.onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified) - if not targetMonster or targetMonster:getName():lower() ~= "rift invader" then + local pos = Position(33392 + math.random(-10, 10), 31473 + math.random(-10, 10), 14) + local name = creature:getName():lower() + if name ~= "rift invader" then return true end - - local targetMonster = creature:getMonster() - local pos = Position(33392 + math.random(-10, 10), 31473 + math.random(-10, 10), 14) - local name = targetMonster:getName():lower() Game.createMonster(name, pos) for i = 1, #crystals do local crystal = crystals[i] - if isInRange(targetMonster:getPosition(), crystal.fromPosition, crystal.toPosition) then + if isInRange(creature:getPosition(), crystal.fromPosition, crystal.toPosition) then if Game.getStorageValue(crystal.globalStorage) > 8 then local item = Tile(crystal.crystalPosition):getItemById(14955) if not item then diff --git a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/zamulosh_clone.lua b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/zamulosh_clone.lua index 6b73b47c2e8..6b6a2b4494c 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/zamulosh_clone.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/ferumbras_ascendant/zamulosh_clone.lua @@ -1,10 +1,5 @@ function onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified) - local targetMonster = creature:getMonster() - if not targetMonster or targetMonster:getName():lower() ~= "zamulosh" and not targetMonster:getMaster() then - return true - end - - local monster = Game.createMonster("Zamulosh3", targetMonster:getPosition(), true, true) + local monster = Game.createMonster("Zamulosh3", creature:getPosition(), true, true) if not monster then return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/astral_glyph_death.lua b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/astral_glyph_death.lua index 07e48921c7d..18cb3f3a9f5 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/astral_glyph_death.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/astral_glyph_death.lua @@ -1,13 +1,6 @@ local astralGlyphDeath = CreatureEvent("AstralGlyphDeath") function astralGlyphDeath.onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified) - local targetMonster = creature:getMonster() - if not targetMonster then - return true - end - - if targetMonster:getName():lower() == "an astral glyph" then - Game.createMonster("the last lore keeper", targetMonster:getPosition(), true, true) - end + Game.createMonster("the last lore keeper", creature:getPosition(), true, true) return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/bosses_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/bosses_kill.lua index cf573ea81d7..6bd27821be6 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/bosses_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/bosses_kill.lua @@ -15,7 +15,7 @@ local bosses = { local bossesForgottenKill = CreatureEvent("ForgottenKnowledgeBossDeath") function bossesForgottenKill.onDeath(creature) - local bossConfig = bosses[targetMonster:getName():lower()] + local bossConfig = bosses[creature:getName():lower()] if not bossConfig then return true end @@ -23,13 +23,13 @@ function bossesForgottenKill.onDeath(creature) onDeathForDamagingPlayers(creature, function(creature, player) if bossConfig.storage then player:setStorageValue(bossConfig.storage, os.time() + 20 * 3600) - elseif targetMonster:getName():lower() == "the enraged thorn knight" then + elseif creature:getName():lower() == "the enraged thorn knight" then player:setStorageValue(Storage.ForgottenKnowledge.PlantCounter, 0) player:setStorageValue(Storage.ForgottenKnowledge.BirdCounter, 0) end end) - if targetMonster:getName():lower() == "melting frozen horror" then + if creature:getName():lower() == "melting frozen horror" then local egg = Tile(Position(32269, 31084, 14)):getTopCreature() if egg then local pos = egg:getPosition() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/lloyd_preparedeath.lua b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/lloyd_preparedeath.lua index ba912aed7f2..6296763be81 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/lloyd_preparedeath.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/lloyd_preparedeath.lua @@ -13,8 +13,14 @@ local function revertLloyd(prismId) lloyd:getPosition():sendMagicEffect(CONST_ME_TELEPORT) end - Tile(monsters[prismId].pos):getTopCreature():remove() - Game.createMonster(monsters[prismId].cosmicInvu, Position(monsters[prismId].pos), true, true) + local tile = Tile(monsters[prismId].pos) + if tile then + local creature = tile:getTopCreature() + if creature then + creature:remove() + end + Game.createMonster(monsters[prismId].cosmicInvu, Position(monsters[prismId].pos), true, true) + end end local lloydPrepareDeath = CreatureEvent("LloydPrepareDeath") diff --git a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/replica_servants.lua b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/replica_servants.lua index f15ee99f3a1..acb25740216 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/replica_servants.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/replica_servants.lua @@ -10,7 +10,7 @@ local servants = { } local replicaServant = CreatureEvent("ReplicaServantDeath") function replicaServant.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) - local bossConfig = servants[targetMonster:getName():lower()] + local bossConfig = servants[creature:getName():lower()] if not bossConfig then return true end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/thorn_knight_death.lua b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/thorn_knight_death.lua index 058612fc21d..f8b17adf708 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/thorn_knight_death.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/thorn_knight_death.lua @@ -10,19 +10,15 @@ local function checkBlood(position) end local thornKnightDeath = CreatureEvent("ThornKnightDeath") function thornKnightDeath.onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified) - local targetMonster = creature:getMonster() - if not targetMonster then + if creature:getName():lower() == "mounted thorn knight" then + creature:say("The thorn knight unmounts!", TALKTYPE_MONSTER_SAY) + Game.createMonster("the shielded thorn knight", creature:getPosition(), true, true) + Game.createMonster("thorn steed", creature:getPosition(), false, true) + addEvent(checkBlood, 1, creature:getPosition()) return true - end - if targetMonster:getName():lower() == "mounted thorn knight" then - targetMonster:say("The thorn knight unmounts!", TALKTYPE_MONSTER_SAY) - Game.createMonster("the shielded thorn knight", targetMonster:getPosition(), true, true) - Game.createMonster("thorn steed", targetMonster:getPosition(), false, true) - addEvent(checkBlood, 1, targetMonster:getPosition()) - return true - elseif targetMonster:getName():lower() == "the shielded thorn knight" then - Game.createMonster("the enraged thorn knight", targetMonster:getPosition(), true, true) - addEvent(checkBlood, 1, targetMonster:getPosition()) + elseif creature:getName():lower() == "the shielded thorn knight" then + Game.createMonster("the enraged thorn knight", creature:getPosition(), true, true) + addEvent(checkBlood, 1, creature:getPosition()) return true end return true diff --git a/data-otservbr-global/scripts/creaturescripts/quests/hero_of_rathleton/bosses_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/hero_of_rathleton/bosses_kill.lua index db11a05fd13..4a0687ee059 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/hero_of_rathleton/bosses_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/hero_of_rathleton/bosses_kill.lua @@ -47,11 +47,11 @@ end local rathletonBossKill = CreatureEvent("RathletonBossDeath") function rathletonBossKill.onDeath(creature) - local bossConfig = bosses[targetMonster:getName():lower()] + local bossConfig = bosses[creature:getName():lower()] if not bossConfig then return true end - if targetMonster:getName():lower() == "empowered glooth horror" then + if creature:getName():lower() == "empowered glooth horror" then if checkHorror() == true then return true end @@ -67,7 +67,7 @@ function rathletonBossKill.onDeath(creature) local newPos = bossConfig.nextpos if teleport then teleport:transform(22761) - targetMonster:getPosition():sendMagicEffect(CONST_ME_THUNDER) + creature:getPosition():sendMagicEffect(CONST_ME_THUNDER) teleport:setDestination(newPos) addEvent(revertTeleport, 2 * 60 * 1000, teleportPos, 22761, 1949, oldPos) Game.setStorageValue(bossConfig.globaltimer, 0) diff --git a/data-otservbr-global/scripts/creaturescripts/quests/hero_of_rathleton/glooth_horror.lua b/data-otservbr-global/scripts/creaturescripts/quests/hero_of_rathleton/glooth_horror.lua index 6a3bb27b3dc..e09c7b0fc6f 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/hero_of_rathleton/glooth_horror.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/hero_of_rathleton/glooth_horror.lua @@ -7,12 +7,7 @@ local config = { local gloothHorror = CreatureEvent("GloothHorror") function gloothHorror.onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified) - local targetMonster = creature:getMonster() - if not targetMonster or targetMonster:getMaster() then - return true - end - - local name = targetMonster:getName() + local name = creature:getName() for i = 1, #config do if name == config[i].name then for j = 1, 2 do diff --git a/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/diseased_trio_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/diseased_trio_kill.lua index 7c020aec611..b9a0aea39b3 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/diseased_trio_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/in_service_of_yalahar/diseased_trio_kill.lua @@ -6,7 +6,7 @@ local diseasedTrio = { local diseasedTrioKill = CreatureEvent("DiseasedTrioDeath") function diseasedTrioKill.onDeath(creature) - local bossStorage = diseasedTrio[targetMonster:getName():lower()] + local bossStorage = diseasedTrio[creature:getName():lower()] if not bossStorage then return true end @@ -14,7 +14,7 @@ function diseasedTrioKill.onDeath(creature) onDeathForDamagingPlayers(creature, function(creature, player) if player:getStorageValue(bossStorage) < 1 then player:setStorageValue(bossStorage, 1) - player:say("You slayed " .. targetMonster:getName() .. ".", TALKTYPE_MONSTER_SAY) + player:say("You slayed " .. creature:getName() .. ".", TALKTYPE_MONSTER_SAY) end if player:getStorageValue(Storage.InServiceofYalahar.DiseasedDan) == 1 and player:getStorageValue(Storage.InServiceofYalahar.DiseasedBill) == 1 and player:getStorageValue(Storage.InServiceofYalahar.DiseasedFred) == 1 and player:getStorageValue(Storage.InServiceofYalahar.AlchemistFormula) ~= 1 then diff --git a/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/raging_mage_2.lua b/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/raging_mage_2.lua index 222ac163523..50dd16de684 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/raging_mage_2.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/raging_mage_tower/raging_mage_2.lua @@ -1,16 +1,11 @@ local ragingMage2 = CreatureEvent("RagingMage2") function ragingMage2.onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified) - local targetMonster = creature:getMonster() - if not creature or not targetMonster or targetMonster:getName():lower() ~= "raging mage" then - return true - end - broadcastMessage( "The remains of the Raging Mage are scattered on the floor of his Tower. \z The dimensional portal quakes.", MESSAGE_EVENT_ADVANCE ) - targetMonster:say( + creature:say( "I WILL RETURN!! My death will just be a door to await my homecoming, \z my physical hull will be... my... argh...", TALKTYPE_MONSTER_SAY, diff --git a/data/libs/functions/load.lua b/data/libs/functions/load.lua index 0ab33f5de11..9319bc97ac6 100644 --- a/data/libs/functions/load.lua +++ b/data/libs/functions/load.lua @@ -26,3 +26,4 @@ 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") diff --git a/data/libs/functions/party.lua b/data/libs/functions/party.lua index d33d8dbd703..c2fdffffc28 100644 --- a/data/libs/functions/party.lua +++ b/data/libs/functions/party.lua @@ -73,3 +73,16 @@ end function Party.hasDruid(self) return self:hasVocation(VOCATION.BASE_ID.DRUID) end + +function Participants(player, requireSharedExperience) + local party = player:getParty() + if not party then + return { player } + end + if requiredSharedExperience and not party:isSharedExperienceActive() then + return { player } + end + local members = party:getMembers() + table.insert(members, party:getLeader()) + return members +end From 20cd0ff62d0c15f282d56d29189befffc3386ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Lu=C3=ADs=20Lucarelo=20Lamonato?= Date: Fri, 3 Nov 2023 19:06:18 -0300 Subject: [PATCH 07/12] fix: npc lokur bank functionality (#1768) --- data-otservbr-global/npc/lokur.lua | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/data-otservbr-global/npc/lokur.lua b/data-otservbr-global/npc/lokur.lua index 0da622e8ba8..62fb5a50864 100644 --- a/data-otservbr-global/npc/lokur.lua +++ b/data-otservbr-global/npc/lokur.lua @@ -63,6 +63,13 @@ local function creatureSayCallback(npc, creature, type, message) return false end + -- Parse bank + npc:parseBank(message, npc, creature, npcHandler) + -- Parse guild bank + npc:parseGuildBank(message, npc, creature, playerId, npcHandler) + -- Normal messages + npc:parseBankMessages(message, npc, creature, npcHandler) + if MsgContains(message, "ticket") then if Player(creature):getStorageValue(Storage.WagonTicket) >= os.time() then npcHandler:say("Your weekly ticket is still valid. Would be a waste of money to purchase a second one", npc, creature) @@ -89,12 +96,6 @@ local function creatureSayCallback(npc, creature, type, message) npcHandler:setTopic(playerId, 0) end - -- Parse bank - npc:parseBank(message, npc, creature, npcHandler) - -- Parse guild bank - npc:parseGuildBank(message, npc, creature, playerId, npcHandler) - -- Normal messages - npc:parseBankMessages(message, npc, creature, npcHandler) return true end From c43753e1843766d8ed30e7c0dc9e68c543e5c3f8 Mon Sep 17 00:00:00 2001 From: Luan Santos Date: Fri, 3 Nov 2023 17:08:13 -0700 Subject: [PATCH 08/12] fix: lloyd and thorn knight boss fights (#1775) --- .../bosses/mounted_thorn_knight.lua | 2 +- .../bosses/the_shielded_thorn_knight.lua | 2 +- .../thorn_knight_lever.lua | 2 +- .../time_guardian_lever.lua | 6 ------ .../lloyd_preparedeath.lua | 19 +++++++++---------- .../killing_in_the_name_of/monster_kill.lua | 1 - data/scripts/reward_chest/boss_death.lua | 2 +- 7 files changed, 13 insertions(+), 21 deletions(-) diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/mounted_thorn_knight.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/mounted_thorn_knight.lua index 05e436339b9..f46efa303a8 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/mounted_thorn_knight.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/mounted_thorn_knight.lua @@ -38,7 +38,7 @@ monster.flags = { hostile = true, convinceable = false, pushable = false, - rewardBoss = true, + rewardBoss = false, illusionable = false, canPushItems = true, canPushCreatures = true, diff --git a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_shielded_thorn_knight.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_shielded_thorn_knight.lua index 15adaa5ef7f..f3539476809 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_shielded_thorn_knight.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_shielded_thorn_knight.lua @@ -38,7 +38,7 @@ monster.flags = { hostile = true, convinceable = false, pushable = false, - rewardBoss = true, + rewardBoss = false, illusionable = false, canPushItems = true, canPushCreatures = true, diff --git a/data-otservbr-global/scripts/actions/quests/forgotten_knowledge/thorn_knight_lever.lua b/data-otservbr-global/scripts/actions/quests/forgotten_knowledge/thorn_knight_lever.lua index 2a7811d3423..c62514fbaf3 100644 --- a/data-otservbr-global/scripts/actions/quests/forgotten_knowledge/thorn_knight_lever.lua +++ b/data-otservbr-global/scripts/actions/quests/forgotten_knowledge/thorn_knight_lever.lua @@ -68,7 +68,7 @@ function forgottenKnowledgeThorn.onUse(player, item, fromPosition, target, toPos return true end lever:teleportPlayers() - lever:setCooldownAllPlayers(config.bossName, os.time() + config.timeToFightAgain * 3600) + lever:setCooldownAllPlayers("The Enraged Thorn Knight", os.time() + config.timeToFightAgain * 3600) addEvent(function() local old_players = lever:getInfoPositions() spec:clearCreaturesCache() diff --git a/data-otservbr-global/scripts/actions/quests/forgotten_knowledge/time_guardian_lever.lua b/data-otservbr-global/scripts/actions/quests/forgotten_knowledge/time_guardian_lever.lua index f4d42e52c45..832e42e2c6c 100644 --- a/data-otservbr-global/scripts/actions/quests/forgotten_knowledge/time_guardian_lever.lua +++ b/data-otservbr-global/scripts/actions/quests/forgotten_knowledge/time_guardian_lever.lua @@ -14,12 +14,6 @@ local config = { { bossPosition = Position(32975, 31664, 13), bossName = "The Freezing Time Guardian" }, { bossPosition = Position(32980, 31664, 13), bossName = "The Blazing Time Guardian" }, }, - monsters = { - { cosmic = "cosmic energy prism a invu", pos = Position(32801, 32827, 14) }, - { cosmic = "cosmic energy prism b invu", pos = Position(32798, 32827, 14) }, - { cosmic = "cosmic energy prism c invu", pos = Position(32803, 32826, 14) }, - { cosmic = "cosmic energy prism d invu", pos = Position(32796, 32826, 14) }, - }, specPos = { from = Position(32967, 31654, 13), to = Position(32989, 31677, 14), diff --git a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/lloyd_preparedeath.lua b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/lloyd_preparedeath.lua index 6296763be81..e00624aa53d 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/lloyd_preparedeath.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/forgotten_knowledge/lloyd_preparedeath.lua @@ -9,15 +9,19 @@ local function revertLloyd(prismId) local lloydTile = Tile(Position(32799, 32826, 14)) if lloydTile then local lloyd = lloydTile:getTopCreature() - lloyd:teleportTo(Position(32799, 32829, 14)) - lloyd:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + if lloyd then + lloyd:teleportTo(Position(32799, 32829, 14)) + lloyd:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + end end local tile = Tile(monsters[prismId].pos) if tile then - local creature = tile:getTopCreature() - if creature then - creature:remove() + local creatures = tile:getCreatures() + for _, creature in ipairs(creatures) do + if creature:isMonster() then + creature:remove() + end end Game.createMonster(monsters[prismId].cosmicInvu, Position(monsters[prismId].pos), true, true) end @@ -25,11 +29,6 @@ end local lloydPrepareDeath = CreatureEvent("LloydPrepareDeath") function lloydPrepareDeath.onPrepareDeath(creature, lastHitKiller, mostDamageKiller) - local targetMonster = creature:getMonster() - if not creature or not targetMonster then - return true - end - local prismCount = 1 for m = 1, #monsters do local cosmic = Tile(Position(monsters[m].pos)):getTopCreature() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/monster_kill.lua b/data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/monster_kill.lua index 01b1648c25b..b2ba681d251 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/monster_kill.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/killing_in_the_name_of/monster_kill.lua @@ -83,7 +83,6 @@ deathEvent:register() local serverstartup = GlobalEvent("KillingInTheNameOfMonsterDeathStartup") function serverstartup.onStartup() - logger.info("[KillingInTheNameOfMonsterDeathStartup] registering monsters") local monsters = Set({}, { insensitive = true }) for _, task in pairs(tasks.GrizzlyAdams) do monsters = monsters:union(task.creatures) diff --git a/data/scripts/reward_chest/boss_death.lua b/data/scripts/reward_chest/boss_death.lua index f3a80909c8f..1a979e945ab 100644 --- a/data/scripts/reward_chest/boss_death.lua +++ b/data/scripts/reward_chest/boss_death.lua @@ -14,7 +14,7 @@ function bossDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUn -- Make sure it is a boss if monsterType and monsterType:isRewardBoss() then if not corpse.isContainer or not corpse:isContainer() then - if corpse.getId() then + if corpse.getId then logger.warn("[bossDeath.onDeath] Corpse (id: {}, name: {}) for reward boss {} is not a container.", corpse:getId(), corpse:getName(), creature:getName()) else logger.warn("[bossDeath.onDeath] Error to get corpseId from boss: {}", creature:getName()) From 666fbdf6892250a5b9f1afa6bdda7cc275a75225 Mon Sep 17 00:00:00 2001 From: Luan Luciano Date: Fri, 3 Nov 2023 21:24:59 -0300 Subject: [PATCH 09/12] improve: check and return in addChildLoot Method (#1774) Check child loot and return boolean in addChildLoot Method --- src/lua/functions/creatures/monster/loot_functions.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/lua/functions/creatures/monster/loot_functions.cpp b/src/lua/functions/creatures/monster/loot_functions.cpp index 81e42535f92..b23508033bc 100644 --- a/src/lua/functions/creatures/monster/loot_functions.cpp +++ b/src/lua/functions/creatures/monster/loot_functions.cpp @@ -259,7 +259,13 @@ int LootFunctions::luaLootAddChildLoot(lua_State* L) { // loot:addChildLoot(loot) const auto loot = getUserdataShared(L, 1); if (loot) { - loot->lootBlock.childLoot.push_back(getUserdata(L, 2)->lootBlock); + const auto childLoot = getUserdata(L, 2); + if (childLoot) { + loot->lootBlock.childLoot.push_back(childLoot->lootBlock); + pushBoolean(L, true); + } else { + pushBoolean(L, false); + } } else { lua_pushnil(L); } From 1ad50f0bffa67d6fb93b84cbbd4bdd0e67935166 Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Fri, 3 Nov 2023 23:03:28 -0300 Subject: [PATCH 10/12] improve: review of everything using set (#1705) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor set implementation across the codebase for optimal performance. Detailed Description: This encompasses a comprehensive review and overhaul of `std::set` usage within the project, replacing it with more efficient collections as applicable. The refactoring targets instances where set operations are utilized, with a critical analysis of performance considerations. Key Changes: • Avoid `std::set` due to ordering overhead when order is not a requirement. • Employ `std::unordered_set` for scenarios with infrequent insertions and deletions but frequent searches. • Integrate `phmap::flat_hash_set` as a balanced option for various operations without linear searches. • Introduce `vector_set` for batch insertions and short-term unique data handling within methods. Performance Insights: The `vector_set` is particularly notable for its batch insertion efficiency and automatic sorting and deduplication upon search or deletion operations, making it suitable for maintaining a unique set of elements temporarily. Example Usage: stdext::vector_set unique_list; unique_list.insertAll({1, 3, 4, 5}); unique_list.insertAll({4, 2, 87, 2}); unique_list.insertAll({3, 1, 99, 5}); unique_list now contains 1, 2, 3, 4, 5, 87, 99 without duplicates --- src/creatures/combat/combat.cpp | 2 +- src/creatures/creature.cpp | 24 +++---- src/creatures/creature.hpp | 6 +- src/creatures/monsters/monster.hpp | 13 ++-- src/creatures/monsters/monsters.hpp | 2 +- src/creatures/npcs/npc.cpp | 6 +- src/creatures/npcs/npc.hpp | 2 +- src/creatures/players/player.cpp | 64 +++++++++---------- src/creatures/players/player.hpp | 17 +++-- src/game/game.cpp | 26 ++++---- src/game/game.hpp | 16 ++--- src/game/scheduling/events_scheduler.cpp | 2 +- src/game/zones/zone.hpp | 1 - src/io/io_bosstiary.cpp | 13 ++-- src/io/io_bosstiary.hpp | 2 +- src/io/iobestiary.cpp | 17 ++--- src/io/iobestiary.hpp | 2 +- src/items/containers/container.cpp | 6 +- src/items/containers/container.hpp | 2 +- src/items/tile.cpp | 10 +-- src/items/tile.hpp | 6 +- src/lua/creature/events.cpp | 4 +- .../creatures/monster/monster_functions.cpp | 4 +- .../monster/monster_type_functions.cpp | 4 +- .../creatures/player/player_functions.cpp | 3 +- src/lua/functions/lua_functions_loader.cpp | 2 +- src/map/house/house.cpp | 19 ++---- src/map/house/house.hpp | 12 ++-- src/map/map.cpp | 12 ++-- src/map/spectators.hpp | 2 +- src/pch.hpp | 1 + src/server/network/protocol/protocolgame.cpp | 34 +++++----- src/server/network/protocol/protocolgame.hpp | 6 +- src/utils/vectorset.hpp | 31 +++++++-- 34 files changed, 192 insertions(+), 181 deletions(-) diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp index 38f2c5de217..9a80ad55ce3 100644 --- a/src/creatures/combat/combat.cpp +++ b/src/creatures/combat/combat.cpp @@ -1311,7 +1311,7 @@ std::vector>> Combat::pickChainTargets std::vector>> resultMap; std::vector> targets; - std::set visited; + phmap::flat_hash_set visited; if (initialTarget && initialTarget != caster) { targets.push_back(initialTarget); diff --git a/src/creatures/creature.cpp b/src/creatures/creature.cpp index a001e9087a5..2b3d9ae0ebd 100644 --- a/src/creatures/creature.cpp +++ b/src/creatures/creature.cpp @@ -431,9 +431,9 @@ void Creature::checkSummonMove(const Position &newPos, bool teleportSummon) { if (hasSummons()) { std::vector> despawnMonsterList; for (const auto &summon : getSummons()) { - const Position &pos = summon->getPosition(); - std::shared_ptr monster = summon->getMonster(); - auto tile = getTile(); + const auto &pos = summon->getPosition(); + const auto &monster = summon->getMonster(); + const auto &tile = getTile(); bool protectionZoneCheck = tile ? tile->hasFlag(TILESTATE_PROTECTIONZONE) : false; // Check if any of our summons is out of range (+/- 0 floors or 15 tiles away) bool checkSummonDist = Position::getDistanceZ(newPos, pos) > 0 || (std::max(Position::getDistanceX(newPos, pos), Position::getDistanceY(newPos, pos)) > 15); @@ -441,12 +441,12 @@ void Creature::checkSummonMove(const Position &newPos, bool teleportSummon) { bool checkRemoveDist = Position::getDistanceZ(newPos, pos) > 2 || (std::max(Position::getDistanceX(newPos, pos), Position::getDistanceY(newPos, pos)) > 30); if (monster && monster->isFamiliar() && checkSummonDist || teleportSummon && !protectionZoneCheck && checkSummonDist) { - auto creatureMaster = summon->getMaster(); + const auto &creatureMaster = summon->getMaster(); if (!creatureMaster) { continue; } - if (std::shared_ptr masterTile = creatureMaster->getTile()) { + if (const auto &masterTile = creatureMaster->getTile()) { if (masterTile->hasFlag(TILESTATE_TELEPORT)) { g_logger().warn("[{}] cannot teleport summon, position has teleport. {}", __FUNCTION__, creatureMaster->getPosition().toString()); } else { @@ -461,7 +461,7 @@ void Creature::checkSummonMove(const Position &newPos, bool teleportSummon) { } } - for (std::shared_ptr despawnCreature : despawnMonsterList) { + for (const auto &despawnCreature : despawnMonsterList) { if (!despawnMonsterList.empty()) { g_game().removeCreature(despawnCreature, true); } @@ -1243,13 +1243,16 @@ bool Creature::setMaster(std::shared_ptr newMaster, bool reloadCreatur g_game().reloadCreature(self); } if (newMaster) { - newMaster->m_summons.insert(self); + newMaster->m_summons.emplace_back(self); } m_master = newMaster; if (oldMaster) { - oldMaster->m_summons.erase(self); + const auto &it = std::ranges::find(oldMaster->m_summons, self); + if (it != oldMaster->m_summons.end()) { + oldMaster->m_summons.erase(it); + } } return true; } @@ -1796,9 +1799,8 @@ void Creature::setIncreasePercent(CombatType_t combat, int32_t value) { } } -phmap::flat_hash_set> Creature::getZones() { - auto tile = getTile(); - if (tile) { +std::unordered_set> Creature::getZones() { + if (const auto &tile = getTile()) { return tile->getZones(); } return {}; diff --git a/src/creatures/creature.hpp b/src/creatures/creature.hpp index 5e03e33d703..e6e8e005ee7 100644 --- a/src/creatures/creature.hpp +++ b/src/creatures/creature.hpp @@ -267,7 +267,7 @@ class Creature : virtual public Thing, public SharedObject { return ZONE_NORMAL; } - phmap::flat_hash_set> getZones(); + std::unordered_set> getZones(); // walk functions void startAutoWalk(const std::vector &listDir, bool ignoreConditions = false); @@ -341,7 +341,7 @@ class Creature : virtual public Thing, public SharedObject { return m_master.lock(); } - const phmap::flat_hash_set> &getSummons() const { + const auto &getSummons() const { return m_summons; } @@ -666,7 +666,7 @@ class Creature : virtual public Thing, public SharedObject { CountMap damageMap; - phmap::flat_hash_set> m_summons; + std::vector> m_summons; CreatureEventList eventsList; ConditionList conditions; diff --git a/src/creatures/monsters/monster.hpp b/src/creatures/monsters/monster.hpp index e6178a4f77c..29182fe6865 100644 --- a/src/creatures/monsters/monster.hpp +++ b/src/creatures/monsters/monster.hpp @@ -17,7 +17,6 @@ class Creature; class Game; class Spawn; -using CreatureHashSet = phmap::flat_hash_set>; using CreatureList = std::list>; using CreatureWeakHashMap = phmap::flat_hash_map>; @@ -99,7 +98,7 @@ class Monster final : public Creature { if (master && master->getMonster()) { return master->getMonster()->isEnemyFaction(faction); } - return mType->info.enemyFactions.empty() ? false : mType->info.enemyFactions.find(faction) != mType->info.enemyFactions.end(); + return mType->info.enemyFactions.empty() ? false : mType->info.enemyFactions.contains(faction); } bool isPushable() override { @@ -204,17 +203,19 @@ class Monster final : public Creature { } return list; } - CreatureHashSet getFriendList() { - CreatureHashSet set; + + std::vector> getFriendList() { + std::vector> list; + for (auto it = friendList.begin(); it != friendList.end();) { if (auto friendCreature = it->second.lock()) { - set.insert(friendCreature); + list.emplace_back(friendCreature); ++it; } else { it = friendList.erase(it); } } - return set; + return list; } bool isTarget(std::shared_ptr creature); diff --git a/src/creatures/monsters/monsters.hpp b/src/creatures/monsters/monsters.hpp index e0cc79b88e9..a4723fcaac2 100644 --- a/src/creatures/monsters/monsters.hpp +++ b/src/creatures/monsters/monsters.hpp @@ -136,7 +136,7 @@ class MonsterType { bool targetPreferMaster = false; Faction_t faction = FACTION_DEFAULT; - phmap::flat_hash_set enemyFactions; + stdext::vector_set enemyFactions; bool canPushItems = false; bool canPushCreatures = false; diff --git a/src/creatures/npcs/npc.cpp b/src/creatures/npcs/npc.cpp index 2df46c285cb..431d3113ccd 100644 --- a/src/creatures/npcs/npc.cpp +++ b/src/creatures/npcs/npc.cpp @@ -151,7 +151,7 @@ void Npc::onPlayerAppear(std::shared_ptr player) { if (player->hasFlag(PlayerFlags_t::IgnoredByNpcs) || playerSpectators.contains(player)) { return; } - playerSpectators.emplace_back(player); + playerSpectators.emplace(player); manageIdle(); } @@ -531,7 +531,7 @@ void Npc::onThinkWalk(uint32_t interval) { void Npc::onCreatureWalk() { Creature::onCreatureWalk(); - playerSpectators.erase_if([this](const auto &creature) { return !this->canSee(creature->getPosition()); }); + phmap::erase_if(playerSpectators, [this](const auto &creature) { return !this->canSee(creature->getPosition()); }); } void Npc::onPlacedCreature() { @@ -542,7 +542,7 @@ void Npc::loadPlayerSpectators() { auto spec = Spectators().find(position, true); for (const auto &creature : spec) { if (!creature->getPlayer()->hasFlag(PlayerFlags_t::IgnoredByNpcs)) { - playerSpectators.emplace_back(creature->getPlayer()); + playerSpectators.emplace(creature->getPlayer()); } } } diff --git a/src/creatures/npcs/npc.hpp b/src/creatures/npcs/npc.hpp index 38cd9840a17..993934374d5 100644 --- a/src/creatures/npcs/npc.hpp +++ b/src/creatures/npcs/npc.hpp @@ -188,7 +188,7 @@ class Npc final : public Creature { bool ignoreHeight; - stdext::vector_set> playerSpectators; + phmap::flat_hash_set> playerSpectators; Position masterPos; friend class LuaScriptInterface; diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 1178a666e1c..d26952bc54c 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -484,54 +484,48 @@ uint32_t Player::getClientIcons() { } void Player::addMonsterToCyclopediaTrackerList(const std::shared_ptr mtype, bool isBoss, bool reloadClient /* = false */) { - if (client) { - uint16_t raceId = mtype ? mtype->info.raceid : 0; - // Bostiary tracker logic - if (isBoss) { - m_bosstiaryMonsterTracker.insert(mtype); - if (reloadClient && raceId != 0) { + if (!client) { + return; + } + + const uint16_t raceId = mtype ? mtype->info.raceid : 0; + auto &tracker = isBoss ? m_bosstiaryMonsterTracker : m_bestiaryMonsterTracker; + if (tracker.emplace(mtype).second) { + if (reloadClient && raceId != 0) { + if (isBoss) { client->parseSendBosstiary(); + } else { + client->sendBestiaryEntryChanged(raceId); } - client->refreshCyclopediaMonsterTracker(m_bosstiaryMonsterTracker, true); - return; } - // Bestiary tracker logic - m_bestiaryMonsterTracker.insert(mtype); - if (reloadClient && raceId != 0) { - client->sendBestiaryEntryChanged(raceId); - } - client->refreshCyclopediaMonsterTracker(m_bestiaryMonsterTracker, false); + client->refreshCyclopediaMonsterTracker(tracker, isBoss); } } void Player::removeMonsterFromCyclopediaTrackerList(std::shared_ptr mtype, bool isBoss, bool reloadClient /* = false */) { - if (client) { - uint16_t raceId = mtype ? mtype->info.raceid : 0; - // Bostiary tracker logic - if (isBoss) { - m_bosstiaryMonsterTracker.erase(mtype); - if (reloadClient && raceId != 0) { + if (!client) { + return; + } + + const uint16_t raceId = mtype ? mtype->info.raceid : 0; + auto &tracker = isBoss ? m_bosstiaryMonsterTracker : m_bestiaryMonsterTracker; + + if (tracker.erase(mtype) > 0) { + if (reloadClient && raceId != 0) { + if (isBoss) { client->parseSendBosstiary(); + } else { + client->sendBestiaryEntryChanged(raceId); } - client->refreshCyclopediaMonsterTracker(m_bosstiaryMonsterTracker, true); - return; } - // Bestiary tracker logic - m_bestiaryMonsterTracker.erase(mtype); - if (reloadClient && raceId != 0) { - client->sendBestiaryEntryChanged(raceId); - } - client->refreshCyclopediaMonsterTracker(m_bestiaryMonsterTracker, false); + client->refreshCyclopediaMonsterTracker(tracker, isBoss); } } -bool Player::isBossOnBosstiaryTracker(const std::shared_ptr monsterType) const { - if (!monsterType) { - return false; - } - return m_bosstiaryMonsterTracker.contains(monsterType); +bool Player::isBossOnBosstiaryTracker(const std::shared_ptr &monsterType) const { + return monsterType ? m_bosstiaryMonsterTracker.contains(monsterType) : false; } void Player::updateInventoryWeight() { @@ -2925,7 +2919,7 @@ void Player::removePlayer(bool displayEffect, bool forced /*= true*/) { } } -void Player::notifyStatusChange(std::shared_ptr loginPlayer, VipStatus_t status, bool message) { +void Player::notifyStatusChange(std::shared_ptr loginPlayer, VipStatus_t status, bool message) const { if (!client) { return; } @@ -2989,7 +2983,7 @@ bool Player::addVIPInternal(uint32_t vipGuid) { return VIPList.insert(vipGuid).second; } -bool Player::editVIP(uint32_t vipGuid, const std::string &description, uint32_t icon, bool notify) { +bool Player::editVIP(uint32_t vipGuid, const std::string &description, uint32_t icon, bool notify) const { auto it = VIPList.find(vipGuid); if (it == VIPList.end()) { return false; // player is not in VIP diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 2a32a838c36..1b35273b9cf 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -304,7 +304,7 @@ class Player final : public Creature, public Cylinder, public Bankable { return guildWarVector; } - const phmap::parallel_flat_hash_set> &getCyclopediaMonsterTrackerSet(bool isBoss) const { + const std::unordered_set> &getCyclopediaMonsterTrackerSet(bool isBoss) const { return isBoss ? m_bosstiaryMonsterTracker : m_bestiaryMonsterTracker; } @@ -318,17 +318,17 @@ class Player final : public Creature, public Cylinder, public Bankable { } } - void refreshCyclopediaMonsterTracker(bool isBoss = false) const { + void refreshCyclopediaMonsterTracker(bool isBoss = false) { refreshCyclopediaMonsterTracker(getCyclopediaMonsterTrackerSet(isBoss), isBoss); } - void refreshCyclopediaMonsterTracker(const phmap::parallel_flat_hash_set> &trackerList, bool isBoss) const { + void refreshCyclopediaMonsterTracker(const std::unordered_set> &trackerList, bool isBoss) const { if (client) { client->refreshCyclopediaMonsterTracker(trackerList, isBoss); } } - bool isBossOnBosstiaryTracker(const std::shared_ptr monsterType) const; + bool isBossOnBosstiaryTracker(const std::shared_ptr &monsterType) const; Vocation* getVocation() const { return vocation; @@ -804,11 +804,11 @@ class Player final : public Creature, public Cylinder, public Bankable { } // V.I.P. functions - void notifyStatusChange(std::shared_ptr player, VipStatus_t status, bool message = true); + void notifyStatusChange(std::shared_ptr player, VipStatus_t status, bool message = true) const; bool removeVIP(uint32_t vipGuid); bool addVIP(uint32_t vipGuid, const std::string &vipName, VipStatus_t status); bool addVIPInternal(uint32_t vipGuid); - bool editVIP(uint32_t vipGuid, const std::string &description, uint32_t icon, bool notify); + bool editVIP(uint32_t vipGuid, const std::string &description, uint32_t icon, bool notify) const; // follow functions bool setFollowCreature(std::shared_ptr creature) override; @@ -2609,7 +2609,6 @@ class Player final : public Creature, public Cylinder, public Bankable { bool onKilledMonster(const std::shared_ptr &target, bool lastHit); phmap::flat_hash_set attackedSet; - phmap::flat_hash_set VIPList; std::map openContainers; @@ -2646,8 +2645,8 @@ class Player final : public Creature, public Cylinder, public Bankable { // TODO: This variable is only temporarily used when logging in, get rid of it somehow. std::forward_list> storedConditionList; - phmap::parallel_flat_hash_set> m_bestiaryMonsterTracker; - phmap::parallel_flat_hash_set> m_bosstiaryMonsterTracker; + std::unordered_set> m_bestiaryMonsterTracker; + std::unordered_set> m_bosstiaryMonsterTracker; std::string name; std::string guildNick; diff --git a/src/game/game.cpp b/src/game/game.cpp index a01ac60bff8..64cbf5cec97 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -7617,8 +7617,7 @@ void Game::updatePlayerHelpers(std::shared_ptr player) { return; } - uint16_t helpers = player->getHelpers(); - + const uint16_t helpers = player->getHelpers(); for (const auto &spectator : Spectators().find(player->getPosition(), true)) { spectator->getPlayer()->sendCreatureHelpers(player->getID(), helpers); } @@ -9925,25 +9924,28 @@ void Game::setTransferPlayerHouseItems(uint32_t houseId, uint32_t playerId) { } template -phmap::parallel_flat_hash_set setDifference(const phmap::flat_hash_set &setA, const phmap::flat_hash_set &setB) { - phmap::parallel_flat_hash_set setResult; +std::vector setDifference(const std::unordered_set &setA, const std::unordered_set &setB) { + std::vector setResult; + setResult.reserve(setA.size()); + for (const auto &elem : setA) { - if (setB.find(elem) == setB.end()) { - setResult.insert(elem); + if (!setB.contains(elem)) { + setResult.emplace_back(elem); } } + return setResult; } -ReturnValue Game::beforeCreatureZoneChange(std::shared_ptr creature, const phmap::flat_hash_set> &fromZones, const phmap::flat_hash_set> &toZones, bool force /* = false*/) const { +ReturnValue Game::beforeCreatureZoneChange(std::shared_ptr creature, const std::unordered_set> &fromZones, const std::unordered_set> &toZones, bool force /* = false*/) const { if (!creature) { return RETURNVALUE_NOTPOSSIBLE; } // fromZones - toZones = zones that creature left - auto zonesLeaving = setDifference(fromZones, toZones); + const auto &zonesLeaving = setDifference(fromZones, toZones); // toZones - fromZones = zones that creature entered - auto zonesEntering = setDifference(toZones, fromZones); + const auto &zonesEntering = setDifference(toZones, fromZones); if (zonesLeaving.empty() && zonesEntering.empty()) { return RETURNVALUE_NOERROR; @@ -9965,15 +9967,15 @@ ReturnValue Game::beforeCreatureZoneChange(std::shared_ptr creature, c return RETURNVALUE_NOERROR; } -void Game::afterCreatureZoneChange(std::shared_ptr creature, const phmap::flat_hash_set> &fromZones, const phmap::flat_hash_set> &toZones) const { +void Game::afterCreatureZoneChange(std::shared_ptr creature, const std::unordered_set> &fromZones, const std::unordered_set> &toZones) const { if (!creature) { return; } // fromZones - toZones = zones that creature left - auto zonesLeaving = setDifference(fromZones, toZones); + const auto &zonesLeaving = setDifference(fromZones, toZones); // toZones - fromZones = zones that creature entered - auto zonesEntering = setDifference(toZones, fromZones); + const auto &zonesEntering = setDifference(toZones, fromZones); for (const auto &zone : zonesLeaving) { zone->creatureRemoved(creature); diff --git a/src/game/game.hpp b/src/game/game.hpp index 2b30a31d2f4..9dbbbca9f63 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -557,7 +557,7 @@ class Game { Raids raids; Canary::protobuf::appearances::Appearances appearances; - phmap::flat_hash_set> getTilesToClean() const { + auto getTilesToClean() const { return tilesToClean; } void addTileToClean(std::shared_ptr tile) { @@ -599,11 +599,11 @@ class Game { mapLuaItemsStored[position] = itemId; } - std::set getFiendishMonsters() const { + auto getFiendishMonsters() const { return fiendishMonsters; } - std::set getInfluencedMonsters() const { + auto getInfluencedMonsters() const { return influencedMonsters; } @@ -673,8 +673,8 @@ class Game { */ bool tryRetrieveStashItems(std::shared_ptr player, std::shared_ptr item); - ReturnValue beforeCreatureZoneChange(std::shared_ptr creature, const phmap::flat_hash_set> &fromZones, const phmap::flat_hash_set> &toZones, bool force = false) const; - void afterCreatureZoneChange(std::shared_ptr creature, const phmap::flat_hash_set> &fromZones, const phmap::flat_hash_set> &toZones) const; + ReturnValue beforeCreatureZoneChange(std::shared_ptr creature, const std::unordered_set> &fromZones, const std::unordered_set> &toZones, bool force = false) const; + void afterCreatureZoneChange(std::shared_ptr creature, const std::unordered_set> &fromZones, const std::unordered_set> &toZones) const; std::unique_ptr &getIOWheel(); const std::unique_ptr &getIOWheel() const; @@ -684,8 +684,8 @@ class Game { private: std::map forgeMonsterEventIds; - std::set fiendishMonsters; - std::set influencedMonsters; + std::unordered_set fiendishMonsters; + std::unordered_set influencedMonsters; void checkImbuements(); bool playerSaySpell(std::shared_ptr player, SpeakClasses type, const std::string &text); void playerWhisper(std::shared_ptr player, const std::string &text); @@ -822,7 +822,7 @@ class Game { std::map> bedSleepersMap; - phmap::flat_hash_set> tilesToClean; + std::unordered_set> tilesToClean; ModalWindow offlineTrainingWindow { std::numeric_limits::max(), "Choose a Skill", "Please choose a skill:" }; diff --git a/src/game/scheduling/events_scheduler.cpp b/src/game/scheduling/events_scheduler.cpp index d5c71378f4a..fc41f2c8b64 100644 --- a/src/game/scheduling/events_scheduler.cpp +++ b/src/game/scheduling/events_scheduler.cpp @@ -28,7 +28,7 @@ bool EventsScheduler::loadScheduleEventFromXml() { // Keep track of loaded scripts to check for duplicates int count = 0; - std::set> loadedScripts; + phmap::flat_hash_set loadedScripts; std::map eventsOnSameDay; for (const auto &eventNode : doc.child("events").children()) { std::string eventScript = eventNode.attribute("script").as_string(); diff --git a/src/game/zones/zone.hpp b/src/game/zones/zone.hpp index 4a0c0318006..91fa6f25e29 100644 --- a/src/game/zones/zone.hpp +++ b/src/game/zones/zone.hpp @@ -9,7 +9,6 @@ #pragma once -#include #include "game/movement/position.hpp" #include "items/item.hpp" #include "creatures/creature.hpp" diff --git a/src/io/io_bosstiary.cpp b/src/io/io_bosstiary.cpp index e4aecee5fc8..10c4f2f088c 100644 --- a/src/io/io_bosstiary.cpp +++ b/src/io/io_bosstiary.cpp @@ -234,14 +234,13 @@ uint32_t IOBosstiary::calculateBossPoints(uint16_t lootBonus) const { return static_cast((2.5 * lootBonus * lootBonus) - (477.5 * lootBonus) + 24000); } -phmap::parallel_flat_hash_set IOBosstiary::getBosstiaryFinished(std::shared_ptr player, uint8_t level /* = 1*/) const { - phmap::parallel_flat_hash_set unlockedMonsters; +std::vector IOBosstiary::getBosstiaryFinished(const std::shared_ptr &player, uint8_t level /* = 1*/) const { if (!player) { - return unlockedMonsters; + return {}; } - for (std::map bossesMap = getBosstiaryMap(); - const auto &[bossId, bossName] : bossesMap) { + stdext::vector_set unlockedMonsters; + for (const auto &[bossId, bossName] : getBosstiaryMap()) { uint32_t bossKills = player->getBestiaryKillCount(bossId); if (bossKills == 0) { continue; @@ -258,14 +257,14 @@ phmap::parallel_flat_hash_set IOBosstiary::getBosstiaryFinished(std::s const std::vector &infoForCurrentRace = it->second; auto levelKills = infoForCurrentRace.at(level - 1).kills; if (bossKills >= levelKills) { - unlockedMonsters.insert(bossId); + unlockedMonsters.emplace(bossId); } } else { g_logger().warn("[{}] boss with id {} and name {} not found in bossRace", __FUNCTION__, bossId, bossName); } } - return unlockedMonsters; + return unlockedMonsters.data(); } uint8_t IOBosstiary::getBossCurrentLevel(std::shared_ptr player, uint16_t bossId) const { diff --git a/src/io/io_bosstiary.hpp b/src/io/io_bosstiary.hpp index a253be3b467..b491247b295 100644 --- a/src/io/io_bosstiary.hpp +++ b/src/io/io_bosstiary.hpp @@ -63,7 +63,7 @@ class IOBosstiary { void addBosstiaryKill(std::shared_ptr player, const std::shared_ptr mtype, uint32_t amount = 1) const; uint16_t calculateLootBonus(uint32_t bossPoints) const; uint32_t calculateBossPoints(uint16_t lootBonus) const; - phmap::parallel_flat_hash_set getBosstiaryFinished(std::shared_ptr player, uint8_t level = 1) const; + std::vector getBosstiaryFinished(const std::shared_ptr &player, uint8_t level = 1) const; uint8_t getBossCurrentLevel(std::shared_ptr player, uint16_t bossId) const; uint32_t calculteRemoveBoss(uint8_t removeTimes) const; const std::vector &getBossRaceKillStages(BosstiaryRarity_t race) const; diff --git a/src/io/iobestiary.cpp b/src/io/iobestiary.cpp index c9fb933bc8c..2f66c53ad26 100644 --- a/src/io/iobestiary.cpp +++ b/src/io/iobestiary.cpp @@ -227,7 +227,6 @@ void IOBestiary::addBestiaryKill(std::shared_ptr player, const std::shar (curCount < mtype->info.bestiaryFirstUnlock && (curCount + amount) >= mtype->info.bestiaryFirstUnlock) || // First kill stage reached (curCount < mtype->info.bestiarySecondUnlock && (curCount + amount) >= mtype->info.bestiarySecondUnlock) || // Second kill stage reached (curCount < mtype->info.bestiaryToUnlock && (curCount + amount) >= mtype->info.bestiaryToUnlock)) { // Final kill stage reached - ss << "You unlocked details for the creature '" << mtype->name << "'"; player->sendTextMessage(MESSAGE_STATUS, ss.str()); player->sendBestiaryEntryChanged(raceid); @@ -305,7 +304,6 @@ void IOBestiary::sendBuyCharmRune(std::shared_ptr player, charmRune_t ru int32_t value = bitToggle(player->getUnlockedRunesBit(), charm, true); player->setUnlockedRunesBit(value); - } else if (action == 1) { std::list usedRunes = getCharmUsedRuneBitAll(player); uint16_t limitRunes = 0; @@ -396,18 +394,21 @@ std::map IOBestiary::getBestiaryKillCountByMonsterIDs(std::s return raceMonsters; } -phmap::parallel_flat_hash_set IOBestiary::getBestiaryFinished(std::shared_ptr player) const { - phmap::parallel_flat_hash_set finishedMonsters; - auto bestiaryMap = g_game().getBestiaryList(); +std::vector IOBestiary::getBestiaryFinished(const std::shared_ptr &player) const { + const auto &bestiaryMap = g_game().getBestiaryList(); + + stdext::vector_set finishedMonsters; + finishedMonsters.reserve(bestiaryMap.size()); for (const auto &[monsterTypeRaceId, monsterTypeName] : bestiaryMap) { - uint32_t thisKilled = player->getBestiaryKillCount(monsterTypeRaceId); - auto mtype = g_monsters().getMonsterType(monsterTypeName); + const auto &mtype = g_monsters().getMonsterType(monsterTypeName); + const uint32_t thisKilled = player->getBestiaryKillCount(monsterTypeRaceId); + if (mtype && thisKilled >= mtype->info.bestiaryToUnlock) { finishedMonsters.insert(monsterTypeRaceId); } } - return finishedMonsters; + return finishedMonsters.data(); } int8_t IOBestiary::calculateDifficult(uint32_t chance) const { diff --git a/src/io/iobestiary.hpp b/src/io/iobestiary.hpp index 26f802dcb5b..896e00434a1 100644 --- a/src/io/iobestiary.hpp +++ b/src/io/iobestiary.hpp @@ -72,7 +72,7 @@ class IOBestiary { bool hasCharmUnlockedRuneBit(const std::shared_ptr charm, int32_t input) const; std::list getCharmUsedRuneBitAll(std::shared_ptr player); - phmap::parallel_flat_hash_set getBestiaryFinished(std::shared_ptr player) const; + std::vector getBestiaryFinished(const std::shared_ptr &player) const; charmRune_t getCharmFromTarget(std::shared_ptr player, const std::shared_ptr mtype); diff --git a/src/items/containers/container.cpp b/src/items/containers/container.cpp index 54ce00acec4..af17ce692bc 100644 --- a/src/items/containers/container.cpp +++ b/src/items/containers/container.cpp @@ -278,8 +278,8 @@ std::deque> Container::getStoreInboxFilteredItems() const return storeInboxFilteredList; } -phmap::flat_hash_set Container::getStoreInboxValidCategories() const { - phmap::flat_hash_set validCategories; +std::vector Container::getStoreInboxValidCategories() const { + stdext::vector_set validCategories; for (const auto &item : itemlist) { auto itemId = item->getID(); auto attribute = item->getCustomAttribute("unWrapId"); @@ -297,7 +297,7 @@ phmap::flat_hash_set Container::getStoreInboxValidCategorie } } - return validCategories; + return validCategories.data(); } std::shared_ptr Container::getFilteredItemByIndex(size_t index) const { diff --git a/src/items/containers/container.hpp b/src/items/containers/container.hpp index 0b014aee58f..56d048f3b10 100644 --- a/src/items/containers/container.hpp +++ b/src/items/containers/container.hpp @@ -109,7 +109,7 @@ class Container : public Item, public Cylinder { bool isStoreInbox() const; bool isStoreInboxFiltered() const; std::deque> getStoreInboxFilteredItems() const; - phmap::flat_hash_set getStoreInboxValidCategories() const; + std::vector getStoreInboxValidCategories() const; std::shared_ptr getFilteredItemByIndex(size_t index) const; std::shared_ptr getItemByIndex(size_t index) const; bool isHoldingItem(std::shared_ptr item); diff --git a/src/items/tile.cpp b/src/items/tile.cpp index 44631406fda..22c325cfda2 100644 --- a/src/items/tile.cpp +++ b/src/items/tile.cpp @@ -1800,12 +1800,8 @@ std::shared_ptr Tile::getDoorItem() const { return nullptr; } -phmap::flat_hash_set> Tile::getZones() { - return zones; -} - void Tile::addZone(std::shared_ptr zone) { - zones.insert(zone); + zones.emplace(zone); const auto &items = getItemList(); if (items) { for (const auto &item : *items) { @@ -1821,12 +1817,12 @@ void Tile::addZone(std::shared_ptr zone) { } void Tile::clearZones() { - phmap::flat_hash_set> zonesToRemove; + std::vector> zonesToRemove; for (const auto &zone : zones) { if (zone->isStatic()) { continue; } - zonesToRemove.insert(zone); + zonesToRemove.emplace_back(zone); const auto &items = getItemList(); if (items) { for (const auto &item : *items) { diff --git a/src/items/tile.hpp b/src/items/tile.hpp index c5471756159..bb10b309147 100644 --- a/src/items/tile.hpp +++ b/src/items/tile.hpp @@ -176,7 +176,9 @@ class Tile : public Cylinder, public SharedObject { void addZone(std::shared_ptr zone); void clearZones(); - phmap::flat_hash_set> getZones(); + auto getZones() const { + return zones; + } ZoneType_t getZoneType() const { if (hasFlag(TILESTATE_PROTECTIONZONE)) { @@ -270,7 +272,7 @@ class Tile : public Cylinder, public SharedObject { std::shared_ptr ground = nullptr; Position tilePos; uint32_t flags = 0; - phmap::flat_hash_set> zones; + std::unordered_set> zones; }; // Used for walkable tiles, where there is high likeliness of diff --git a/src/lua/creature/events.cpp b/src/lua/creature/events.cpp index 176044d666e..055394214b1 100644 --- a/src/lua/creature/events.cpp +++ b/src/lua/creature/events.cpp @@ -30,14 +30,14 @@ bool Events::loadFromXml() { info = {}; - std::set classes; + phmap::flat_hash_set classes; for (auto eventNode : doc.child("events").children()) { if (!eventNode.attribute("enabled").as_bool()) { continue; } const std::string &className = eventNode.attribute("class").as_string(); - auto res = classes.insert(className); + auto res = classes.emplace(className); if (res.second) { const std::string &lowercase = asLowerCaseString(className); const std::string &scriptName = lowercase + ".lua"; diff --git a/src/lua/functions/creatures/monster/monster_functions.cpp b/src/lua/functions/creatures/monster/monster_functions.cpp index 60e60fe876c..e0f702f249e 100644 --- a/src/lua/functions/creatures/monster/monster_functions.cpp +++ b/src/lua/functions/creatures/monster/monster_functions.cpp @@ -219,11 +219,11 @@ int MonsterFunctions::luaMonsterGetFriendList(lua_State* L) { return 1; } - const auto friendList = monster->getFriendList(); + const auto &friendList = monster->getFriendList(); lua_createtable(L, friendList.size(), 0); int index = 0; - for (std::shared_ptr creature : friendList) { + for (const auto &creature : friendList) { pushUserdata(L, creature); setCreatureMetatable(L, -1, creature); lua_rawseti(L, -2, ++index); diff --git a/src/lua/functions/creatures/monster/monster_type_functions.cpp b/src/lua/functions/creatures/monster/monster_type_functions.cpp index 0db51998ea7..146ee7b1a20 100644 --- a/src/lua/functions/creatures/monster/monster_type_functions.cpp +++ b/src/lua/functions/creatures/monster/monster_type_functions.cpp @@ -426,13 +426,13 @@ int MonsterTypeFunctions::luaMonsterTypeEnemyFactions(lua_State* L) { lua_createtable(L, monsterType->info.enemyFactions.size(), 0); int index = 0; - for (auto faction : monsterType->info.enemyFactions) { + for (const auto &faction : monsterType->info.enemyFactions) { lua_pushnumber(L, faction); lua_rawseti(L, -2, ++index); } } else { Faction_t faction = getNumber(L, 2); - monsterType->info.enemyFactions.emplace(faction); + monsterType->info.enemyFactions.insert(faction); pushBoolean(L, true); } } else { diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index 12e7379a26d..7c8934b4574 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -328,8 +328,7 @@ int PlayerFunctions::luaPlayerIsMonsterBestiaryUnlocked(lua_State* L) { return 0; } - for (auto finishedMonsters = g_iobestiary().getBestiaryFinished(player); - uint16_t finishedRaceId : finishedMonsters) { + for (uint16_t finishedRaceId : g_iobestiary().getBestiaryFinished(player)) { if (raceId == finishedRaceId) { pushBoolean(L, true); return 1; diff --git a/src/lua/functions/lua_functions_loader.cpp b/src/lua/functions/lua_functions_loader.cpp index 0973876c294..bdf7dbb37bc 100644 --- a/src/lua/functions/lua_functions_loader.cpp +++ b/src/lua/functions/lua_functions_loader.cpp @@ -239,11 +239,11 @@ void LuaFunctionsLoader::setMetatable(lua_State* L, int32_t index, const std::st } void LuaFunctionsLoader::setWeakMetatable(lua_State* L, int32_t index, const std::string &name) { + static phmap::flat_hash_set weakObjectTypes; if (validateDispatcherContext(__FUNCTION__)) { return; } - static std::set weakObjectTypes; const std::string &weakName = name + "_weak"; auto result = weakObjectTypes.emplace(name); diff --git a/src/map/house/house.cpp b/src/map/house/house.cpp index 8bb26bcfb6b..748e24aeed8 100644 --- a/src/map/house/house.cpp +++ b/src/map/house/house.cpp @@ -163,7 +163,7 @@ void House::updateDoorDescription() const { } } -AccessHouseLevel_t House::getHouseAccessLevel(std::shared_ptr player) { +AccessHouseLevel_t House::getHouseAccessLevel(std::shared_ptr player) const { if (!player) { return HOUSE_OWNER; } @@ -369,10 +369,6 @@ bool House::getAccessList(uint32_t listId, std::string &list) const { return door->getAccessList(list); } -bool House::isInvited(std::shared_ptr player) { - return getHouseAccessLevel(player) != HOUSE_NOT_INVITED; -} - void House::addDoor(std::shared_ptr door) { doorList.push_back(door); door->setHouse(static_self_cast()); @@ -414,7 +410,7 @@ std::shared_ptr House::getDoorByPosition(const Position &pos) { return nullptr; } -bool House::canEditAccessList(uint32_t listId, std::shared_ptr player) { +bool House::canEditAccessList(uint32_t listId, const std::shared_ptr &player) const { switch (getHouseAccessLevel(player)) { case HOUSE_OWNER: return true; @@ -602,18 +598,17 @@ void AccessList::addGuildRank(const std::string &name, const std::string &guildN } } -bool AccessList::isInList(std::shared_ptr player) { +bool AccessList::isInList(std::shared_ptr player) const { if (allowEveryone) { return true; } - auto playerIt = playerList.find(player->getGUID()); - if (playerIt != playerList.end()) { + if (playerList.contains(player->getGUID())) { return true; } - GuildRank_ptr rank = player->getGuildRank(); - return rank && guildRankList.find(rank->id) != guildRankList.end(); + const auto &rank = player->getGuildRank(); + return rank && guildRankList.contains(rank->id); } void AccessList::getList(std::string &retList) const { @@ -648,7 +643,7 @@ void Door::setHouse(std::shared_ptr newHouse) { } } -bool Door::canUse(std::shared_ptr player) { +bool Door::canUse(std::shared_ptr player) const { if (!house) { return true; } diff --git a/src/map/house/house.hpp b/src/map/house/house.hpp index 845693e303e..2e8427a57a0 100644 --- a/src/map/house/house.hpp +++ b/src/map/house/house.hpp @@ -25,7 +25,7 @@ class AccessList { void addGuild(const std::string &name); void addGuildRank(const std::string &name, const std::string &rankName); - bool isInList(std::shared_ptr player); + bool isInList(std::shared_ptr player) const; void getList(std::string &list) const; @@ -63,7 +63,7 @@ class Door final : public Item { return getAttribute(ItemAttribute_t::DOORID); } - bool canUse(std::shared_ptr player); + bool canUse(std::shared_ptr player) const; void setAccessList(const std::string &textlist); bool getAccessList(std::string &list) const; @@ -104,16 +104,18 @@ class House : public SharedObject { void addTile(std::shared_ptr tile); void updateDoorDescription() const; - bool canEditAccessList(uint32_t listId, std::shared_ptr player); + bool canEditAccessList(uint32_t listId, const std::shared_ptr &player) const; // listId special = values: // GUEST_LIST = guest list // SUBOWNER_LIST = subowner list void setAccessList(uint32_t listId, const std::string &textlist); bool getAccessList(uint32_t listId, std::string &list) const; - bool isInvited(std::shared_ptr player); + bool isInvited(const std::shared_ptr &player) const { + return getHouseAccessLevel(player) != HOUSE_NOT_INVITED; + } - AccessHouseLevel_t getHouseAccessLevel(std::shared_ptr player); + AccessHouseLevel_t getHouseAccessLevel(std::shared_ptr player) const; bool kickPlayer(std::shared_ptr player, std::shared_ptr target); void setEntryPos(Position pos) { diff --git a/src/map/map.cpp b/src/map/map.cpp index 72e867551be..3771f5662ec 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -325,8 +325,8 @@ void Map::moveCreature(const std::shared_ptr &creature, const std::sha Position oldPos = oldTile->getPosition(); Position newPos = newTile->getPosition(); - auto fromZones = oldTile->getZones(); - auto toZones = newTile->getZones(); + const auto &fromZones = oldTile->getZones(); + const auto &toZones = newTile->getZones(); if (auto ret = g_game().beforeCreatureZoneChange(creature, fromZones, toZones); ret != RETURNVALUE_NOERROR) { return; } @@ -694,13 +694,13 @@ uint32_t Map::clean() { } std::vector> toRemove; - for (auto tile : g_game().getTilesToClean()) { + for (const auto &tile : g_game().getTilesToClean()) { if (!tile) { continue; } - if (auto items = tile->getItemList()) { + if (const auto items = tile->getItemList()) { ++tiles; - for (auto item : *items) { + for (const auto &item : *items) { if (item->isCleanable()) { toRemove.emplace_back(item); } @@ -708,7 +708,7 @@ uint32_t Map::clean() { } } - for (auto item : toRemove) { + for (const auto &item : toRemove) { g_game().internalRemoveItem(item, -1); } diff --git a/src/map/spectators.hpp b/src/map/spectators.hpp index 886a51d8c1f..8e73df9ad6f 100644 --- a/src/map/spectators.hpp +++ b/src/map/spectators.hpp @@ -64,7 +64,7 @@ class Spectators { Spectators insert(const std::shared_ptr &creature) { if (creature) { - creatures.emplace_back(creature); + creatures.emplace(creature); } return *this; } diff --git a/src/pch.hpp b/src/pch.hpp index ab57f178e84..0f5775b73d3 100644 --- a/src/pch.hpp +++ b/src/pch.hpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index e81933610a8..8b1a67aaada 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -217,7 +217,7 @@ namespace { * @param msg The network message to send the category to. */ template - void sendContainerCategory(NetworkMessage &msg, phmap::flat_hash_set categories = {}, uint8_t categoryType = 0) { + void sendContainerCategory(NetworkMessage &msg, const std::vector &categories = {}, uint8_t categoryType = 0) { msg.addByte(categoryType); g_logger().debug("Sendding category type '{}', categories total size '{}'", categoryType, categories.size()); msg.addByte(categories.size()); @@ -2728,7 +2728,7 @@ void ProtocolGame::parseSendBuyCharmRune(NetworkMessage &msg) { g_iobestiary().sendBuyCharmRune(player, runeID, action, raceid); } -void ProtocolGame::refreshCyclopediaMonsterTracker(const phmap::parallel_flat_hash_set> &trackerSet, bool isBoss) { +void ProtocolGame::refreshCyclopediaMonsterTracker(const std::unordered_set> &trackerSet, bool isBoss) { if (!player || oldProtocol) { return; } @@ -2809,12 +2809,11 @@ void ProtocolGame::BestiarysendCharms() { msg.addByte(4); // Unknown auto finishedMonstersSet = g_iobestiary().getBestiaryFinished(player); - std::list usedRunes = g_iobestiary().getCharmUsedRuneBitAll(player); - - for (charmRune_t charmRune : usedRunes) { + for (charmRune_t charmRune : g_iobestiary().getCharmUsedRuneBitAll(player)) { const auto tmpCharm = g_iobestiary().getBestiaryCharm(charmRune); uint16_t tmp_raceid = player->parseRacebyCharm(tmpCharm->id, false, 0); - finishedMonstersSet.erase(tmp_raceid); + + std::erase(finishedMonstersSet, tmp_raceid); } msg.add(finishedMonstersSet.size()); @@ -4261,7 +4260,7 @@ void ProtocolGame::sendContainer(uint8_t cid, std::shared_ptr contain } if (container->isStoreInbox()) { - auto categories = container->getStoreInboxValidCategories(); + const auto &categories = container->getStoreInboxValidCategories(); const auto enumName = container->getAttribute(ItemAttribute_t::STORE_INBOX_CATEGORY); auto category = magic_enum::enum_cast(enumName); if (category.has_value()) { @@ -5819,7 +5818,7 @@ void ProtocolGame::sendPartyCreatureUpdate(std::shared_ptr target) { void ProtocolGame::sendPartyCreatureShield(std::shared_ptr target) { uint32_t cid = target->getID(); - if (knownCreatureSet.find(cid) == knownCreatureSet.end()) { + if (!knownCreatureSet.contains(cid)) { sendPartyCreatureUpdate(target); return; } @@ -5837,7 +5836,7 @@ void ProtocolGame::sendPartyCreatureSkull(std::shared_ptr target) { } uint32_t cid = target->getID(); - if (knownCreatureSet.find(cid) == knownCreatureSet.end()) { + if (!knownCreatureSet.contains(cid)) { sendPartyCreatureUpdate(target); return; } @@ -5851,7 +5850,7 @@ void ProtocolGame::sendPartyCreatureSkull(std::shared_ptr target) { void ProtocolGame::sendPartyCreatureHealth(std::shared_ptr target, uint8_t healthPercent) { uint32_t cid = target->getID(); - if (knownCreatureSet.find(cid) == knownCreatureSet.end()) { + if (!knownCreatureSet.contains(cid)) { sendPartyCreatureUpdate(target); return; } @@ -5865,7 +5864,7 @@ void ProtocolGame::sendPartyCreatureHealth(std::shared_ptr target, uin void ProtocolGame::sendPartyPlayerMana(std::shared_ptr target, uint8_t manaPercent) { uint32_t cid = target->getID(); - if (knownCreatureSet.find(cid) == knownCreatureSet.end()) { + if (!knownCreatureSet.contains(cid)) { sendPartyCreatureUpdate(target); } @@ -5883,7 +5882,7 @@ void ProtocolGame::sendPartyPlayerMana(std::shared_ptr target, uint8_t m void ProtocolGame::sendPartyCreatureShowStatus(std::shared_ptr target, bool showStatus) { uint32_t cid = target->getID(); - if (knownCreatureSet.find(cid) == knownCreatureSet.end()) { + if (!knownCreatureSet.contains(cid)) { sendPartyCreatureUpdate(target); } @@ -5901,7 +5900,7 @@ void ProtocolGame::sendPartyCreatureShowStatus(std::shared_ptr target, void ProtocolGame::sendPartyPlayerVocation(std::shared_ptr target) { uint32_t cid = target->getID(); - if (knownCreatureSet.find(cid) == knownCreatureSet.end()) { + if (!knownCreatureSet.contains(cid)) { sendPartyCreatureUpdate(target); return; } @@ -7808,8 +7807,7 @@ void ProtocolGame::reloadCreature(std::shared_ptr creature) { NetworkMessage msg; - phmap::flat_hash_set::iterator it = std::find(knownCreatureSet.begin(), knownCreatureSet.end(), creature->getID()); - if (it != knownCreatureSet.end()) { + if (knownCreatureSet.contains(creature->getID())) { msg.addByte(0x6B); msg.addPosition(creature->getPosition()); msg.addByte(stackpos); @@ -8308,7 +8306,7 @@ void ProtocolGame::parseBosstiarySlot(NetworkMessage &msg) { addGameTask(&Game::playerBosstiarySlot, player->getID(), slotBossId, selectedBossId); } -void ProtocolGame::sendPodiumDetails(NetworkMessage &msg, const phmap::parallel_flat_hash_set &toSendMonsters, bool isBoss) const { +void ProtocolGame::sendPodiumDetails(NetworkMessage &msg, const std::vector &toSendMonsters, bool isBoss) const { auto toSendMonstersSize = static_cast(toSendMonsters.size()); msg.add(toSendMonstersSize); for (const auto &raceId : toSendMonsters) { @@ -8388,10 +8386,10 @@ void ProtocolGame::sendMonsterPodiumWindow(std::shared_ptr podium, const P bool isBossPodium = podium->getID() == ITEM_PODIUM_OF_VIGOUR; msg.addByte(isBossPodium ? 0x01 : 0x00); // Bosstiary or bestiary if (isBossPodium) { - const auto unlockedBosses = g_ioBosstiary().getBosstiaryFinished(player, 2); + const auto &unlockedBosses = g_ioBosstiary().getBosstiaryFinished(player, 2); sendPodiumDetails(msg, unlockedBosses, true); } else { - const auto unlockedMonsters = g_iobestiary().getBestiaryFinished(player); + const auto &unlockedMonsters = g_iobestiary().getBestiaryFinished(player); sendPodiumDetails(msg, unlockedMonsters, false); } diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index 2295c1036ea..8838fc39e7d 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -145,7 +145,7 @@ class ProtocolGame final : public Protocol { void parseBestiarysendCreatures(NetworkMessage &msg); void BestiarysendCharms(); void sendBestiaryEntryChanged(uint16_t raceid); - void refreshCyclopediaMonsterTracker(const phmap::parallel_flat_hash_set> &trackerSet, bool isBoss); + void refreshCyclopediaMonsterTracker(const std::unordered_set> &trackerSet, bool isBoss); void sendTeamFinderList(); void sendLeaderTeamFinder(bool reset); void createLeaderTeamFinder(NetworkMessage &msg); @@ -265,7 +265,7 @@ class ProtocolGame final : public Protocol { void parseSendBosstiary(); void parseSendBosstiarySlots(); void parseBosstiarySlot(NetworkMessage &msg); - void sendPodiumDetails(NetworkMessage &msg, const phmap::parallel_flat_hash_set &toSendMonsters, bool isBoss) const; + void sendPodiumDetails(NetworkMessage &msg, const std::vector &toSendMonsters, bool isBoss) const; void sendMonsterPodiumWindow(std::shared_ptr podium, const Position &position, uint16_t itemId, uint8_t stackPos); void parseSetMonsterPodium(NetworkMessage &msg) const; void sendBosstiaryCooldownTimer(); @@ -471,7 +471,7 @@ class ProtocolGame final : public Protocol { friend class Player; friend class PlayerWheel; - phmap::flat_hash_set knownCreatureSet; + std::unordered_set knownCreatureSet; std::shared_ptr player = nullptr; uint32_t eventConnect = 0; diff --git a/src/utils/vectorset.hpp b/src/utils/vectorset.hpp index 29c6b37665e..dab8901bfc5 100644 --- a/src/utils/vectorset.hpp +++ b/src/utils/vectorset.hpp @@ -22,13 +22,13 @@ namespace stdext { public: bool contains(const T &v) { update(); - return v && std::ranges::binary_search(container, v); + return std::ranges::binary_search(container.begin(), container.end(), v, std::less()); } bool erase(const T &v) { update(); - const auto &it = std::ranges::lower_bound(container, v); + const auto it = std::ranges::lower_bound(container.begin(), container.end(), v, std::less()); if (it == container.end()) { return false; } @@ -43,13 +43,13 @@ namespace stdext { return std::erase_if(container, std::move(fnc)) > 0; } - void push_back(const T &v) { + void insert(const T &v) { needUpdate = true; return container.push_back(v); } template - auto emplace_back(_Valty &&... v) { + auto emplace(_Valty &&... v) { needUpdate = true; return container.emplace_back(v...); } @@ -64,6 +64,22 @@ namespace stdext { return container.insert(container.end(), list.begin(), list.end()); } + constexpr auto insert(std::vector::const_iterator _Where, const T &_Val) { + needUpdate = true; + return container.insert(_Where, _Val); + } + + constexpr auto insert(std::vector::const_iterator _Where, T &&_Val) { + needUpdate = true; + return container.insert(_Where, std::move(_Val)); + } + + template + constexpr auto insert(std::vector::const_iterator _Where, _Iter _First, _Iter _Last) { + needUpdate = true; + return container.insert(_Where, _First, _Last); + } + bool empty() const noexcept { return container.empty(); } @@ -95,6 +111,11 @@ namespace stdext { return container; } + T &operator[](const size_t i) { + update(); + return container[i]; + } + private: void update() noexcept { if (!needUpdate) { @@ -102,7 +123,7 @@ namespace stdext { } needUpdate = false; - std::ranges::sort(container); + std::ranges::sort(container.begin(), container.end(), std::less()); const auto &[f, l] = std::ranges::unique(container); container.erase(f, l); } From b1f9fb2e531e1747d17489e98782ba8b6ca5136b Mon Sep 17 00:00:00 2001 From: Karin Date: Fri, 3 Nov 2023 23:05:11 -0300 Subject: [PATCH 11/12] fix: monster speed (#1734) --- .../monster/quests/the_inquisition/eye_of_the_seven.lua | 2 +- data-otservbr-global/scripts/spells/healing/mass_healing.lua | 1 - data/items/items.xml | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/data-otservbr-global/monster/quests/the_inquisition/eye_of_the_seven.lua b/data-otservbr-global/monster/quests/the_inquisition/eye_of_the_seven.lua index 4a409d1a8ee..492e09217ea 100644 --- a/data-otservbr-global/monster/quests/the_inquisition/eye_of_the_seven.lua +++ b/data-otservbr-global/monster/quests/the_inquisition/eye_of_the_seven.lua @@ -17,7 +17,7 @@ monster.health = 120 monster.maxHealth = 120 monster.race = "venom" monster.corpse = 6036 -monster.speed = 40 +monster.speed = 0 monster.manaCost = 0 monster.changeTarget = { diff --git a/data-otservbr-global/scripts/spells/healing/mass_healing.lua b/data-otservbr-global/scripts/spells/healing/mass_healing.lua index 880c08cb666..ac412dd370d 100644 --- a/data-otservbr-global/scripts/spells/healing/mass_healing.lua +++ b/data-otservbr-global/scripts/spells/healing/mass_healing.lua @@ -58,7 +58,6 @@ spell:cooldown(2 * 1000) spell:groupCooldown(1 * 1000) spell:level(36) spell:mana(150) -spell:isAggressive(false) spell:isPremium(true) spell:isAggressive(false) spell:needLearn(false) diff --git a/data/items/items.xml b/data/items/items.xml index ec4ab6f9bbb..c46348b55b7 100644 --- a/data/items/items.xml +++ b/data/items/items.xml @@ -3690,7 +3690,7 @@ - + From 961db0cad965e0c19b9d1c55cd3374c438267547 Mon Sep 17 00:00:00 2001 From: Luan Luciano Date: Sat, 4 Nov 2023 11:33:36 -0300 Subject: [PATCH 12/12] fix: adjust autoloot as it is activated by default (-1) (#1767) --- data/scripts/talkactions/player/auto_loot.lua | 2 +- src/creatures/players/player.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/scripts/talkactions/player/auto_loot.lua b/data/scripts/talkactions/player/auto_loot.lua index 0b03b0101bd..a5541d51438 100644 --- a/data/scripts/talkactions/player/auto_loot.lua +++ b/data/scripts/talkactions/player/auto_loot.lua @@ -16,7 +16,7 @@ function autoLoot.onSay(player, words, param) player:setStorageValue(STORAGEVALUE_AUTO_LOOT, 1) player:sendTextMessage(MESSAGE_LOOK, "You have successfully enabled your automatic looting!") elseif param == "off" then - player:setStorageValue(STORAGEVALUE_AUTO_LOOT, 0) + player:setStorageValue(STORAGEVALUE_AUTO_LOOT, -1) player:sendTextMessage(MESSAGE_LOOK, "You have successfully disabled your automatic looting!") end return true diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 1b35273b9cf..418f8659e49 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -2502,7 +2502,7 @@ class Player final : public Creature, public Cylinder, public Bankable { } bool checkAutoLoot() const { - const bool autoLoot = g_configManager().getBoolean(AUTOLOOT) && getStorageValue(STORAGEVALUE_AUTO_LOOT) != 0; + const bool autoLoot = g_configManager().getBoolean(AUTOLOOT) && getStorageValue(STORAGEVALUE_AUTO_LOOT) > 0; if (g_configManager().getBoolean(VIP_SYSTEM_ENABLED) && g_configManager().getBoolean(VIP_AUTOLOOT_VIP_ONLY)) { return autoLoot && isVip(); }