BHD2 and infantry update (#48)

* BHD2 and infantry update

- default to easy comms
- modify ctld for better infantry models
- cleaner logging
- warn user if no resources for fat cow FARPs
- condition for fat cow added; not available if enemies too close

* Update README.md
This commit is contained in:
spencershepard 2023-02-11 20:54:37 -08:00 committed by GitHub
parent be89639e6d
commit bca47d63d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 153 additions and 53 deletions

View File

@ -593,6 +593,7 @@ class Window(QMainWindow, Ui_MainWindow):
"blue_cap": self.scenario.getConfigValue("blue_cap", default=True), "blue_cap": self.scenario.getConfigValue("blue_cap", default=True),
"rotorops_server": self.scenario.getConfigValue("rotorops_server", default=False), "rotorops_server": self.scenario.getConfigValue("rotorops_server", default=False),
"perks": self.perks_checkBox.isChecked(), "perks": self.perks_checkBox.isChecked(),
"easy_comms": self.scenario.getConfigValue("easy_comms", default=True)
} }
logger.info("Generating mission with options:") logger.info("Generating mission with options:")

View File

@ -401,6 +401,12 @@ class RotorOpsMission:
self.m.random_daytime(options["time"].lower()) self.m.random_daytime(options["time"].lower())
print("Time set to " + options["time"]) print("Time set to " + options["time"])
# set the mission options
if options["easy_comms"]:
# to simplify rearm/refuel at FARPs
self.m.options.difficulty.easyCommunication = True
# Save the mission file # Save the mission file
window.statusBar().showMessage("Saving mission...", 10000) window.statusBar().showMessage("Saving mission...", 10000)
if window.user_output_dir: if window.user_output_dir:
@ -824,7 +830,7 @@ class RotorOpsMission:
self.m.triggers.add_triggerzone(f_cap_spawn_point, 30000, hidden=True, name="BLUE_CAP_SPAWN") self.m.triggers.add_triggerzone(f_cap_spawn_point, 30000, hidden=True, name="BLUE_CAP_SPAWN")
# Fat Cow # Fat Cow
if True: if options["perks"]:
helo_type = dcs.helicopters.CH_47D helo_type = dcs.helicopters.CH_47D
name = "FAT COW" name = "FAT COW"
@ -852,6 +858,24 @@ class RotorOpsMission:
afg.set_skill(dcs.unit.Skill.Excellent) afg.set_skill(dcs.unit.Skill.Excellent)
afg.late_activation = True afg.late_activation = True
else:
afg = self.m.flight_group_inflight(
combinedJointTaskForcesBlue,
name,
helo_type,
position=primary_f_airport.position,
altitude=500,
speed=50,
group_size=1
)
if afg:
afg.set_skill(dcs.unit.Skill.Excellent)
afg.late_activation = True
else:
raise Exception("Unable to insert Fat Cow CH-47")
if options["f_awacs"]: if options["f_awacs"]:
awacs_name = "AWACS" awacs_name = "AWACS"

View File

@ -1,7 +1,7 @@
# ROTOROPS VERSION # ROTOROPS VERSION
maj_version = 1 maj_version = 1
minor_version = 4 minor_version = 4
patch_version = 3 patch_version = 4
version_url = 'https://dcs-helicopters.com/app-updates/versioncheck.yaml' version_url = 'https://dcs-helicopters.com/app-updates/versioncheck.yaml'

View File

@ -24,15 +24,24 @@ At the core of the RotorOps script are AI enhancements that provide a dynamic gr
- Single-player and multiplayer slot creation. - Single-player and multiplayer slot creation.
## Demo Missions ## Demo Missions
RotorOps: Aleppo Under Siege https://www.digitalcombatsimulator.com/en/files/3320079/
Newest to oldest:
Black Hawk Down Pt 1 (UH-1H UH-60L) https://www.digitalcombatsimulator.com/en/files/3328428/
NightHawks (AH-64D) https://www.digitalcombatsimulator.com/en/files/3322036/
RotorOps: Aleppo Under Siege https://www.digitalcombatsimulator.com/en/files/3320079/
Rota Landing (Mr. Nobody) https://www.digitalcombatsimulator.com/en/files/3320186/ Rota Landing (Mr. Nobody) https://www.digitalcombatsimulator.com/en/files/3320186/
# RotorOps: Conflict # RotorOps: Conflict
Conflict is a game type in which attacking forces must clear Conflict Zones of defending ground forces. Once a zone is cleared, the next zone is activated and attacking ground vehicles will move to the next Conflict Zone automatically. Conflict is a game type in which attacking forces must clear Conflict Zones of defending ground forces. Once a zone is cleared, the next zone is activated and attacking ground vehicles will move to the next Conflict Zone automatically.
![alt text](https://raw.githubusercontent.com/spencershepard/RotorOps/develop/documentation/images/rotorops%20conflict%20zones.png?raw=true) ![alt text](https://raw.githubusercontent.com/spencershepard/RotorOps/main/documentation/images/rotorops%20conflict%20zones.png?raw=true)
## Dynamic Roles ## Dynamic Roles
A RotorOps Conflict mission has opportunities for a variety of roles and tasks. There's no need to artificially select these roles, as the mission is fully dynamic. A RotorOps Conflict mission has opportunities for a variety of roles and tasks. There's no need to artificially select these roles, as the mission is fully dynamic.

View File

@ -26,7 +26,7 @@ ctld = {} -- DONT REMOVE!
ctld.Id = "CTLD - " ctld.Id = "CTLD - "
--- Version. --- Version.
ctld.Version = "20211113.01" ctld.Version = "20211113.01 GRIMM01"
-- debug level, specific to this module -- debug level, specific to this module
ctld.Debug = true ctld.Debug = true
@ -1976,9 +1976,9 @@ function ctld.generateTroopTypes(_side, _countOrTemplate, _country)
if _countOrTemplate.inf then if _countOrTemplate.inf then
ctld.logTrace(string.format("_countOrTemplate.inf=%s", ctld.p(_countOrTemplate.inf))) ctld.logTrace(string.format("_countOrTemplate.inf=%s", ctld.p(_countOrTemplate.inf)))
if _side == 2 then if _side == 2 then
_troops = ctld.insertIntoTroopsArray("Soldier M4",_countOrTemplate.inf,_troops) _troops = ctld.insertIntoTroopsArray("Soldier M4 GRG",_countOrTemplate.inf,_troops)
else else
_troops = ctld.insertIntoTroopsArray("Soldier AK",_countOrTemplate.inf,_troops) _troops = ctld.insertIntoTroopsArray("Infantry AK",_countOrTemplate.inf,_troops)
end end
_weight = _weight + getSoldiersWeight(_countOrTemplate.inf, ctld.RIFLE_WEIGHT) _weight = _weight + getSoldiersWeight(_countOrTemplate.inf, ctld.RIFLE_WEIGHT)
ctld.logTrace(string.format("_weight=%s", ctld.p(_weight))) ctld.logTrace(string.format("_weight=%s", ctld.p(_weight)))
@ -2012,9 +2012,9 @@ function ctld.generateTroopTypes(_side, _countOrTemplate, _country)
if _countOrTemplate.jtac then if _countOrTemplate.jtac then
ctld.logTrace(string.format("_countOrTemplate.jtac=%s", ctld.p(_countOrTemplate.jtac))) ctld.logTrace(string.format("_countOrTemplate.jtac=%s", ctld.p(_countOrTemplate.jtac)))
if _side == 2 then if _side == 2 then
_troops = ctld.insertIntoTroopsArray("Soldier M4",_countOrTemplate.jtac,_troops, "JTAC") _troops = ctld.insertIntoTroopsArray("Soldier M4 GRG",_countOrTemplate.jtac,_troops, "JTAC")
else else
_troops = ctld.insertIntoTroopsArray("Soldier AK",_countOrTemplate.jtac,_troops, "JTAC") _troops = ctld.insertIntoTroopsArray("Infantry AK",_countOrTemplate.jtac,_troops, "JTAC")
end end
_hasJTAC = true _hasJTAC = true
_weight = _weight + getSoldiersWeight(_countOrTemplate.jtac, ctld.JTAC_WEIGHT + ctld.RIFLE_WEIGHT) _weight = _weight + getSoldiersWeight(_countOrTemplate.jtac, ctld.JTAC_WEIGHT + ctld.RIFLE_WEIGHT)
@ -2024,7 +2024,7 @@ function ctld.generateTroopTypes(_side, _countOrTemplate, _country)
else else
for _i = 1, _countOrTemplate do for _i = 1, _countOrTemplate do
local _unitType = "Soldier AK" local _unitType = "Infantry AK"
if _side == 2 then if _side == 2 then
if _i <=2 then if _i <=2 then
@ -2040,7 +2040,7 @@ function ctld.generateTroopTypes(_side, _countOrTemplate, _country)
_weight = _weight + getSoldiersWeight(1, ctld.MANPAD_WEIGHT) _weight = _weight + getSoldiersWeight(1, ctld.MANPAD_WEIGHT)
ctld.logTrace(string.format("_unitType=%s, _weight=%s", ctld.p(_unitType), ctld.p(_weight))) ctld.logTrace(string.format("_unitType=%s, _weight=%s", ctld.p(_unitType), ctld.p(_weight)))
else else
_unitType = "Soldier M4" _unitType = "Soldier M4 GRG"
_weight = _weight + getSoldiersWeight(1, ctld.RIFLE_WEIGHT) _weight = _weight + getSoldiersWeight(1, ctld.RIFLE_WEIGHT)
ctld.logTrace(string.format("_unitType=%s, _weight=%s", ctld.p(_unitType), ctld.p(_weight))) ctld.logTrace(string.format("_unitType=%s, _weight=%s", ctld.p(_unitType), ctld.p(_weight)))
end end

View File

@ -1,6 +1,6 @@
RotorOps = {} RotorOps = {}
RotorOps.version = "1.3.4" RotorOps.version = "1.3.4"
local debug = true local debug = false
@ -65,7 +65,7 @@ RotorOps.game_state = 0
RotorOps.zones = {} RotorOps.zones = {}
RotorOps.active_zone = "" --name of the active zone RotorOps.active_zone = "" --name of the active zone
RotorOps.active_zone_index = 0 RotorOps.active_zone_index = 0
RotorOps.game_state_flag = 1 --user flag to store the game state RotorOps.game_state_flag = 100 --user flag to store the game state
RotorOps.staging_zones = {} RotorOps.staging_zones = {}
RotorOps.ai_defending_infantry_groups = {} RotorOps.ai_defending_infantry_groups = {}
RotorOps.ai_attacking_infantry_groups = {} RotorOps.ai_attacking_infantry_groups = {}
@ -1200,6 +1200,7 @@ function RotorOps.assessUnitsInZone(var)
--RotorOps.inf_spawns_avail = RotorOps.inf_spawns_per_zone * RotorOps.inf_spawn_multiplier[RotorOps.active_zone_index] --RotorOps.inf_spawns_avail = RotorOps.inf_spawns_per_zone * RotorOps.inf_spawn_multiplier[RotorOps.active_zone_index]
if total_spawn_zones > 0 then if total_spawn_zones > 0 then
RotorOps.inf_spawns_avail = (RotorOps.inf_spawns_total / total_spawn_zones) * #inf_spawn_zones RotorOps.inf_spawns_avail = (RotorOps.inf_spawns_total / total_spawn_zones) * #inf_spawn_zones
RotorOps.inf_spawns_avail = math.ceil(RotorOps.inf_spawns_avail)
end end
env.info("ROTOR OPS: zone activated: "..RotorOps.active_zone..", inf spawns avail:"..RotorOps.inf_spawns_avail..", spawn zones:"..#inf_spawn_zones) env.info("ROTOR OPS: zone activated: "..RotorOps.active_zone..", inf spawns avail:"..RotorOps.inf_spawns_avail..", spawn zones:"..#inf_spawn_zones)
@ -1285,7 +1286,8 @@ function RotorOps.assessUnitsInZone(var)
for index, vehicle in pairs(units_table) do for index, vehicle in pairs(units_table) do
local should_deploy = false local should_deploy = false
if vehicle:hasAttribute("Infantry carriers") and RotorOps.isUnitInZone(vehicle, RotorOps.active_zone) then --if a vehicle is an APC and in zone if vehicle:hasAttribute("Infantry carriers") or vehicle:hasAttribute("Trucks") then --if a vehicle is an APC
if RotorOps.isUnitInZone(vehicle, RotorOps.active_zone) then --if a vehicle is an APC and in zone
local apc_name = vehicle:getName() local apc_name = vehicle:getName()
if tableHasKey(apcs, apc_name) == true then --if we have this apc in our table already if tableHasKey(apcs, apc_name) == true then --if we have this apc in our table already
@ -1303,6 +1305,7 @@ function RotorOps.assessUnitsInZone(var)
should_deploy = true should_deploy = true
apcs[apc_name] = {['deployed_zones'] = {RotorOps.active_zone,}} apcs[apc_name] = {['deployed_zones'] = {RotorOps.active_zone,}}
end end
end
end end
@ -1314,7 +1317,7 @@ function RotorOps.assessUnitsInZone(var)
end end
end end
local id = timer.scheduleFunction(timedDeploy, nil, timer.getTime() + math.random(90, 180)) local id = timer.scheduleFunction(timedDeploy, nil, timer.getTime() + math.random(90, 300))
end end
end end
@ -1332,7 +1335,9 @@ function RotorOps.assessUnitsInZone(var)
local zone = inf_spawn_zones[rand_index] local zone = inf_spawn_zones[rand_index]
ctld.spawnGroupAtTrigger("red", RotorOps.inf_spawn_red, zone, 1000) ctld.spawnGroupAtTrigger("red", RotorOps.inf_spawn_red, zone, 1000)
RotorOps.gameMsg(RotorOps.gameMsgs.infantry_spawned, math.random(1, #RotorOps.gameMsgs.infantry_spawned)) if RotorOps.inf_spawn_messages then
RotorOps.gameMsg(RotorOps.gameMsgs.infantry_spawned, math.random(1, #RotorOps.gameMsgs.infantry_spawned))
end
RotorOps.inf_spawns_avail = RotorOps.inf_spawns_avail - 1 RotorOps.inf_spawns_avail = RotorOps.inf_spawns_avail - 1
env.info("ROTOR OPS: Attempting to spawn infantry. "..RotorOps.inf_spawns_avail.." spawns remaining in "..zone) env.info("ROTOR OPS: Attempting to spawn infantry. "..RotorOps.inf_spawns_avail.." spawns remaining in "..zone)
@ -2226,3 +2231,4 @@ function RotorOps.predSpawnRedCap()
return true return true
end end

View File

@ -9,13 +9,13 @@
-- Issues: -- Issues:
-- - You will not get points for your troops' kills if you leave your group (ie switch aircraft) -- - You will not get points for your troops' kills if you leave your group (ie switch aircraft)
-- - Currently requires a modified version of MIST (see rotorops repo /scripts)
--Todo: --Todo:
-- - more testing needed in RotorOpsPerks.monitorFarps() to check for destroyed farp objects.
RotorOpsPerks = {} RotorOpsPerks = {}
RotorOpsPerks.version = "1.5.1" RotorOpsPerks.version = "1.5.2"
env.warning('ROTOROPS PERKS STARTED: '..RotorOpsPerks.version) env.warning('ROTOROPS PERKS STARTED: '..RotorOpsPerks.version)
trigger.action.outText('ROTOROPS PERKS STARTED: '..RotorOpsPerks.version, 10) trigger.action.outText('ROTOROPS PERKS STARTED: '..RotorOpsPerks.version, 10)
RotorOpsPerks.perks = {} RotorOpsPerks.perks = {}
@ -52,11 +52,17 @@ RotorOpsPerks.player_fatcow_types = {
} }
---- END OPTIONS ---- ---- END OPTIONS ----
local function log(msg)
env.info("ROTOROPS PERKS: " .. msg)
end
local function debugMsg(msg) local function debugMsg(msg)
if RotorOpsPerks.debug then if RotorOpsPerks.debug then
env.info("ROTOROPS PERKS:") log("ROTOROPS PERKS:")
env.info(msg) if msg then
log(msg)
end
end end
end end
@ -91,7 +97,28 @@ end
RotorOpsPerks.perks.fatcow["action_condition"] = function(args) RotorOpsPerks.perks.fatcow["action_condition"] = function(args)
if #RotorOpsPerks.fat_cow_farps < 1 then if #RotorOpsPerks.fat_cow_farps < 1 then
return {msg="No FARP resources available!", valid=false} return {msg="No FARP resources available!", valid=false}
end end
--rearming/refueling doesn't work if enemies are nearby (within 1.1nm)
--this is a DCS feature/limitation so we won't deploy the farp to avoid confusing the players
local units_in_proximity = RotorOpsPerks.findUnitsInVolume({
volume_type = world.VolumeType.SPHERE,
point = args.target_point,
radius = 2050
})
log("units_in_proximity: "..#units_in_proximity)
local enemy_coal = 1
if args.player_coalition == 1 then
enemy_coal = 2
end
for _, unit in pairs(units_in_proximity) do
if unit:getCoalition() == enemy_coal then
return {msg="Too close to enemy!", valid=false}
end
end
return {valid=true} return {valid=true}
end end
@ -267,17 +294,42 @@ end
RotorOpsPerks.perks.player_fatcow["action_condition"] = function(args) RotorOpsPerks.perks.player_fatcow["action_condition"] = function(args)
local player_unit = Group.getByName(args.player_group_name):getUnit(1) local player_unit = Group.getByName(args.player_group_name):getUnit(1)
local agl_altitude = player_unit:getPosition().p.y - land.getHeight(player_unit:getPosition().p) local agl_altitude = player_unit:getPosition().p.y - land.getHeight(player_unit:getPosition().p)
if RotorOpsPerks.perks.player_fatcow.active[args.player_group_name] then if RotorOpsPerks.perks.player_fatcow.active[args.player_group_name] then
return {msg="FARP already deployed at your position!", valid=false} return {msg="FARP already deployed at your position!", valid=false}
end end
if #RotorOpsPerks.fat_cow_farps < 1 then if #RotorOpsPerks.fat_cow_farps < 1 then
return {msg="No FARP resources available!", valid=false} return {msg="No FARP resources available!", valid=false}
end end
if agl_altitude > 100 then if agl_altitude > 100 then
return {msg="You must be on the ground! "..agl_altitude.." AGL", valid=false} return {msg="You must be on the ground! "..agl_altitude.." AGL", valid=false}
else
return {msg="Stay on the ground.", valid=true}
end end
--rearming/refueling doesn't work if enemies are nearby (within 1.1nm)
--this is a DCS feature/limitation so we won't deploy the farp to avoid confusing the players
local units_in_proximity = RotorOpsPerks.findUnitsInVolume({
volume_type = world.VolumeType.SPHERE,
point = args.target_point,
radius = 2050
})
log("units_in_proximity: "..#units_in_proximity)
local enemy_coal = 1
if args.player_coalition == 1 then
enemy_coal = 2
end
for _, unit in pairs(units_in_proximity) do
if unit:getCoalition() == enemy_coal then
return {msg="Too close to enemy!", valid=false}
end
end
return {msg="Stay on the ground.", valid=true}
end end
RotorOpsPerks.perks.player_fatcow["action_function"] = function(args) RotorOpsPerks.perks.player_fatcow["action_function"] = function(args)
@ -302,10 +354,10 @@ RotorOpsPerks.perks.player_fatcow["monitor_player"] = function(args)
local agl_altitude = player_unit:getPosition().p.y - land.getHeight(player_unit:getPosition().p) local agl_altitude = player_unit:getPosition().p.y - land.getHeight(player_unit:getPosition().p)
if agl_altitude > 100 or not player_unit:isExist() then if agl_altitude > 100 or not player_unit:isExist() then
despawn_farp = true despawn_farp = true
env.info("Player is no longer on the ground, despawning FARP!") log("Player is no longer on the ground, despawning FARP!")
end end
if math.abs(player_unit:getPosition().p.x - args.target_point.x) > 50 or math.abs(player_unit:getPosition().p.z - args.target_point.z) > 50 then if math.abs(player_unit:getPosition().p.x - args.target_point.x) > 50 or math.abs(player_unit:getPosition().p.z - args.target_point.z) > 50 then
env.info("Player has moved from target position, despawning FARP!") log("Player has moved from target position, despawning FARP!")
despawn_farp = true despawn_farp = true
end end
else else
@ -435,8 +487,8 @@ function RotorOpsPerks.checkPoints(player_group_name)
return false return false
end end
env.info("Checking points for "..player_group_name.."...") log("Checking points for "..player_group_name.."...")
env.info(mist.utils.tableShow(players, "players")) log(mist.utils.tableShow(players, "players"))
--get combined points from all Players --get combined points from all Players
local total_points = 0 local total_points = 0
@ -510,7 +562,7 @@ function RotorOpsPerks.updatePlayer(identifier, groupName, name, slot)
perks_used = {}, perks_used = {},
} }
env.warning('ADDED ' .. identifier .. ' TO PLAYERS TABLE') env.warning('ADDED ' .. identifier .. ' TO PLAYERS TABLE')
env.info(mist.utils.tableShow(RotorOpsPerks.players[identifier])) log(mist.utils.tableShow(RotorOpsPerks.players[identifier]))
missionCommands.removeItemForGroup(groupId, {[1] = 'ROTOROPS PERKS'}) missionCommands.removeItemForGroup(groupId, {[1] = 'ROTOROPS PERKS'})
RotorOpsPerks.addRadioMenuForGroup(groupName) RotorOpsPerks.addRadioMenuForGroup(groupName)
if RotorOpsPerks.player_update_messages then if RotorOpsPerks.player_update_messages then
@ -520,7 +572,7 @@ function RotorOpsPerks.updatePlayer(identifier, groupName, name, slot)
--update an existing player --update an existing player
elseif RotorOpsPerks.players[identifier].groupId ~= groupId then elseif RotorOpsPerks.players[identifier].groupId ~= groupId then
env.warning('UPDATING ' .. identifier .. ' TO GROUP NAME: ' .. groupName) env.warning('UPDATING ' .. identifier .. ' TO GROUP NAME: ' .. groupName)
env.info(mist.utils.tableShow(RotorOpsPerks.players[identifier])) log(mist.utils.tableShow(RotorOpsPerks.players[identifier]))
if RotorOpsPerks.player_update_messages then if RotorOpsPerks.player_update_messages then
trigger.action.outText('PERKS: ' .. name .. ' moved to '.. groupName, 10) trigger.action.outText('PERKS: ' .. name .. ' moved to '.. groupName, 10)
end end
@ -590,7 +642,7 @@ end
---- FATCOW FARP SUPPORTING FUNCTIONS ---- ---- FATCOW FARP SUPPORTING FUNCTIONS ----
function RotorOpsPerks.monitorFarps() function RotorOpsPerks.monitorFarps()
env.info(mist.utils.tableShow(RotorOpsPerks.fat_cow_farps)) --log(mist.utils.tableShow(RotorOpsPerks.fat_cow_farps))
local function farpExists(i) local function farpExists(i)
local farp = StaticObject.getByName('FAT COW FARP ' .. i) local farp = StaticObject.getByName('FAT COW FARP ' .. i)
@ -627,7 +679,7 @@ function RotorOpsPerks.buildFatCowFarpTable()
local ammo = StaticObject.getByName('FAT COW AMMO ' .. i) local ammo = StaticObject.getByName('FAT COW AMMO ' .. i)
local fuel = StaticObject.getByName('FAT COW FUEL ' .. i) local fuel = StaticObject.getByName('FAT COW FUEL ' .. i)
if farp and tent and ammo and fuel then if farp and tent and ammo and fuel then
env.info("FAT COW FARP " .. i .. " FOUND") log("FAT COW FARP " .. i .. " FOUND")
RotorOpsPerks.fat_cow_farps[i] = { RotorOpsPerks.fat_cow_farps[i] = {
index = i, index = i,
farp = farp, farp = farp,
@ -655,7 +707,7 @@ function RotorOpsPerks.teleportStatic(source_name, dest_point)
debugMsg('RotorOpsPerks.teleportStatic: ' .. source_name) debugMsg('RotorOpsPerks.teleportStatic: ' .. source_name)
local source = StaticObject.getByName(source_name) local source = StaticObject.getByName(source_name)
if not source then if not source then
env.info('RotorOpsPerks.teleportStatic: source not found: ' .. source_name) log('RotorOpsPerks.teleportStatic: source not found: ' .. source_name)
return return
end end
local vars = {} local vars = {}
@ -664,14 +716,14 @@ function RotorOpsPerks.teleportStatic(source_name, dest_point)
vars.point = mist.utils.makeVec3(dest_point) vars.point = mist.utils.makeVec3(dest_point)
local res = mist.teleportToPoint(vars) local res = mist.teleportToPoint(vars)
if res then if res then
env.info('RotorOpsPerks.teleportStatic: ' .. source_name .. ' success') log('RotorOpsPerks.teleportStatic: ' .. source_name .. ' success')
else else
env.info('RotorOpsPerks.teleportStatic: ' .. source_name .. ' failed') log('RotorOpsPerks.teleportStatic: ' .. source_name .. ' failed')
end end
end end
function RotorOpsPerks.spawnFatCowFarpObjects(pt_x, pt_y, index, delay) function RotorOpsPerks.spawnFatCowFarpObjects(pt_x, pt_y, index, delay)
env.info('spawnFatCowFarpObjects called. Looking for static group names ending in ' .. index) log('spawnFatCowFarpObjects called. Looking for static group names ending in ' .. index)
local dest_point = mist.utils.makeVec3GL({x = pt_x, y = pt_y}) local dest_point = mist.utils.makeVec3GL({x = pt_x, y = pt_y})
trigger.action.smoke(dest_point, 2) trigger.action.smoke(dest_point, 2)
@ -693,12 +745,12 @@ function RotorOpsPerks.spawnFatCow(dest_point, farp)
local fatcow_name = 'FAT COW' local fatcow_name = 'FAT COW'
local source_farp_name = 'FAT COW FARP ' .. index local source_farp_name = 'FAT COW FARP ' .. index
env.info('spawnFatCow called with ' .. source_farp_name) log('spawnFatCow called with ' .. source_farp_name)
--set a timer to return the farp static resources to be reused --set a timer to return the farp static resources to be reused
timer.scheduleFunction(function() timer.scheduleFunction(function()
table.insert(RotorOpsPerks.fat_cow_farps, farp) --put it back at the end of the list table.insert(RotorOpsPerks.fat_cow_farps, farp) --put it back at the end of the list
env.info('FatCow FARP timer expired, making the farp available to be used again.') log('FatCow FARP timer expired, making the farp available to be used again.')
end, nil, timer.getTime() + 1800) end, nil, timer.getTime() + 1800)
dest_point = mist.utils.makeVec2(dest_point) dest_point = mist.utils.makeVec2(dest_point)
@ -793,8 +845,8 @@ function RotorOpsPerks.spawnFatCow(dest_point, farp)
end end
function RotorOpsPerks.requestPerk(args) function RotorOpsPerks.requestPerk(args)
env.info('requestPerk called for ' .. args.perk_name) log('requestPerk called for ' .. args.perk_name)
--env.info(mist.utils.tableShow(args, 'args')) --log(mist.utils.tableShow(args, 'args'))
local player_group = Group.getByName(args.player_group_name) local player_group = Group.getByName(args.player_group_name)
local player_unit = player_group:getUnits()[1] local player_unit = player_group:getUnits()[1]
local player_unit_name = player_unit:getName() local player_unit_name = player_unit:getName()
@ -834,7 +886,7 @@ function RotorOpsPerks.requestPerk(args)
mark_name = mark_name:gsub("\n", "") mark_name = mark_name:gsub("\n", "")
if mark_name == args.perk_name then if mark_name == args.perk_name then
perk_name_matches = true perk_name_matches = true
env.info("mark name matches perk name") log("mark name matches perk name")
end end
if perk_name_matches then if perk_name_matches then
@ -866,9 +918,9 @@ function RotorOpsPerks.requestPerk(args)
end end
end end
-- env.info(mist.utils.tableShow(mist.DBs.markList, 'markList')) -- log(mist.utils.tableShow(mist.DBs.markList, 'markList'))
-- env.info('player group' .. mist.utils.tableShow(player_group, 'player_group')) -- log('player group' .. mist.utils.tableShow(player_group, 'player_group'))
-- env.info('player' .. mist.utils.tableShow(player_unit, 'player_unit')) -- log('player' .. mist.utils.tableShow(player_unit, 'player_unit'))
if temp_mark then if temp_mark then
target_point = temp_mark.pos target_point = temp_mark.pos
end end
@ -923,9 +975,10 @@ function RotorOpsPerks.requestPerk(args)
args.player_group = player_group args.player_group = player_group
args.player_unit = player_unit args.player_unit = player_unit
args.player_unit_name = player_unit_name args.player_unit_name = player_unit_name
args.player_coalition = player_group:getCoalition()
--show all variables available to perk actions and conditions --show all variables available to perk actions and conditions
--env.info('args: ' .. mist.utils.tableShow(args, 'args')) --log('args: ' .. mist.utils.tableShow(args, 'args'))
--check the perk's unique prerequisite conditions --check the perk's unique prerequisite conditions
@ -947,9 +1000,9 @@ function RotorOpsPerks.requestPerk(args)
--check points --check points
if RotorOpsPerks.spendPoints(args.player_group_name, perk.cost, false) then if RotorOpsPerks.spendPoints(args.player_group_name, perk.cost, false) then
env.info(args.player_group_name.. ' has sufficient (' .. perk.cost .. ') points for ' .. args.perk_name) log(args.player_group_name.. ' has sufficient (' .. perk.cost .. ') points for ' .. args.perk_name)
else else
env.info(args.player_group_name.. ' tried to spend ' .. perk.cost .. ' points for ' .. args.perk_name .. ' but did not have enough points') log(args.player_group_name.. ' tried to spend ' .. perk.cost .. ' points for ' .. args.perk_name .. ' but did not have enough points')
if #players == 1 then if #players == 1 then
trigger.action.outTextForGroup(player_group:getID(), 'NEGATIVE. You have ' .. RotorOpsPerks.getPlayerGroupSum(args.player_group_name, "points") .. ' points. (cost '.. perk.cost .. ')', 10) trigger.action.outTextForGroup(player_group:getID(), 'NEGATIVE. You have ' .. RotorOpsPerks.getPlayerGroupSum(args.player_group_name, "points") .. ' points. (cost '.. perk.cost .. ')', 10)
else else
@ -996,7 +1049,7 @@ function RotorOpsPerks.requestPerk(args)
trigger.action.outTextForGroup(_player.groupId, 'AFFIRM. ' .. RotorOpsPerks.perks[args.perk_name].display_name .. position_string, 10) trigger.action.outTextForGroup(_player.groupId, 'AFFIRM. ' .. RotorOpsPerks.perks[args.perk_name].display_name .. position_string, 10)
else else
-- send messages to all other players -- send messages to all other players
env.info(player_unit:getPlayerName() .. ' requested ' .. RotorOpsPerks.perks[args.perk_name].display_name .. position_string) log(player_unit:getPlayerName() .. ' requested ' .. RotorOpsPerks.perks[args.perk_name].display_name .. position_string)
trigger.action.outTextForGroup(_player.groupId, player_unit:getPlayerName() .. ' requested ' .. RotorOpsPerks.perks[args.perk_name].display_name .. position_string, 10) trigger.action.outTextForGroup(_player.groupId, player_unit:getPlayerName() .. ' requested ' .. RotorOpsPerks.perks[args.perk_name].display_name .. position_string, 10)
end end
end end
@ -1157,11 +1210,11 @@ function RotorOpsPerks.registerCtldCallbacks()
local unit = _args.unit local unit = _args.unit
local picked_troops = _args.onboard local picked_troops = _args.onboard
local dropped_troops = _args.unloaded local dropped_troops = _args.unloaded
--env.info("ctld callback: ".. mist.utils.tableShow(_args)) --log("ctld callback: ".. mist.utils.tableShow(_args))
if dropped_troops then if dropped_troops then
--env.info('dropped troops: ' .. mist.utils.tableShow(dropped_troops)) --log('dropped troops: ' .. mist.utils.tableShow(dropped_troops))
--env.info('dropped troops group name: ' .. dropped_troops:getName()) --log('dropped troops group name: ' .. dropped_troops:getName())
RotorOpsPerks.troops[dropped_troops:getName()] = {dropped_troops=dropped_troops:getName(), player_group=unit:getGroup():getName(), player_name=unit:getPlayerName(), player_unit=unit:getName(), side=unit:getGroup():getCoalition() , qty=#dropped_troops:getUnits()} RotorOpsPerks.troops[dropped_troops:getName()] = {dropped_troops=dropped_troops:getName(), player_group=unit:getGroup():getName(), player_name=unit:getPlayerName(), player_unit=unit:getName(), side=unit:getGroup():getCoalition() , qty=#dropped_troops:getUnits()}
end end
@ -1253,16 +1306,23 @@ function RotorOpsPerks.monitorPlayers()
end end
if mist.grimm_version then if mist.grimm_version then
env.info("GRIMM's version of MIST is loaded") log("GRIMM's version of MIST is loaded")
else else
env.warning("ROTOROPS PERKS REQUIRES A MODIFIED VERSION OF MIST TO WORK PROPERLY. PLEASE SEE THE SCRIPTS FOLDER IN THE ROTOROPS GITHUB REPO") env.warning("ERROR: ROTOROPS PERKS REQUIRES A MODIFIED VERSION OF MIST TO WORK PROPERLY. PLEASE SEE THE SCRIPTS FOLDER IN THE ROTOROPS GITHUB REPO")
trigger.action.outText("ERROR: ROTOROPS PERKS REQUIRES A MODIFIED VERSION OF MIST TO WORK PROPERLY.", 30) trigger.action.outText("ERROR: ROTOROPS PERKS REQUIRES A MODIFIED VERSION OF MIST TO WORK PROPERLY.", 30)
end end
RotorOpsPerks.buildFatCowFarpTable() RotorOpsPerks.buildFatCowFarpTable()
env.info("Found " .. #RotorOpsPerks.fat_cow_farps .. " Fat Cow FARPs") log("Found " .. #RotorOpsPerks.fat_cow_farps .. " Fat Cow FARPs")
if #RotorOpsPerks.fat_cow_farps > 0 then if #RotorOpsPerks.fat_cow_farps > 0 then
RotorOpsPerks.monitorFarps() RotorOpsPerks.monitorFarps()
else
env.warning("NO FAT COW FARPS FOUND. PLEASE SEE THE ROTOROPS WIKI FOR INSTRUCTIONS ON HOW TO SET UP FAT COW FARPS")
trigger.action.outText("WARNING: NO FAT COW FARPS FOUND.", 30)
end
if not Group.getByName('FAT COW') then
env.warning("NO AI FAT COW HELICOPTER FOUND. PLEASE SEE THE ROTOROPS WIKI FOR INSTRUCTIONS ON HOW TO SET UP FAT COW FARPS")
trigger.action.outText("WARNING: NO AI FAT COW HELICOPTER FOUND.", 30)
end end
RotorOpsPerks.registerCtldCallbacks() RotorOpsPerks.registerCtldCallbacks()
-- start a 5 second timer to monitor players, to allow other scripts to load -- start a 5 second timer to monitor players, to allow other scripts to load