Skip to content

Commit 89a9e10

Browse files
Implement Cerberus Mechanics
Co-Authored-By: Xaver-DaRed <Xaver-DaRed@users.noreply.github.com>
1 parent 7425d85 commit 89a9e10

12 files changed

Lines changed: 249 additions & 92 deletions

File tree

scripts/actions/mobskills/gates_of_hades.lua

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@
88
local mobskillObject = {}
99

1010
mobskillObject.onMobSkillCheck = function(target, mob, skill)
11-
if mob:getHPP() < 25 then -- TODO: Move to mob scripts?
12-
return 0
13-
end
14-
15-
return 1
11+
return 0
1612
end
1713

1814
mobskillObject.onMobWeaponSkill = function(mob, target, skill, action)

scripts/actions/mobskills/lava_spit.lua

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@
77
local mobskillObject = {}
88

99
mobskillObject.onMobSkillCheck = function(target, mob, skill)
10-
if target:isBehind(mob, 48) then
11-
return 1
12-
else
13-
return 0
14-
end
10+
return 0
1511
end
1612

1713
mobskillObject.onMobWeaponSkill = function(mob, target, skill, action)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
-----------------------------------
2+
-- Roar Cerberus (Emote)
3+
-- Description: Cerberus roars at the sky.
4+
-----------------------------------
5+
---@type TMobSkill
6+
local mobskillObject = {}
7+
8+
mobskillObject.onMobSkillCheck = function(target, mob, skill)
9+
return 0
10+
end
11+
12+
mobskillObject.onMobWeaponSkill = function(mob, target, skill, action)
13+
skill:setMsg(xi.msg.basic.NONE)
14+
15+
return 0
16+
end
17+
18+
return mobskillObject

scripts/actions/mobskills/scorching_lash.lua

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@
99
local mobskillObject = {}
1010

1111
mobskillObject.onMobSkillCheck = function(target, mob, skill)
12-
if not target:isBehind(mob, 48) then
13-
return 1
14-
else
15-
return 0
16-
end
12+
return 0
1713
end
1814

1915
mobskillObject.onMobWeaponSkill = function(mob, target, skill, action)

scripts/actions/mobskills/sulfurous_breath.lua

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@
77
local mobskillObject = {}
88

99
mobskillObject.onMobSkillCheck = function(target, mob, skill)
10-
if target:isBehind(mob, 48) then
11-
return 1
12-
else
13-
return 0
14-
end
10+
return 0
1511
end
1612

1713
mobskillObject.onMobWeaponSkill = function(mob, target, skill, action)

scripts/enum/mob_skill.lua

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1027,7 +1027,10 @@ xi.mobSkill =
10271027
FIRESPIT = 1733,
10281028

10291029
LAVA_SPIT = 1785,
1030-
1030+
SULFUROUS_BREATH = 1786,
1031+
SCORCHING_LASH = 1787,
1032+
ULULATION = 1788,
1033+
MAGMA_HOPLON = 1789,
10311034
GATES_OF_HADES = 1790,
10321035

10331036
VAMPIRIC_ROOT = 1793,
@@ -1053,6 +1056,7 @@ xi.mobSkill =
10531056
PIT_AMBUSH_2 = 1844,
10541057
MANDIBULAR_BITE_2 = 1845,
10551058

1059+
ROAR_CERBERUS = 1892,
10561060
-- SPIRIT_SURGE = 1893,
10571061

10581062
FIRESPIT_BLUE_MAMOOLJA = 1923, -- Ignores shadows

scripts/utils/utils.lua

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,38 +1039,41 @@ table =
10391039
}
10401040
--]]
10411041
---@param target CBaseEntity
1042-
---@param table table
1042+
---@param params table
10431043
---@return boolean
1044-
function utils.drawIn(target, table)
1045-
if table.position then
1046-
local nextDrawIn = target:getLocalVar('[Draw-In]WaitTime')
1047-
local conditions = table.conditions and table.conditions or { true }
1048-
for _, condition in ipairs(conditions) do
1049-
if condition then
1050-
if nextDrawIn > 0 then
1051-
if GetSystemTime() > nextDrawIn then
1052-
local position = {}
1053-
if table.position then
1054-
position.x = table.position.x and table.position.x or table.position[1]
1055-
position.y = table.position.y and table.position.y or table.position[2]
1056-
position.z = table.position.z and table.position.z or table.position[3]
1057-
position.rot = table.position.rot and table.position.rot or table.position[4]
1058-
end
1059-
1060-
local offset = table.offset and table.offset or 0
1061-
local degrees = table.degrees and table.degrees or 0
1044+
function utils.drawIn(target, params)
1045+
if not params.position then
1046+
target:setLocalVar('[Draw-In]WaitTime', 0)
1047+
return false
1048+
end
10621049

1063-
DrawIn(target, position, offset, degrees)
1064-
target:setLocalVar('[Draw-In]WaitTime', 0)
1065-
return true
1050+
local nextDrawIn = target:getLocalVar('[Draw-In]WaitTime')
1051+
local conditions = params.conditions and params.conditions or { true }
1052+
for _, condition in ipairs(conditions) do
1053+
if condition then
1054+
if nextDrawIn > 0 then
1055+
if GetSystemTime() > nextDrawIn then
1056+
local position = {}
1057+
if params.position then
1058+
position.x = params.position.x and params.position.x or params.position[1]
1059+
position.y = params.position.y and params.position.y or params.position[2]
1060+
position.z = params.position.z and params.position.z or params.position[3]
1061+
position.rot = params.position.rot and params.position.rot or params.position[4]
10661062
end
10671063

1068-
return false
1069-
else
1070-
local wait = table.wait and table.wait or 1
1071-
target:setLocalVar('[Draw-In]WaitTime', GetSystemTime() + wait)
1072-
return false
1064+
local offset = params.offset and params.offset or 0
1065+
local degrees = params.degrees and params.degrees or 0
1066+
1067+
DrawIn(target, position, offset, degrees)
1068+
target:setLocalVar('[Draw-In]WaitTime', 0)
1069+
return true
10731070
end
1071+
1072+
return false
1073+
else
1074+
local wait = params.wait and params.wait or 1
1075+
target:setLocalVar('[Draw-In]WaitTime', GetSystemTime() + wait)
1076+
return false
10741077
end
10751078
end
10761079
end

scripts/zones/Mount_Zhayolm/mobs/Cerberus.lua

Lines changed: 151 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,57 +5,170 @@
55
---@type TMobEntity
66
local entity = {}
77

8+
local drawInPositions =
9+
{
10+
{ 330.166, -23.909, -89.456 },
11+
{ 314.186, -24.180, -89.331 },
12+
{ 314.372, -23.985, -82.1 },
13+
{ 321.629, -24, -90.936 },
14+
{ 329.969, -24, -73.665 },
15+
{ 322.330, -24, -82.168 },
16+
{ 331.026, -24, -81.093 },
17+
{ 321.795, -23.978, -73.724 },
18+
}
19+
20+
entity.spawnPoints =
21+
{
22+
{ x = 310.427, y = -24.142, z = -86.671 },
23+
{ x = 319.374, y = -24.007, z = -88.509 },
24+
{ x = 319.599, y = -23.992, z = -82.799 },
25+
{ x = 313.390, y = -23.871, z = -78.151 },
26+
{ x = 318.662, y = -23.890, z = -73.773 },
27+
{ x = 324.362, y = -24.269, z = -75.149 },
28+
{ x = 323.935, y = -24.000, z = -80.289 },
29+
{ x = 323.565, y = -24.000, z = -84.583 },
30+
{ x = 323.058, y = -23.995, z = -90.231 },
31+
{ x = 328.670, y = -23.984, z = -90.623 },
32+
{ x = 331.835, y = -23.889, z = -89.472 },
33+
{ x = 330.609, y = -24.054, z = -84.279 },
34+
{ x = 330.292, y = -24.000, z = -79.809 },
35+
{ x = 329.868, y = -24.109, z = -76.046 },
36+
}
37+
38+
entity.onMobInitialize = function(mob)
39+
mob:setRespawnTime(math.randomInt(48, 72) * 3600) -- 48 - 72 hours with 1 hour windows
40+
xi.mob.updateNMSpawnPoint(mob)
41+
42+
mob:addImmunity(xi.immunity.LIGHT_SLEEP)
43+
mob:addImmunity(xi.immunity.DARK_SLEEP)
44+
mob:addImmunity(xi.immunity.PLAGUE)
45+
mob:addImmunity(xi.immunity.SILENCE)
46+
47+
mob:setMobMod(xi.mobMod.GIL_MIN, 20000)
48+
mob:setMobMod(xi.mobMod.GIL_MAX, 20000)
49+
50+
mob:addListener('TAKE_DAMAGE', 'CERBERUS_TAKE_DAMAGE', function(mobArg, damage, attacker, attackType, damageType)
51+
local damageAmount = damage
52+
local damageThreshold = math.max(1, math.floor(mob:getMaxHP() * 0.005))
53+
54+
if damageAmount < damageThreshold then
55+
return
56+
end
57+
58+
local dmgPhysical = mobArg:getMod(xi.mod.UDMGPHYS)
59+
local dmgRanged = mobArg:getMod(xi.mod.UDMGRANGE)
60+
local dmgMagical = mobArg:getMod(xi.mod.UDMGMAGIC)
61+
local dmgBreath = mobArg:getMod(xi.mod.UDMGBREATH)
62+
63+
local modifierAdjustment = math.floor(damageAmount / damageThreshold) * 50
64+
65+
if
66+
attackType == xi.attackType.PHYSICAL or
67+
attackType == xi.attackType.RANGED
68+
then
69+
dmgPhysical = utils.clamp(dmgPhysical - modifierAdjustment, -8500, 8500)
70+
dmgRanged = utils.clamp(dmgRanged - modifierAdjustment, -8500, 8500)
71+
dmgMagical = utils.clamp(dmgMagical + modifierAdjustment, -8500, 8500)
72+
dmgBreath = utils.clamp(dmgBreath + modifierAdjustment, -8500, 8500)
73+
elseif
74+
attackType == xi.attackType.MAGICAL or
75+
attackType == xi.attackType.BREATH
76+
then
77+
dmgPhysical = utils.clamp(dmgPhysical + modifierAdjustment, -8500, 8500)
78+
dmgRanged = utils.clamp(dmgRanged + modifierAdjustment, -8500, 8500)
79+
dmgMagical = utils.clamp(dmgMagical - modifierAdjustment, -8500, 8500)
80+
dmgBreath = utils.clamp(dmgBreath - modifierAdjustment, -8500, 8500)
81+
end
82+
83+
mobArg:setMod(xi.mod.UDMGPHYS, dmgPhysical)
84+
mobArg:setMod(xi.mod.UDMGRANGE, dmgRanged)
85+
mobArg:setMod(xi.mod.UDMGMAGIC, dmgMagical)
86+
mobArg:setMod(xi.mod.UDMGBREATH, dmgBreath)
87+
end)
88+
end
89+
890
entity.onMobSpawn = function(mob)
991
mob:setMobMod(xi.mobMod.NO_MOVE, 0)
1092
mob:setMobMod(xi.mobMod.AOE_HIT_ALL, 1)
93+
94+
mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 200)
95+
mob:setMod(xi.mod.DOUBLE_ATTACK, 15)
96+
mob:setMod(xi.mod.DEF, 486)
97+
mob:setMod(xi.mod.ATT, 615)
98+
mob:setMod(xi.mod.REGAIN, 10)
99+
100+
mob:setMod(xi.mod.FIRE_RES_RANK, 7)
101+
mob:setMod(xi.mod.ICE_RES_RANK, 7)
102+
mob:setMod(xi.mod.WIND_RES_RANK, 7)
103+
mob:setMod(xi.mod.EARTH_RES_RANK, 7)
104+
mob:setMod(xi.mod.THUNDER_RES_RANK, 7)
105+
mob:setMod(xi.mod.WATER_RES_RANK, 7)
106+
mob:setMod(xi.mod.LIGHT_RES_RANK, 7)
107+
mob:setMod(xi.mod.DARK_RES_RANK, 7)
108+
109+
mob:setMod(xi.mod.BIND_RES_RANK, 7)
110+
mob:setMod(xi.mod.BLIND_RES_RANK, 7)
111+
mob:setMod(xi.mod.GRAVITY_RES_RANK, 7)
112+
mob:setMod(xi.mod.PARALYZE_RES_RANK, 7)
113+
mob:setMod(xi.mod.POISON_RES_RANK, 7)
114+
mob:setMod(xi.mod.SLOW_RES_RANK, 7)
115+
116+
mob:setMod(xi.mod.UDMGBREATH, -1250)
117+
mob:setMod(xi.mod.UDMGMAGIC, -1250)
118+
119+
mob:setMod(xi.mod.CURSE_MEVA, 1000)
120+
end
121+
122+
entity.onMobRoam = function(mob)
123+
local currentTime = GetSystemTime()
124+
if currentTime < mob:getLocalVar('roarTimer') then
125+
return
126+
end
127+
128+
mob:useMobAbility(xi.mobSkill.ROAR_CERBERUS)
129+
mob:setLocalVar('roarTimer', currentTime + math.random(150, 210))
11130
end
12131

13132
entity.onMobFight = function(mob, target)
14-
local targetPos = target:getPos()
15-
local spawnPos = mob:getSpawnPos()
16-
local arenaBoundaries =
17-
{
18-
{ { 335, -92 }, { 332, -94 } },
19-
}
133+
if mob:getHPP() > 25 then
134+
mob:setMod(xi.mod.REGAIN, 10)
135+
else
136+
mob:setMod(xi.mod.REGAIN, 60)
137+
end
20138

21-
local drawInPositions =
22-
{
23-
{ 330.166, -23.909, -89.456, targetPos.rot },
24-
{ 314.186, -24.180, -89.331, targetPos.rot },
25-
{ 314.372, -23.985, -82.1, targetPos.rot },
26-
{ 321.629, -24, -90.936, targetPos.rot },
27-
{ 329.969, -24, -73.665, targetPos.rot },
28-
{ 322.330, -24, -82.168, targetPos.rot },
29-
{ 331.026, -24, -81.093, targetPos.rot },
30-
{ 321.795, -23.978, -73.724, targetPos.rot },
31-
}
139+
if
140+
target:getZPos() <= -70 and
141+
target:getXPos() >= 310 and
142+
utils.sameSideOfLine({ { 335, -92 }, { 332, -94 } }, target:getPos(), mob:getSpawnPos())
143+
then
144+
mob:setMobMod(xi.mobMod.NO_MOVE, 0)
145+
return
146+
end
147+
148+
mob:setMobMod(xi.mobMod.NO_MOVE, 1)
32149

33-
local drawInTable =
150+
local pos = utils.randomEntry(drawInPositions)
151+
utils.drawIn(target, { position = { pos[1], pos[2], pos[3], target:getRotPos() }, wait = 2 })
152+
end
153+
154+
entity.onMobMobskillChoose = function(mob, target, skillId)
155+
local skillList =
34156
{
35-
conditions =
36-
{
37-
target:getZPos() > -70,
38-
target:getXPos() < 310,
39-
not utils.sameSideOfLine(arenaBoundaries[1], targetPos, spawnPos),
40-
},
41-
position = utils.randomEntry(drawInPositions),
42-
wait = 2,
157+
xi.mobSkill.ULULATION,
158+
xi.mobSkill.MAGMA_HOPLON,
43159
}
44-
for _, condition in ipairs(drawInTable.conditions) do
45-
if condition then
46-
mob:setMobMod(xi.mobMod.NO_MOVE, 1)
47-
utils.drawIn(target, drawInTable)
48-
break
49-
else
50-
mob:setMobMod(xi.mobMod.NO_MOVE, 0)
51-
end
160+
161+
if target:isInfront(mob, 128) then
162+
table.insert(skillList, xi.mobSkill.LAVA_SPIT)
163+
table.insert(skillList, xi.mobSkill.SULFUROUS_BREATH)
164+
table.insert(skillList, xi.mobSkill.SCORCHING_LASH)
52165
end
53166

54-
if mob:getHPP() > 25 then
55-
mob:setMod(xi.mod.REGAIN, 10)
56-
else
57-
mob:setMod(xi.mod.REGAIN, 70)
167+
if mob:getHPP() < 25 then
168+
table.insert(skillList, xi.mobSkill.GATES_OF_HADES)
58169
end
170+
171+
return skillList[math.randomInt(1, #skillList)]
59172
end
60173

61174
entity.onMobDisengage = function(mob)

scripts/zones/Mount_Zhayolm/mobs/Sarameya.lua

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,26 @@ entity.onMobSpawn = function(mob)
2626
mob:setLocalVar('[rage]timer', 3600) -- 60 minutes
2727
end
2828

29+
entity.onMobMobskillChoose = function(mob, target, skillId)
30+
local skillList =
31+
{
32+
xi.mobSkill.ULULATION,
33+
xi.mobSkill.MAGMA_HOPLON,
34+
}
35+
36+
if target:isInfront(mob, 128) then
37+
table.insert(skillList, xi.mobSkill.LAVA_SPIT)
38+
table.insert(skillList, xi.mobSkill.SULFUROUS_BREATH)
39+
table.insert(skillList, xi.mobSkill.SCORCHING_LASH)
40+
end
41+
42+
if mob:getHPP() < 25 then
43+
table.insert(skillList, xi.mobSkill.GATES_OF_HADES)
44+
end
45+
46+
return skillList[math.randomInt(1, #skillList)]
47+
end
48+
2949
entity.onMobFight = function(mob, target)
3050
local hpp = mob:getHPP()
3151
local useChainspell = false

0 commit comments

Comments
 (0)