Hello, i found this code here on otland made by: Snavy
And the problem is that when someone kill the boss it doesn't check if the tile is free to spawn on.
So sometimes it spawn in walls, stones, on water and in mountains
Lua:
--[[
[+] = done
[-] = not done
[+] random spawn location
[+] lost hp% mob/item spawn
[+] spawn items + monsters on death & start next spawn countdown
[-] DPS
]]
local config = {
SPAWN_AREAS = {
{
TOP_LEFT = Position(1082, 1048, 7),
BOTTOM_RIGHT = Position(1095, 1056, 7)
}
},
BOSS_NAME = 'cyclops smith',
-- How long after death should the boss respawn?
SPAWN_INTERVAL = 5, -- seconds
-- Item rewards
MIN_REWARD_AMOUNT = 1,
MAX_REWARD_AMOUNT = 3,
REWARDS = {
{2160, 1},
{2159, 2},
{8976, 1},
{13537, 1},
{2148, 5},
{2135, 1}
},
-- What the boss will spawn
SUMMONS = { 'rat', 'orc', 'troll', 'bear', 'wolf', 'snake', 'larva' },
-- Minimum and maximum amount of mobs to be spawned.
MIN_SUMMON_AMOUNT = 1,
MAX_SUMMON_AMOUNT = 5,
-- What will be created everytime a certain HP% is reached.
SPAWN_CHOICE_ITEMS = 1,
SPAWN_CHOICE_MOBS = 2,
SPAWN_CHOICE_BOTH = 3,
-- Radius to top-left & to bottom-right from boss position.
SPAWN_OBJECT_RADIUS = 3
}
local DAMAGE_REWARD_CONFIG = {
[1] = { hpPercent = 10 },
[2] = { hpPercent = 30 },
[3] = { hpPercent = 60 },
[4] = { hpPercent = 90 }
}
------------------------------------------------------------------------------------
---------------------------------[ GLOBALEVENT ]----------------------------------
------------------------------------------------------------------------------------
local function spawnLootBoss()
local area = config.SPAWN_AREAS[math.random(1, #config.SPAWN_AREAS)]
local spawnPos = Position(
math.random(area.TOP_LEFT.x, area.BOTTOM_RIGHT.x),
math.random(area.TOP_LEFT.y, area.BOTTOM_RIGHT.y),
area.TOP_LEFT.z
)
Game.createMonster(config.BOSS_NAME, spawnPos, false, true)
Game.broadcastMessage('The vicious boss '.. config.BOSS_NAME ..' has risen from the dead', MESSAGE_EVENT_ADVANCE)
REWARDS_COLLECTED = {}
end
local lootBoss = GlobalEvent('lootBoss')
function lootBoss.onStartup()
spawnLootBoss()
return true
end
lootBoss:register()
------------------------------------------------------------------------------------
-------------------------------[ CREATURESCRIPTS ]--------------------------------
------------------------------------------------------------------------------------
local function secondsToReadable(s)
local hours = math.floor(s / 3600)
local minutes = math.floor(math.mod(s, 3600)/60)
local seconds = math.floor(math.mod(s, 60))
return (hours > 0 and (hours .. ' hour' .. (hours > 1 and 's ' or ' ')) or '') ..
(minutes > 0 and (minutes .. ' minute' .. (minutes > 1 and 's ' or ' ')) or '') ..
(seconds > 0 and (seconds .. ' second' .. (seconds > 1 and 's ' or ' ')) or '')
end
local function getClosestFreeTile(pos, radius)
for y = pos.y - radius, pos.y + radius do
for x = pos.x - radius, pos.x + radius do
local tile = Tile(x, y, pos.z)
if tile and tile:isWalkable() then
return Position(x, y, pos.z)
end
end
end
return nil
end
local function spawnItem(spawnObjectArea)
local reward_idx = math.random(1, #config.REWARDS)
local reward_item_pos = Position(
math.random(spawnObjectArea.TOP_LEFT.x, spawnObjectArea.BOTTOM_RIGHT.x),
math.random(spawnObjectArea.TOP_LEFT.y, spawnObjectArea.BOTTOM_RIGHT.y),
spawnObjectArea.TOP_LEFT.z
)
local tile = Tile(reward_item_pos)
if (not tile) or (not tile:isWalkable()) then
reward_item_pos = getClosestFreeTile(reward_item_pos, 1)
end
if not reward_item_pos then
return
end
Game.createItem(config.REWARDS[reward_idx][1], config.REWARDS[reward_idx][2], reward_item_pos)
reward_item_pos:sendMagicEffect(CONST_ME_MAGIC_BLUE)
end
local function spawnMob(spawnObjectArea)
local mob_pos = Position(
math.random(spawnObjectArea.TOP_LEFT.x, spawnObjectArea.BOTTOM_RIGHT.x),
math.random(spawnObjectArea.TOP_LEFT.y, spawnObjectArea.BOTTOM_RIGHT.y),
spawnObjectArea.TOP_LEFT.z
)
local tile = Tile(mob_pos)
if (not tile) or (not tile:isWalkable()) then
mob_pos = getClosestFreeTile(mob_pos, 1)
end
if not mob_pos then
return
end
Game.createMonster(config.SUMMONS[math.random(1, #config.SUMMONS)], mob_pos, true, true)
mob_pos:sendMagicEffect(CONST_ME_MAGIC_BLUE)
end
------------------------------------------------------------------------------------
REWARDS_COLLECTED = {}
local lootBoss_ce = CreatureEvent('lootBossCE')
function lootBoss_ce.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
local hpAfterDmg = creature:getHealth() - (primaryDamage + secondaryDamage)
local hpDiffPercent = math.floor((creature:getMaxHealth() - hpAfterDmg) * 100 / creature:getMaxHealth())
local bossPos = creature:getPosition()
for i = #DAMAGE_REWARD_CONFIG, 1, -1 do
local f = (function(hpPercent)
----------------------------------------
if hpDiffPercent < hpPercent then
return false
end
if REWARDS_COLLECTED[i] then
return false
end
REWARDS_COLLECTED[i] = 1
local spawnObjectArea = {
TOP_LEFT = Position(
bossPos.x - config.SPAWN_OBJECT_RADIUS,
bossPos.y - config.SPAWN_OBJECT_RADIUS,
bossPos.z
),
BOTTOM_RIGHT = Position(
bossPos.x + config.SPAWN_OBJECT_RADIUS,
bossPos.y + config.SPAWN_OBJECT_RADIUS,
bossPos.z
),
}
local spawnChoice = math.random(config.SPAWN_CHOICE_ITEMS, config.SPAWN_CHOICE_BOTH)
if spawnChoice == config.SPAWN_CHOICE_ITEMS then
for ix = config.MIN_REWARD_AMOUNT, config.MAX_REWARD_AMOUNT do
spawnItem(spawnObjectArea)
end
return true
end
if spawnChoice == config.SPAWN_CHOICE_MOBS then
for ix = config.MIN_REWARD_AMOUNT, config.MAX_REWARD_AMOUNT do
spawnMob(spawnObjectArea)
end
return true
end
if spawnChoice == config.SPAWN_CHOICE_BOTH then
for ix = config.MIN_REWARD_AMOUNT, config.MAX_SUMMON_AMOUNT do
spawnChoice = math.random(config.SPAWN_CHOICE_ITEMS, config.SPAWN_CHOICE_MOBS)
if spawnChoice == config.SPAWN_CHOICE_ITEMS then
spawnItem(spawnObjectArea)
else
spawnMob(spawnObjectArea)
end
end
return true
end
----------------------------------------
end)(DAMAGE_REWARD_CONFIG[i].hpPercent)
if f then break end
end
return primaryDamage, primaryType, secondaryDamage, secondaryType
end
lootBoss_ce:register()
local lootBossDeath = CreatureEvent('lootBossDeath')
function lootBossDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
REWARDS_COLLECTED = {}
local bossPos = creature:getPosition()
local spawnObjectArea = {
TOP_LEFT = Position(
bossPos.x - config.SPAWN_OBJECT_RADIUS,
bossPos.y - config.SPAWN_OBJECT_RADIUS,
bossPos.z
),
BOTTOM_RIGHT = Position(
bossPos.x + config.SPAWN_OBJECT_RADIUS,
bossPos.y + config.SPAWN_OBJECT_RADIUS,
bossPos.z
),
}
for i = config.MIN_REWARD_AMOUNT, config.MAX_REWARD_AMOUNT * 2 do
spawnItem(spawnObjectArea)
end
Game.broadcastMessage(creature:getName() .. ' has been killed. Next spawn in ' .. secondsToReadable(config.SPAWN_INTERVAL), MESSAGE_EVENT_ADVANCE)
addEvent(spawnLootBoss, config.SPAWN_INTERVAL * 1000)
return true
end
lootBossDeath:register()
And the problem is that when someone kill the boss it doesn't check if the tile is free to spawn on.
So sometimes it spawn in walls, stones, on water and in mountains