mirror of
https://github.com/otland/forgottenserver
synced 2026-08-15 16:32:07 -04:00
it was preventing items like costume bags to change player outfit because monster list was not illusionable but was allowed in this item, in other words this check is useless and only breaks functionality
205 lines
4.7 KiB
Lua
205 lines
4.7 KiB
Lua
function Creature.getClosestFreePosition(self, position, maxRadius, mustBeReachable)
|
|
maxRadius = maxRadius or 1
|
|
|
|
-- backward compatability (extended)
|
|
if maxRadius then
|
|
maxRadius = 2
|
|
end
|
|
|
|
local checkPosition = Position(position)
|
|
for radius = 0, maxRadius do
|
|
checkPosition.x = checkPosition.x - math.min(1, radius)
|
|
checkPosition.y = checkPosition.y + math.min(1, radius)
|
|
|
|
local total = math.max(1, radius * 8)
|
|
for i = 1, total do
|
|
if radius > 0 then
|
|
local direction = math.floor((i - 1) / (radius * 2))
|
|
checkPosition:getNextPosition(direction)
|
|
end
|
|
|
|
local tile = Tile(checkPosition)
|
|
if tile and tile:getCreatureCount() == 0 and not tile:hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID) and
|
|
(not mustBeReachable or self:getPathTo(checkPosition)) then
|
|
return checkPosition
|
|
end
|
|
end
|
|
end
|
|
return Position()
|
|
end
|
|
|
|
function Creature.getPlayer(self)
|
|
return self:isPlayer() and self or nil
|
|
end
|
|
|
|
function Creature.isContainer(self)
|
|
return false
|
|
end
|
|
|
|
function Creature.isItem(self)
|
|
return false
|
|
end
|
|
|
|
function Creature.isMonster(self)
|
|
return false
|
|
end
|
|
|
|
function Creature.isNpc(self)
|
|
return false
|
|
end
|
|
|
|
function Creature.isPlayer(self)
|
|
return false
|
|
end
|
|
|
|
function Creature.isTeleport(self)
|
|
return false
|
|
end
|
|
|
|
function Creature.isTile(self)
|
|
return false
|
|
end
|
|
|
|
function Creature:setMonsterOutfit(monster, time)
|
|
local monsterType = MonsterType(monster)
|
|
if not monsterType then
|
|
return false
|
|
end
|
|
|
|
local condition = Condition(CONDITION_OUTFIT)
|
|
condition:setOutfit(monsterType:getOutfit())
|
|
condition:setTicks(time)
|
|
self:addCondition(condition)
|
|
|
|
return true
|
|
end
|
|
|
|
function Creature:setItemOutfit(item, time)
|
|
local itemType = ItemType(item)
|
|
if not itemType then
|
|
return false
|
|
end
|
|
|
|
local condition = Condition(CONDITION_OUTFIT)
|
|
condition:setOutfit({
|
|
lookTypeEx = itemType:getId()
|
|
})
|
|
condition:setTicks(time)
|
|
self:addCondition(condition)
|
|
|
|
return true
|
|
end
|
|
|
|
function Creature:addSummon(monster)
|
|
local summon = Monster(monster)
|
|
if not summon then
|
|
return false
|
|
end
|
|
|
|
summon:setTarget(nil)
|
|
summon:setFollowCreature(nil)
|
|
summon:setDropLoot(false)
|
|
summon:setSkillLoss(false)
|
|
summon:setMaster(self)
|
|
|
|
if self:isPlayer() then
|
|
summon:getPosition():notifySummonAppear(summon)
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function Creature:removeSummon(monster)
|
|
local summon = Monster(monster)
|
|
if not summon or summon:getMaster() ~= self then
|
|
return false
|
|
end
|
|
|
|
summon:setTarget(nil)
|
|
summon:setFollowCreature(nil)
|
|
summon:setDropLoot(true)
|
|
summon:setSkillLoss(true)
|
|
summon:setMaster(nil)
|
|
|
|
return true
|
|
end
|
|
|
|
function Creature:addDamageCondition(target, type, list, damage, period, rounds)
|
|
if damage <= 0 or not target or target:isImmune(type) then
|
|
return false
|
|
end
|
|
|
|
local condition = Condition(type)
|
|
condition:setParameter(CONDITION_PARAM_OWNER, self:getId())
|
|
condition:setParameter(CONDITION_PARAM_DELAYED, true)
|
|
|
|
if list == DAMAGELIST_EXPONENTIAL_DAMAGE then
|
|
local exponent, value = -10, 0
|
|
while value < damage do
|
|
value = math.floor(10 * math.pow(1.2, exponent) + 0.5)
|
|
condition:addDamage(1, period or 4000, -value)
|
|
|
|
if value >= damage then
|
|
local permille = math.random(10, 1200) / 1000
|
|
condition:addDamage(1, period or 4000, -math.max(1, math.floor(value * permille + 0.5)))
|
|
else
|
|
exponent = exponent + 1
|
|
end
|
|
end
|
|
elseif list == DAMAGELIST_LOGARITHMIC_DAMAGE then
|
|
local n, value = 0, damage
|
|
while value > 0 do
|
|
value = math.floor(damage * math.pow(2.718281828459, -0.05 * n) + 0.5)
|
|
if value ~= 0 then
|
|
condition:addDamage(1, period or 4000, -value)
|
|
n = n + 1
|
|
end
|
|
end
|
|
elseif list == DAMAGELIST_VARYING_PERIOD then
|
|
for _ = 1, rounds do
|
|
condition:addDamage(1, math.random(period[1], period[2]) * 1000, -damage)
|
|
end
|
|
elseif list == DAMAGELIST_CONSTANT_PERIOD then
|
|
condition:addDamage(rounds, period * 1000, -damage)
|
|
end
|
|
|
|
target:addCondition(condition)
|
|
return true
|
|
end
|
|
|
|
function Creature:canAccessPz()
|
|
if self:isMonster() or (self:isPlayer() and self:isPzLocked()) then
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
|
|
function Creature.getMonster(self)
|
|
return self:isMonster() and self or nil
|
|
end
|
|
|
|
function Creature.getKillers(self, onlyPlayers)
|
|
local killers = {}
|
|
local inFightTicks = configManager.getNumber(configKeys.PZ_LOCKED)
|
|
local timeNow = os.mtime()
|
|
local getCreature = onlyPlayers and Player or Creature
|
|
for cid, cb in pairs(self:getDamageMap()) do
|
|
local creature = getCreature(cid)
|
|
if creature and creature ~= self and (timeNow - cb.ticks) <= inFightTicks then
|
|
killers[#killers + 1] = {
|
|
creature = creature,
|
|
damage = cb.total
|
|
}
|
|
end
|
|
end
|
|
|
|
table.sort(killers, function(a, b) return a.damage > b.damage end)
|
|
for i, killer in pairs(killers) do
|
|
killers[i] = killer.creature
|
|
end
|
|
return killers
|
|
end
|
|
|
|
function Creature.removeStorageValue(self, key)
|
|
return self:setStorageValue(key, nil)
|
|
end
|