mirror of
https://gitlab.com/hoggit/developers/hoggit.git
synced 2025-11-10 15:43:28 +00:00
Added comments, added base framework for respawning
This commit is contained in:
parent
d3efee7595
commit
07de403128
264
lib/spawner.lua
264
lib/spawner.lua
@ -1,59 +1,229 @@
|
|||||||
|
--- spawner.lua
|
||||||
|
-- Spawning utilities for H.O.G.G.I.T. Framework
|
||||||
|
|
||||||
|
--Groups that should be auto-respawned along with their delay, and respawn percentage
|
||||||
|
HOGGIT.zombies = {}
|
||||||
|
|
||||||
|
-- Scheduled functions to check for respawns. This allows us to queue up functions to check for
|
||||||
|
-- dead zombies, and by keeping a reference to the scheduled functions ID we can cancel it if
|
||||||
|
-- another unit in the same group dies a short while after, and queue up another one, basically
|
||||||
|
-- batching the dead checks if you kill many units in the same group in quick succession.
|
||||||
|
HOGGIT.zombie_checks = {}
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
spawner.lua
|
Auto generated spawner objects created from the .miz
|
||||||
|
Example usage: if you have a red coalition group in the .miz named "Bad Guys":
|
||||||
Automatically create a table of all units in the game and create a spawner for them.
|
HOGGIT.spawners.red['Bad Guys']:Spawn()
|
||||||
]]
|
]]
|
||||||
|
HOGGIT.spawners = {['neutral'] = {}, ['red'] = {}, ['blue'] = {}}
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Spawner object that takes a group name from the ME.
|
||||||
|
Has flexible options for spawning a group once defined. One of these are created for each group that exists
|
||||||
|
in the .miz later on (stored in HOGGIT.spawners), but you can also define your own if you'd like to have groups
|
||||||
|
that have the same template in the .miz, but have different behaviors
|
||||||
|
(like spawning in a different location, or adding respawn options)
|
||||||
|
|
||||||
|
Example usage: With a group in your .miz with the name "Good Guys 1":
|
||||||
|
local good_guys_spawn = HOGGIT.Spawner("Good Guys 1")
|
||||||
|
local spawned_good_guys_group = good_guys_spawn:Spawn()
|
||||||
|
|
||||||
|
@param grpName Name of a group defined in the mission editor
|
||||||
|
@return HOGGIT.Spawner
|
||||||
|
]]
|
||||||
HOGGIT.Spawner = function(grpName)
|
HOGGIT.Spawner = function(grpName)
|
||||||
|
local GroupName = grpName
|
||||||
|
|
||||||
|
--- holds the function and args that are called when this spawner spawns a group
|
||||||
local CallBack = {}
|
local CallBack = {}
|
||||||
|
|
||||||
|
--- Table/Dictionary keyed by a group object with true value if group is alive.
|
||||||
|
-- Dead groups will be set to nil and garbage collected
|
||||||
|
local SpawnedGroups = {}
|
||||||
|
|
||||||
|
--- Respawn options
|
||||||
|
local zombie = false
|
||||||
|
local respawn_delay = 60
|
||||||
|
local partial_death_threshold_percent = nil
|
||||||
|
local partial_death_respawn_delay = respawn_delay
|
||||||
|
|
||||||
return {
|
return {
|
||||||
Spawn = function(self)
|
--- Spawns a copy of the "template" group in the mission editor
|
||||||
local added_grp = Group.getByName(mist.cloneGroup(grpName, true).name)
|
-- Spawns the group at the same location and with the same parameters as the 'template' in the mission editor.
|
||||||
if CallBack.func then
|
-- @param self HOGGIT.Spawner object
|
||||||
if not CallBack.args then CallBack.args = {} end
|
-- @return Group
|
||||||
mist.scheduleFunction(CallBack.func, {added_grp, unpack(CallBack.args)}, timer.getTime() + 1)
|
Spawn = function(self)
|
||||||
end
|
local added_grp = Group.getByName(mist.cloneGroup(grpName, true).name)
|
||||||
return added_grp
|
if CallBack.func then
|
||||||
end,
|
|
||||||
SpawnAtPoint = function(self, point)
|
|
||||||
local vars = {
|
|
||||||
groupName = grpName,
|
|
||||||
point = point,
|
|
||||||
action = "clone"
|
|
||||||
}
|
|
||||||
|
|
||||||
local new_group = mist.teleportToPoint(vars)
|
|
||||||
if new_group then
|
|
||||||
local name = new_group.name
|
|
||||||
if CallBack.func then
|
|
||||||
if not CallBack.args then CallBack.args = {} end
|
if not CallBack.args then CallBack.args = {} end
|
||||||
mist.scheduleFunction(CallBack.func, {Group.getByName(name), unpack(CallBack.args)}, timer.getTime() + 1)
|
mist.scheduleFunction(CallBack.func, {added_grp, unpack(CallBack.args)}, timer.getTime() + 1)
|
||||||
end
|
end
|
||||||
return Group.getByName(name)
|
SpawnedGroups[added_grp] = true
|
||||||
else
|
if zombie then HOGGIT.setZombie(HOGGIT.zombies, added_grp, self, true) end
|
||||||
trigger.action.outText("Error spawning " .. grpName, 15)
|
return added_grp
|
||||||
end
|
end,
|
||||||
|
|
||||||
end,
|
--- Same as 'Spawn', but takes an SSE Vec2 (table with an X and Y keys)
|
||||||
SpawnInZone = function(self, zoneName)
|
-- @param self HOGGIT.Spawner object
|
||||||
local added_grp = Group.getByName(mist.cloneInZone(grpName, zoneName).name)
|
-- @param point Vec2
|
||||||
if CallBack.func then
|
-- @return Group
|
||||||
if not CallBack.args then CallBack.args = {} end
|
SpawnAtPoint = function(self, point)
|
||||||
mist.scheduleFunction(CallBack.func, {added_grp, unpack(CallBack.args)}, timer.getTime() + 1)
|
local vars = {
|
||||||
end
|
groupName = grpName,
|
||||||
return added_grp
|
point = point,
|
||||||
end,
|
action = "clone"
|
||||||
OnSpawnGroup = function(self, f, args)
|
}
|
||||||
CallBack.func = f
|
|
||||||
CallBack.args = args
|
local new_group = mist.teleportToPoint(vars)
|
||||||
end
|
if new_group then
|
||||||
|
local name = new_group.name
|
||||||
|
if CallBack.func then
|
||||||
|
if not CallBack.args then CallBack.args = {} end
|
||||||
|
mist.scheduleFunction(CallBack.func, {Group.getByName(name), unpack(CallBack.args)}, timer.getTime() + 1)
|
||||||
|
end
|
||||||
|
local added_grp = Group.getByName(name)
|
||||||
|
SpawnedGroups[added_grp] = true
|
||||||
|
if zombie then HOGGIT.setZombie(HOGGIT.zombies, added_grp, self, true) end
|
||||||
|
return added_grp
|
||||||
|
else
|
||||||
|
trigger.action.outText("Error spawning " .. grpName, 15)
|
||||||
|
end
|
||||||
|
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Same as 'Spawn' but takes a zone name defined in the mission editor
|
||||||
|
-- @param self HOGGIT.Spawner object
|
||||||
|
-- @param zoneName Name of a zone that's defined in the mission editor
|
||||||
|
-- @return Group
|
||||||
|
SpawnInZone = function(self, zoneName)
|
||||||
|
local added_grp = Group.getByName(mist.cloneInZone(grpName, zoneName).name)
|
||||||
|
if CallBack.func then
|
||||||
|
if not CallBack.args then CallBack.args = {} end
|
||||||
|
mist.scheduleFunction(CallBack.func, {added_grp, unpack(CallBack.args)}, timer.getTime() + 1)
|
||||||
|
end
|
||||||
|
SpawnedGroups[added_grp] = true
|
||||||
|
if zombie then HOGGIT.setZombie(HOGGIT.zombies, added_grp, self, true) end
|
||||||
|
return added_grp
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Add a function with arguments to be called when this Spawner actually spawns a unit
|
||||||
|
-- @param self HOGGIT.Spawner
|
||||||
|
-- @param f the function to be called, always called with spawned group as first param
|
||||||
|
-- @param args table of additional arguments that the callback function will be called with
|
||||||
|
OnSpawnGroup = function(self, f, args)
|
||||||
|
CallBack.func = f
|
||||||
|
CallBack.args = args
|
||||||
|
end,
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Setup Zombies that respawn upon death!
|
||||||
|
|
||||||
|
Adds groups to the HOGGIT.zombies table for evaulation for respawning.
|
||||||
|
@param spawner HOGGIT.Spawner object
|
||||||
|
@param respawn_delay Amount of seconds group will respawn after emitting S_EVENT_DEAD event
|
||||||
|
@param partial_death_threshold_percent Percentage of dead units in group to consider whole group dead
|
||||||
|
@param partial_death_respawn_delay Amount of time that a partially dead unit that meets the threshold percent
|
||||||
|
to be considered completely dead takes to respawn in seconds, default: respawn_delay
|
||||||
|
]]
|
||||||
|
SetGroupRespawnOptions = function(
|
||||||
|
self,
|
||||||
|
respawn_delay,
|
||||||
|
partial_death_threshold_percent,
|
||||||
|
partial_death_respawn_delay) do
|
||||||
|
if partial_death_respawn_delay == nil and partial_death_threshold_percent ~= nil then
|
||||||
|
partial_death_respawn_delay = respawn_delay
|
||||||
|
end
|
||||||
|
|
||||||
|
self:SetZombieOptions({
|
||||||
|
['zombie'] = true,
|
||||||
|
['respawn_delay'] = respawn_delay,
|
||||||
|
['partial_death_threshold_percent'] = respawn_delay,
|
||||||
|
['partial_death_respawn_delay'] = partial_death_respawn_delay
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
SetZombieOptions = function(self, options)
|
||||||
|
zombie = options['zombie']
|
||||||
|
if zombie then
|
||||||
|
respawn_delay = options['respawn_delay']
|
||||||
|
partial_death_threshold_percent = options['partial_death_threshold_percent']
|
||||||
|
if options['partial_death_respawn_delay'] then
|
||||||
|
partial_death_respawn_delay = options['partial_death_respawn_delay']
|
||||||
|
else
|
||||||
|
partial_death_respawn_delay = respawn_delay
|
||||||
|
end
|
||||||
|
|
||||||
|
trigger.action.outText(GroupName .. " is now a zombie! Arggghhh!", 10)
|
||||||
|
end
|
||||||
|
end,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
HOGGIT.spawners = {['neutral'] = {}, ['red'] = {}, ['blue'] = {}}
|
--- Setup the default table of spawners, one for every group in the .miz
|
||||||
|
HOGGIT.SetupDefaultSpawners = function()
|
||||||
for cidx, coalitionName in ipairs({'neutral', 'red', 'blue'}) do
|
for cidx, coalitionName in ipairs({'neutral', 'red', 'blue'}) do
|
||||||
for gidx, group in pairs(coalition.getGroups(cidx - 1)) do
|
for gidx, group in pairs(coalition.getGroups(cidx - 1)) do
|
||||||
HOGGIT.spawners[coalitionName][Group.getName(group)] = HOGGIT.Spawner(Group.getName(group))
|
HOGGIT.spawners[coalitionName][Group.getName(group)] = HOGGIT.Spawner(Group.getName(group))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
HOGGIT.setZombie = function(zombie_tracker, group, spawner, state)
|
||||||
|
if state then
|
||||||
|
zombie_tracker[group] = spawner
|
||||||
|
else
|
||||||
|
zombie_tracker[group] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
HOGGIT._deathHandler = function(event)
|
||||||
|
if event.id ~= world.event.S_EVENT_DEAD then return end
|
||||||
|
if not event.initiator then return end
|
||||||
|
if not event.initiator.getGroup then return end
|
||||||
|
|
||||||
|
local grp = event.initiator:getGroup()
|
||||||
|
if grp then
|
||||||
|
if HOGGIT.zombies[grp] then
|
||||||
|
local spawner = HOGGIT.zombies[grp]
|
||||||
|
if HOGGIT.zombie_checks[spawner] then
|
||||||
|
local s_func_id = HOGGIT.zombie_checks[spawner]
|
||||||
|
mist.removeFunction(s_func_id)
|
||||||
|
trigger.action.outText("Removing dead check id ".. s_func_id .." for group: " + grp:getName())
|
||||||
|
end
|
||||||
|
local new_func_id = mist.scheduleFunction(function()
|
||||||
|
local needs_respawn = false
|
||||||
|
local partial_respawn = false
|
||||||
|
if not HOGGIT.GroupIsAlive(grp) then
|
||||||
|
needs_respawn = true
|
||||||
|
elseif spawner.partial_death_threshold_percent then
|
||||||
|
local group_size = grp:getSize()
|
||||||
|
local initial_size = grp:getInitialSize()
|
||||||
|
local percent_alive = group_size / initial_size * 100
|
||||||
|
|
||||||
|
if (percent_alive - 100) >= partial_death_threshold_percent then
|
||||||
|
needs_respawn = true
|
||||||
|
partial_respawn = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if needs_respawn then
|
||||||
|
local delay = spawner.respawn_delay
|
||||||
|
if partial_respawn then delay = spawner.partial_death_respawn_delay end
|
||||||
|
HOGGIT.zombies[grp] = nil
|
||||||
|
|
||||||
|
mist.scheduleFunction(function()
|
||||||
|
spawner.Spawn()
|
||||||
|
end, {}, timer.getTime() + delay)
|
||||||
|
end
|
||||||
|
HOGGIT.zombie_checks[spawner] = nil
|
||||||
|
|
||||||
|
end, {}, timer.getTime() + 10)
|
||||||
|
|
||||||
|
trigger.action.outText("Scheduled NEW dead check id ".. new_func_id .." for group: " .. grp:getName())
|
||||||
|
HOGGIT.zombie_checks[spawner] = new_func_id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
mist.addEventHandler(HOGGIT._deathHandler)
|
||||||
|
|||||||
@ -20,3 +20,13 @@ HOGGIT.listContains = function(list, elem)
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
HOGGIT.GroupIsAlive = function(group)
|
||||||
|
local grp = nil
|
||||||
|
if type(group) == "string" then
|
||||||
|
grp = Group.getByName(group)
|
||||||
|
else
|
||||||
|
grp = group
|
||||||
|
end
|
||||||
|
if grp and grp:isExist() and grp:getSize() > 0 then return true else return false end
|
||||||
|
end
|
||||||
Loading…
x
Reference in New Issue
Block a user