diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 319d731faf7..5df73dc6115 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -30,14 +30,14 @@ SoulWarQuest = {
timeToReturnImmuneMegalomania = 70, -- In seconds
- baseBagYouDesireChance = 1, -- 1% base chance
+ baseBagYouDesireChance = 500, -- 1000 = 1% chance, 500 = 0.5% chance
bagYouDesireChancePerTaint = 1, -- Increases 1% per taint
bagYouDesireMonsters = {
"Bony Sea Devil",
"Brachiodemon",
"Branchy Crawler",
"Capricious Phantom",
- "Cloak Of Terror",
+ "Cloak of Terror",
"Courage Leech",
"Distorted Phantom",
"Druid's Apparition",
@@ -1092,7 +1092,7 @@ function Monster:generateBagYouDesireLoot(player)
logger.trace("Player {} killed {} with {} taints, loot chance {}", player:getName(), monsterName, playerTaintLevel, totalChance)
- if math.random(1, 100) <= totalChance then
+ if math.random(1, 100000) <= totalChance then
local itemType = ItemType(SoulWarQuest.bagYouDesireItemId)
if itemType then
loot[itemType:getId()] = { count = 1 }
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 2c68f56770d..2ec3a528eb5 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
@@ -69,9 +69,6 @@ monster.light = {
monster.summon = {
maxSummons = 1,
- summons = {
- { name = "dreadful harvester", chance = 10, interval = 1000, count = 1 },
- },
}
monster.voices = {
diff --git a/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua b/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua
index cee228f7185..0ece602eab5 100644
--- a/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua
+++ b/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua
@@ -4,7 +4,7 @@ local monster = {}
monster.description = "a powerful soul"
monster.experience = 0
monster.outfit = {
- lookType = 48,
+ lookType = 568,
lookHead = 0,
lookBody = 0,
lookLegs = 0,
@@ -101,7 +101,7 @@ mType.onThink = function(monster, interval)
boss:addReflectElement(elementType, reflectPercent)
end
boss:addDefense(10)
- boss:setMaxHealth(boss:getHealth() + 10000)
+ boss:setMaxHealth(boss:getMaxHealth() + 10000)
boss:addHealth(10000)
end
transformTimeCount = 0
diff --git a/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua b/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua
index c0142e3e611..5cf6560132f 100644
--- a/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua
+++ b/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua
@@ -84,26 +84,39 @@ monster.immunities = {
}
local moveTimeCount = 0
+local stop = false
mType.onThink = function(monster, interval)
+ if stop then
+ return
+ end
+
moveTimeCount = moveTimeCount + interval
- if moveTimeCount == 3000 then
- monster:move(DIRECTION_WEST)
- moveTimeCount = 0
- local monsterPos = monster:getPosition()
- local nextPos = Position(monsterPos.x - 1, monsterPos.y, monsterPos.z)
- local tile = Tile(nextPos)
- if not tile then
- return
- end
+ if moveTimeCount >= 3000 then
+ local currentPos = monster:getPosition()
+ local newPos = Position(currentPos.x - 1, currentPos.y, currentPos.z)
- for _, creatureId in pairs(tile:getCreatures()) do
- local monster = Monster(creatureId)
- if monster and monster:getName() == "Goshnar's Greed" then
- monster:setHealth(monster:getMaxHealth())
- break
+ local nextTile = Tile(newPos)
+ if nextTile then
+ for _, creatureId in pairs(nextTile:getCreatures()) do
+ local greedMonster = Monster(creatureId)
+ if greedMonster and greedMonster:getName() == "Goshnar's Greed" then
+ greedMonster:setHealth(greedMonster:getMaxHealth())
+ stop = true
+ return
+ end
end
end
+
+ if not stop then
+ monster:teleportTo(newPos, true)
+ moveTimeCount = 0
+ end
end
end
+mType.onSpawn = function(monster)
+ moveTimeCount = 0
+ stop = false
+end
+
mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/strong_soul.lua b/data-otservbr-global/monster/quests/soul_war/strong_soul.lua
index 3fb844d1f97..ae3615b6eb4 100644
--- a/data-otservbr-global/monster/quests/soul_war/strong_soul.lua
+++ b/data-otservbr-global/monster/quests/soul_war/strong_soul.lua
@@ -4,7 +4,7 @@ local monster = {}
monster.description = "a strong soul"
monster.experience = 0
monster.outfit = {
- lookType = 48,
+ lookType = 566,
lookHead = 0,
lookBody = 0,
lookLegs = 0,
diff --git a/data-otservbr-global/world/otservbr-house.xml b/data-otservbr-global/world/otservbr-house.xml
index f7e5cd52370..7eff23b4606 100644
--- a/data-otservbr-global/world/otservbr-house.xml
+++ b/data-otservbr-global/world/otservbr-house.xml
@@ -284,7 +284,7 @@
-
+
diff --git a/data-otservbr-global/world/otservbr-monster.xml b/data-otservbr-global/world/otservbr-monster.xml
index 35d1f20e86d..bde660e0c60 100644
--- a/data-otservbr-global/world/otservbr-monster.xml
+++ b/data-otservbr-global/world/otservbr-monster.xml
@@ -95231,7 +95231,7 @@
-
+
@@ -95839,7 +95839,7 @@
-
+
@@ -96019,7 +96019,7 @@
-
+
@@ -96143,11 +96143,6 @@
-
-
-
-
-
@@ -96156,7 +96151,7 @@
-
+
@@ -96184,7 +96179,11 @@
+
+
+
+
@@ -96427,7 +96426,7 @@
-
+
@@ -117685,7 +117684,7 @@
-
+
@@ -117845,6 +117844,13 @@
+
+
+
+
+
+
+
@@ -117859,18 +117865,13 @@
-
-
-
-
-
-
-
-
+
+
+
@@ -117883,9 +117884,6 @@
-
-
-
@@ -117911,7 +117909,7 @@
-
+
@@ -117931,13 +117929,15 @@
+
+
+
-
-
-
+
+
@@ -117974,7 +117974,6 @@
-
@@ -117988,13 +117987,9 @@
-
+
-
-
-
-
@@ -118066,7 +118061,7 @@
-
+
@@ -118075,6 +118070,7 @@
+
@@ -118147,10 +118143,6 @@
-
-
-
-
@@ -118165,6 +118157,14 @@
+
+
+
+
+
+
+
+
@@ -118176,17 +118176,12 @@
-
+
-
-
-
-
-
@@ -118207,6 +118202,9 @@
+
+
+
@@ -118224,18 +118222,17 @@
-
-
-
-
-
+
+
+
+
@@ -118272,17 +118269,25 @@
-
+
+
-
+
+
+
+
+
-
+
+
+
+
@@ -118300,13 +118305,6 @@
-
-
-
-
-
-
-
@@ -118353,11 +118351,11 @@
-
-
-
+
+
+
@@ -118458,8 +118456,8 @@
+
-
@@ -118496,7 +118494,7 @@
-
+
@@ -118538,6 +118536,11 @@
+
+
+
+
+
@@ -118553,11 +118556,6 @@
-
-
-
-
-
@@ -118572,7 +118570,7 @@
-
+
@@ -118644,7 +118642,7 @@
-
+
@@ -118733,13 +118731,13 @@
+
+
+
+
-
-
-
-
@@ -118757,7 +118755,7 @@
-
+
@@ -118789,6 +118787,12 @@
+
+
+
+
+
+
@@ -118813,36 +118817,30 @@
-
-
-
-
+
-
+
-
+
+
+
+
-
-
-
-
-
-
@@ -133592,6 +133590,10 @@
+
+
+
+
@@ -133613,11 +133615,6 @@
-
-
-
-
-
@@ -133638,6 +133635,9 @@
+
+
+
@@ -133650,7 +133650,7 @@
-
+
@@ -133680,22 +133680,22 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
+
+
@@ -133751,8 +133751,8 @@
-
-
+
+
@@ -133790,7 +133790,7 @@
-
+
@@ -133837,15 +133837,18 @@
+
+
+
-
+
-
+
@@ -133866,9 +133869,6 @@
-
-
-
@@ -133922,18 +133922,18 @@
-
-
-
+
+
-
-
+
+
+
-
-
+
+
@@ -133985,17 +133985,17 @@
-
+
-
+
-
+
@@ -134003,11 +134003,11 @@
-
-
-
+
+
+
@@ -134016,14 +134016,14 @@
-
+
-
+
-
-
+
+
@@ -134036,15 +134036,12 @@
-
-
-
-
-
+
+
@@ -134056,6 +134053,9 @@
+
+
+
@@ -134103,9 +134103,6 @@
-
-
-
@@ -134133,42 +134130,47 @@
+
+
+
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
-
+
@@ -134183,28 +134185,32 @@
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
+
@@ -134219,12 +134225,18 @@
+
+
+
+
+
+
@@ -134233,10 +134245,6 @@
-
-
-
-
@@ -134247,8 +134255,8 @@
-
-
+
+
@@ -134257,15 +134265,13 @@
-
-
+
-
-
+
@@ -142115,9 +142121,6 @@
-
-
-
diff --git a/data-otservbr-global/world/otservbr-zones.xml b/data-otservbr-global/world/otservbr-zones.xml
index 4740d50385c..44cff897a42 100644
--- a/data-otservbr-global/world/otservbr-zones.xml
+++ b/data-otservbr-global/world/otservbr-zones.xml
@@ -1,4 +1,4 @@
-
+
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty.otbm b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty.otbm
index 6d37ae4fb88..9d3fa897425 100644
Binary files a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty.otbm and b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty.otbm differ
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml
index a476474dd74..af4787bae03 100644
--- a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml
+++ b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml
@@ -522,8 +522,7 @@
-
-
+
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow.otbm b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow.otbm
index b8ba1414d09..5a8d5d16fef 100644
Binary files a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow.otbm and b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow.otbm differ
diff --git a/data/items/items.xml b/data/items/items.xml
index 90bb8b1c883..444785b125c 100644
--- a/data/items/items.xml
+++ b/data/items/items.xml
@@ -74773,12 +74773,31 @@ Granted by TibiaGoals.com"/>
+
+ -
+
+
+
+ -
+
+
+
+ -
+
+
+
+ -
+
+
+
-
+
-
+
-
@@ -74813,6 +74832,22 @@ Granted by TibiaGoals.com"/>
-
+
+ -
+
+
+
+ -
+
+
+
+ -
+
+
+
+ -
+
+
-
@@ -74831,6 +74866,15 @@ Granted by TibiaGoals.com"/>
+
+ -
+
+
+
+ -
+
+
+
-
diff --git a/data/libs/functions/boss_lever.lua b/data/libs/functions/boss_lever.lua
index cbecfc26f8c..9cd577ee911 100644
--- a/data/libs/functions/boss_lever.lua
+++ b/data/libs/functions/boss_lever.lua
@@ -174,14 +174,15 @@ function BossLever:onUse(player)
return true
end
- if creature:getLevel() < self.requiredLevel then
+ local isAccountNormal = creature:getAccountType() == ACCOUNT_TYPE_NORMAL
+ if isAccountNormal and creature:getLevel() < self.requiredLevel then
local message = "All players need to be level " .. self.requiredLevel .. " or higher."
creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
return false
end
- if creature:getGroup():getId() < GROUP_TYPE_GOD and self:lastEncounterTime(creature) > os.time() then
+ if creature:getGroup():getId() < GROUP_TYPE_GOD and isAccountNormal and self:lastEncounterTime(creature) > os.time() then
local infoPositions = lever:getInfoPositions()
for _, posInfo in pairs(infoPositions) do
local currentPlayer = posInfo.creature
diff --git a/data/libs/systems/zones.lua b/data/libs/systems/zones.lua
index 1406242517a..698a464fe87 100644
--- a/data/libs/systems/zones.lua
+++ b/data/libs/systems/zones.lua
@@ -148,7 +148,7 @@ function ZoneEvent:register()
end
if self.onSpawn then
- local afterEnter = EventCallback("ZoneEventAfterEnter", true)
+ local afterEnter = EventCallback("ZoneEventAfterEnterOnSpawn", true)
function afterEnter.zoneAfterCreatureEnter(zone, creature)
if zone ~= self.zone then
return true
diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp
index 7a19a292728..d65d10e4e6f 100644
--- a/src/creatures/combat/combat.cpp
+++ b/src/creatures/combat/combat.cpp
@@ -1167,7 +1167,9 @@ void Combat::CombatFunc(std::shared_ptr caster, const Position &origin
if (CreatureVector* creatures = tile->getCreatures()) {
const std::shared_ptr topCreature = tile->getTopCreature();
- for (auto &creature : *creatures) {
+ // A copy of the tile's creature list is made because modifications to this vector, such as adding or removing creatures through a Lua callback, may occur during the iteration within the for loop.
+ CreatureVector creaturesCopy = *creatures;
+ for (auto &creature : creaturesCopy) {
if (params.targetCasterOrTopMost) {
if (caster && caster->getTile() == tile) {
if (creature != caster) {
@@ -1222,7 +1224,9 @@ void Combat::CombatFunc(std::shared_ptr caster, const Position &origin
if (CreatureVector* creatures = tile->getCreatures()) {
const std::shared_ptr topCreature = tile->getTopCreature();
- for (auto &creature : *creatures) {
+ // A copy of the tile's creature list is made because modifications to this vector, such as adding or removing creatures through a Lua callback, may occur during the iteration within the for loop.
+ CreatureVector creaturesCopy = *creatures;
+ for (auto &creature : creaturesCopy) {
if (params.targetCasterOrTopMost) {
if (caster && caster->getTile() == tile) {
if (creature != caster) {
diff --git a/src/creatures/combat/condition.cpp b/src/creatures/combat/condition.cpp
index c06d9a792d5..6784e8786f3 100644
--- a/src/creatures/combat/condition.cpp
+++ b/src/creatures/combat/condition.cpp
@@ -257,6 +257,8 @@ std::shared_ptr Condition::createCondition(ConditionId_t id, Conditio
return std::make_shared(id, type, ticks, buff, subId);
case CONDITION_BAKRAGORE:
return std::make_shared(id, type, ticks, buff, subId, isPersistent);
+ case CONDITION_GOSHNARTAINT:
+ return std::make_shared(id, type, ticks, buff, subId);
default:
return nullptr;
@@ -345,7 +347,14 @@ bool Condition::isRemovableOnDeath() const {
return false;
}
- if (conditionType == CONDITION_SPELLCOOLDOWN || conditionType == CONDITION_SPELLGROUPCOOLDOWN || conditionType == CONDITION_MUTED) {
+ static const std::unordered_set nonRemovableConditions = {
+ CONDITION_SPELLCOOLDOWN,
+ CONDITION_SPELLGROUPCOOLDOWN,
+ CONDITION_MUTED,
+ CONDITION_GOSHNARTAINT
+ };
+
+ if (nonRemovableConditions.find(conditionType) != nonRemovableConditions.end()) {
return false;
}
@@ -418,7 +427,26 @@ std::unordered_set ConditionGeneric::getIcons() const {
case CONDITION_ROOTED:
icons.insert(PlayerIcon::Rooted);
break;
-
+ case CONDITION_GOSHNARTAINT:
+ switch (subId) {
+ case 1:
+ icons.insert(PlayerIcon::GoshnarTaint1);
+ break;
+ case 2:
+ icons.insert(PlayerIcon::GoshnarTaint2);
+ break;
+ case 3:
+ icons.insert(PlayerIcon::GoshnarTaint3);
+ break;
+ case 4:
+ icons.insert(PlayerIcon::GoshnarTaint4);
+ break;
+ case 5:
+ icons.insert(PlayerIcon::GoshnarTaint5);
+ break;
+ default:
+ break;
+ }
default:
break;
}
diff --git a/src/creatures/creatures_definitions.hpp b/src/creatures/creatures_definitions.hpp
index 410349a67fb..9594a704eed 100644
--- a/src/creatures/creatures_definitions.hpp
+++ b/src/creatures/creatures_definitions.hpp
@@ -113,15 +113,11 @@ enum ConditionType_t : uint8_t {
CONDITION_LESSERHEX = 31,
CONDITION_INTENSEHEX = 32,
CONDITION_GREATERHEX = 33,
- CONDITION_GOSHNAR1 = 34,
- CONDITION_GOSHNAR2 = 35,
- CONDITION_GOSHNAR3 = 36,
- CONDITION_GOSHNAR4 = 37,
- CONDITION_GOSHNAR5 = 38,
- CONDITION_BAKRAGORE = 39,
+ CONDITION_BAKRAGORE = 34,
+ CONDITION_GOSHNARTAINT = 35,
// Need the last ever
- CONDITION_COUNT = 39
+ CONDITION_COUNT
};
// constexpr definiting suppressible conditions
@@ -492,12 +488,14 @@ enum BestiaryType_t : uint8_t {
};
enum MonstersEvent_t : uint8_t {
- MONSTERS_EVENT_NONE = 0,
- MONSTERS_EVENT_THINK = 1,
- MONSTERS_EVENT_APPEAR = 2,
- MONSTERS_EVENT_DISAPPEAR = 3,
- MONSTERS_EVENT_MOVE = 4,
- MONSTERS_EVENT_SAY = 5,
+ MONSTERS_EVENT_NONE,
+ MONSTERS_EVENT_THINK,
+ MONSTERS_EVENT_APPEAR,
+ MONSTERS_EVENT_DISAPPEAR,
+ MONSTERS_EVENT_MOVE,
+ MONSTERS_EVENT_SAY,
+ MONSTERS_EVENT_ATTACKED_BY_PLAYER,
+ MONSTERS_EVENT_ON_SPAWN,
};
enum NpcsEvent_t : uint8_t {
diff --git a/src/enums/player_icons.hpp b/src/enums/player_icons.hpp
index c289144bd7b..7878d9e5037 100644
--- a/src/enums/player_icons.hpp
+++ b/src/enums/player_icons.hpp
@@ -35,11 +35,11 @@ enum class PlayerIcon : uint8_t {
GreaterHex = 18,
Rooted = 19,
Feared = 20,
- Goshnar1 = 21,
- Goshnar2 = 22,
- Goshnar3 = 23,
- Goshnar4 = 24,
- Goshnar5 = 25,
+ GoshnarTaint1 = 21,
+ GoshnarTaint2 = 22,
+ GoshnarTaint3 = 23,
+ GoshnarTaint4 = 24,
+ GoshnarTaint5 = 25,
NewManaShield = 26,
Agony = 27,
diff --git a/src/game/game.cpp b/src/game/game.cpp
index b3a8d1d9357..1fb4664eb7b 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -1477,7 +1477,7 @@ ReturnValue Game::internalMoveCreature(std::shared_ptr creature, Direc
return RETURNVALUE_NOTPOSSIBLE;
}
- if (creature->getBaseSpeed() == 0 && flags != FLAG_IGNORENOTMOVABLE) {
+ if (creature->getBaseSpeed() == 0) {
return RETURNVALUE_NOTMOVABLE;
}
diff --git a/src/lua/callbacks/events_callbacks.cpp b/src/lua/callbacks/events_callbacks.cpp
index 1ab64957497..13a42baa15a 100644
--- a/src/lua/callbacks/events_callbacks.cpp
+++ b/src/lua/callbacks/events_callbacks.cpp
@@ -39,10 +39,13 @@ bool EventsCallbacks::isCallbackRegistered(const std::shared_ptr
}
void EventsCallbacks::addCallback(const std::shared_ptr &callback) {
- if (m_callbacks.find(callback->getName()) != m_callbacks.end()) {
+ if (m_callbacks.find(callback->getName()) != m_callbacks.end() && !callback->skipDuplicationCheck()) {
+ g_logger().trace("Event callback already registered: {}", callback->getName());
return;
}
+ g_logger().trace("Registering event callback: {}", callback->getName());
+
m_callbacks[callback->getName()] = callback;
}
diff --git a/src/lua/callbacks/events_callbacks.hpp b/src/lua/callbacks/events_callbacks.hpp
index 4d3758405a6..dff5cec30c5 100644
--- a/src/lua/callbacks/events_callbacks.hpp
+++ b/src/lua/callbacks/events_callbacks.hpp
@@ -97,6 +97,7 @@ class EventsCallbacks {
},
argsCopy
);
+ g_logger().trace("Executed callback: {}", name);
}
}
}
diff --git a/src/lua/functions/creatures/creature_functions.cpp b/src/lua/functions/creatures/creature_functions.cpp
index da935d05fdc..6b09945971a 100644
--- a/src/lua/functions/creatures/creature_functions.cpp
+++ b/src/lua/functions/creatures/creature_functions.cpp
@@ -968,7 +968,7 @@ int CreatureFunctions::luaCreatureMove(lua_State* L) {
lua_pushnil(L);
return 1;
}
- lua_pushnumber(L, g_game().internalMoveCreature(creature, direction, FLAG_IGNORENOTMOVABLE));
+ lua_pushnumber(L, g_game().internalMoveCreature(creature, direction, FLAG_NOLIMIT));
} else {
std::shared_ptr tile = getUserdataShared(L, 2);
if (!tile) {
diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp
index d360b482a7b..ef171fd7196 100644
--- a/src/lua/functions/creatures/player/player_functions.cpp
+++ b/src/lua/functions/creatures/player/player_functions.cpp
@@ -2272,10 +2272,23 @@ int PlayerFunctions::luaPlayerGetParty(lua_State* L) {
}
int PlayerFunctions::luaPlayerAddOutfit(lua_State* L) {
- // player:addOutfit(lookType)
+ // player:addOutfit(lookType or name, addon = 0)
std::shared_ptr player = getUserdataShared(L, 1);
if (player) {
- player->addOutfit(getNumber(L, 2), 0);
+ auto addon = getNumber(L, 3, 0);
+ if (lua_isnumber(L, 2)) {
+ player->addOutfit(getNumber(L, 2), addon);
+ } else if (lua_isstring(L, 2)) {
+ const std::string &outfitName = getString(L, 2);
+ const auto &outfit = Outfits::getInstance().getOutfitByName(player->getSex(), outfitName);
+ if (!outfit) {
+ reportErrorFunc("Outfit not found");
+ return 1;
+ }
+
+ player->addOutfit(outfit->lookType, addon);
+ }
+
pushBoolean(L, true);
} else {
lua_pushnil(L);
@@ -4224,12 +4237,8 @@ int PlayerFunctions::luaPlayerAddAchievement(lua_State* L) {
achievementId = g_game().getAchievementByName(getString(L, 2)).id;
}
- bool success = player->achiev()->add(achievementId, getBoolean(L, 3, true));
- if (success) {
- player->sendTakeScreenshot(SCREENSHOT_TYPE_ACHIEVEMENT);
- }
-
- pushBoolean(L, success);
+ player->sendTakeScreenshot(SCREENSHOT_TYPE_ACHIEVEMENT);
+ pushBoolean(L, player->achiev()->add(achievementId, getBoolean(L, 3, true)));
return 1;
}
@@ -4398,7 +4407,6 @@ int PlayerFunctions::luaPlayerTakeScreenshot(lua_State* L) {
pushBoolean(L, true);
return 1;
}
-
int PlayerFunctions::luaPlayerSendIconBakragore(lua_State* L) {
// player:sendIconBakragore()
const auto &player = getUserdataShared(L, 1);
@@ -4412,3 +4420,16 @@ int PlayerFunctions::luaPlayerSendIconBakragore(lua_State* L) {
pushBoolean(L, true);
return 1;
}
+
+int PlayerFunctions::luaPlayerSendCreatureAppear(lua_State* L) {
+ auto player = getUserdataShared(L, 1);
+ if (!player) {
+ reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND));
+ return 1;
+ }
+
+ bool isLogin = getBoolean(L, 2, false);
+ player->sendCreatureAppear(player, player->getPosition(), isLogin);
+ pushBoolean(L, true);
+ return 1;
+}
diff --git a/src/lua/functions/creatures/player/player_functions.hpp b/src/lua/functions/creatures/player/player_functions.hpp
index 000c5f755c0..136eada7d45 100644
--- a/src/lua/functions/creatures/player/player_functions.hpp
+++ b/src/lua/functions/creatures/player/player_functions.hpp
@@ -372,12 +372,11 @@ class PlayerFunctions final : LuaScriptInterface {
registerMethod(L, "Player", "getTitles", PlayerFunctions::luaPlayerGetTitles);
registerMethod(L, "Player", "setCurrentTitle", PlayerFunctions::luaPlayerSetCurrentTitle);
- // Store Summary
registerMethod(L, "Player", "createTransactionSummary", PlayerFunctions::luaPlayerCreateTransactionSummary);
registerMethod(L, "Player", "takeScreenshot", PlayerFunctions::luaPlayerTakeScreenshot);
-
registerMethod(L, "Player", "sendIconBakragore", PlayerFunctions::luaPlayerSendIconBakragore);
+ registerMethod(L, "Player", "sendCreatureAppear", PlayerFunctions::luaPlayerSendCreatureAppear);
GroupFunctions::init(L);
GuildFunctions::init(L);
@@ -744,5 +743,7 @@ class PlayerFunctions final : LuaScriptInterface {
static int luaPlayerTakeScreenshot(lua_State* L);
static int luaPlayerSendIconBakragore(lua_State* L);
+ static int luaPlayerSendCreatureAppear(lua_State* L);
+
friend class CreatureFunctions;
};