Skip to content

Commit bb522ee

Browse files
committed
Pirates Spawning Behavior
1 parent fdc2471 commit bb522ee

10 files changed

Lines changed: 137 additions & 21 deletions

File tree

scripts/globals/pirates.lua

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ local piratesSchedule =
2626
{ endTime = utils.timeStringToMinutes('01:10'), action = actions.ARRIVING },
2727
{ endTime = utils.timeStringToMinutes('01:30'), action = actions.ARRIVE },
2828
{ endTime = utils.timeStringToMinutes('01:32'), action = actions.PIRATES_ARRIVE },
29-
{ endTime = utils.timeStringToMinutes('01:35'), action = actions.MOBS_SPAWN },
29+
{ endTime = utils.timeStringToMinutes('01:34'), action = actions.MOBS_SPAWN },
3030
{ endTime = utils.timeStringToMinutes('04:20'), action = actions.PIRATES_RETREAT },
3131
{ endTime = utils.timeStringToMinutes('04:27'), action = actions.DEPART },
3232
{ endTime = utils.timeStringToMinutes('04:48'), action = actions.DEPARTING },
@@ -68,6 +68,35 @@ local piratesData =
6868
},
6969
}
7070

71+
-- This ride's NM: Blackbeard sails the Selbina route, Silverhook the Mhaura route
72+
local function getNMId(zone)
73+
if zone:getID() == xi.zone.SHIP_BOUND_FOR_SELBINA_PIRATES then
74+
return zones[zone:getID()].mob.BLACKBEARD
75+
end
76+
77+
return zones[zone:getID()].mob.SILVERHOOK
78+
end
79+
80+
-- Clear the deck of pirate mobs: disable respawns, despawn idle ones, and leave any still in
81+
-- combat to be finished off (they won't respawn). Used at retreat and before a fresh ride spawns
82+
local function clearPirates(zone)
83+
local ID = zones[zone:getID()]
84+
local ids = { ID.mob.SHIP_WIGHT, getNMId(zone) }
85+
for _, id in ipairs(ID.mob.CROSSBONES) do
86+
table.insert(ids, id)
87+
end
88+
89+
for _, id in ipairs(ids) do
90+
local mob = GetMobByID(id)
91+
if mob then
92+
mob:setRespawnTime(0) -- stop the waves / cancel any pending respawn
93+
if mob:isSpawned() and not mob:isEngaged() then
94+
DespawnMob(id) -- engaged mobs stay until killed, then won't return
95+
end
96+
end
97+
end
98+
end
99+
71100
xi.pirates.setupPirateNPCSchedule = function(npc)
72101
npc:initNpcAi()
73102

@@ -151,15 +180,10 @@ xi.pirates.pirateNPCTimeTrigger = function(npc, triggerId, zoneKey)
151180
-- Pirates appear and run to position
152181
if pirateIdx == 2 then
153182
-- middle pirate has chance to wear a verm cloak, which then means the pirate encounter _might_ have the NM spawn
154-
local bodyModel = 8195
155-
local nmCanSpawn = 0
156-
if math.random(1, 100) <= vermCloakPirateChance then
157-
bodyModel = 47
158-
nmCanSpawn = 1
159-
end
160-
161-
npc:setModelId(bodyModel, xi.slot.BODY)
162-
pirateZone:setLocalVar('nmCanSpawn', nmCanSpawn)
183+
local hasVermCloak = math.random(1, 100) <= vermCloakPirateChance
184+
npc:setModelId(hasVermCloak and 47 or 8195, xi.slot.BODY) -- 47 = verm cloak body, 8195 = default body
185+
pirateZone:setLocalVar('nmCanSpawn', hasVermCloak and 1 or 0)
186+
pirateZone:setLocalVar('nmSpawned', 0) -- reset NM tracking for this ride
163187
end
164188

165189
npc:setPos(pirateData.startPos)
@@ -196,11 +220,35 @@ xi.pirates.zoneStateChange = function(zone, action)
196220
zone:setLocalVar('currPiratesAction', action)
197221

198222
if action == actions.MOBS_SPAWN then
199-
-- TODO enable mob spawns (and NM spawns if nmCanSpawn is set to 1)
200-
-- set them to setRespawn(1s), then set normal respawnTime in onMobSpawn
223+
local ID = zones[zone:getID()]
224+
225+
-- clear any mobs lingering from a previous ride before summoning fresh ones
226+
clearPirates(zone)
227+
228+
-- the skeletons the pirate NPCs are "summoning" onto the deck
229+
for _, id in ipairs(ID.mob.CROSSBONES) do
230+
local crossbones = GetMobByID(id)
231+
if crossbones then
232+
crossbones:setRespawnTime(1)
233+
end
234+
end
235+
236+
if zone:getLocalVar('nmCanSpawn') == 1 and math.random(1, 100) <= 75 then
237+
-- HQ ride, 75%: NM appears from the start
238+
local nm = GetMobByID(getNMId(zone))
239+
if nm then
240+
nm:setRespawnTime(1)
241+
zone:setLocalVar('nmSpawned', 1)
242+
end
243+
else
244+
-- normal ride, or the 25% placeholder Wight on an HQ ride
245+
local wight = GetMobByID(ID.mob.SHIP_WIGHT)
246+
if wight then
247+
wight:setRespawnTime(1)
248+
end
249+
end
201250
elseif action == actions.PIRATES_RETREAT then
202-
-- TODO disable all spawns and despawn any not in combat
203-
-- mobs in combat do not despawn when the ship leaves
251+
clearPirates(zone)
204252
end
205253
end
206254
end

scripts/zones/Ship_bound_for_Mhaura_Pirates/IDs.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ zones[xi.zone.SHIP_BOUND_FOR_MHAURA_PIRATES] =
2323
},
2424
mob =
2525
{
26-
WIGHT = GetFirstID('Ship_Wight'),
26+
CROSSBONES = GetTableOfIDs('Crossbones'),
27+
SHIP_WIGHT = GetFirstID('Ship_Wight'),
2728
SILVERHOOK = GetFirstID('Silverhook'),
2829
},
2930
npc =

scripts/zones/Ship_bound_for_Mhaura_Pirates/mobs/Crossbones.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@ entity.onMobInitialize = function(mob)
99
mob:setMobMod(xi.mobMod.NO_STANDBACK, 1)
1010
end
1111

12+
entity.onMobSpawn = function(mob)
13+
mob:setRespawnTime(60) -- respawns every 60s while the pirate ship is alongside
14+
end
15+
1216
return entity

scripts/zones/Ship_bound_for_Mhaura_Pirates/mobs/Ship_Wight.lua

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,31 @@ entity.onMobInitialize = function(mob)
99
mob:setMobMod(xi.mobMod.NO_STANDBACK, 1)
1010
end
1111

12+
entity.onMobSpawn = function(mob)
13+
mob:setRespawnTime(60) -- respawns every 60s while the pirate ship is alongside
14+
end
15+
16+
entity.onMobDeath = function(mob, player, optParams)
17+
local zone = mob:getZone()
18+
if not zone then
19+
return
20+
end
21+
22+
-- On an HQ ride, the Ship Wight is Silverhook's placeholder (90%) until he appears.
23+
if
24+
zone:getLocalVar('nmCanSpawn') == 1 and
25+
zone:getLocalVar('nmSpawned') == 0 and
26+
math.random(1, 100) <= 90
27+
then
28+
local silverhook = GetMobByID(zones[zone:getID()].mob.SILVERHOOK)
29+
if silverhook then
30+
mob:setRespawnTime(0) -- this Wight stays down; Silverhook takes its slot
31+
silverhook:setRespawnTime(1)
32+
zone:setLocalVar('nmSpawned', 1)
33+
end
34+
end
35+
36+
-- otherwise the Wight respawns in 60s and rolls again
37+
end
38+
1239
return entity

scripts/zones/Ship_bound_for_Mhaura_Pirates/mobs/Silverhook.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
-----------------------------------
22
-- Area: Ship Bound for Mhaura (Pirates)
33
-- NM: Silverhook
4-
-- To do: This NM does not use an SP ability like JP wiki claims but it does have a dust cloud animation that triggers as soon as it is pushed below 50% HP. It is unclear what this does, if anything, after multiple retail captures.
4+
-- To do: This NM does not use an SP ability like JP wiki claims but it does have a dust cloud animation that triggers as soon as it is pushed below 50% HP.
5+
-- It is unclear what this does, if anything, after multiple retail captures.
56
-----------------------------------
67
---@type TMobEntity
78
local entity = {}
@@ -19,6 +20,7 @@ entity.onMobSpawn = function(mob)
1920
mob:setMod(xi.mod.ICE_RES_RANK, 10)
2021
mob:setMod(xi.mod.POWER_MULTIPLIER_SPELL, 55)
2122
mob:setMobMod(xi.mobMod.NO_STANDBACK, 1)
23+
mob:setRespawnTime(0) -- one-and-done per ride; the 1s spawn timer must not respawn him
2224
end
2325

2426
entity.onMobSpellChoose = function(mob, target, spellId)

scripts/zones/Ship_bound_for_Selbina_Pirates/IDs.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ zones[xi.zone.SHIP_BOUND_FOR_SELBINA_PIRATES] =
2424
mob =
2525
{
2626
BLACKBEARD = GetFirstID('Blackbeard'),
27+
CROSSBONES = GetTableOfIDs('Crossbones'),
2728
ENAGAKURE = GetFirstID('Enagakure'),
2829
SHIP_WIGHT = GetFirstID('Ship_Wight'),
2930
},

scripts/zones/Ship_bound_for_Selbina_Pirates/mobs/Blackbeard.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
-----------------------------------
22
-- Area: Ship Bound for Selbina (Pirates)
33
-- NM: Blackbeard
4-
-- To do: This NM does not use an SP ability like JP wiki claims but it does have a dust cloud animation that triggers as soon as it is pushed below 50% HP. It is unclear what this does, if anything, after multiple retail captures.
4+
-- To do: This NM does not use an SP ability like JP wiki claims but it does have a dust cloud animation that triggers as soon as it is pushed below 50% HP.
5+
-- It is unclear what this does, if anything, after multiple retail captures.
56
-----------------------------------
67
---@type TMobEntity
78
local entity = {}
@@ -19,6 +20,7 @@ entity.onMobSpawn = function(mob)
1920
mob:setMod(xi.mod.ICE_RES_RANK, 10)
2021
mob:setMod(xi.mod.POWER_MULTIPLIER_SPELL, 55)
2122
mob:setMobMod(xi.mobMod.NO_STANDBACK, 1)
23+
mob:setRespawnTime(0) -- one-and-done per ride; the 1s spawn timer must not respawn him
2224
end
2325

2426
entity.onMobSpellChoose = function(mob, target, spellId)
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
-----------------------------------
22
-- Area: Ship bound for Selbina Pirates
3-
-- Mob: Ship Wight
3+
-- Mob: Crossbones
44
-----------------------------------
55
---@type TMobEntity
66
local entity = {}
@@ -9,4 +9,8 @@ entity.onMobInitialize = function(mob)
99
mob:setMobMod(xi.mobMod.NO_STANDBACK, 1)
1010
end
1111

12+
entity.onMobSpawn = function(mob)
13+
mob:setRespawnTime(60) -- respawns every 60s while the pirate ship is alongside
14+
end
15+
1216
return entity
Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
-----------------------------------
22
-- Area: Ship bound for Selbina Pirates
3-
-- Mob: Crossbones
3+
-- Mob: Ship Wight
44
-----------------------------------
55
---@type TMobEntity
66
local entity = {}
@@ -9,4 +9,31 @@ entity.onMobInitialize = function(mob)
99
mob:setMobMod(xi.mobMod.NO_STANDBACK, 1)
1010
end
1111

12+
entity.onMobSpawn = function(mob)
13+
mob:setRespawnTime(60) -- respawns every 60s while the pirate ship is alongside
14+
end
15+
16+
entity.onMobDeath = function(mob, player, optParams)
17+
local zone = mob:getZone()
18+
if not zone then
19+
return
20+
end
21+
22+
-- On an HQ ride, the Ship Wight is Blackbeard's placeholder (90%) until he appears
23+
if
24+
zone:getLocalVar('nmCanSpawn') == 1 and
25+
zone:getLocalVar('nmSpawned') == 0 and
26+
math.random(1, 100) <= 90
27+
then
28+
local blackbeard = GetMobByID(zones[zone:getID()].mob.BLACKBEARD)
29+
if blackbeard then
30+
mob:setRespawnTime(0) -- this Wight stays down; Blackbeard takes its slot
31+
blackbeard:setRespawnTime(1)
32+
zone:setLocalVar('nmSpawned', 1)
33+
end
34+
end
35+
36+
-- otherwise the Wight respawns in 60s and rolls again
37+
end
38+
1239
return entity

sql/mob_spawn_points.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79257,7 +79257,7 @@ INSERT INTO `mob_spawn_points` VALUES (17707021,0,'Crossbones','Crossbones',10,2
7925779257
INSERT INTO `mob_spawn_points` VALUES (17707022,0,'Crossbones','Crossbones',11,28,31,-7.737,-7.279,11.354,155);
7925879258
INSERT INTO `mob_spawn_points` VALUES (17707023,0,'Crossbones','Crossbones',11,28,31,7.177,-7.309,17.648,54);
7925979259
INSERT INTO `mob_spawn_points` VALUES (17707024,0,'Ship_Wight','Ship Wight',12,36,39,-0.725,-7.312,23.111,60);
79260-
INSERT INTO `mob_spawn_points` VALUES (17707025,0,'Blackbeard','Blackbeard',13,67,68,-6.387,-11.662,-13.986,56);
79260+
INSERT INTO `mob_spawn_points` VALUES (17707025,0,'Blackbeard','Blackbeard',13,67,68,-0.725,-7.312,23.111,60);
7926179261
INSERT INTO `mob_spawn_points` VALUES (17707026,0,'Enagakure','Enagakure',14,55,55,1.000,-7.000,13.000,60);
7926279262

7926379263
-- ------------------------------------------------------------
@@ -79282,7 +79282,7 @@ INSERT INTO `mob_spawn_points` VALUES (17711117,0,'Crossbones','Crossbones',10,2
7928279282
INSERT INTO `mob_spawn_points` VALUES (17711118,0,'Crossbones','Crossbones',11,28,31,8.710,-7.560,13.220,176);
7928379283
INSERT INTO `mob_spawn_points` VALUES (17711119,0,'Crossbones','Crossbones',11,28,31,7.040,-7.510,11.060,107);
7928479284
INSERT INTO `mob_spawn_points` VALUES (17711120,0,'Ship_Wight','Ship Wight',12,36,39,7.770,-7.450,17.190,188);
79285-
INSERT INTO `mob_spawn_points` VALUES (17711121,0,'Silverhook','Silverhook',13,68,70,-3.560,-7.290,2.430,13);
79285+
INSERT INTO `mob_spawn_points` VALUES (17711121,0,'Silverhook','Silverhook',13,68,70,7.770,-7.450,17.190,188);
7928679286

7928779287
-- ------------------------------------------------------------
7928879288
-- Throne Room [V] (Zone 229)

0 commit comments

Comments
 (0)