creature.lua

main 177 lines · 4 KB Raw
Alex Alex Commit Server upload 18/10/2026 23:38
1function Creature.getClosestFreePosition(self, position, maxRadius, mustBeReachable)
2 maxRadius = maxRadius or 1
3
4 -- backward compatability (extended)
5 if maxRadius == true then
6 maxRadius = 2
7 end
8
9 local checkPosition = Position(position)
10 for radius = 0, maxRadius do
11 checkPosition.x = checkPosition.x - math.min(1, radius)
12 checkPosition.y = checkPosition.y + math.min(1, radius)
13
14 local total = math.max(1, radius * 8)
15 for i = 1, total do
16 if radius > 0 then
17 local direction = math.floor((i - 1) / (radius * 2))
18 checkPosition:getNextPosition(direction)
19 end
20
21 local tile = Tile(checkPosition)
22 if tile:getCreatureCount() == 0 and not tile:hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID) and
23 (not mustBeReachable or self:getPathTo(checkPosition)) then
24 return checkPosition
25 end
26 end
27 end
28 return Position()
29end
30
31function Creature.getPlayer(self)
32 return self:isPlayer() and self or nil
33end
34
35function Creature.isContainer(self)
36 return false
37end
38
39function Creature.isItem(self)
40 return false
41end
42
43function Creature.isMonster(self)
44 return false
45end
46
47function Creature.isNpc(self)
48 return false
49end
50
51function Creature.isPlayer(self)
52 return false
53end
54
55function Creature.isTeleport(self)
56 return false
57end
58
59function Creature.isTile(self)
60 return false
61end
62
63function Creature:setMonsterOutfit(monster, time)
64 local monsterType = MonsterType(monster)
65 if not monsterType then
66 return false
67 end
68
69 if self:isPlayer() and not (self:hasFlag(PlayerFlag_CanIllusionAll) or monsterType:isIllusionable()) then
70 return false
71 end
72
73 local condition = Condition(CONDITION_OUTFIT)
74 condition:setOutfit(monsterType:getOutfit())
75 condition:setTicks(time)
76 self:addCondition(condition)
77
78 return true
79end
80
81function Creature:setItemOutfit(item, time)
82 local itemType = ItemType(item)
83 if not itemType then
84 return false
85 end
86
87 local condition = Condition(CONDITION_OUTFIT)
88 condition:setOutfit({
89 lookTypeEx = itemType:getId()
90 })
91 condition:setTicks(time)
92 self:addCondition(condition)
93
94 return true
95end
96
97function Creature:addSummon(monster)
98 local summon = Monster(monster)
99 if not summon then
100 return false
101 end
102
103 summon:setTarget(nil)
104 summon:setFollowCreature(nil)
105 summon:setDropLoot(false)
106 summon:setSkillLoss(false)
107 summon:setMaster(self)
108 summon:getPosition():notifySummonAppear(summon)
109
110 return true
111end
112
113function Creature:removeSummon(monster)
114 local summon = Monster(monster)
115 if not summon or summon:getMaster() ~= self then
116 return false
117 end
118
119 summon:setTarget(nil)
120 summon:setFollowCreature(nil)
121 summon:setDropLoot(true)
122 summon:setSkillLoss(true)
123 summon:setMaster(nil)
124
125 return true
126end
127
128function Creature:addDamageCondition(target, type, list, damage, period, rounds)
129 if damage <= 0 or not target or target:isImmune(type) then
130 return false
131 end
132
133 local condition = Condition(type)
134 condition:setParameter(CONDITION_PARAM_OWNER, self:getId())
135 condition:setParameter(CONDITION_PARAM_DELAYED, true)
136
137 if list == DAMAGELIST_EXPONENTIAL_DAMAGE then
138 local exponent, value = -10, 0
139 while value < damage do
140 value = math.floor(10 * math.pow(1.2, exponent) + 0.5)
141 condition:addDamage(1, period or 4000, -value)
142
143 if value >= damage then
144 local permille = math.random(10, 1200) / 1000
145 condition:addDamage(1, period or 4000, -math.max(1, math.floor(value * permille + 0.5)))
146 else
147 exponent = exponent + 1
148 end
149 end
150 elseif list == DAMAGELIST_LOGARITHMIC_DAMAGE then
151 local n, value = 0, damage
152 while value > 0 do
153 value = math.floor(damage * math.pow(2.718281828459, -0.05 * n) + 0.5)
154 if value ~= 0 then
155 condition:addDamage(1, period or 4000, -value)
156 n = n + 1
157 end
158 end
159 elseif list == DAMAGELIST_VARYING_PERIOD then
160 for _ = 1, rounds do
161 condition:addDamage(1, math.random(period[1], period[2]) * 1000, -damage)
162 end
163 elseif list == DAMAGELIST_CONSTANT_PERIOD then
164 condition:addDamage(rounds, period * 1000, -damage)
165 end
166
167 target:addCondition(condition)
168 return true
169end
170
171function Creature:canAccessPz()
172 if self:isMonster() or (self:isPlayer() and self:isPzLocked()) then
173 return false
174 end
175 return true
176end
177
Top