forgottenserver/data/lib/core/creature.lua
Evil Puncker 244e28c735
Removed unnecessary check in setMonsterOutfit function (#4633)
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
2024-03-14 13:53:57 -03:00

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