Skip to content

Commit

Permalink
feat: add upgrade soul prism mechanic
Browse files Browse the repository at this point in the history
  • Loading branch information
FelipePaluco committed Dec 4, 2024
1 parent 89efd86 commit dd2f967
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 27 deletions.
91 changes: 68 additions & 23 deletions data-otservbr-global/lib/others/soulpit.lua
Original file line number Diff line number Diff line change
@@ -1,65 +1,110 @@
SoulPit = {
SoulCoresConfiguration = {
chanceToGetSameMonsterSoulCore = 30, -- 30%
chanceToDropSoulCore = 50, -- 50%
chanceToGetOminousSoulCore = 5, -- 5%
monsterVariationsSoulCore = {
["Horse"] = "horse soul core (taupe)",
["Brown Horse"] = "horse soul core (brown)",
["Grey Horse"] = "horse soul core (gray)",
["Nomad"] = "nomad soul core (basic)",
["Nomad Blue"] = "nomad soul core (blue)",
["Nomad Female"] = "nomad soul core (female)",
["Purple Butterfly"] = "butterfly soul core (purple)",
["Butterfly"] = "butterfly soul core (blue)",
["Blue Butterfly"] = "butterfly soul core (blue)",
["Red Butterfly"] = "butterfly soul core (red)"
},
monstersDifficulties = {
["Harmless"] = 1,
["Trivial"] = 2,
["Easy"] = 3,
["Medium"] = 4,
["Hard"] = 5,
["Challenge"] = 6
}
},
encounter = nil,
kickEvent = nil,
soulCores = Game.getSoulCoreItems(),
requiredLevel = 8,
playerPositions = {
{ pos = Position(32371, 31155, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
{ pos = Position(32371, 31156, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
{ pos = Position(32371, 31157, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
{ pos = Position(32371, 31158, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
{ pos = Position(32371, 31159, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
{
pos = Position(32371, 31155, 8),
teleport = Position(32373, 31138, 8),
effect = CONST_ME_TELEPORT
},
{
pos = Position(32371, 31156, 8),
teleport = Position(32373, 31138, 8),
effect = CONST_ME_TELEPORT
},
{
pos = Position(32371, 31157, 8),
teleport = Position(32373, 31138, 8),
effect = CONST_ME_TELEPORT
},
{
pos = Position(32371, 31158, 8),
teleport = Position(32373, 31138, 8),
effect = CONST_ME_TELEPORT
},
{
pos = Position(32371, 31159, 8),
teleport = Position(32373, 31138, 8),
effect = CONST_ME_TELEPORT
}
},
waves = {
[1] = {
stacks = {
[1] = 7,
},
[1] = 7
}
},
[2] = {
stacks = {
[1] = 4,
[5] = 3,
},
[5] = 3
}
},
[3] = {
stacks = {
[1] = 5,
[15] = 2,
},
[15] = 2
}
},
[4] = {
stacks = {
[1] = 3,
[5] = 3,
[40] = 1,
},
},
[40] = 1
}
}
},
effects = {
[1] = CONST_ME_TELEPORT,
[5] = CONST_ME_ORANGETELEPORT,
[15] = CONST_ME_REDTELEPORT,
[40] = CONST_ME_PURPLETELEPORT,
[40] = CONST_ME_PURPLETELEPORT
},
possibleAbilities = {
"overpowerSoulPit",
"enrageSoulPit",
"opressorSoulPit",
"opressorSoulPit"
},
bossAbilities = {
["overpowerSoulPit"] = {
overpowerSoulPit = {
player = true,
monster = false,
monster = false
},
["enrageSoulPit"] = {
enrageSoulPit = {
player = false,
monster = true,
monster = true
},
["opressorSoulPit"] = {
opressorSoulPit = {
player = false,
monster = true,
},
monster = true
}
},
timeToKick = 3 * 1000, -- 3 seconds
checkMonstersDelay = 4.5 * 1000, -- 4.5 seconds | The check delay should never be less than the timeToSpawnMonsters.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ function soulPitAction.onUse(player, item, fromPosition, target, toPosition, isH
end

for _, itemType in pairs(SoulPit.soulCores) do
soulPitAction:id(itemType:getId())
if itemType:getId() ~= 49164 then -- TO-DO: currently Game.getSoulCoreItems() it's returning soul prism item in the results, we don't want this.
soulPitAction:id(itemType:getId())
end
end
soulPitAction:register()
4 changes: 4 additions & 0 deletions data/items/items.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79730,5 +79730,9 @@ Granted by TibiaGoals.com"/>
<attribute key="description" value="Offers a soul to the Soulpit. Combine with an exalted core to turn it into a lesser soul core."/>
<attribute key="weight" value="100"/>
</item>
<item id="49164" article="a" name="soul prism">
<attribute key="description" value="Focalises the soul within a core. Can be used to turn a soul core into a greater version"/>
<attribute key="weight" value="100"/>
</item>
</items>

106 changes: 106 additions & 0 deletions data/scripts/actions/items/soul_prism.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
local soulPrism = Action()

local function getNextDifficultyLevel(currentLevel)
for level, value in pairs(SoulPit.SoulCoresConfiguration.monstersDifficulties) do
if value == currentLevel + 1 then
return level
end
end
return nil
end

local function getPreviousDifficultyLevel(currentLevel)
for level, value in pairs(SoulPit.SoulCoresConfiguration.monstersDifficulties) do
if value == currentLevel - 1 then
return level
end
end
return nil
end

local function getSoulCoreItemForMonster(monsterName)
local lowerMonsterName = monsterName:lower()
local soulCoreName = SoulPit.SoulCoresConfiguration.monsterVariationsSoulCore[monsterName]

if soulCoreName then
local newSoulCoreId = getItemIdByName(soulCoreName)
if newSoulCoreId then
return newSoulCoreId
end
else
local newMonsterSoulCore = monsterName .. " soul core"
local newSoulCoreId = getItemIdByName(newMonsterSoulCore)
if newSoulCoreId then
return newSoulCoreId
end
end

return false
end

function soulPrism.onUse(player, item, fromPosition, target, toPosition, isHotkey)
local itemName = target:getName()
local monsterName = itemName:match("^(.-) soul core")

if not monsterName then
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can only use Soul Prism with a Soul Core.")
player:getPosition():sendMagicEffect(CONST_ME_POFF)
return false
end

local monsterType = MonsterType(monsterName)
if not monsterType then
player:sendTextMessage(MESSAGE_GAME_HIGHLIGHT, "Invalid monster type. Please contact an administrator.")
player:getPosition():sendMagicEffect(CONST_ME_POFF)
return false
end

local currentDifficulty = monsterType:getBestiaryStars()
local nextDifficultyLevel = getNextDifficultyLevel(currentDifficulty)
local nextDifficultyMonsters = nil

if nextDifficultyLevel then
nextDifficultyMonsters = monsterType:getMonstersByBestiaryStars(SoulPit.SoulCoresConfiguration.monstersDifficulties[nextDifficultyLevel])
else
nextDifficultyLevel = currentDifficulty
nextDifficultyMonsters = monsterType:getMonstersByBestiaryStars(SoulPit.SoulCoresConfiguration.monstersDifficulties[currentDifficulty])
end

if #nextDifficultyMonsters == 0 then
player:sendTextMessage(MESSAGE_GAME_HIGHLIGHT, "No monsters available for the next difficulty level. Please contact an administrator.")
player:getPosition():sendMagicEffect(CONST_ME_POFF)
return false
end

local newMonsterType = nextDifficultyMonsters[math.random(#nextDifficultyMonsters)]
local newSoulCoreItem = getSoulCoreItemForMonster(newMonsterType:getName())
if not newSoulCoreItem then -- Retry a second time.
newSoulCoreItem = getSoulCoreItemForMonster(newMonsterType:getName())
if not newSoulCoreItem then
player:sendTextMessage(MESSAGE_GAME_HIGHLIGHT, "Failed to generate a Soul Core. Please contact an administrator.")
player:getPosition():sendMagicEffect(CONST_ME_POFF)
return false
end
end

if player:getFreeCapacity() < ItemType(newSoulCoreItem):getWeight() then
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You do not have enough capacity.")
player:getPosition():sendMagicEffect(CONST_ME_POFF)
return false
end

if math.random(100) <= SoulPit.SoulCoresConfiguration.chanceToGetOminousSoulCore then
player:addItem(49163, 1)
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have received an Ominous Soul Core.")
else
player:addItem(newSoulCoreItem, 1)
player:removeItem(target:getId(), 1)
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have received a " .. newMonsterType:getName() .. " soul core.")
end
player:removeItem(item:getId(), 1)
player:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
return true
end

soulPrism:id(49164)
soulPrism:register()
5 changes: 2 additions & 3 deletions data/scripts/eventcallbacks/monster/ondroploot_soul_core.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
local callback = EventCallback("MonsterOnDropLootSoulCore")
local soulCores = Game.getSoulCoreItems()

function callback.monsterOnDropLoot(monster, corpse)
if not monster or not corpse then
Expand All @@ -14,11 +13,11 @@ function callback.monsterOnDropLoot(monster, corpse)
end

local soulCoreId = nil
local trySameMonsterSoulCore = math.random() <= 0.3 -- 30% of chance to drop the same monster soul core | WIP: Externalize this to a lib like libs/soulpit.lua
local trySameMonsterSoulCore = math.random(100) <= SoulPit.SoulCoresConfiguration.chanceToGetSameMonsterSoulCore
local mType = monster:getType()
local lootTable = {}

if math.random() < 0.5 then -- WIP: Externalize this to a lib like libs/soulpit.lua
if math.random(100) < SoulPit.SoulCoresConfiguration.chanceToDropSoulCore then
if trySameMonsterSoulCore then
local itemName = monster:getName():lower() .. " soul core"
soulCoreId = getItemIdByName(itemName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1896,6 +1896,7 @@ int MonsterTypeFunctions::luaMonsterTypeGetMonstersByBestiaryStars(lua_State* L)
int index = 0;
for (const auto &monsterType : monstersByStars) {
Lua::pushUserdata<MonsterType>(L, monsterType);
Lua::setMetatable(L, -1, "MonsterType");
lua_rawseti(L, -2, ++index);
}
return 1;
Expand Down

0 comments on commit dd2f967

Please sign in to comment.