Merge branch 'develop' into fob

This commit is contained in:
walterroach 2020-11-30 12:18:38 -06:00
commit d04be4d71b
49 changed files with 172 additions and 146 deletions

View File

@ -1234,7 +1234,7 @@ def find_unittype(for_task: Task, country_name: str) -> List[Type[UnitType]]:
return [x for x in UNIT_BY_TASK[for_task] if x in FACTIONS[country_name].units] return [x for x in UNIT_BY_TASK[for_task] if x in FACTIONS[country_name].units]
def find_infantry(country_name: str) -> List[UnitType]: def find_infantry(country_name: str, allow_manpad: bool = False) -> List[UnitType]:
inf = [ inf = [
Infantry.Paratrooper_AKS, Infantry.Paratrooper_AKS, Infantry.Paratrooper_AKS, Infantry.Paratrooper_AKS, Infantry.Paratrooper_AKS, Infantry.Paratrooper_AKS, Infantry.Paratrooper_AKS, Infantry.Paratrooper_AKS,
Infantry.Paratrooper_AKS, Infantry.Paratrooper_AKS,
@ -1253,6 +1253,10 @@ def find_infantry(country_name: str) -> List[UnitType]:
Infantry.Infantry_M1_Garand, Infantry.Infantry_M1_Garand, Infantry.Infantry_M1_Garand, Infantry.Infantry_M1_Garand, Infantry.Infantry_M1_Garand, Infantry.Infantry_M1_Garand,
Infantry.Infantry_Soldier_Insurgents, Infantry.Infantry_Soldier_Insurgents, Infantry.Infantry_Soldier_Insurgents Infantry.Infantry_Soldier_Insurgents, Infantry.Infantry_Soldier_Insurgents, Infantry.Infantry_Soldier_Insurgents
] ]
if allow_manpad:
inf.append(AirDefence.SAM_SA_18_Igla_MANPADS)
inf.append(AirDefence.SAM_SA_18_Igla_S_MANPADS)
inf.append(AirDefence.Stinger_MANPADS)
return [x for x in inf if x in FACTIONS[country_name].infantry_units] return [x for x in inf if x in FACTIONS[country_name].infantry_units]

View File

@ -26,6 +26,7 @@ class Settings:
multiplier: float = 1.0 multiplier: float = 1.0
generate_marks: bool = True generate_marks: bool = True
sams: bool = True # Legacy parameter do not use sams: bool = True # Legacy parameter do not use
manpads: bool = True
cold_start: bool = False # Legacy parameter do not use cold_start: bool = False # Legacy parameter do not use
version: Optional[str] = None version: Optional[str] = None

View File

@ -293,12 +293,19 @@ class FlightData:
#: Map of radio frequencies to their assigned radio and channel, if any. #: Map of radio frequencies to their assigned radio and channel, if any.
frequency_to_channel_map: Dict[RadioFrequency, ChannelAssignment] frequency_to_channel_map: Dict[RadioFrequency, ChannelAssignment]
#: Bingo fuel value in lbs.
bingo_fuel: Optional[int]
joker_fuel: Optional[int]
def __init__(self, package: Package, flight_type: FlightType, def __init__(self, package: Package, flight_type: FlightType,
units: List[FlyingUnit], size: int, friendly: bool, units: List[FlyingUnit], size: int, friendly: bool,
departure_delay: timedelta, departure: RunwayData, departure_delay: timedelta, departure: RunwayData,
arrival: RunwayData, divert: Optional[RunwayData], arrival: RunwayData, divert: Optional[RunwayData],
waypoints: List[FlightWaypoint], waypoints: List[FlightWaypoint],
intra_flight_channel: RadioFrequency) -> None: intra_flight_channel: RadioFrequency,
bingo_fuel: Optional[int],
joker_fuel: Optional[int]) -> None:
self.package = package self.package = package
self.flight_type = flight_type self.flight_type = flight_type
self.units = units self.units = units
@ -311,6 +318,8 @@ class FlightData:
self.waypoints = waypoints self.waypoints = waypoints
self.intra_flight_channel = intra_flight_channel self.intra_flight_channel = intra_flight_channel
self.frequency_to_channel_map = {} self.frequency_to_channel_map = {}
self.bingo_fuel = bingo_fuel
self.joker_fuel = joker_fuel
self.callsign = create_group_callsign_from_unit(self.units[0]) self.callsign = create_group_callsign_from_unit(self.units[0])
@property @property
@ -777,7 +786,9 @@ class AircraftConflictGenerator:
divert=divert, divert=divert,
# Waypoints are added later, after they've had their TOTs set. # Waypoints are added later, after they've had their TOTs set.
waypoints=[], waypoints=[],
intra_flight_channel=channel intra_flight_channel=channel,
bingo_fuel=flight.flight_plan.bingo_fuel,
joker_fuel=flight.flight_plan.joker_fuel
)) ))
# Special case so Su 33 carrier take off # Special case so Su 33 carrier take off

View File

@ -179,7 +179,7 @@ class GroundConflictGenerator:
else: else:
faction = self.game.enemy_name faction = self.game.enemy_name
possible_infantry_units = db.find_infantry(faction) possible_infantry_units = db.find_infantry(faction, allow_manpad=self.game.settings.manpads)
if len(possible_infantry_units) == 0: if len(possible_infantry_units) == 0:
return return
@ -203,7 +203,6 @@ class GroundConflictGenerator:
heading=forward_heading, heading=forward_heading,
move_formation=PointAction.OffRoad) move_formation=PointAction.OffRoad)
def plan_action_for_groups(self, stance, ally_groups, enemy_groups, forward_heading, from_cp, to_cp): def plan_action_for_groups(self, stance, ally_groups, enemy_groups, forward_heading, from_cp, to_cp):
if not self.game.settings.perf_moving_units: if not self.game.settings.perf_moving_units:
@ -334,7 +333,6 @@ class GroundConflictGenerator:
dcs_group.add_waypoint(retreat_point, PointAction.OnRoad) dcs_group.add_waypoint(retreat_point, PointAction.OnRoad)
dcs_group.add_waypoint(reposition_point, PointAction.OffRoad) dcs_group.add_waypoint(reposition_point, PointAction.OffRoad)
def add_morale_trigger(self, dcs_group, forward_heading): def add_morale_trigger(self, dcs_group, forward_heading):
""" """
This add a trigger to manage units fleeing whenever their group is hit hard, or being engaged by CAS This add a trigger to manage units fleeing whenever their group is hit hard, or being engaged by CAS
@ -371,7 +369,6 @@ class GroundConflictGenerator:
self.mission.triggerrules.triggers.append(fallback) self.mission.triggerrules.triggers.append(fallback)
def find_retreat_point(self, dcs_group, frontline_heading, distance=RETREAT_DISTANCE): def find_retreat_point(self, dcs_group, frontline_heading, distance=RETREAT_DISTANCE):
""" """
Find a point to retreat to Find a point to retreat to
@ -438,7 +435,6 @@ class GroundConflictGenerator:
return potential_target.points[0].position return potential_target.points[0].position
return None return None
def get_artilery_group_distance_from_frontline(self, group): def get_artilery_group_distance_from_frontline(self, group):
""" """
For artilery group, decide the distance from frontline with the range of the unit For artilery group, decide the distance from frontline with the range of the unit
@ -450,7 +446,6 @@ class GroundConflictGenerator:
rg = DISTANCE_FROM_FRONTLINE[CombatGroupRole.TANK] + 100 rg = DISTANCE_FROM_FRONTLINE[CombatGroupRole.TANK] + 100
return rg return rg
def get_valid_position_for_group( def get_valid_position_for_group(
self, self,
conflict_position: Point, conflict_position: Point,

View File

@ -481,7 +481,7 @@ STRIKE_PREFERRED = [
ANTISHIP_CAPABLE = [ ANTISHIP_CAPABLE = [
AJS37, AJS37,
C_101CC,
Su_24M, Su_24M,
Su_17M4, Su_17M4,
FA_18C_hornet, FA_18C_hornet,
@ -503,6 +503,7 @@ ANTISHIP_CAPABLE = [
ANTISHIP_PREFERRED = [ ANTISHIP_PREFERRED = [
AJS37, AJS37,
C_101CC,
FA_18C_hornet, FA_18C_hornet,
JF_17, JF_17,
Rafale_A_S, Rafale_A_S,

View File

@ -28,7 +28,7 @@ from game.theater import (
TheaterGroundObject, TheaterGroundObject,
) )
from game.theater.theatergroundobject import EwrGroundObject from game.theater.theatergroundobject import EwrGroundObject
from game.utils import nm_to_meter from game.utils import nm_to_meter, meter_to_nm
from .closestairfields import ObjectiveDistanceCache from .closestairfields import ObjectiveDistanceCache
from .flight import Flight, FlightType, FlightWaypoint, FlightWaypointType from .flight import Flight, FlightType, FlightWaypoint, FlightWaypointType
from .traveltime import GroundSpeed, TravelTime from .traveltime import GroundSpeed, TravelTime
@ -69,6 +69,8 @@ class FlightPlan:
"""A list of all waypoints in the flight plan, in order.""" """A list of all waypoints in the flight plan, in order."""
return list(self.iter_waypoints()) return list(self.iter_waypoints())
def iter_waypoints(self) -> Iterator[FlightWaypoint]: def iter_waypoints(self) -> Iterator[FlightWaypoint]:
"""Iterates over all waypoints in the flight plan, in order.""" """Iterates over all waypoints in the flight plan, in order."""
raise NotImplementedError raise NotImplementedError
@ -115,6 +117,38 @@ class FlightPlan:
""" """
raise NotImplementedError raise NotImplementedError
@cached_property
def bingo_fuel(self) -> int:
"""Bingo fuel value for the FlightPlan
"""
distance_to_arrival = meter_to_nm(self.max_distance_from(self.flight.arrival))
bingo = 1000 # Minimum Emergency Fuel
bingo += 500 # Visual Traffic
bingo += 15 * distance_to_arrival
# TODO: Per aircraft tweaks.
if self.flight.divert is not None:
bingo += 10 * meter_to_nm(self.max_distance_from(self.flight.divert))
return round(bingo / 100) * 100
@cached_property
def joker_fuel(self) -> int:
"""Joker fuel value for the FlightPlan
"""
return self.bingo_fuel + 1000
def max_distance_from(self, cp: ControlPoint) -> int:
"""Returns the farthest waypoint of the flight plan from a ControlPoint.
:arg cp The ControlPoint to measure distance from.
"""
if not self.waypoints:
return 0
return max([cp.position.distance_to_point(w.position) for w in self.waypoints])
@property @property
def tot_offset(self) -> timedelta: def tot_offset(self) -> timedelta:
"""This flight's offset from the package's TOT. """This flight's offset from the package's TOT.

View File

@ -230,28 +230,37 @@ class BriefingPage(KneeboardPage):
"#", "Action", "Alt", "Dist", "GSPD", "Time", "Departure" "#", "Action", "Alt", "Dist", "GSPD", "Time", "Departure"
]) ])
writer.heading("Comm Ladder") flight_plan_builder
comms = [] writer.table([
["{}lbs".format(self.flight.bingo_fuel), "{}lbs".format(self.flight.joker_fuel)]
], ['Bingo', 'Joker'])
# Package Section
writer.heading("Comm ladder")
comm_ladder = []
for comm in self.comms: for comm in self.comms:
comms.append([comm.name, self.format_frequency(comm.freq)]) comm_ladder.append([comm.name, '', '', '', self.format_frequency(comm.freq)])
writer.table(comms, headers=["Name", "UHF"])
writer.heading("AWACS")
awacs = []
for a in self.awacs: for a in self.awacs:
awacs.append([a.callsign, self.format_frequency(a.freq)]) comm_ladder.append([
writer.table(awacs, headers=["Callsign", "UHF"]) a.callsign,
'AWACS',
writer.heading("Tankers") '',
tankers = [] '',
self.format_frequency(a.freq)
])
for tanker in self.tankers: for tanker in self.tankers:
tankers.append([ comm_ladder.append([
tanker.callsign, tanker.callsign,
"Tanker",
tanker.variant, tanker.variant,
str(tanker.tacan), str(tanker.tacan),
self.format_frequency(tanker.freq), self.format_frequency(tanker.freq),
]) ])
writer.table(tankers, headers=["Callsign", "Type", "TACAN", "UHF"])
writer.table(comm_ladder, headers=["Callsign","Task", "Type", "TACAN", "FREQ"])
writer.heading("JTAC") writer.heading("JTAC")
jtacs = [] jtacs = []

View File

@ -151,6 +151,10 @@ class QSettingsWindow(QDialog):
self.enemyCoalitionSkill.currentIndexChanged.connect(self.applySettings) self.enemyCoalitionSkill.currentIndexChanged.connect(self.applySettings)
self.enemyAASkill.currentIndexChanged.connect(self.applySettings) self.enemyAASkill.currentIndexChanged.connect(self.applySettings)
self.manpads = QCheckBox()
self.manpads.setChecked(self.game.settings.manpads)
self.manpads.toggled.connect(self.applySettings)
self.difficultyLayout.addWidget(QLabel("Player coalition skill"), 0, 0) self.difficultyLayout.addWidget(QLabel("Player coalition skill"), 0, 0)
self.difficultyLayout.addWidget(self.playerCoalitionSkill, 0, 1, Qt.AlignRight) self.difficultyLayout.addWidget(self.playerCoalitionSkill, 0, 1, Qt.AlignRight)
self.difficultyLayout.addWidget(QLabel("Enemy skill"), 1, 0) self.difficultyLayout.addWidget(QLabel("Enemy skill"), 1, 0)
@ -158,19 +162,22 @@ class QSettingsWindow(QDialog):
self.difficultyLayout.addWidget(QLabel("Enemy AA and vehicles skill"), 2, 0) self.difficultyLayout.addWidget(QLabel("Enemy AA and vehicles skill"), 2, 0)
self.difficultyLayout.addWidget(self.enemyAASkill, 2, 1, Qt.AlignRight) self.difficultyLayout.addWidget(self.enemyAASkill, 2, 1, Qt.AlignRight)
self.difficultyLayout.addWidget(QLabel("Manpads"), 3, 0)
self.difficultyLayout.addWidget(self.manpads, 3, 1, Qt.AlignRight)
self.difficultyLabel = QComboBox() self.difficultyLabel = QComboBox()
[self.difficultyLabel.addItem(t) for t in CONST.LABELS_OPTIONS] [self.difficultyLabel.addItem(t) for t in CONST.LABELS_OPTIONS]
self.difficultyLabel.setCurrentIndex(CONST.LABELS_OPTIONS.index(self.game.settings.labels)) self.difficultyLabel.setCurrentIndex(CONST.LABELS_OPTIONS.index(self.game.settings.labels))
self.difficultyLabel.currentIndexChanged.connect(self.applySettings) self.difficultyLabel.currentIndexChanged.connect(self.applySettings)
self.difficultyLayout.addWidget(QLabel("In Game Labels"), 3, 0) self.difficultyLayout.addWidget(QLabel("In Game Labels"), 4, 0)
self.difficultyLayout.addWidget(self.difficultyLabel, 3, 1, Qt.AlignRight) self.difficultyLayout.addWidget(self.difficultyLabel, 4, 1, Qt.AlignRight)
self.noNightMission = QCheckBox() self.noNightMission = QCheckBox()
self.noNightMission.setChecked(self.game.settings.night_disabled) self.noNightMission.setChecked(self.game.settings.night_disabled)
self.noNightMission.toggled.connect(self.applySettings) self.noNightMission.toggled.connect(self.applySettings)
self.difficultyLayout.addWidget(QLabel("No night missions"), 4, 0) self.difficultyLayout.addWidget(QLabel("No night missions"), 5, 0)
self.difficultyLayout.addWidget(self.noNightMission, 4, 1, Qt.AlignRight) self.difficultyLayout.addWidget(self.noNightMission, 5, 1, Qt.AlignRight)
self.mapVisibiitySelection = QComboBox() self.mapVisibiitySelection = QComboBox()
self.mapVisibiitySelection.addItem("All", ForcedOptions.Views.All) self.mapVisibiitySelection.addItem("All", ForcedOptions.Views.All)
@ -189,14 +196,14 @@ class QSettingsWindow(QDialog):
if self.game.settings.map_coalition_visibility == ForcedOptions.Views.OnlyMap: if self.game.settings.map_coalition_visibility == ForcedOptions.Views.OnlyMap:
self.mapVisibiitySelection.setCurrentIndex(4) self.mapVisibiitySelection.setCurrentIndex(4)
self.mapVisibiitySelection.currentIndexChanged.connect(self.applySettings) self.mapVisibiitySelection.currentIndexChanged.connect(self.applySettings)
self.difficultyLayout.addWidget(QLabel("Map visibility options"), 5, 0) self.difficultyLayout.addWidget(QLabel("Map visibility options"), 6, 0)
self.difficultyLayout.addWidget(self.mapVisibiitySelection, 5, 1, Qt.AlignRight) self.difficultyLayout.addWidget(self.mapVisibiitySelection, 6, 1, Qt.AlignRight)
self.ext_views = QCheckBox() self.ext_views = QCheckBox()
self.ext_views.setChecked(self.game.settings.external_views_allowed) self.ext_views.setChecked(self.game.settings.external_views_allowed)
self.ext_views.toggled.connect(self.applySettings) self.ext_views.toggled.connect(self.applySettings)
self.difficultyLayout.addWidget(QLabel("Allow external views"), 6, 0) self.difficultyLayout.addWidget(QLabel("Allow external views"), 7, 0)
self.difficultyLayout.addWidget(self.ext_views, 6, 1, Qt.AlignRight) self.difficultyLayout.addWidget(self.ext_views, 7, 1, Qt.AlignRight)
def initGeneratorLayout(self): def initGeneratorLayout(self):
@ -353,6 +360,7 @@ class QSettingsWindow(QDialog):
self.game.settings.player_skill = CONST.SKILL_OPTIONS[self.playerCoalitionSkill.currentIndex()] self.game.settings.player_skill = CONST.SKILL_OPTIONS[self.playerCoalitionSkill.currentIndex()]
self.game.settings.enemy_skill = CONST.SKILL_OPTIONS[self.enemyCoalitionSkill.currentIndex()] self.game.settings.enemy_skill = CONST.SKILL_OPTIONS[self.enemyCoalitionSkill.currentIndex()]
self.game.settings.enemy_vehicle_skill = CONST.SKILL_OPTIONS[self.enemyAASkill.currentIndex()] self.game.settings.enemy_vehicle_skill = CONST.SKILL_OPTIONS[self.enemyAASkill.currentIndex()]
self.game.settings.manpads = self.manpads.isChecked()
self.game.settings.labels = CONST.LABELS_OPTIONS[self.difficultyLabel.currentIndex()] self.game.settings.labels = CONST.LABELS_OPTIONS[self.difficultyLabel.currentIndex()]
self.game.settings.night_disabled = self.noNightMission.isChecked() self.game.settings.night_disabled = self.noNightMission.isChecked()
self.game.settings.map_coalition_visibility = self.mapVisibiitySelection.currentData() self.game.settings.map_coalition_visibility = self.mapVisibiitySelection.currentData()

View File

@ -67,7 +67,7 @@ DCS Liberation 第 {{ game.turn }} 回合
{% for flight in flights if flight.client_units %} {% for flight in flights if flight.client_units %}
-------------------------------------------------- --------------------------------------------------
{{ flight.flight_type }} {{ flight.units[0].type }} x {{ flight.size }}, {{ flight.package.target.name}} {{ flight.flight_type }} {{ flight.units[0].type }} x {{ flight.size }}, {{ flight.package.target.name}}
{% for waypoint in flight.waypoints %}{{ loop.index }} -- {{waypoint.name}} : {{ waypoint.description}} {% for waypoint in flight.waypoints %}{{ loop.index0 }} -- {{waypoint.name}} : {{ waypoint.description}}
{% endfor %} {% endfor %}
--------------------------------------------------{% endfor %} --------------------------------------------------{% endfor %}

View File

@ -67,7 +67,7 @@ Your flights:
{% for flight in flights if flight.client_units %} {% for flight in flights if flight.client_units %}
-------------------------------------------------- --------------------------------------------------
{{ flight.flight_type }} {{ flight.units[0].type }} x {{ flight.size }}, {{ flight.package.target.name}} {{ flight.flight_type }} {{ flight.units[0].type }} x {{ flight.size }}, {{ flight.package.target.name}}
{% for waypoint in flight.waypoints %}{{ loop.index }} -- {{waypoint.name}} : {{ waypoint.description}} {% for waypoint in flight.waypoints %}{{ loop.index0 }} -- {{waypoint.name}} : {{ waypoint.description}}
{% endfor %} {% endfor %}
--------------------------------------------------{% endfor %} --------------------------------------------------{% endfor %}

View File

@ -67,7 +67,7 @@ Vols :
{% for flight in flights if flight.client_units %} {% for flight in flights if flight.client_units %}
-------------------------------------------------- --------------------------------------------------
{{ flight.flight_type }} {{ flight.units[0].type }} x {{ flight.size }}, {{ flight.package.target.name}} {{ flight.flight_type }} {{ flight.units[0].type }} x {{ flight.size }}, {{ flight.package.target.name}}
{% for waypoint in flight.waypoints %}{{ loop.index }} -- {{waypoint.name}} : {{ waypoint.description}} {% for waypoint in flight.waypoints %}{{ loop.index0 }} -- {{waypoint.name}} : {{ waypoint.description}}
{% endfor %} {% endfor %}
--------------------------------------------------{% endfor %} --------------------------------------------------{% endfor %}

View File

@ -3,75 +3,5 @@
"theater": "Persian Gulf", "theater": "Persian Gulf",
"authors": "Khopa", "authors": "Khopa",
"description": "<p>This is lighter version of the invasion of Iran scenario.</p>", "description": "<p>This is lighter version of the invasion of Iran scenario.</p>",
"player_points": [ "miz": "invasion_of_iran_lite.miz"
{
"type": "airbase",
"id": "Bandar Lengeh",
"radials": [
270,
315,
0,
45
],
"size": 600,
"importance": 1.4
},
{
"type": "carrier",
"id": 1001,
"x": 72000.324335475,
"y": -376000
},
{
"type": "lha",
"id": 1002,
"x": -27500.813952358,
"y": -147000.65947136
}
],
"enemy_points": [
{
"type": "airbase",
"id": "Shiraz International Airport",
"size": 2000,
"importance": 1.4,
"captured_invert": true
},
{
"type": "airbase",
"id": "Jiroft Airport",
"size": 2000,
"importance": 1.4
},
{
"type": "airbase",
"id": "Kerman Airport",
"size": 2000,
"importance": 1.4
},
{
"type": "airbase",
"id": "Lar Airbase",
"size": 1000,
"importance": 1.4
}
],
"links": [
[
"Bandar Lengeh",
"Lar Airbase"
],
[
"Lar Airbase",
"Shiraz International Airport"
],
[
"Kerman Airport",
"Shiraz International Airport"
],
[
"Jiroft Airport",
"Kerman Airport"
]
]
} }

Binary file not shown.

View File

@ -29,7 +29,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"HawkGenerator", "HawkGenerator",

View File

@ -54,7 +54,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"AvengerGenerator", "AvengerGenerator",

View File

@ -29,7 +29,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"AvengerGenerator", "AvengerGenerator",

View File

@ -35,7 +35,8 @@
"infantry_units": [ "infantry_units": [
"Paratrooper_AKS", "Paratrooper_AKS",
"Infantry_Soldier_Rus", "Infantry_Soldier_Rus",
"Paratrooper_RPG_16" "Paratrooper_RPG_16",
"SAM_SA_18_Igla_S_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"HQ7Generator", "HQ7Generator",

View File

@ -35,7 +35,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"RolandGenerator", "RolandGenerator",

View File

@ -45,7 +45,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"RolandGenerator", "RolandGenerator",

View File

@ -30,7 +30,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Paratrooper_AKS", "Paratrooper_AKS",
"Paratrooper_RPG_16" "Paratrooper_RPG_16",
"SAM_SA_18_Igla_S_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"SA3Generator", "SA3Generator",

View File

@ -31,7 +31,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"GepardGenerator", "GepardGenerator",

View File

@ -34,7 +34,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Paratrooper_RPG_16" "Paratrooper_RPG_16",
"SAM_SA_18_Igla_S_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"SA3Generator", "SA3Generator",

View File

@ -21,7 +21,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_Soldier_Insurgents", "Infantry_Soldier_Insurgents",
"Soldier_RPG" "Soldier_RPG",
"SAM_SA_18_Igla_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"SA9Generator", "SA9Generator",

View File

@ -22,7 +22,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_Soldier_Insurgents", "Infantry_Soldier_Insurgents",
"Soldier_RPG" "Soldier_RPG",
"SAM_SA_18_Igla_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"SA9Generator", "SA9Generator",

View File

@ -40,7 +40,8 @@
"infantry_units": [ "infantry_units": [
"Paratrooper_AKS", "Paratrooper_AKS",
"Infantry_Soldier_Insurgents", "Infantry_Soldier_Insurgents",
"Paratrooper_RPG_16" "Paratrooper_RPG_16",
"SAM_SA_18_Igla_S_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"HawkGenerator", "HawkGenerator",

View File

@ -34,7 +34,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"ChaparralGenerator", "ChaparralGenerator",

View File

@ -28,7 +28,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"AvengerGenerator", "AvengerGenerator",

View File

@ -29,7 +29,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"AvengerGenerator", "AvengerGenerator",

View File

@ -27,7 +27,8 @@
], ],
"artillery_units": [ "artillery_units": [
"SPH_M109_Paladin", "SPH_M109_Paladin",
"MLRS_M270" "MLRS_M270",
"Stinger_MANPADS"
], ],
"logistics_units": [ "logistics_units": [
"Transport_M818" "Transport_M818"

View File

@ -31,7 +31,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_Soldier_Insurgents", "Infantry_Soldier_Insurgents",
"Paratrooper_RPG_16" "Paratrooper_RPG_16",
"SAM_SA_18_Igla_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"HQ7Generator", "HQ7Generator",

View File

@ -26,7 +26,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"AvengerGenerator", "AvengerGenerator",

View File

@ -38,7 +38,8 @@
"infantry_units": [ "infantry_units": [
"Paratrooper_AKS", "Paratrooper_AKS",
"Infantry_Soldier_Rus", "Infantry_Soldier_Rus",
"Paratrooper_RPG_16" "Paratrooper_RPG_16",
"SAM_SA_18_Igla_S_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"SA2Generator", "SA2Generator",

View File

@ -36,7 +36,8 @@
"infantry_units": [ "infantry_units": [
"Paratrooper_AKS", "Paratrooper_AKS",
"Infantry_Soldier_Rus", "Infantry_Soldier_Rus",
"Paratrooper_RPG_16" "Paratrooper_RPG_16",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"HQ7Generator", "HQ7Generator",

View File

@ -24,7 +24,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Paratrooper_AKS", "Paratrooper_AKS",
"Paratrooper_RPG_16" "Paratrooper_RPG_16",
"SAM_SA_18_Igla_S_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"SA9Generator", "SA9Generator",

View File

@ -20,7 +20,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"AvengerGenerator" "AvengerGenerator"

View File

@ -21,7 +21,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"AvengerGenerator" "AvengerGenerator"

View File

@ -42,7 +42,8 @@
"infantry_units": [ "infantry_units": [
"Paratrooper_AKS", "Paratrooper_AKS",
"Infantry_Soldier_Rus", "Infantry_Soldier_Rus",
"Paratrooper_RPG_16" "Paratrooper_RPG_16",
"SAM_SA_18_Igla_S_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"SA2Generator", "SA2Generator",

View File

@ -46,7 +46,8 @@
"infantry_units": [ "infantry_units": [
"Paratrooper_AKS", "Paratrooper_AKS",
"Infantry_Soldier_Rus", "Infantry_Soldier_Rus",
"Paratrooper_RPG_16" "Paratrooper_RPG_16",
"SAM_SA_18_Igla_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"SA8Generator", "SA8Generator",

View File

@ -45,7 +45,8 @@
"infantry_units": [ "infantry_units": [
"Paratrooper_AKS", "Paratrooper_AKS",
"Infantry_Soldier_Rus", "Infantry_Soldier_Rus",
"Paratrooper_RPG_16" "Paratrooper_RPG_16",
"SAM_SA_18_Igla_S_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"SA8Generator", "SA8Generator",

View File

@ -26,7 +26,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"AvengerGenerator", "AvengerGenerator",

View File

@ -46,7 +46,8 @@
"infantry_units": [ "infantry_units": [
"Paratrooper_AKS", "Paratrooper_AKS",
"Infantry_Soldier_Rus", "Infantry_Soldier_Rus",
"Paratrooper_RPG_16" "Paratrooper_RPG_16",
"SAM_SA_18_Igla_S_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"ColdWarFlakGenerator", "ColdWarFlakGenerator",
@ -59,10 +60,7 @@
"SA10Generator", "SA10Generator",
"SA11Generator", "SA11Generator",
"SA13Generator", "SA13Generator",
"SA15Generator",
"SA19Generator", "SA19Generator",
"Tier2SA10Generator",
"Tier3SA10Generator",
"ZSU23Generator", "ZSU23Generator",
"ZU23Generator", "ZU23Generator",
"ZU23UralGenerator" "ZU23UralGenerator"

View File

@ -32,7 +32,8 @@
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249", "Soldier_M249",
"Paratrooper_AKS" "Paratrooper_AKS",
"SAM_SA_18_Igla_S_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"AvengerGenerator", "AvengerGenerator",

View File

@ -28,7 +28,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"SAM_SA_18_Igla_S_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"HawkGenerator", "HawkGenerator",

View File

@ -32,7 +32,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"AvengerGenerator", "AvengerGenerator",

View File

@ -36,7 +36,8 @@
"infantry_units": [ "infantry_units": [
"Paratrooper_AKS", "Paratrooper_AKS",
"Infantry_Soldier_Rus", "Infantry_Soldier_Rus",
"Paratrooper_RPG_16" "Paratrooper_RPG_16",
"SAM_SA_18_Igla_S_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"SA3Generator", "SA3Generator",

View File

@ -43,7 +43,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"AvengerGenerator", "AvengerGenerator",

View File

@ -43,7 +43,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"AvengerGenerator", "AvengerGenerator",

View File

@ -44,7 +44,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"AvengerGenerator", "AvengerGenerator",

View File

@ -31,7 +31,8 @@
], ],
"infantry_units": [ "infantry_units": [
"Infantry_M4", "Infantry_M4",
"Soldier_M249" "Soldier_M249",
"Stinger_MANPADS"
], ],
"air_defenses": [ "air_defenses": [
"ChaparralGenerator", "ChaparralGenerator",