diff --git a/RotorOps.lua b/RotorOps.lua index 3cf8037..beb83ce 100644 --- a/RotorOps.lua +++ b/RotorOps.lua @@ -1,28 +1,33 @@ RotorOps = {} +--RotorOps settings that are safe to change dynamically (ideally from the mission editor in DO SCRIPT for ease of use) RotorOps.voice_overs = true RotorOps.ground_speed = 60 --max speed for ground vehicles moving between zones RotorOps.zone_status_display = true --constantly show units remaining and zone status on screen 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.force_offroad = false --affects "move_to_zone" tasks only -RotorOps.zone_states = {not_started = 0, active = 1, cleared = 2, started = 3, most_remain = 4, half_remain = 5, quarter_remain = 6 } --zone level user flags will use these values. _remain flags compare the active red ground units vs their initial numbers +--RotorOps settings that are proabably safe to change +RotorOps.transports = {'UH-1H', 'Mi-8MT', 'Mi-24P', 'SA342M', 'SA342L', 'SA342Mistral'} --players flying these will have ctld transport access +RotorOps.auto_push = true --should attacking ground units move to the next zone after clearing? +RotorOps.CTLD_crates = false -RotorOps.game_states = {not_started = 0, in_progress = 1, won = 2, lost = 3} --game level user flag will use these values ---RotorOps.game_states = {not_started = 0, alpha = 1, bravo = 2, charlie = 3, delta = 4, game_won = 100} --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 variables that are safe to read only +RotorOps.game_states = {not_started = 0, alpha_active = 1, bravo_active = 2, charlie_active = 3, delta_active = 4, won = 99} --game level user flag will use these values RotorOps.game_state = 0 RotorOps.zones = {} RotorOps.active_zone = "" --name of the active zone -RotorOps.active_zone_index = 1 +RotorOps.active_zone_index = 0 RotorOps.game_state_flag = 1 --user flag to store the game state RotorOps.staging_zone = "" -RotorOps.auto_push = true --leave true for now - RotorOps.ctld_pickup_zones = {} --keep track of ctld zones we've added, mainly for map markup +RotorOps.ai_red_infantry_groups = {} +RotorOps.ai_blue_infantry_groups = {} +RotorOps.ai_red_vehicle_groups = {} +RotorOps.ai_blue_vehicle_groups = {} +RotorOps.ai_tasks = {} trigger.action.outText("ROTOR OPS STARTED", 5) env.info("ROTOR OPS STARTED") @@ -32,11 +37,6 @@ local commandDB = {} local game_message_buffer = {} local active_zone_initial_enemy_units -RotorOps.ai_red_infantry_groups = {} -RotorOps.ai_blue_infantry_groups = {} -RotorOps.ai_red_vehicle_groups = {} -RotorOps.ai_blue_vehicle_groups = {} -RotorOps.ai_tasks = {} --simply use the group ID for schedulefunction id local gameMsgs = { push = { @@ -46,12 +46,6 @@ local gameMsgs = { {'ALL GROUND UNITS, PUSH TO CHARLIE!', 'push_charlie.ogg'}, {'ALL GROUND UNITS, PUSH TO DELTA!', 'push_delta.ogg'}, }, - fallback = { - {'ALL GROUND UNITS, FALL BACK!', '.wav'}, - {'ALL GROUND UNITS, FALL BACK TO ALPHA!', '.wav'}, - {'ALL GROUND UNITS, FALL BACK TO BRAVO!', '.wav'}, - {'ALL GROUND UNITS, FALL BACK TO CHARLIE!', '.wav'}, - }, cleared = { {'ZONE CLEARED!', 'cleared_active.ogg'}, {'ALPHA CLEARED!', 'cleared_alpha.ogg'}, @@ -83,7 +77,7 @@ local gameMsgs = { } ---[[ UTILITY FUNCTIONS ]]-- +---UTILITY FUNCTIONS--- local function debugMsg(text) trigger.action.outText(text, 5) @@ -149,17 +143,11 @@ end function RotorOps.groupsFromUnits(units, table) local groups = {} - --debugTable(units) - - --local groupIndex = {} for i = 1, #units do if units[i]:isExist() then if hasValue(groups, units[i]:getGroup():getName()) == false then - --debugMsg("added: "..units[i]:getGroup():getName()) - --groups[units[i]:getGroup():getName()] = true - --groupIndex[#groupIndex + 1] = groups[units[i]:getGroup():getName()] groups[#groups + 1] = units[i]:getGroup():getName() - else --debugMsg(units[i]:getGroup():getName().." was already in the table") + else end end end @@ -204,7 +192,14 @@ function RotorOps.sortOutInfantry(mixed_units) return {infantry = _infantry, not_infantry = _not_infantry} end + function RotorOps.getValidUnitFromGroup(grp) + local group_obj + if type(grp) == 'string' then + group_obj = Group.getByName(grp) + else + group_obj = grp + end if grp:isExist() ~= true then return nil end local first_valid_unit for index, unit in pairs(grp:getUnits()) @@ -220,7 +215,9 @@ 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!) See chargeEnemy for grabing first valid unit +----USEFUL PUBLIC FUNCTIONS FOR THE MISSION EDITOR--- + +--Spawn/clone a group onto the location of one unit in the group. This is similar to deployTroops, but it does not use CTLD. You must provide a source group to copy. function RotorOps.spawnInfantryOnGrp(grp, src_grp_name, ai_task) --allow to spawn on other group units local valid_unit = RotorOps.getValidUnitFromGroup(grp) if not valid_unit then return end @@ -239,7 +236,15 @@ function RotorOps.spawnInfantryOnGrp(grp, src_grp_name, ai_task) --allow to spaw end end -function RotorOps.deployTroops(quantity, target_group_obj) + +--Easy way to deploy troops from a vehicle with waypoint action. Spawns from the first valid unit found in a group +function RotorOps.deployTroops(quantity, target_group) + local target_group_obj + if type(target_group) == 'string' then + target_group_obj = Group.getByName(target_group) + else + target_group_obj = target_group + end local valid_unit = RotorOps.getValidUnitFromGroup(target_group_obj) if not valid_unit then return end local coalition = valid_unit:getCoalition() @@ -261,6 +266,37 @@ function RotorOps.deployTroops(quantity, target_group_obj) end end + +--see list of tasks in aiExecute. Zone is optional for many tasks +function RotorOps.aiTask(grp, task, zone) + local group_name + if type(grp) == 'string' then + group_name = grp + else + group_name = Group.getName(grp) + end + if tableHasKey(RotorOps.ai_tasks, group_name) == true then --if we already have this group in our list to manage + --debugMsg("timer already exists, updating task for "..group_name.." : ".. RotorOps.ai_tasks[group_name].ai_task.." to "..task) + RotorOps.ai_tasks[group_name].ai_task = task + RotorOps.ai_tasks[group_name].zone = zone + else + local vars = {} + vars.group_name = group_name + --vars.last_task = task + if zone then + vars.zone = zone + end + local timer_id = timer.scheduleFunction(RotorOps.aiExecute, vars, timer.getTime() + 5) + RotorOps.ai_tasks[group_name] = {['timer_id'] = timer_id, ['ai_task'] = task, ['zone'] = zone} + end +end + + + + +---AI CORE BEHAVIOR-- + + function RotorOps.chargeEnemy(vars) --trigger.action.outText("charge enemies: "..mist.utils.tableShow(vars), 5) local grp = vars.grp @@ -288,7 +324,7 @@ function RotorOps.chargeEnemy(vars) } } else - debugMsg("CHARGE ENEMY in radius: "..search_radius) + --debugMsg("CHARGE ENEMY in radius: "..search_radius) volS = { id = world.VolumeType.SPHERE, params = { @@ -320,7 +356,7 @@ function RotorOps.chargeEnemy(vars) end --default path if no units found if false then - debugMsg("group going back to origin") + --debugMsg("group going back to origin") path[1] = mist.ground.buildWP(start_point, '', 5) path[2] = mist.ground.buildWP(vars.spawn_point, '', 5) @@ -397,47 +433,19 @@ end ------------------------------------------- - - -local function changeGameState(new_state) - RotorOps.game_state = new_state - trigger.action.setUserFlag(RotorOps.game_state_flag, new_state) -end - -function RotorOps.aiTask(group_name, task, zone) - if tableHasKey(RotorOps.ai_tasks, group_name) == true then --if we already have this group id in our list of timers - --debugMsg("timer already exists, updating task for "..group_name.." : ".. RotorOps.ai_tasks[group_name].ai_task.." to "..task) - RotorOps.ai_tasks[group_name].ai_task = task - RotorOps.ai_tasks[group_name].zone = zone - else - --debugMsg("adding timer: "..group_name.." task: "..task) - local vars = {} - vars.group_name = group_name - --vars.last_task = task - if zone then - vars.zone = zone - end - local timer_id = timer.scheduleFunction(RotorOps.aiExecute, vars, timer.getTime() + 5) - RotorOps.ai_tasks[group_name] = {['timer_id'] = timer_id, ['ai_task'] = task, ['zone'] = zone} - end - -end - function RotorOps.aiExecute(vars) local update_interval = 60 local last_task = vars.last_task local group_name = vars.group_name local task = RotorOps.ai_tasks[group_name].ai_task local zone = vars.zone - --local zone = "" + if vars.zone then zone = vars.zone end - --debugMsg("aiExecute: "..group_name.." : "..task .." zone:"..zone) - --debugMsg("task:"..RotorOps.ai_tasks[group_name].ai_task) + --debugMsg("tasking: "..group_name.." : "..task .." zone:"..zone) - --we should remove inactive/dead groups and cancel timer here if Group.isExist(Group.getByName(group_name)) ~= true or #Group.getByName(group_name):getUnits() < 1 then --debugMsg("group no longer exists") + RotorOps.ai_tasks[group_name] = nil return end @@ -466,55 +474,32 @@ function RotorOps.aiExecute(vars) local formation = 'cone' local final_heading = nil local speed = RotorOps.ground_speed - local force_offroad = false + local force_offroad = RotorOps.force_offroad mist.groupToPoint(group_name, zone, formation, final_heading, speed, force_offroad) elseif task == "move_to_active_zone" then update_interval = math.random(90,120) local formation = 'cone' local final_heading = nil local speed = RotorOps.ground_speed - local force_offroad = false + local force_offroad = RotorOps.force_offroad mist.groupToPoint(group_name, RotorOps.active_zone, formation, final_heading, speed, force_offroad) end ---end - - vars.last_task = task local timer_id = timer.scheduleFunction(RotorOps.aiExecute, vars, timer.getTime() + update_interval) 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 - if group then - RotorOps.aiTask(group, "patrol") - end - end - - for index, group in pairs(RotorOps.ai_blue_infantry_groups) do - if group then - RotorOps.aiTask(group, "clear_zone", RotorOps.active_zone) - end - end - - for index, group in pairs(RotorOps.ai_blue_vehicle_groups) do - if group then - RotorOps.aiTask(group, "clear_zone", RotorOps.active_zone) - end - end - - - local id = timer.scheduleFunction(RotorOps.aiActiveZone, 1, timer.getTime() + 10) ]]-- -end + +---CONFLICT ZONES GAME FUNCTIONS--- + +--take stock of the blue/red forces in zone and apply some logic to determine game/zone states function RotorOps.assessUnitsInZone(var) - if RotorOps.game_state ~= RotorOps.game_states.in_progress then return end + if RotorOps.game_state == RotorOps.game_states.not_started then return end + --find and sort units found in the active zone local red_ground_units = mist.getUnitsInZones(mist.makeUnitTable({'[red][vehicle]'}), {RotorOps.active_zone}) local red_infantry = RotorOps.sortOutInfantry(red_ground_units).infantry @@ -523,14 +508,12 @@ function RotorOps.assessUnitsInZone(var) local blue_infantry = RotorOps.sortOutInfantry(blue_ground_units).infantry local blue_vehicles = RotorOps.sortOutInfantry(blue_ground_units).not_infantry -------- --- --ground unit ai stuff +--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) - for index, group in pairs(RotorOps.ai_red_infantry_groups) do if group then RotorOps.aiTask(group, "patrol") @@ -549,56 +532,41 @@ function RotorOps.assessUnitsInZone(var) end end - ----- - local active_zone_status_flag = RotorOps.zones[RotorOps.active_zone_index].zone_status_flag - local active_zone_status = trigger.misc.getUserFlag(active_zone_status_flag) - - --set user flags based on quantities of enemy units remaining + + --let's compare the defending units in zone vs their initial numbers and set a game flag if not active_zone_initial_enemy_units then --debugMsg("taking stock of the active zone") active_zone_initial_enemy_units = red_ground_units - trigger.action.setUserFlag(active_zone_status_flag, RotorOps.zone_states.active) --set the zone's flag to active ---patch solution...would this work if there were no enemies in zone?? - end - - local enemy_remain_status - if #red_ground_units < #active_zone_initial_enemy_units * 0.75 then - enemy_remain_status = RotorOps.zone_states.most_remain - debugMsg("most remain at "..RotorOps.active_zone) - end - if #red_ground_units < #active_zone_initial_enemy_units * 0.5 then - enemy_remain_status = RotorOps.zone_states.half_remain - debugMsg("half remain at "..RotorOps.active_zone) - end - if #red_ground_units < #active_zone_initial_enemy_units * 0.25 then - enemy_remain_status = RotorOps.zone_states.quarter_remain - debugMsg("quarter remain at "..RotorOps.active_zone) end + local defenders_status_flag = RotorOps.zones[RotorOps.active_zone_index].defenders_status_flag + if #active_zone_initial_enemy_units == 0 then active_zone_initial_enemy_units = 1 end --prevent divide by zero + local defenders_remaining_percent = math.floor((#red_ground_units / #active_zone_initial_enemy_units) * 100) - if #red_ground_units <= RotorOps.max_units_left then --if we should declare the zone cleared - active_zone_initial_enemy_units = nil - trigger.action.setUserFlag(active_zone_status_flag, RotorOps.zone_states.cleared) --set the zone's flag to cleared - gameMsg(gameMsgs.cleared, RotorOps.active_zone_index) - if RotorOps.auto_push then - RotorOps.setActiveZone(RotorOps.active_zone_index + 1) - local staged_groups = RotorOps.groupsFromUnits(staged_units) - for index, group in pairs(staged_groups) do - RotorOps.aiTask(group,"move_to_active_zone", RotorOps.zones[RotorOps.active_zone_index].name) --send vehicles to next zone - end - end - elseif enemy_remain_status then - trigger.action.setUserFlag(active_zone_status_flag, enemy_remain_status) --set the zones flage to indicate the status of remaining enemies - end + if #red_ground_units <= RotorOps.max_units_left then --if we should declare the zone cleared + active_zone_initial_enemy_units = nil + defenders_remaining_percent = 0 + trigger.action.setUserFlag(defenders_status_flag, 0) --set the zone's flag to cleared + gameMsg(gameMsgs.cleared, RotorOps.active_zone_index) + + if RotorOps.auto_push then --push units to the next zone + RotorOps.setActiveZone(RotorOps.active_zone_index + 1) + end + + else + trigger.action.setUserFlag(defenders_status_flag, defenders_remaining_percent) --set the zones flag to indicate the status of remaining enemies + end --are all zones clear? local all_zones_clear = true for key, value in pairs(RotorOps.zones) do - local zone_status = trigger.misc.getUserFlag(RotorOps.zones[key].zone_status_flag) - if zone_status ~= RotorOps.zone_states.cleared then + local defenders_remaining = trigger.misc.getUserFlag(RotorOps.zones[key].defenders_status_flag) + if defenders_remaining ~= 0 then all_zones_clear = false end end + --is the game finished? if all_zones_clear then changeGameState(RotorOps.game_states.won) gameMsg(gameMsgs.success) @@ -607,20 +575,19 @@ function RotorOps.assessUnitsInZone(var) - --zone status display stuff + --zone status display local message = "" local header = "" local body = "" - if active_zone_status == RotorOps.zone_states.cleared then + if defenders_remaining_percent == 0 then header = "["..RotorOps.active_zone .. " CLEARED!] " else header = "[BATTLE FOR "..RotorOps.active_zone .. "] " end - body = "RED: " ..#red_infantry.. " infantry, " .. #red_vehicles .. " vehicles. BLUE: "..#blue_infantry.. " infantry, " .. #blue_vehicles.." vehicles." + body = "RED: " ..#red_infantry.. " infantry, " .. #red_vehicles .. " vehicles. BLUE: "..#blue_infantry.. " infantry, " .. #blue_vehicles.." vehicles. ["..defenders_remaining_percent.."%]" message = header .. body if RotorOps.zone_status_display then - --trigger.action.outText(message , 5, true) game_message_buffer[#game_message_buffer + 1] = {message, ""} --don't load the buffer faster than it's cleared. end local id = timer.scheduleFunction(RotorOps.assessUnitsInZone, 1, timer.getTime() + 10) @@ -686,31 +653,11 @@ function RotorOps.drawZones() --this could use a lot of work, we should use tri end ---[[ -function RotorOps.clearActiveZone() - local active_zone_status_flag = RotorOps.zones[RotorOps.active_zone_index].zone_status_flag - trigger.action.setUserFlag(active_zone_status_flag, RotorOps.zone_states.cleared) --set the zone's flag to cleared - gameMsg(gameMsgs.cleared, RotorOps.active_zone_index) - if RotorOps.auto_push then - RotorOps.setActiveZone(RotorOps.active_zone_index + 1) - local staged_groups = RotorOps.groupsFromUnits(staged_units) - for index, group in pairs(staged_groups) do - RotorOps.aiTask(group,"move_to_active_zone", RotorOps.zones[RotorOps.active_zone_index].name) - end - end + +local function changeGameState(new_state) + RotorOps.game_state = new_state + trigger.action.setUserFlag(RotorOps.game_state_flag, new_state) 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) @@ -726,13 +673,18 @@ function RotorOps.setActiveZone(new_index) RotorOps.active_zone = RotorOps.zones[new_index].name if new_index ~= old_index then --the active zone is changing - trigger.action.setUserFlag(RotorOps.zones[new_index].zone_status_flag, RotorOps.zone_states.active) --set the new zone to active - ctld.activatePickupZone(RotorOps.zones[old_index].name) + if old_index > 0 then + ctld.activatePickupZone(RotorOps.zones[old_index].name) + end ctld.deactivatePickupZone(RotorOps.zones[new_index].name) - + changeGameState(new_index) if new_index < old_index then gameMsg(gameMsgs.fallback, new_index) end - --if new_index > old_index then gameMsg(gameMsgs.push, new_index) end if new_index > old_index then gameMsg(gameMsgs.get_troops_to_zone, new_index) end + + local staged_groups = RotorOps.groupsFromUnits(staged_units) + for index, group in pairs(staged_groups) do + RotorOps.aiTask(group,"move_to_active_zone", RotorOps.zones[RotorOps.active_zone_index].name) --send vehicles to next zone + end end @@ -742,9 +694,9 @@ function RotorOps.setActiveZone(new_index) end - +--make some changes to the CTLD script/settings function RotorOps.setupCTLD() - ctld.enableCrates = false + ctld.enableCrates = RotorOps.CTLD_crates ctld.enabledFOBBuilding = false ctld.JTAC_lock = "vehicle" ctld.location_DMS = true @@ -763,22 +715,20 @@ function RotorOps.setupCTLD() } ctld.loadableGroups = { - -- {name = "Mortar Squad Red", inf = 2, mortar = 5, side =1 }, --would make a group loadable by RED only - {name = "Standard Group (10)", inf = 6, mg = 2, at = 2 }, -- will make a loadable group with 6 infantry, 2 MGs and 2 anti-tank for both coalitions + {name = "Standard Group (8)", inf = 4, mg = 2, at = 2 }, -- will make a loadable group with 6 infantry, 2 MGs and 2 anti-tank for both coalitions {name = "Anti Air (5)", inf = 2, aa = 3 }, {name = "Anti Tank (8)", inf = 2, at = 6 }, {name = "Mortar Squad (6)", mortar = 6 }, {name = "Small Standard Group (4)", inf = 2, mg = 1, at = 1 }, - {name = "JTAC Group (5)", inf = 4, jtac = 1 }, -- will make a loadable group with 4 infantry and a JTAC soldier for both coalitions + {name = "JTAC Group (5)", inf = 4, jtac = 1 }, {name = "Single JTAC (1)", jtac = 1 }, + {name = "Small Platoon (16)", inf = 10, mg = 3, at = 3 }, {name = "Platoon (24)", inf = 12, mg = 4, at = 3, aa = 1 }, } end - - function RotorOps.setupRadioMenu() commandDB['conflict_zones_menu'] = missionCommands.addSubMenu( "ROTOR OPS") local conflict_zones_menu = commandDB['conflict_zones_menu'] @@ -788,15 +738,11 @@ end - -function RotorOps.addZone(_name, _zone_status_flag) - table.insert(RotorOps.zones, {name = _name, zone_status_flag = _zone_status_flag}) - trigger.action.setUserFlag(_zone_status_flag, RotorOps.zone_states.not_started) +function RotorOps.addZone(_name, _zone_defenders_flag) + table.insert(RotorOps.zones, {name = _name, defenders_status_flag = _zone_defenders_flag}) + trigger.action.setUserFlag(_zone_defenders_flag, 101) RotorOps.drawZones() - --ctld.dropOffZones[#ctld.dropOffZones + 1] = { _name, "green", 0 } RotorOps.addPickupZone(_name, "blue", -1, "no", 0) - --ctld.dropOffZones[#ctld.dropOffZones + 1] = { _name, "none", 1 } - --trigger.action.outText("zones: ".. mist.utils.tableShow(RotorOps.zones), 5) end function RotorOps.stagingZone(_name) @@ -804,6 +750,7 @@ function RotorOps.stagingZone(_name) RotorOps.staging_zone = _name 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 @@ -817,10 +764,11 @@ function RotorOps.addPilots(var) local id = timer.scheduleFunction(RotorOps.addPilots, 1, timer.getTime() + 15) end + function RotorOps.setupConflict(_game_state_flag) RotorOps.addPilots(1) RotorOps.setupCTLD() - RotorOps.setupRadioMenu() + --RotorOps.setupRadioMenu() RotorOps.game_state_flag = _game_state_flag changeGameState(RotorOps.game_states.not_started) trigger.action.outText("ALL TROOPS GET TO TRANSPORT AND PREPARE FOR DEPLOYMENT!" , 10, false) @@ -835,26 +783,20 @@ end function RotorOps.startConflict() - if RotorOps.game_state == RotorOps.game_states.in_progress then return end - changeGameState(RotorOps.game_states.in_progress) - + if RotorOps.game_state ~= RotorOps.game_states.not_started then return end + --make some changes to the radio menu - local conflict_zones_menu = commandDB['conflict_zones_menu'] - missionCommands.removeItem(commandDB['start_conflict']) + --local conflict_zones_menu = commandDB['conflict_zones_menu'] + --missionCommands.removeItem(commandDB['start_conflict']) --commandDB['clear_zone'] = missionCommands.addCommand( "[CHEAT] Force Clear Zone" , conflict_zones_menu , RotorOps.clearActiveZone) - RotorOps.setActiveZone(1) + gameMsg(gameMsgs.start) gameMsg(gameMsgs.push, 1) processMsgBuffer() - RotorOps.aiActiveZone() staged_units = mist.getUnitsInZones(mist.makeUnitTable({'[all][vehicle]'}), {RotorOps.staging_zone}) - local staged_groups = RotorOps.groupsFromUnits(staged_units) - for index, group in pairs(staged_groups) do - RotorOps.aiTask(group,"move_to_active_zone") - end - + RotorOps.setActiveZone(1) local id = timer.scheduleFunction(RotorOps.assessUnitsInZone, 1, timer.getTime() + 5) end diff --git a/documentation/images/conflict_setup.PNG b/documentation/images/conflict_setup.PNG new file mode 100644 index 0000000..da48960 Binary files /dev/null and b/documentation/images/conflict_setup.PNG differ diff --git a/documentation/images/deploytroops.PNG b/documentation/images/deploytroops.PNG new file mode 100644 index 0000000..cdef8d5 Binary files /dev/null and b/documentation/images/deploytroops.PNG differ diff --git a/documentation/images/game status trigger.PNG b/documentation/images/game status trigger.PNG new file mode 100644 index 0000000..399139d Binary files /dev/null and b/documentation/images/game status trigger.PNG differ diff --git a/documentation/images/rotorops conflict zones.png b/documentation/images/rotorops conflict zones.png new file mode 100644 index 0000000..c172da9 Binary files /dev/null and b/documentation/images/rotorops conflict zones.png differ diff --git a/documentation/images/trigger load.PNG b/documentation/images/trigger load.PNG new file mode 100644 index 0000000..4282476 Binary files /dev/null and b/documentation/images/trigger load.PNG differ diff --git a/documentation/images/trigger reinforcements.PNG b/documentation/images/trigger reinforcements.PNG new file mode 100644 index 0000000..3b2b32d Binary files /dev/null and b/documentation/images/trigger reinforcements.PNG differ diff --git a/documentation/images/trigger sounds.PNG b/documentation/images/trigger sounds.PNG new file mode 100644 index 0000000..82b773f Binary files /dev/null and b/documentation/images/trigger sounds.PNG differ diff --git a/documentation/images/zone status trigger.PNG b/documentation/images/zone status trigger.PNG new file mode 100644 index 0000000..73d0ba7 Binary files /dev/null and b/documentation/images/zone status trigger.PNG differ diff --git a/sound/beacon.ogg b/sound/embedded/beacon.ogg similarity index 100% rename from sound/beacon.ogg rename to sound/embedded/beacon.ogg diff --git a/sound/beaconsilent.ogg b/sound/embedded/beaconsilent.ogg similarity index 100% rename from sound/beaconsilent.ogg rename to sound/embedded/beaconsilent.ogg diff --git a/sound/cleared_active.ogg b/sound/embedded/cleared_active.ogg similarity index 100% rename from sound/cleared_active.ogg rename to sound/embedded/cleared_active.ogg diff --git a/sound/cleared_alpha.ogg b/sound/embedded/cleared_alpha.ogg similarity index 100% rename from sound/cleared_alpha.ogg rename to sound/embedded/cleared_alpha.ogg diff --git a/sound/cleared_bravo.ogg b/sound/embedded/cleared_bravo.ogg similarity index 100% rename from sound/cleared_bravo.ogg rename to sound/embedded/cleared_bravo.ogg diff --git a/sound/cleared_charlie.ogg b/sound/embedded/cleared_charlie.ogg similarity index 100% rename from sound/cleared_charlie.ogg rename to sound/embedded/cleared_charlie.ogg diff --git a/sound/cleared_delta.ogg b/sound/embedded/cleared_delta.ogg similarity index 100% rename from sound/cleared_delta.ogg rename to sound/embedded/cleared_delta.ogg diff --git a/sound/get_troops_alpha.ogg b/sound/embedded/get_troops_alpha.ogg similarity index 100% rename from sound/get_troops_alpha.ogg rename to sound/embedded/get_troops_alpha.ogg diff --git a/sound/get_troops_bravo.ogg b/sound/embedded/get_troops_bravo.ogg similarity index 100% rename from sound/get_troops_bravo.ogg rename to sound/embedded/get_troops_bravo.ogg diff --git a/sound/get_troops_charlie.ogg b/sound/embedded/get_troops_charlie.ogg similarity index 100% rename from sound/get_troops_charlie.ogg rename to sound/embedded/get_troops_charlie.ogg diff --git a/sound/get_troops_delta.ogg b/sound/embedded/get_troops_delta.ogg similarity index 100% rename from sound/get_troops_delta.ogg rename to sound/embedded/get_troops_delta.ogg diff --git a/sound/get_troops_next_zone.ogg b/sound/embedded/get_troops_next_zone.ogg similarity index 100% rename from sound/get_troops_next_zone.ogg rename to sound/embedded/get_troops_next_zone.ogg diff --git a/sound/mission_success.ogg b/sound/embedded/mission_success.ogg similarity index 100% rename from sound/mission_success.ogg rename to sound/embedded/mission_success.ogg diff --git a/sound/push_alpha.ogg b/sound/embedded/push_alpha.ogg similarity index 100% rename from sound/push_alpha.ogg rename to sound/embedded/push_alpha.ogg diff --git a/sound/push_bravo.ogg b/sound/embedded/push_bravo.ogg similarity index 100% rename from sound/push_bravo.ogg rename to sound/embedded/push_bravo.ogg diff --git a/sound/push_charlie.ogg b/sound/embedded/push_charlie.ogg similarity index 100% rename from sound/push_charlie.ogg rename to sound/embedded/push_charlie.ogg diff --git a/sound/push_delta.ogg b/sound/embedded/push_delta.ogg similarity index 100% rename from sound/push_delta.ogg rename to sound/embedded/push_delta.ogg diff --git a/sound/push_next_zone.ogg b/sound/embedded/push_next_zone.ogg similarity index 100% rename from sound/push_next_zone.ogg rename to sound/embedded/push_next_zone.ogg diff --git a/sound/support_troops.ogg b/sound/embedded/support_troops.ogg similarity index 100% rename from sound/support_troops.ogg rename to sound/embedded/support_troops.ogg diff --git a/sound/troops_dropped_active.ogg b/sound/embedded/troops_dropped_active.ogg similarity index 100% rename from sound/troops_dropped_active.ogg rename to sound/embedded/troops_dropped_active.ogg diff --git a/sound/troops_dropped_alpha.ogg b/sound/embedded/troops_dropped_alpha.ogg similarity index 100% rename from sound/troops_dropped_alpha.ogg rename to sound/embedded/troops_dropped_alpha.ogg diff --git a/sound/troops_dropped_bravo.ogg b/sound/embedded/troops_dropped_bravo.ogg similarity index 100% rename from sound/troops_dropped_bravo.ogg rename to sound/embedded/troops_dropped_bravo.ogg diff --git a/sound/troops_dropped_charlie.ogg b/sound/embedded/troops_dropped_charlie.ogg similarity index 100% rename from sound/troops_dropped_charlie.ogg rename to sound/embedded/troops_dropped_charlie.ogg diff --git a/sound/troops_dropped_delta.ogg b/sound/embedded/troops_dropped_delta.ogg similarity index 100% rename from sound/troops_dropped_delta.ogg rename to sound/embedded/troops_dropped_delta.ogg