Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
luanluciano93 committed Nov 23, 2024
2 parents a85cb37 + 34b6fa8 commit fceeaea
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 81 deletions.
2 changes: 2 additions & 0 deletions data-canary/scripts/actions/objects/imbuement_shrine.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ function imbuement.onUse(player, item, fromPosition, target, toPosition, isHotke
return true
end

imbuement:position({ x = 1943, y = 1340, z = 7 }, 25061)

imbuement:id(25060, 25061, 25103, 25104, 25202, 25174, 25175, 25182, 25183)
imbuement:register()
68 changes: 49 additions & 19 deletions data-otservbr-global/npc/hireling.lua
Original file line number Diff line number Diff line change
Expand Up @@ -420,11 +420,13 @@ function createHirelingType(HirelingName)

local TOPIC_FOOD = {
SKILL_CHOOSE = 1301,
SKILL_SURPRISE = 1302,
}

local GREETINGS = {
BANK = "Alright! What can I do for you and your bank business, |PLAYERNAME|?",
FOOD = "Hmm, yes! A variety of fine food awaits! However, a small expense of 15000 gold is expected to make these delicious masterpieces happen. Shall I?",
FOOD = [[Hmm, yes! A variety of fine food awaits! However, a small expense of 15000 gold is expected to make these delicious masterpieces happen.
For 90000 gold I will also serve you a specific dish. Just tell me what it shall be: a {specific} meal or a little {surprise}.]],
STASH = "Of course, here is your stash! Well-maintained and neatly sorted for your convenience!",
}

Expand Down Expand Up @@ -513,7 +515,7 @@ function createHirelingType(HirelingName)
return message
end

local function deliverFood(npc, creature, food_id)
local function deliverFood(npc, creature, food_id, cost)
local playerId = creature:getId()
local player = Player(creature)
local itType = ItemType(food_id)
Expand All @@ -523,8 +525,8 @@ function createHirelingType(HirelingName)
npcHandler:say("Sorry, but you don't have enough capacity.", npc, creature)
elseif not inbox or #inboxItems >= inbox:getMaxCapacity() then
player:getPosition():sendMagicEffect(CONST_ME_POFF)
npcHandler:say("Sorry, you don't have enough room on your inbox", npc, creature)
elseif not player:removeMoneyBank(15000) then
npcHandler:say("Sorry, you don't have enough room on your inbox.", npc, creature)
elseif not player:removeMoneyBank(cost) then
npcHandler:say("Sorry, you don't have enough money.", npc, creature)
else
local message = getDeliveredMessageByFoodId(food_id)
Expand All @@ -534,38 +536,66 @@ function createHirelingType(HirelingName)
npcHandler:setTopic(playerId, TOPIC.SERVICES)
end

local function cookFood(npc, creature)
local function cookFood(npc, creature, specificRequest)
local playerId = creature:getId()
local random = math.random(6)
if random == 6 then
-- ask for preferred skill
if specificRequest then
npcHandler:say("Very well. You may choose one of the following: {chilli con carniphila}, {svargrond salmon filet}, {carrion casserole}, {consecrated beef}, {roasted wyvern wings}, {carrot pie}, {tropical marinated tiger}, or {delicatessen salad}.", npc, creature)
npcHandler:setTopic(playerId, TOPIC_FOOD.SKILL_CHOOSE)
npcHandler:say("Yay! I have the ingredients to make a skill boost dish. Would you rather like to boost your {magic}, {melee}, {shielding} or {distance} skill?", npc, creature)
else -- deliver the random generated index
deliverFood(npc, creature, HIRELING_FOODS_IDS[random])
else
npcHandler:say("Alright, let me astonish you. Shall I?", npc, creature)
deliverFood(npc, creature, HIRELING_FOODS_IDS[math.random(#HIRELING_FOODS_IDS)], 15000)
end
end

local function handleFoodActions(npc, creature, message)
local playerId = creature:getId()

if npcHandler:getTopic(playerId) == TOPIC.FOOD then
if MsgContains(message, "yes") then
cookFood(npc, creature)
if MsgContains(message, "specific") then
npcHandler:setTopic(playerId, TOPIC_FOOD.SPECIFIC)
npcHandler:say("Which specific meal would you like? Choices are: {chilli con carniphila}, {svargrond salmon filet}, {carrion casserole}, {consecrated beef}, {roasted wyvern wings}, {carrot pie}, {tropical marinated tiger}, or {delicatessen salad}.", npc, creature)
elseif MsgContains(message, "surprise") then
local random = math.random(6)
if random == 6 then
npcHandler:setTopic(playerId, TOPIC_FOOD.SKILL_CHOOSE)
npcHandler:say("Yay! I have the ingredients to make a skill boost dish. Would you rather like to boost your {magic}, {melee}, {shielding}, or {distance} skill?", npc, creature)
else
deliverFood(npc, creature, HIRELING_FOODS_IDS[random], 15000)
end
elseif MsgContains(message, "yes") then
deliverFood(npc, creature, HIRELING_FOODS_IDS[math.random(#HIRELING_FOODS_IDS)], 15000)
elseif MsgContains(message, "no") then
npcHandler:setTopic(playerId, TOPIC.SERVICES)
npcHandler:say("Alright then, ask me for other {services}, if you want.", npc, creature)
end
elseif npcHandler:getTopic(playerId) == TOPIC_FOOD.SKILL_CHOOSE then
if MsgContains(message, "magic") then
deliverFood(npc, creature, HIRELING_FOODS_BOOST.MAGIC)
deliverFood(npc, creature, HIRELING_FOODS_BOOST.MAGIC, 15000)
elseif MsgContains(message, "melee") then
deliverFood(npc, creature, HIRELING_FOODS_BOOST.MELEE)
deliverFood(npc, creature, HIRELING_FOODS_BOOST.MELEE, 15000)
elseif MsgContains(message, "shielding") then
deliverFood(npc, creature, HIRELING_FOODS_BOOST.SHIELDING)
deliverFood(npc, creature, HIRELING_FOODS_BOOST.SHIELDING, 15000)
elseif MsgContains(message, "distance") then
deliverFood(npc, creature, HIRELING_FOODS_BOOST.DISTANCE)
deliverFood(npc, creature, HIRELING_FOODS_BOOST.DISTANCE, 15000)
else
npcHandler:say("Sorry, but you must choose a valid skill class. Would you like to boost your {magic}, {melee}, {shielding}, or {distance} skill?", npc, creature)
end
elseif npcHandler:getTopic(playerId) == TOPIC_FOOD.SPECIFIC then
local specificFoodOptions = {
["chilli con carniphila"] = 29412,
["svargrond salmon filet"] = 29413,
["carrion casserole"] = 29414,
["consecrated beef"] = 29415,
["roasted wyvern wings"] = 29408,
["carrot pie"] = 29409,
["tropical marinated tiger"] = 29410,
["delicatessen salad"] = 29411,
}

if specificFoodOptions[message:lower()] then
deliverFood(npc, creature, specificFoodOptions[message:lower()], 90000)
else
npcHandler:say("Sorry, but you must choose a valid skill class. Would you like to boost your {magic}, {melee}, {shielding} or {distance} skill?", npc, creature)
npcHandler:say("I'm sorry, but that's not a valid food option. Please choose from: {chilli con carniphila}, {svargrond salmon filet}, {carrion casserole}, {consecrated beef}, {roasted wyvern wings}, {carrot pie}, {tropical marinated tiger}, or {delicatessen salad}.", npc, creature)
end
end
end
Expand Down Expand Up @@ -656,7 +686,7 @@ function createHirelingType(HirelingName)
end
elseif npcHandler:getTopic(playerId) == TOPIC.BANK then
enableBankSystem[playerId] = true
elseif npcHandler:getTopic(playerId) == TOPIC.FOOD or npcHandler:getTopic(playerId) == TOPIC_FOOD.SKILL_CHOOSE then
elseif npcHandler:getTopic(playerId) == TOPIC.FOOD or npcHandler:getTopic(playerId) == TOPIC_FOOD.SKILL_CHOOSE or npcHandler:getTopic(playerId) == TOPIC_FOOD.SPECIFIC then
handleFoodActions(npc, creature, message)
elseif npcHandler:getTopic(playerId) == TOPIC.GOODS then
-- Ensures players cannot access other shop categories
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,35 +26,3 @@ end

rewardSoulWar:position({ x = 33620, y = 31400, z = 10 })
rewardSoulWar:register()

local phantasmalJadeMount = Action()

function phantasmalJadeMount.onUse(player, item, fromPosition, target, toPosition, isHotkey)
local soulWarQuest = player:soulWarQuestKV()
if soulWarQuest:get("panthasmal-jade-mount") then
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You already have Phantasmal Jade mount!")
return true
end

if table.contains({ 34072, 34073, 34074 }, item.itemid) then
if player:getItemCount(34072) >= 4 and player:getItemCount(34073) == 1 and player:getItemCount(34074) == 1 then
player:removeItem(34072, 4)
player:removeItem(34073, 1)
player:removeItem(34074, 1)
player:addMount(167)
player:addAchievement("You got Horse Power")
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Congratulations! You won Phantasmal Jade mount.")
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Congratulations! You won You got Horse Power achievement.")
player:getPosition():sendMagicEffect(CONST_ME_HOLYDAMAGE)
soulWarQuest:set("panthasmal-jade-mount", true)
else
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You don't have the necessary items!")
player:getPosition():sendMagicEffect(CONST_ME_POFF)
end
end

return true
end

phantasmalJadeMount:id(34072, 34073, 34074)
phantasmalJadeMount:register()
3 changes: 2 additions & 1 deletion data/events/scripts/player.lua
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,8 @@ function Player:onMoveItem(item, count, fromPosition, toPosition, fromCylinder,
end

-- Reward System
if toPosition.x == CONTAINER_POSITION then
local containerThing = tile and tile:getItemByType(ITEM_TYPE_CONTAINER)
if containerThing and toPosition.x == CONTAINER_POSITION then
local containerId = toPosition.y - 64
local container = self:getContainerById(containerId)
if not container then
Expand Down
2 changes: 1 addition & 1 deletion data/libs/functions/boss_lever.lua
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ function BossLever:onUse(player)
return true
end

local isAccountNormal = creature:getAccountType() == ACCOUNT_TYPE_NORMAL
local isAccountNormal = creature:getAccountType() < ACCOUNT_TYPE_GAMEMASTER
if isAccountNormal and creature:getLevel() < self.requiredLevel then
local message = "All players need to be level " .. self.requiredLevel .. " or higher."
creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
Expand Down
15 changes: 8 additions & 7 deletions data/libs/systems/blessing.lua
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,9 @@ Blessings.BuyAllBlesses = function(player)
local hasToF = Blessings.Config.HasToF and player:hasBlessing(1) or true
local missingBless = player:getBlessings(nil, donthavefilter)
local missingBlessAmt = #missingBless + (hasToF and 0 or 1)
local totalCost
for i, bless in ipairs(missingBless) do
local totalCost = 0

for _, bless in ipairs(missingBless) do
totalCost = totalCost + Blessings.getBlessingCost(player:getLevel(), true, bless.id >= 7)
end

Expand All @@ -274,19 +275,19 @@ Blessings.BuyAllBlesses = function(player)
end

if player:removeMoneyBank(totalCost) then
metrics.addCounter("balance_decrease", remainsPrice, {
metrics.addCounter("balance_decrease", totalCost, {
player = player:getName(),
context = "blessings",
})

for i, v in ipairs(missingBless) do
player:addBlessing(v.id, 1)
for _, bless in ipairs(missingBless) do
player:addBlessing(bless.id, 1)
end

player:sendCancelMessage("You received the remaining " .. missingBlessAmt .. " blesses for a total of " .. totalCost .. " gold.")
player:sendCancelMessage(string.format("You received the remaining %d blesses for a total of %d gold.", missingBlessAmt, totalCost))
player:getPosition():sendMagicEffect(CONST_ME_HOLYAREA)
else
player:sendCancelMessage("You don't have enough money. You need " .. totalCost .. " to buy all blesses.", cid)
player:sendCancelMessage(string.format("You don't have enough money. You need %d to buy all blesses.", totalCost))
player:getPosition():sendMagicEffect(CONST_ME_POFF)
end

Expand Down
45 changes: 45 additions & 0 deletions data/scripts/actions/items/usable_phantasmal_jade_items.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
local config = {
requiredItems = {
[34072] = { key = "spectral-horseshoes", count = 4 },
[34073] = { key = "spectral-saddle", count = 1 },
[34074] = { key = "spectral-horse-tac", count = 1 },
},

mountId = 167,
}

local usablePhantasmalJadeItems = Action()

function usablePhantasmalJadeItems.onUse(player, item, fromPosition, target, toPosition, isHotkey)
local itemInfo = config.requiredItems[item:getId()]
if not itemInfo then
return true
end

if player:hasMount(config.mountId) then
return true
end

local currentCount = (player:kv():get(itemInfo.key) or 0) + 1
player:kv():set(itemInfo.key, currentCount)
player:getPosition():sendMagicEffect(CONST_ME_HOLYDAMAGE)
item:remove(1)

for _, info in pairs(config.requiredItems) do
if (player:kv():get(info.key) or 0) < info.count then
return true
end
end

player:addMount(config.mountId)
player:addAchievement("Natural Born Cowboy")
player:addAchievement("You got Horse Power")
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Phantasmal jade is now yours!")
return true
end

for itemId, _ in pairs(config.requiredItems) do
usablePhantasmalJadeItems:id(itemId)
end

usablePhantasmalJadeItems:register()
33 changes: 29 additions & 4 deletions src/game/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3409,18 +3409,22 @@ void Game::playerEquipItem(uint32_t playerId, uint16_t itemId, bool hasTier /* =
const auto &slotItem = player->getInventoryItem(slot);
const auto &equipItem = searchForItem(backpack, it.id, hasTier, tier);
ReturnValue ret = RETURNVALUE_NOERROR;

if (slotItem && slotItem->getID() == it.id && (!it.stackable || slotItem->getItemCount() == slotItem->getStackSize() || !equipItem)) {
ret = internalMoveItem(slotItem->getParent(), player, CONST_SLOT_WHEREEVER, slotItem, slotItem->getItemCount(), nullptr);
g_logger().debug("Item {} was unequipped", slotItem->getName());
} else if (equipItem) {
// Shield slot item
const auto &rightItem = player->getInventoryItem(CONST_SLOT_RIGHT);

// Check Ammo item
if (it.weaponType == WEAPON_AMMO) {
if (rightItem && rightItem->isQuiver()) {
ret = internalMoveItem(equipItem->getParent(), rightItem->getContainer(), 0, equipItem, equipItem->getItemCount(), nullptr);
}
} else {
const auto &leftItem = player->getInventoryItem(CONST_SLOT_LEFT);

const int32_t &slotPosition = equipItem->getSlotPosition();
// Checks if a two-handed item is being equipped in the left slot when the right slot is already occupied and move to backpack
if (
Expand All @@ -3429,10 +3433,35 @@ void Game::playerEquipItem(uint32_t playerId, uint16_t itemId, bool hasTier /* =
&& rightItem
&& !(it.weaponType == WEAPON_DISTANCE)
&& !rightItem->isQuiver()
&& (!leftItem || leftItem->getWeaponType() != WEAPON_DISTANCE)
) {
ret = internalCollectManagedItems(player, rightItem, getObjectCategory(rightItem), false);
}

// Check if trying to equip a quiver while another quiver is already equipped in the right slot
if (slot == CONST_SLOT_RIGHT && rightItem && rightItem->isQuiver() && it.isQuiver()) {
// Replace the existing quiver with the new one
ret = internalMoveItem(rightItem->getParent(), player, INDEX_WHEREEVER, rightItem, rightItem->getItemCount(), nullptr);
if (ret == RETURNVALUE_NOERROR) {
g_logger().debug("Quiver {} was unequipped to equip new quiver", rightItem->getName());
} else {
player->sendCancelMessage(ret);
return;
}
} else {
// Check if trying to equip a shield while a two-handed weapon is equipped in the left slot
if (slot == CONST_SLOT_RIGHT && leftItem && leftItem->getSlotPosition() & SLOTP_TWO_HAND) {
// Unequip the two-handed weapon from the left slot
ret = internalMoveItem(leftItem->getParent(), player, INDEX_WHEREEVER, leftItem, leftItem->getItemCount(), nullptr);
if (ret == RETURNVALUE_NOERROR) {
g_logger().debug("Two-handed weapon {} was unequipped to equip shield", leftItem->getName());
} else {
player->sendCancelMessage(ret);
return;
}
}
}

if (slotItem) {
ret = internalMoveItem(slotItem->getParent(), player, INDEX_WHEREEVER, slotItem, slotItem->getItemCount(), nullptr);
g_logger().debug("Item {} was moved back to player", slotItem->getName());
Expand Down Expand Up @@ -7428,10 +7457,6 @@ bool Game::combatChangeHealth(const std::shared_ptr<Creature> &attacker, const s

target->drainHealth(attacker, realDamage);
if (realDamage > 0 && targetMonster) {
if (attackerPlayer && attackerPlayer->getPlayer()) {
attackerPlayer->updateImpactTracker(damage.secondary.type, damage.secondary.value);
}

if (targetMonster->israndomStepping()) {
targetMonster->setIgnoreFieldDamage(true);
}
Expand Down
20 changes: 9 additions & 11 deletions src/game/movement/teleport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,29 +80,27 @@ void Teleport::addThing(int32_t, const std::shared_ptr<Thing> &thing) {
// Prevent infinity loop
if (checkInfinityLoop(destTile)) {
const Position &pos = getPosition();
g_logger().warn("[Teleport:addThing] - "
"Infinity loop teleport at position: {}",
pos.toString());
g_logger().warn("[Teleport:addThing] - Infinity loop teleport at position: {}", pos.toString());
return;
}

const MagicEffectClasses effect = Item::items[id].magicEffect;

if (const std::shared_ptr<Creature> &creature = thing->getCreature()) {
if (const auto &creature = thing->getCreature()) {
Position origPos = creature->getPosition();
g_game().internalCreatureTurn(creature, origPos.x > destPos.x ? DIRECTION_WEST : DIRECTION_EAST);
g_dispatcher().addWalkEvent([=] {
g_game().map.moveCreature(creature, destTile);
if (effect != CONST_ME_NONE) {
g_game().addMagicEffect(origPos, effect);
g_game().addMagicEffect(destTile->getPosition(), effect);
}
});
g_game().map.moveCreature(creature, destTile);

if (effect != CONST_ME_NONE) {
g_game().addMagicEffect(origPos, effect);
g_game().addMagicEffect(destTile->getPosition(), effect);
}
} else if (const auto &item = thing->getItem()) {
if (effect != CONST_ME_NONE) {
g_game().addMagicEffect(destTile->getPosition(), effect);
g_game().addMagicEffect(item->getPosition(), effect);
}

g_game().internalMoveItem(getTile(), destTile, INDEX_WHEREEVER, item, item->getItemCount(), nullptr);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/lua/functions/lua_functions_loader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class Lua {
static void setCreatureMetatable(lua_State* L, int32_t index, const std::shared_ptr<Creature> &creature);

template <typename T>
static T getNumber(lua_State* L, int32_t arg) {
static T getNumber(lua_State* L, int32_t arg, std::source_location location = std::source_location::current()) {
auto number = lua_tonumber(L, arg);

if constexpr (std::is_enum_v<T>) {
Expand All @@ -73,7 +73,7 @@ class Lua {
if constexpr (std::is_integral_v<T>) {
if constexpr (std::is_unsigned_v<T>) {
if (number < 0) {
g_logger().debug("[{}] overflow, setting to default unsigned value (0)", __FUNCTION__);
g_logger().debug("[{}] overflow, setting to default unsigned value (0), called line: {}:{}, in {}", __FUNCTION__, location.line(), location.column(), location.function_name());
return T(0);
}
}
Expand Down
Loading

0 comments on commit fceeaea

Please sign in to comment.