This commit is contained in:
spencer-ki 2022-01-02 16:30:36 -08:00
parent dc4a0a8e79
commit f0f6c0f221
3 changed files with 138 additions and 86 deletions

View File

@ -1,30 +1,39 @@
RotorOps = {} RotorOps = {}
RotorOps.transports = {'UH-1H', 'Mi-8MT', 'Mi-24P'}
RotorOps.zone_states = {not_started = 0, active = 1, cleared = 2, started = 3} RotorOps.voice_overs = true
RotorOps.game_states = {not_started = 0, in_progress = 1, won = 2, lost = 3} RotorOps.ground_speed = 30 --max speed for ground vehicles moving between zones
RotorOps.game_state = 0 RotorOps.zone_status_display = true --constantly show units remaining and zone status on screen
RotorOps.ground_speed = 10
RotorOps.auto_push = true
local last_message_time
local game_message_buffer = {}
RotorOps.zone_status_display = true
RotorOps.max_units_left = 0 --allow clearing the zone when a few units are left to prevent frustration with units getting stuck in buildings etc RotorOps.max_units_left = 0 --allow clearing the zone when a few units are left to prevent frustration with units getting stuck in buildings etc
RotorOps.ai_active_zone = true --allow the script to automatically create waypoints for ground units in the active zone
RotorOps.zone_states = {not_started = 0, active = 1, cleared = 2, started = 3} --zone level user flags will use these values
RotorOps.game_states = {not_started = 0, in_progress = 1, won = 2, lost = 3} --game level user flag will use these values
RotorOps.transports = {'UH-1H', 'Mi-8MT', 'Mi-24P'} --players flying these will have ctld transport access
RotorOps.game_state = 0
RotorOps.zones = {} RotorOps.zones = {}
RotorOps.active_zone = "" RotorOps.active_zone = "" --name of the active zone
RotorOps.active_zone_index = 1 RotorOps.active_zone_index = 1
RotorOps.active_zone_flag = 1 RotorOps.game_state_flag = 1 --user flag to store the game state
RotorOps.staging_zone = "" RotorOps.staging_zone = ""
RotorOps.auto_push = true --leave true for now
RotorOps.ctld_pickup_zones = {} RotorOps.ctld_pickup_zones = {} --keep track of ctld zones we've added, mainly for map markup
trigger.action.outText("ROTOR OPS STARTED", 5) trigger.action.outText("ROTOR OPS STARTED", 5)
env.info("ROTOR OPS STARTED") env.info("ROTOR OPS STARTED")
local staged_units local staged_units --table of ground units that started in the staging zone
local commandDB = {} local commandDB = {}
local game_message_buffer = {}
RotorOps.ai_red_infantry_groups = {}
RotorOps.ai_blue_infantry_groups = {}
RotorOps.ai_red_vehicle_groups = {}
RotorOps.ai_blue_vehicle_groups = {}
RotorOps.ai_timers = {} --simply use the group ID for schedulefunction id
local gameMsgs = { local gameMsgs = {
push = { push = {
@ -61,6 +70,7 @@ local gameMsgs = {
local function debugMsg(text) local function debugMsg(text)
trigger.action.outText(text, 5) trigger.action.outText(text, 5)
env.info("ROTOROPS_DEBUG: "..text)
end end
@ -96,9 +106,11 @@ local function getObjectVolume(obj)
return length * height * depth return length * height * depth
end end
function RotorOps.groupsFromUnits(units)
--debugTable(units) function RotorOps.groupsFromUnits(units, table)
local groups = {} local groups = {}
--debugTable(units)
--local groupIndex = {} --local groupIndex = {}
for i = 1, #units do for i = 1, #units do
if hasValue(groups, units[i]:getGroup():getName()) == false then if hasValue(groups, units[i]:getGroup():getName()) == false then
@ -129,14 +141,32 @@ local function processMsgBuffer(vars)
if #game_message_buffer > 0 then if #game_message_buffer > 0 then
local message = table.remove(game_message_buffer, 1) local message = table.remove(game_message_buffer, 1)
trigger.action.outText(message[1], 10, true) trigger.action.outText(message[1], 10, true)
if RotorOps.voice_overs then
trigger.action.outSound(message[2]) trigger.action.outSound(message[2])
end end
end
local id = timer.scheduleFunction(processMsgBuffer, 1, timer.getTime() + 5) local id = timer.scheduleFunction(processMsgBuffer, 1, timer.getTime() + 5)
end end
function RotorOps.sortOutInfantry(mixed_units)
local _infantry = {}
local _not_infantry = {}
for index, unit in pairs(mixed_units)
do
if unit:hasAttribute("Infantry") then
_infantry[#_infantry + 1] = unit
else _not_infantry[#_not_infantry + 1] = unit
end
end
return {infantry = _infantry, not_infantry = _not_infantry}
end
--spawn/clone a group onto the location of the first unit in a group (best to only use this for groups of one unit only for now!)
function RotorOps.spawnInfantryOnGrp(grp, src_grp_name, behavior) --allow to spawn on other group units function RotorOps.spawnInfantryOnGrp(grp, src_grp_name, behavior) --allow to spawn on other group units
debugMsg("attempting to spawn at "..grp:getUnit(1):getTypeName()) debugMsg("attempting to spawn at "..grp:getUnit(1):getTypeName())
local vars = {} local vars = {}
@ -230,7 +260,7 @@ end
function RotorOps.patrolRadius(vars) function RotorOps.patrolRadius(vars)
debugMsg("patrol radius: "..mist.utils.tableShow(vars)) debugMsg("patrol radius: "..mist.utils.tableShow(vars.grp))
local grp = vars.grp local grp = vars.grp
local search_radius = vars.radius or 100 local search_radius = vars.radius or 100
local first_valid_unit local first_valid_unit
@ -292,32 +322,45 @@ function RotorOps.patrolRadius(vars)
--trigger.action.outText("new waypoints created: "..(#path - 1), 5) --trigger.action.outText("new waypoints created: "..(#path - 1), 5)
mist.goRoute(grp, path) mist.goRoute(grp, path)
--local timing = mist.getPathLength(path) / 5 --local timing = mist.getPathLength(path) / 5
local id = timer.scheduleFunction(RotorOps.patrolRadius, vars, timer.getTime() + math.random(50,70)) --local id = timer.scheduleFunction(RotorOps.patrolRadius, vars, timer.getTime() + math.random(50,70))
local group_name = grp:getName()
if tableHasKey(RotorOps.ai_timers, group_name) == true then --if we already have this group id in our list of timers
debugMsg("timer already active, do nothing for "..group_name.." : ".. RotorOps.ai_timers[group_name])
--timer.removeFunction(RotorOps.ai_timers[group_name])
else
debugMsg("adding timer: "..group_name)
local timer_id = timer.scheduleFunction(RotorOps.patrolRadius, vars, timer.getTime() + math.random(50,70))
RotorOps.ai_timers[group_name] = timer_id
end end
end
------------------------------------------ ------------------------------------------
local function changeGameState(new_state)
RotorOps.game_state = new_state
trigger.action.setUserFlag(RotorOps.game_state_flag, new_state)
end
function RotorOps.aiActiveZone(var)
if RotorOps.ai_active_zone == false then return end
--debugMsg("aiActiveZone func")
for index, group in pairs(RotorOps.ai_red_infantry_groups) do
function RotorOps.sortOutInfantry(mixed_units) if group then
local _infantry = {} debugMsg("grp="..group)
local _not_infantry = {} RotorOps.patrolRadius({grp=Group.getByName(group), radius=400})
for index, unit in pairs(mixed_units)
do
if unit:hasAttribute("Infantry") then
_infantry[#_infantry + 1] = unit
else _not_infantry[#_not_infantry + 1] = unit
end end
end end
return {infantry = _infantry, not_infantry = _not_infantry}
local id = timer.scheduleFunction(RotorOps.aiActiveZone, 1, timer.getTime() + 10)
end end
@ -354,10 +397,17 @@ function RotorOps.assessUnitsInZone(var)
if all_zones_clear then if all_zones_clear then
RotorOps.gameWon() RotorOps.gameWon()
return
end end
--ground unit ai stuff
RotorOps.ai_red_infantry_groups = RotorOps.groupsFromUnits(red_infantry)
RotorOps.ai_blue_infantry_groups = RotorOps.groupsFromUnits(blue_infantry)
RotorOps.ai_red_vehicle_groups = RotorOps.groupsFromUnits(red_vehicles)
RotorOps.ai_blue_vehicle_groups = RotorOps.groupsFromUnits(blue_vehicles)
--zone status display stuff
local message = "" local message = ""
local header = "" local header = ""
local body = "" local body = ""
@ -435,18 +485,7 @@ function RotorOps.drawZones() --this could use a lot of work, we should use tri
end end
--function to automatically add transport craft to ctld, rather than having to define each in the mission editor
function RotorOps.addPilots(var)
for uName, uData in pairs(mist.DBs.humansByName) do
if hasValue(RotorOps.transports, uData.type) then
if hasValue(ctld.transportPilotNames, uData.unitName) ~= true then
ctld.transportPilotNames [#ctld.transportPilotNames + 1] = uData.unitName
--else trigger.action.outText("player already in pilot table", 5)
end
end
end
local id = timer.scheduleFunction(RotorOps.addPilots, 1, timer.getTime() + 15)
end
function RotorOps.sendUnitsToZone(units_table, zone, _formation, _final_heading, _speed, _force_offroad) function RotorOps.sendUnitsToZone(units_table, zone, _formation, _final_heading, _speed, _force_offroad)
@ -480,32 +519,22 @@ function RotorOps.fallBack()
RotorOps.sendUnitsToZone(staged_units, RotorOps.zones[RotorOps.active_zone_index].name) RotorOps.sendUnitsToZone(staged_units, RotorOps.zones[RotorOps.active_zone_index].name)
end end
function RotorOps.startConflict()
if RotorOps.game_state == RotorOps.game_states.in_progress then return end
RotorOps.game_state = RotorOps.game_states.in_progress
--make some changes to the radio menu
local conflict_zones_menu = commandDB['conflict_zones_menu']
missionCommands.removeItem(commandDB['start_conflict'])
commandDB['push_zone'] = missionCommands.addCommand( "Push to next zone", conflict_zones_menu , RotorOps.pushZone)
commandDB['fall_back'] = missionCommands.addCommand( "Fall back to prev zone" , conflict_zones_menu , RotorOps.fallBack)
staged_units = mist.getUnitsInZones(mist.makeUnitTable({'[all][vehicle]'}), {RotorOps.staging_zone})
--local helicopters = mist.getUnitsInZones(mist.makeUnitTable({'[all][helicopter]'}), {RotorOps.zones[1].name})
--RotorOps.sendUnitsToZone(helicopters, RotorOps.zones[2].name, nil, nil, 90)
RotorOps.sendUnitsToZone(staged_units, RotorOps.zones[1].name)
RotorOps.setActiveZone(1)
gameMsg(gameMsgs.start)
gameMsg(gameMsgs.push, 1)
processMsgBuffer()
local id = timer.scheduleFunction(RotorOps.assessUnitsInZone, 1, timer.getTime() + 5)
end
function RotorOps.gameWon() function RotorOps.gameWon()
RotorOps.game_state = RotorOps.game_states.won changeGameState(RotorOps.game_states.won)
gameMsg(gameMsgs.success) gameMsg(gameMsgs.success)
end end
function RotorOps.spawnInfantryAtZone(vars)
local side = vars.side
local inf = vars.inf
local zone = vars.zone
local radius = vars.radius
ctld.spawnGroupAtTrigger(side, inf, zone, radius)
end
function RotorOps.setActiveZone(new_index) function RotorOps.setActiveZone(new_index)
local old_index = RotorOps.active_zone_index local old_index = RotorOps.active_zone_index
@ -531,7 +560,7 @@ function RotorOps.setActiveZone(new_index)
RotorOps.active_zone = RotorOps.zones[new_index].name RotorOps.active_zone = RotorOps.zones[new_index].name
--debugMsg("active zone: "..RotorOps.active_zone.." old zone: "..RotorOps.zones[old_index].name) --debugMsg("active zone: "..RotorOps.active_zone.." old zone: "..RotorOps.zones[old_index].name)
trigger.action.setUserFlag(RotorOps.active_zone_flag, RotorOps.active_zone_index)
RotorOps.drawZones() RotorOps.drawZones()
end end
@ -570,30 +599,15 @@ end
function RotorOps.debugAction()
--trigger.action.outText("zones: ".. mist.utils.tableShow(RotorOps.zones), 5)
RotorOps.clearActiveZone()
end
function RotorOps.setupRadioMenu() function RotorOps.setupRadioMenu()
commandDB['conflict_zones_menu'] = missionCommands.addSubMenu( "ROTOR OPS") commandDB['conflict_zones_menu'] = missionCommands.addSubMenu( "ROTOR OPS")
local conflict_zones_menu = commandDB['conflict_zones_menu'] local conflict_zones_menu = commandDB['conflict_zones_menu']
commandDB['start_conflict'] = missionCommands.addCommand( "Start conflict" , conflict_zones_menu , RotorOps.startConflict) commandDB['start_conflict'] = missionCommands.addCommand( "Start conflict" , conflict_zones_menu , RotorOps.startConflict)
commandDB['debug_action'] = missionCommands.addCommand( "Debug action" , conflict_zones_menu , RotorOps.debugAction)
end end
function RotorOps.spawnInfantryAtZone(vars)
local side = vars.side
local inf = vars.inf
local zone = vars.zone
local radius = vars.radius
ctld.spawnGroupAtTrigger(side, inf, zone, radius)
end
function RotorOps.addZone(_name, _zone_status_flag) function RotorOps.addZone(_name, _zone_status_flag)
@ -611,12 +625,25 @@ function RotorOps.stagingZone(_name)
RotorOps.staging_zone = _name RotorOps.staging_zone = _name
end end
function RotorOps.setupConflict(_active_zone_flag) --function to automatically add transport craft to ctld, rather than having to define each in the mission editor
function RotorOps.addPilots(var)
for uName, uData in pairs(mist.DBs.humansByName) do
if hasValue(RotorOps.transports, uData.type) then
if hasValue(ctld.transportPilotNames, uData.unitName) ~= true then
ctld.transportPilotNames [#ctld.transportPilotNames + 1] = uData.unitName
--else trigger.action.outText("player already in pilot table", 5)
end
end
end
local id = timer.scheduleFunction(RotorOps.addPilots, 1, timer.getTime() + 15)
end
function RotorOps.setupConflict(_game_state_flag)
RotorOps.addPilots(1) RotorOps.addPilots(1)
RotorOps.setupCTLD() RotorOps.setupCTLD()
RotorOps.setupRadioMenu() RotorOps.setupRadioMenu()
RotorOps.active_zone_flag = _active_zone_flag RotorOps.game_state_flag = _game_state_flag
RotorOps.game_state = RotorOps.game_states.not_started changeGameState(RotorOps.game_states.not_started)
trigger.action.outText("ALL TROOPS GET TO TRANSPORT AND PREPARE FOR DEPLOYMENT!" , 10, false) trigger.action.outText("ALL TROOPS GET TO TRANSPORT AND PREPARE FOR DEPLOYMENT!" , 10, false)
end end
@ -628,3 +655,28 @@ function RotorOps.addPickupZone(zone_name, smoke, limit, active, side)
end end
function RotorOps.startConflict()
if RotorOps.game_state == RotorOps.game_states.in_progress then return end
changeGameState(RotorOps.game_states.in_progress)
--make some changes to the radio menu
local conflict_zones_menu = commandDB['conflict_zones_menu']
missionCommands.removeItem(commandDB['start_conflict'])
--commandDB['push_zone'] = missionCommands.addCommand( "Push to next zone", conflict_zones_menu , RotorOps.pushZone)
--commandDB['fall_back'] = missionCommands.addCommand( "Fall back to prev zone" , conflict_zones_menu , RotorOps.fallBack)
commandDB['clear_zone'] = missionCommands.addCommand( "Force Clear Zone" , conflict_zones_menu , RotorOps.clearActiveZone)
staged_units = mist.getUnitsInZones(mist.makeUnitTable({'[all][vehicle]'}), {RotorOps.staging_zone})
--local helicopters = mist.getUnitsInZones(mist.makeUnitTable({'[all][helicopter]'}), {RotorOps.zones[1].name})
--RotorOps.sendUnitsToZone(helicopters, RotorOps.zones[2].name, nil, nil, 90)
RotorOps.sendUnitsToZone(staged_units, RotorOps.zones[1].name)
RotorOps.setActiveZone(1)
gameMsg(gameMsgs.start)
gameMsg(gameMsgs.push, 1)
processMsgBuffer()
RotorOps.aiActiveZone()
local id = timer.scheduleFunction(RotorOps.assessUnitsInZone, 1, timer.getTime() + 5)
end

BIN
sound/beacon.ogg Normal file

Binary file not shown.

BIN
sound/beaconsilent.ogg Normal file

Binary file not shown.