diff --git a/game/db.py b/game/db.py index b9b5f4a1..a8b0b094 100644 --- a/game/db.py +++ b/game/db.py @@ -46,18 +46,23 @@ PRICES = { MiG_29A: 18, MiG_29S: 20, - F_5E_3: 6, - MiG_15bis: 5, - MiG_21Bis: 6, - AJS37: 8, + F_5E_3: 8, + MiG_15bis: 4, + MiG_19P: 6, + F_86F_Sabre: 4, + MiG_21Bis: 8, + F_4E: 10, + AJS37: 12, - AV8BNA: 13, - M_2000C: 13, - FA_18C_hornet: 18, - F_15C: 20, - F_14B: 14, + AV8BNA: 14, + M_2000C: 16, + Mirage_2000_5: 22, + FA_18C_hornet: 22, + F_15C: 24, + F_14B: 18, # bomber + Su_17M4: 10, Su_25: 15, Su_25T: 13, L_39ZA: 10, @@ -86,15 +91,25 @@ PRICES = { C_130: 8, # armor - Armor.APC_BTR_80: 16, - Armor.MBT_T_55: 22, - Armor.MBT_T_80U: 28, + Armor.ARV_BRDM_2: 4, + Armor.ARV_BTR_RD: 6, + Armor.APC_BTR_80: 8, + Armor.MBT_T_55: 18, + Armor.MBT_T_72B: 25, + Armor.MBT_T_80U: 30, Armor.MBT_T_90: 35, - Armor.APC_M113: 5, + Armor.IFV_BMD_1: 8, + Armor.IFV_BMP_1: 14, + Armor.IFV_BMP_2: 16, + Armor.IFV_BMP_3: 20, + Armor.APC_M113: 5, + Armor.IFV_M2A2_Bradley: 12, + Armor.APC_M1126_Stryker_ICV: 16, Armor.ATGM_M1134_Stryker: 18, - Armor.MBT_M60A3_Patton: 24, + Armor.MBT_M60A3_Patton: 18, Armor.MBT_M1A2_Abrams: 35, + Armor.MBT_Leclerc: 35, Unarmed.Transport_UAZ_469: 3, Unarmed.Transport_Ural_375: 3, @@ -158,15 +173,18 @@ UNIT_BY_TASK = { ], CAS: [ MiG_15bis, + MiG_19P, L_39ZA, AV8BNA, AJS37, A_10A, A_10C, + Su_17M4, Su_25, Su_25T, Su_34, Ka_50, + F_4E, SA342M, ], @@ -188,16 +206,28 @@ UNIT_BY_TASK = { AWACS: [E_3A, A_50, ], PinpointStrike: [ + Armor.ARV_BRDM_2, + Armor.ARV_BRDM_2, + Armor.ARV_BRDM_2, + Armor.ARV_BTR_RD, Armor.APC_BTR_80, Armor.APC_BTR_80, Armor.APC_BTR_80, Armor.MBT_T_55, Armor.MBT_T_55, Armor.MBT_T_55, + Armor.MBT_T_72B, + Armor.MBT_T_72B, Armor.MBT_T_80U, Armor.MBT_T_80U, Armor.MBT_T_90, + Armor.APC_M113, + Armor.APC_M113, + Armor.APC_M113, + Armor.APC_M113, + Armor.IFV_M2A2_Bradley, + Armor.IFV_M2A2_Bradley, Armor.ATGM_M1134_Stryker, Armor.ATGM_M1134_Stryker, Armor.MBT_M60A3_Patton, @@ -265,31 +295,39 @@ EXTRA_AA = { "Russia": AirDefence.SAM_SA_8_Osa_9A33, "USA": AirDefence.SAM_Linebacker_M6, "Russia 1955": AirDefence.AAA_ZU_23_Closed, + "USA 1955": AirDefence.AAA_Vulcan_M163, + "Russia 1965": AirDefence.AAA_ZU_23_Closed, "USA 1965": AirDefence.AAA_Vulcan_M163, + "Russia 1990": AirDefence.AAA_ZU_23_Closed, + "USA 1990": AirDefence.AAA_Vulcan_M163, } """ Units separated by country. Currently only Russia and USA are supported. + Be advised that putting unit to the country that have not access to the unit in the game itself will result in incorrect missions generated! +So it's better to just use 'Russia' or 'USA', 'Ukraine' and 'USAF Aggresor' faction which have most units. + +country : DCS Country name + """ -UNIT_BY_COUNTRY = { +FACTIONS = { "Russia 2010": { "country": "Russia", + "side":"red", "units": [ AJS37, MiG_23MLD, - F_5E_3, Su_25, Su_27, Su_33, - MiG_15bis, MiG_21Bis, MiG_29A, MiG_29S, - M_2000C, Su_25T, Su_34, + Su_17M4, L_39ZA, IL_76MD, @@ -316,7 +354,9 @@ UNIT_BY_COUNTRY = { Armor.APC_BTR_80, Armor.MBT_T_90, Armor.MBT_T_80U, - Armor.MBT_T_55, + Armor.MBT_T_72B, + + Unarmed.Transport_Ural_375, Unarmed.Transport_UAZ_469, Infantry.Soldier_AK, @@ -327,10 +367,13 @@ UNIT_BY_COUNTRY = { ] }, - "Russia 1955": { + "Russia 1965": { "country": "Russia", + "side": "red", "units": [ MiG_15bis, + MiG_19P, + MiG_21Bis, IL_76MD, IL_78M, @@ -346,11 +389,14 @@ UNIT_BY_COUNTRY = { AirDefence.SAM_SA_6_Kub_LN_2P25, AirDefence.SAM_SA_3_S_125_LN_5P73, - Armor.APC_BTR_80, + Armor.ARV_BRDM_2, + Armor.ARV_BTR_RD, Armor.MBT_T_55, + Unarmed.Transport_Ural_375, Unarmed.Transport_UAZ_469, Infantry.Soldier_AK, + CV_1143_5_Admiral_Kuznetsov, Bulk_cargo_ship_Yakushev, Dry_cargo_ship_Ivanov, @@ -358,20 +404,100 @@ UNIT_BY_COUNTRY = { ] }, - "USA 2010": { - "country":"USA", - "units":[ + "Russia 1955": { + "country": "Russia", + "side": "red", + "units": [ + MiG_15bis, + + IL_76MD, + IL_78M, + An_26B, + An_30M, + Yak_40, + + AirDefence.AAA_ZU_23_Closed, + AirDefence.SAM_SA_6_Kub_LN_2P25, + AirDefence.SAM_SA_3_S_125_LN_5P73, + + Armor.ARV_BRDM_2, + Armor.MBT_T_55, + + Unarmed.Transport_Ural_375, + Unarmed.Transport_UAZ_469, + Infantry.Soldier_AK, + + CV_1143_5_Admiral_Kuznetsov, + Bulk_cargo_ship_Yakushev, + Dry_cargo_ship_Ivanov, + Tanker_Elnya_160 + ] + }, + + "USA 1955": { + "country": "USA", + "side": "blue", + "units": [ + F_86F_Sabre, + P_51D, + P_51D_30_NA, + + KC_135, + S_3B_Tanker, + C_130, + E_3A, + + UH_1H, + + Unarmed.Transport_M818, + Infantry.Infantry_M4, + + AirDefence.AAA_Vulcan_M163, + + CVN_74_John_C__Stennis, + LHA_1_Tarawa, + Armed_speedboat, + ] + }, + + "USA 1965": { + "country": "USA", + "side": "blue", + "units": [ + F_5E_3, + F_4E, + + KC_135, + S_3B_Tanker, + C_130, + E_3A, + + UH_1H, + + Armor.MBT_M60A3_Patton, + Armor.APC_M113, + Unarmed.Transport_M818, + Infantry.Infantry_M4, + + AirDefence.AAA_Vulcan_M163, + AirDefence.SAM_Linebacker_M6, + + CVN_74_John_C__Stennis, + LHA_1_Tarawa, + Armed_speedboat, + ] + }, + + "USA 1990": { + "country":"USA", + "side":"blue", + "units":[ F_15C, F_14B, FA_18C_hornet, - AJS37, - M_2000C, - MiG_21Bis, - MiG_15bis, A_10A, - A_10C, AV8BNA, KC_135, @@ -379,10 +505,7 @@ UNIT_BY_COUNTRY = { C_130, E_3A, - Ka_50, - SA342M, UH_1H, - Mi_8MT, Armor.MBT_M1A2_Abrams, Armor.MBT_M60A3_Patton, @@ -399,13 +522,17 @@ UNIT_BY_COUNTRY = { ] }, - "USA 1965": { - "country":"USA", - "units":[ - F_86F_Sabre, - F_5E_3, + "USA 2005": { + "country": "USA", + "side": "blue", + "units": [ + F_15C, + F_14B, + FA_18C_hornet, A_10A, + A_10C, + AV8BNA, KC_135, S_3B_Tanker, @@ -414,8 +541,37 @@ UNIT_BY_COUNTRY = { UH_1H, - Armor.MBT_M60A3_Patton, - Armor.APC_M113, + Armor.MBT_M1A2_Abrams, + Armor.ATGM_M1134_Stryker, + Armor.IFV_M2A2_Bradley, + + Unarmed.Transport_M818, + Infantry.Infantry_M4, + + AirDefence.AAA_Vulcan_M163, + AirDefence.SAM_Linebacker_M6, + + CVN_74_John_C__Stennis, + LHA_1_Tarawa, + Armed_speedboat, + ] + }, + + "France 1990": { + "country": "USA", + "side": "blue", + "units":[ + M_2000C, + Mirage_2000_5, + + KC_135, + S_3B_Tanker, + C_130, + E_3A, + + SA342M, + + Armor.MBT_Leclerc, Unarmed.Transport_M818, Infantry.Infantry_M4, @@ -588,7 +744,7 @@ def unit_task(unit: UnitType) -> Task: def find_unittype(for_task: Task, country_name: str) -> typing.List[UnitType]: - return [x for x in UNIT_BY_TASK[for_task] if x in UNIT_BY_COUNTRY[country_name]["units"]] + return [x for x in UNIT_BY_TASK[for_task] if x in FACTIONS[country_name]["units"]] def unit_type_name(unit_type) -> str: @@ -711,13 +867,13 @@ def _validate_db(): total_set = set() for t, unit_collection in UNIT_BY_TASK.items(): for unit_type in set(unit_collection): - assert unit_type not in total_set, "{} is duplicate".format(unit_type) + assert unit_type not in total_set, "{} is duplicate for task {}".format(unit_type, t) total_set.add(unit_type) # check country allegiance for unit_type in total_set: did_find = False - for country_units_list in UNIT_BY_COUNTRY.values(): + for country_units_list in FACTIONS.values(): if unit_type in country_units_list["units"]: did_find = True assert did_find, "{} not in country list".format(unit_type) diff --git a/game/event/baseattack.py b/game/event/baseattack.py index a6bc4a7d..92969deb 100644 --- a/game/event/baseattack.py +++ b/game/event/baseattack.py @@ -39,7 +39,7 @@ class BaseAttackEvent(Event): if self.departure_cp.captured: self.to_cp.captured = True self.to_cp.ground_objects = [] - self.to_cp.base.filter_units(db.UNIT_BY_COUNTRY[self.attacker_name]["units"]) + self.to_cp.base.filter_units(db.FACTIONS[self.attacker_name]["units"]) self.to_cp.base.affect_strength(+self.STRENGTH_RECOVERY) else: diff --git a/game/game.py b/game/game.py index cf21d4d6..4037fdd1 100644 --- a/game/game.py +++ b/game/game.py @@ -103,9 +103,9 @@ class Game: self.events = [] self.theater = theater self.player_name = player_name - self.player_country = db.UNIT_BY_COUNTRY[player_name]["country"] + self.player_country = db.FACTIONS[player_name]["country"] self.enemy_name = enemy_name - self.enemy_country = db.UNIT_BY_COUNTRY[enemy_name]["country"] + self.enemy_country = db.FACTIONS[enemy_name]["country"] self.turn = 0 self.date = datetime(start_date.year, start_date.month, start_date.day) @@ -206,7 +206,7 @@ class Game: if for_task == AirDefence and not self.settings.sams: return [x for x in db.find_unittype(AirDefence, self.enemy_name) if x not in db.SAM_BAN] else: - return db.choose_units(for_task, importance_factor, COMMISION_UNIT_VARIETY, self.enemy_country) + return db.choose_units(for_task, importance_factor, COMMISION_UNIT_VARIETY, self.enemy_name) def _commision_units(self, cp: ControlPoint): for for_task in [PinpointStrike, CAS, CAP, AirDefence]: diff --git a/game/operation/baseattack.py b/game/operation/baseattack.py index 73822cf2..739b007b 100644 --- a/game/operation/baseattack.py +++ b/game/operation/baseattack.py @@ -37,6 +37,8 @@ class BaseAttackOperation(Operation): self.attackers_starting_position = None conflict = Conflict.capture_conflict( + attacker_name=self.attacker_name, + defender_name=self.defender_name, attacker=self.current_mission.country(self.attacker_country), defender=self.current_mission.country(self.defender_country), from_cp=self.from_cp, diff --git a/game/operation/convoystrike.py b/game/operation/convoystrike.py index 07ae3e4c..835cca15 100644 --- a/game/operation/convoystrike.py +++ b/game/operation/convoystrike.py @@ -17,6 +17,8 @@ class ConvoyStrikeOperation(Operation): super(ConvoyStrikeOperation, self).prepare(terrain, is_quick) conflict = Conflict.convoy_strike_conflict( + attacker_name=self.attacker_name, + defender_name=self.defender_name, attacker=self.current_mission.country(self.attacker_country), defender=self.current_mission.country(self.defender_country), from_cp=self.from_cp, diff --git a/game/operation/frontlineattack.py b/game/operation/frontlineattack.py index 9f412fe6..43be8e62 100644 --- a/game/operation/frontlineattack.py +++ b/game/operation/frontlineattack.py @@ -34,6 +34,8 @@ class FrontlineAttackOperation(Operation): self.defenders_starting_position = None conflict = Conflict.frontline_cas_conflict( + attacker_name=self.attacker_name, + defender_name=self.defender_name, attacker=self.current_mission.country(self.attacker_country), defender=self.current_mission.country(self.defender_country), from_cp=self.from_cp, diff --git a/game/operation/frontlinepatrol.py b/game/operation/frontlinepatrol.py index a6446920..cf64d2cb 100644 --- a/game/operation/frontlinepatrol.py +++ b/game/operation/frontlinepatrol.py @@ -32,6 +32,8 @@ class FrontlinePatrolOperation(Operation): self.defenders_starting_position = None conflict = Conflict.frontline_cap_conflict( + attacker_name=self.attacker_name, + defender_name=self.defender_name, attacker=self.current_mission.country(self.attacker_country), defender=self.current_mission.country(self.defender_country), from_cp=self.from_cp, diff --git a/game/operation/infantrytransport.py b/game/operation/infantrytransport.py index 07226cc0..b06fd009 100644 --- a/game/operation/infantrytransport.py +++ b/game/operation/infantrytransport.py @@ -15,6 +15,8 @@ class InfantryTransportOperation(Operation): super(InfantryTransportOperation, self).prepare(terrain, is_quick) conflict = Conflict.transport_conflict( + attacker_name=self.attacker_name, + defender_name=self.defender_name, attacker=self.current_mission.country(self.attacker_country), defender=self.current_mission.country(self.defender_country), from_cp=self.from_cp, diff --git a/game/operation/insurgentattack.py b/game/operation/insurgentattack.py index 36c18190..2e81e831 100644 --- a/game/operation/insurgentattack.py +++ b/game/operation/insurgentattack.py @@ -17,6 +17,8 @@ class InsurgentAttackOperation(Operation): super(InsurgentAttackOperation, self).prepare(terrain, is_quick) conflict = Conflict.ground_attack_conflict( + attacker_name=self.attacker_name, + defender_name=self.defender_name, attacker=self.current_mission.country(self.attacker_country), defender=self.current_mission.country(self.defender_country), from_cp=self.from_cp, diff --git a/game/operation/intercept.py b/game/operation/intercept.py index 1e3feb7e..60d5afd0 100644 --- a/game/operation/intercept.py +++ b/game/operation/intercept.py @@ -31,6 +31,8 @@ class InterceptOperation(Operation): self.attackers_starting_position = None conflict = Conflict.intercept_conflict( + attacker_name=self.attacker_name, + defender_name=self.defender_name, attacker=self.current_mission.country(self.attacker_country), defender=self.current_mission.country(self.defender_country), position=self.location, diff --git a/game/operation/navalintercept.py b/game/operation/navalintercept.py index 9033be40..c4144c1a 100644 --- a/game/operation/navalintercept.py +++ b/game/operation/navalintercept.py @@ -26,6 +26,8 @@ class NavalInterceptionOperation(Operation): self.attackers_starting_position = None conflict = Conflict.naval_intercept_conflict( + attacker_name=self.attacker_name, + defender_name=self.defender_name, attacker=self.current_mission.country(self.attacker_country), defender=self.current_mission.country(self.defender_country), position=self.location, diff --git a/game/operation/operation.py b/game/operation/operation.py index 1cf81c92..24da6cdf 100644 --- a/game/operation/operation.py +++ b/game/operation/operation.py @@ -43,9 +43,9 @@ class Operation: to_cp: ControlPoint = None): self.game = game self.attacker_name = attacker_name - self.attacker_country = db.UNIT_BY_COUNTRY[attacker_name]["country"] + self.attacker_country = db.FACTIONS[attacker_name]["country"] self.defender_name = defender_name - self.defender_country = db.UNIT_BY_COUNTRY[defender_name]["country"] + self.defender_country = db.FACTIONS[defender_name]["country"] print(self.defender_country, self.attacker_country) self.from_cp = from_cp self.departure_cp = departure_cp @@ -137,7 +137,7 @@ class Operation: self.extra_aagen.generate() # triggers - if self.game.is_player_attack(self.conflict.attackers_side): + if self.game.is_player_attack(self.conflict.attackers_country): cp = self.conflict.from_cp else: cp = self.conflict.to_cp diff --git a/game/operation/strike.py b/game/operation/strike.py index d777e6f6..cabf2a77 100644 --- a/game/operation/strike.py +++ b/game/operation/strike.py @@ -29,6 +29,8 @@ class StrikeOperation(Operation): self.attackers_starting_position = None conflict = Conflict.strike_conflict( + attacker_name=self.attacker_name, + defender_name=self.defender_name, attacker=self.current_mission.country(self.attacker_country), defender=self.current_mission.country(self.defender_country), from_cp=self.from_cp, diff --git a/gen/aaa.py b/gen/aaa.py index 930b63b3..1e2b18bf 100644 --- a/gen/aaa.py +++ b/gen/aaa.py @@ -281,7 +281,7 @@ class AAConflictGenerator: for _ in range(count): self.m.vehicle_group( country=self.conflict.defenders_side, - name=namegen.next_unit_name(self.conflict.defenders_side, unit_type), + name=namegen.next_unit_name(self.conflict.defenders_country, unit_type), _type=unit_type, position=self.conflict.ground_defenders_location.random_point_within(100, 100), group_size=1) @@ -294,7 +294,7 @@ class AAConflictGenerator: self.m.aaa_vehicle_group( country=self.conflict.defenders_side, - name=namegen.next_unit_name(self.conflict.defenders_side, type), + name=namegen.next_unit_name(self.conflict.defenders_country, type), _type=type, position=p, group_size=1) diff --git a/gen/aircraft.py b/gen/aircraft.py index 33fd2aff..48177504 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -276,8 +276,8 @@ class AircraftConflictGenerator: for flying_type, count, client_count in self._split_to_groups(attackers, clients): group = self._generate_group( - name=namegen.next_unit_name(self.conflict.attackers_side, flying_type), - side=self.conflict.attackers_side, + name=namegen.next_unit_name(self.conflict.attackers_country, flying_type), + side=self.conflict.attackers_country, unit_type=flying_type, count=count, client_count=client_count, @@ -298,8 +298,8 @@ class AircraftConflictGenerator: for flying_type, count, client_count in self._split_to_groups(strikegroup, clients): group = self._generate_group( - name=namegen.next_unit_name(self.conflict.attackers_side, flying_type), - side=self.conflict.attackers_side, + name=namegen.next_unit_name(self.conflict.attackers_country, flying_type), + side=self.conflict.attackers_country, unit_type=flying_type, count=count, client_count=client_count, @@ -324,8 +324,8 @@ class AircraftConflictGenerator: for flying_type, count, client_count in self._split_to_groups(strikegroup, clients): group = self._generate_group( - name=namegen.next_unit_name(self.conflict.attackers_side, flying_type), - side=self.conflict.attackers_side, + name=namegen.next_unit_name(self.conflict.attackers_country, flying_type), + side=self.conflict.attackers_country, unit_type=flying_type, count=count, client_count=client_count, @@ -350,8 +350,8 @@ class AircraftConflictGenerator: for flying_type, count, client_count in self._split_to_groups(defenders, clients): group = self._generate_group( - name=namegen.next_unit_name(self.conflict.defenders_side, flying_type), - side=self.conflict.defenders_side, + name=namegen.next_unit_name(self.conflict.attackers_country, flying_type), + side=self.conflict.defenders_country, unit_type=flying_type, count=count, client_count=client_count, @@ -376,8 +376,8 @@ class AircraftConflictGenerator: for flying_type, count, client_count in self._split_to_groups(attackers, clients): group = self._generate_group( - name=namegen.next_unit_name(self.conflict.attackers_side, flying_type), - side=self.conflict.attackers_side, + name=namegen.next_unit_name(self.conflict.attackers_country, flying_type), + side=self.conflict.attackers_country, unit_type=flying_type, count=count, client_count=client_count, @@ -395,7 +395,7 @@ class AircraftConflictGenerator: def generate_attackers_escort(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): for g in self._generate_escort( - side=self.conflict.attackers_side, + side=self.conflict.attackers_country, units=attackers, clients=clients, at=at and at or self._group_point(self.conflict.air_attackers_location), @@ -405,7 +405,7 @@ class AircraftConflictGenerator: def generate_defenders_escort(self, escort: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): for g in self._generate_escort( - side=self.conflict.defenders_side, + side=self.conflict.defenders_country, units=escort, clients=clients, at=at and at or self._group_point(self.conflict.air_defenders_location), @@ -416,8 +416,8 @@ class AircraftConflictGenerator: def generate_defense(self, defenders: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): for flying_type, count, client_count in self._split_to_groups(defenders, clients): group = self._generate_group( - name=namegen.next_unit_name(self.conflict.defenders_side, flying_type), - side=self.conflict.defenders_side, + name=namegen.next_unit_name(self.conflict.attackers_country, flying_type), + side=self.conflict.defenders_country, unit_type=flying_type, count=count, client_count=client_count, @@ -433,8 +433,8 @@ class AircraftConflictGenerator: def generate_migcap(self, patrol: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): for flying_type, count, client_count in self._split_to_groups(patrol, clients): group = self._generate_group( - name=namegen.next_unit_name(self.conflict.attackers_side, flying_type), - side=self.conflict.attackers_side, + name=namegen.next_unit_name(self.conflict.attackers_country, flying_type), + side=self.conflict.attackers_country, unit_type=flying_type, count=count, client_count=client_count, @@ -451,8 +451,8 @@ class AircraftConflictGenerator: def generate_barcap(self, patrol: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): for flying_type, count, client_count in self._split_to_groups(patrol, clients): group = self._generate_group( - name=namegen.next_unit_name(self.conflict.defenders_side, flying_type), - side=self.conflict.defenders_side, + name=namegen.next_unit_name(self.conflict.attackers_country, flying_type), + side=self.conflict.defenders_country, unit_type=flying_type, count=count, client_count=client_count, @@ -477,8 +477,8 @@ class AircraftConflictGenerator: for flying_type, count, client_count in self._split_to_groups(transport): group = self._generate_group( - name=namegen.next_unit_name(self.conflict.defenders_side, flying_type), - side=self.conflict.defenders_side, + name=namegen.next_unit_name(self.conflict.attackers_country, flying_type), + side=self.conflict.defenders_country, unit_type=flying_type, count=count, client_count=client_count, @@ -495,8 +495,8 @@ class AircraftConflictGenerator: def generate_interception(self, interceptors: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): for flying_type, count, client_count in self._split_to_groups(interceptors, clients): group = self._generate_group( - name=namegen.next_unit_name(self.conflict.attackers_side, flying_type), - side=self.conflict.attackers_side, + name=namegen.next_unit_name(self.conflict.attackers_country, flying_type), + side=self.conflict.attackers_country, unit_type=flying_type, count=count, client_count=client_count, @@ -517,8 +517,8 @@ class AircraftConflictGenerator: def generate_passenger_transport(self, helis: db.HeliDict, clients: db.HeliDict, at: db.StartingPosition): for heli_type, count, client_count in self._split_to_groups(helis, clients): group = self._generate_group( - name=namegen.next_unit_name(self.conflict.attackers_side, heli_type), - side=self.conflict.attackers_side, + name=namegen.next_unit_name(self.conflict.attackers_country, heli_type), + side=self.conflict.attackers_country, unit_type=heli_type, count=count, client_count=client_count, diff --git a/gen/airsupportgen.py b/gen/airsupportgen.py index 3d63b9c7..7daab645 100644 --- a/gen/airsupportgen.py +++ b/gen/airsupportgen.py @@ -32,7 +32,7 @@ class AirSupportConflictGenerator: def generate(self, is_awacs_enabled): player_cp = self.conflict.from_cp if self.conflict.from_cp.captured else self.conflict.to_cp - for i, tanker_unit_type in enumerate(db.find_unittype(Refueling, self.conflict.attackers_side.name)): + for i, tanker_unit_type in enumerate(db.find_unittype(Refueling, self.conflict.attackers_side)): self.generated_tankers.append(db.unit_type_name(tanker_unit_type)) tanker_heading = self.conflict.to_cp.position.heading_between_point(self.conflict.from_cp.position) + TANKER_HEADING_OFFSET * i tanker_position = player_cp.position.point_from_heading(tanker_heading, TANKER_DISTANCE) @@ -53,7 +53,7 @@ class AirSupportConflictGenerator: tanker_group.points[0].tasks.append(SetImmortalCommand(True)) if is_awacs_enabled: - awacs_unit = db.find_unittype(AWACS, self.conflict.attackers_side.name)[0] + awacs_unit = db.find_unittype(AWACS, self.conflict.attackers_side)[0] awacs_flight = self.mission.awacs_flight( country=self.mission.country(self.game.player_country), name=namegen.next_awacs_name(self.mission.country(self.game.player_country)), diff --git a/gen/armor.py b/gen/armor.py index 92d1d89a..ed91ba40 100644 --- a/gen/armor.py +++ b/gen/armor.py @@ -62,7 +62,7 @@ class ArmorConflictGenerator: attack_dest = position.point_from_heading(self.conflict.heading + 90, FIGHT_DISTANCE * 2) for type, count in attackers.items(): self._generate_group( - side=self.conflict.attackers_side, + side=self.conflict.attackers_country, unit=type, count=count, at=attack_pos, @@ -74,7 +74,7 @@ class ArmorConflictGenerator: def_dest = position.point_from_heading(self.conflict.heading - 90, FIGHT_DISTANCE * 2) for type, count in defenders.items(): self._generate_group( - side=self.conflict.defenders_side, + side=self.conflict.defenders_country, unit=type, count=count, at=def_pos, @@ -84,14 +84,14 @@ class ArmorConflictGenerator: def generate(self, attackers: db.ArmorDict, defenders: db.ArmorDict): for type, count in attackers.items(): self._generate_group( - side=self.conflict.attackers_side, + side=self.conflict.attackers_country, unit=type, count=count, at=self.conflict.ground_attackers_location) for type, count in defenders.items(): self._generate_group( - side=self.conflict.defenders_side, + side=self.conflict.defenders_country, unit=type, count=count, at=self.conflict.ground_defenders_location) @@ -112,7 +112,7 @@ class ArmorConflictGenerator: def generate_convoy(self, units: db.ArmorDict): for type, count in units.items(): self._generate_group( - side=self.conflict.defenders_side, + side=self.conflict.defenders_country, unit=type, count=count, at=self.conflict.ground_defenders_location, diff --git a/gen/conflictgen.py b/gen/conflictgen.py index 775d0787..c807250c 100644 --- a/gen/conflictgen.py +++ b/gen/conflictgen.py @@ -65,8 +65,10 @@ def _heading_sum(h, a) -> int: class Conflict: - attackers_side = None # type: Country - defenders_side = None # type: Country + attackers_side = None # type: str + defenders_side = None # type: str + attackers_country = None # type: Country + defenders_country = None # type: Country from_cp = None # type: ControlPoint to_cp = None # type: ControlPoint position = None # type: Point @@ -85,8 +87,10 @@ class Conflict: theater: ConflictTheater, from_cp: ControlPoint, to_cp: ControlPoint, - attackers_side: Country, - defenders_side: Country, + attackers_side: str, + defenders_side: str, + attackers_country: Country, + defenders_country: Country, position: Point, heading=None, distance=None, @@ -94,8 +98,12 @@ class Conflict: ground_defenders_location: Point = None, air_attackers_location: Point = None, air_defenders_location: Point = None): + self.attackers_side = attackers_side self.defenders_side = defenders_side + self.attackers_country = attackers_country + self.defenders_country = defenders_country + self.from_cp = from_cp self.to_cp = to_cp self.theater = theater @@ -264,7 +272,7 @@ class Conflict: return initial @classmethod - def capture_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): + def capture_conflict(cls, attacker_name: str, defender_name: str, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): position = to_cp.position attack_raw_heading = to_cp.position.heading_between_point(from_cp.position) attack_heading = to_cp.find_radial(attack_raw_heading) @@ -282,8 +290,10 @@ class Conflict: theater=theater, from_cp=from_cp, to_cp=to_cp, - attackers_side=attacker, - defenders_side=defender, + attackers_side=attacker_name, + defenders_side=defender_name, + attackers_country=attacker, + defenders_country=defender, ground_attackers_location=attackers_location, ground_defenders_location=defenders_location, air_attackers_location=position.point_from_heading(attack_raw_heading, CAPTURE_AIR_ATTACKERS_DISTANCE), @@ -291,7 +301,7 @@ class Conflict: ) @classmethod - def strike_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): + def strike_conflict(cls, attacker_name: str, defender_name: str, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): position = to_cp.position attack_raw_heading = to_cp.position.heading_between_point(from_cp.position) attack_heading = to_cp.find_radial(attack_raw_heading) @@ -309,8 +319,10 @@ class Conflict: theater=theater, from_cp=from_cp, to_cp=to_cp, - attackers_side=attacker, - defenders_side=defender, + attackers_side=attacker_name, + defenders_side=defender_name, + attackers_country=attacker, + defenders_country=defender, ground_attackers_location=attackers_location, ground_defenders_location=defenders_location, air_attackers_location=position.point_from_heading(attack_raw_heading, STRIKE_AIR_ATTACKERS_DISTANCE), @@ -325,15 +337,17 @@ class Conflict: return from_cp.position.point_from_heading(heading, distance) @classmethod - def intercept_conflict(cls, attacker: Country, defender: Country, position: Point, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): + def intercept_conflict(cls, attacker_name: str, defender_name: str, attacker: Country, defender: Country, position: Point, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): heading = from_cp.position.heading_between_point(position) return cls( position=position.point_from_heading(position.heading_between_point(to_cp.position), INTERCEPT_CONFLICT_DISTANCE), theater=theater, from_cp=from_cp, to_cp=to_cp, - attackers_side=attacker, - defenders_side=defender, + attackers_side=attacker_name, + defenders_side=defender_name, + attackers_country=attacker, + defenders_country=defender, ground_attackers_location=None, ground_defenders_location=None, air_attackers_location=position.point_from_heading(random.randint(*INTERCEPT_ATTACKERS_HEADING) + heading, INTERCEPT_ATTACKERS_DISTANCE), @@ -341,7 +355,7 @@ class Conflict: ) @classmethod - def ground_attack_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): + def ground_attack_conflict(cls, attacker_name: str, defender_name: str, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): heading = random.choice(to_cp.radials) initial_location = to_cp.position.random_point_within(*GROUND_ATTACK_DISTANCE) position = Conflict._find_ground_position(initial_location, GROUND_INTERCEPT_SPREAD, _heading_sum(heading, 180), theater) @@ -354,8 +368,10 @@ class Conflict: theater=theater, from_cp=from_cp, to_cp=to_cp, - attackers_side=attacker, - defenders_side=defender, + attackers_side=attacker_name, + defenders_side=defender_name, + attackers_country=attacker, + defenders_country=defender, ground_attackers_location=position, ground_defenders_location=None, air_attackers_location=None, @@ -363,7 +379,7 @@ class Conflict: ) @classmethod - def convoy_strike_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): + def convoy_strike_conflict(cls, attacker_name: str, defender_name: str, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): frontline_position, frontline_heading, frontline_length = Conflict.frontline_vector(from_cp, to_cp, theater) if not frontline_position: assert False @@ -383,8 +399,10 @@ class Conflict: theater=theater, from_cp=from_cp, to_cp=to_cp, - attackers_side=attacker, - defenders_side=defender, + attackers_side=attacker_name, + defenders_side=defender_name, + attackers_country=attacker, + defenders_country=defender, ground_attackers_location=None, ground_defenders_location=starting_position, air_attackers_location=starting_position.point_from_heading(_opposite_heading(heading), AIR_DISTANCE), @@ -392,7 +410,7 @@ class Conflict: ) @classmethod - def frontline_cas_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): + def frontline_cas_conflict(cls, attacker_name: str, defender_name: str, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): assert cls.has_frontline_between(from_cp, to_cp) position, heading, distance = cls.frontline_vector(from_cp, to_cp, theater) @@ -403,8 +421,10 @@ class Conflict: theater=theater, from_cp=from_cp, to_cp=to_cp, - attackers_side=attacker, - defenders_side=defender, + attackers_side=attacker_name, + defenders_side=defender_name, + attackers_country=attacker, + defenders_country=defender, ground_attackers_location=None, ground_defenders_location=None, air_attackers_location=position.point_from_heading(random.randint(*INTERCEPT_ATTACKERS_HEADING) + heading, AIR_DISTANCE), @@ -412,7 +432,7 @@ class Conflict: ) @classmethod - def frontline_cap_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): + def frontline_cap_conflict(cls, attacker_name: str, defender_name: str, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): assert cls.has_frontline_between(from_cp, to_cp) position, heading, distance = cls.frontline_vector(from_cp, to_cp, theater) @@ -427,14 +447,16 @@ class Conflict: theater=theater, from_cp=from_cp, to_cp=to_cp, - attackers_side=attacker, - defenders_side=defender, + attackers_side=attacker_name, + defenders_side=defender_name, + attackers_country=attacker, + defenders_country=defender, air_attackers_location=attackers_position, air_defenders_location=defenders_position, ) @classmethod - def ground_base_attack(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): + def ground_base_attack(cls, attacker_name: str, defender_name: str, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): position = to_cp.position attack_heading = to_cp.find_radial(to_cp.position.heading_between_point(from_cp.position)) defense_heading = to_cp.find_radial(from_cp.position.heading_between_point(to_cp.position), ignored_radial=attack_heading) @@ -448,8 +470,10 @@ class Conflict: theater=theater, from_cp=from_cp, to_cp=to_cp, - attackers_side=attacker, - defenders_side=defender, + attackers_side=attacker_name, + defenders_side=defender_name, + attackers_country=attacker, + defenders_country=defender, ground_attackers_location=None, ground_defenders_location=defenders_location, air_attackers_location=position.point_from_heading(attack_heading, AIR_DISTANCE), @@ -470,15 +494,17 @@ class Conflict: return position @classmethod - def naval_intercept_conflict(cls, attacker: Country, defender: Country, position: Point, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): + def naval_intercept_conflict(cls, attacker_name: str, defender_name: str, attacker: Country, defender: Country, position: Point, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): attacker_heading = from_cp.position.heading_between_point(to_cp.position) return cls( position=position, theater=theater, from_cp=from_cp, to_cp=to_cp, - attackers_side=attacker, - defenders_side=defender, + attackers_side=attacker_name, + defenders_side=defender_name, + attackers_country=attacker, + defenders_country=defender, ground_attackers_location=None, ground_defenders_location=position, air_attackers_location=position.point_from_heading(attacker_heading, AIR_DISTANCE), @@ -486,7 +512,7 @@ class Conflict: ) @classmethod - def transport_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): + def transport_conflict(cls, attacker_name: str, defender_name: str, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): frontline_position, heading = cls.frontline_position(theater, from_cp, to_cp) initial_dest = frontline_position.point_from_heading(heading, TRANSPORT_FRONTLINE_DIST) dest = cls._find_ground_position(initial_dest, from_cp.position.distance_to_point(to_cp.position) / 3, heading, theater) @@ -499,8 +525,10 @@ class Conflict: theater=theater, from_cp=from_cp, to_cp=to_cp, - attackers_side=attacker, - defenders_side=defender, + attackers_side=attacker_name, + defenders_side=defender_name, + attackers_country=attacker, + defenders_country=defender, ground_attackers_location=from_cp.position, ground_defenders_location=frontline_position, air_attackers_location=from_cp.position.point_from_heading(0, 100), diff --git a/gen/groundobjectsgen.py b/gen/groundobjectsgen.py index 41d6dff9..4cefee90 100644 --- a/gen/groundobjectsgen.py +++ b/gen/groundobjectsgen.py @@ -45,7 +45,7 @@ class GroundObjectsGenerator: side = self.m.country(self.game.enemy_country) cp = None # type: ControlPoint - if self.conflict.attackers_side.name == self.game.player_country: + if self.conflict.attackers_country.name == self.game.player_country: cp = self.conflict.to_cp else: cp = self.conflict.from_cp diff --git a/resources/tools/generate_loadout_check.py b/resources/tools/generate_loadout_check.py index cded7b57..d5e43258 100644 --- a/resources/tools/generate_loadout_check.py +++ b/resources/tools/generate_loadout_check.py @@ -20,7 +20,7 @@ for t, uts in db.UNIT_BY_TASK.items(): pos.x += 10000 for ut in uts: pos.y += 5000 - ctr = mis.country([v["country"] for k, v in db.UNIT_BY_COUNTRY.items() if ut in v["units"]][0]) + ctr = mis.country([v["country"] for k, v in db.FACTIONS.items() if ut in v["units"]][0]) g = mis.flight_group_inflight( country=ctr, diff --git a/ui/newgamemenu.py b/ui/newgamemenu.py index 1147c6c2..de746f5b 100644 --- a/ui/newgamemenu.py +++ b/ui/newgamemenu.py @@ -27,6 +27,9 @@ class NewGameMenu(Menu): self.selected_time_period = StringVar() + self.selected_blue_faction = StringVar() + self.selected_red_faction = StringVar() + self.sams = BooleanVar() self.sams.set(1) @@ -39,16 +42,16 @@ class NewGameMenu(Menu): @property def player_country_name(self): if self.selected_country.get() == 0: - return "USA 1965" + return self.selected_blue_faction.get() else: - return "Russia 1955" + return self.selected_red_faction.get() @property def enemy_country_name(self): if self.selected_country.get() == 1: - return "USA 1965" + return self.selected_blue_faction.get() else: - return "Russia 1955" + return self.selected_red_faction.get() @property def terrain_name(self) -> str: @@ -71,15 +74,36 @@ class NewGameMenu(Menu): body = Frame(self.frame, **STYLES["body"]) body.grid(row=1, column=0, sticky=NSEW) + # Side Selection + side = LabelFrame(body, text="Player Side", **STYLES["label-frame"]) + side.grid(row=2, column=0, sticky=NW, padx=5) + Radiobutton(side, variable=self.selected_country, value=0, **STYLES["radiobutton"]).grid(row=0, column=0, + sticky=W) + Label(side, text="BLUEFOR", **STYLES["widget"]).grid(row=0, column=1, sticky=W) + Radiobutton(side, variable=self.selected_country, value=1, **STYLES["radiobutton"]).grid(row=1, column=0, + sticky=W) + Label(side, text="REDFOR", **STYLES["widget"]).grid(row=1, column=1, sticky=W) + # Country Selection - country = LabelFrame(body, text="Player Side", **STYLES["label-frame"]) - country.grid(row=0, column=0, sticky=NW, padx=5) - Radiobutton(country, variable=self.selected_country, value=0, **STYLES["radiobutton"]).grid(row=0, column=0, - sticky=W) - Label(country, text="USA 1965", **STYLES["widget"]).grid(row=0, column=1, sticky=W) - Radiobutton(country, variable=self.selected_country, value=1, **STYLES["radiobutton"]).grid(row=1, column=0, - sticky=W) - Label(country, text="Russia 1955", **STYLES["widget"]).grid(row=1, column=1, sticky=W) + + blues = [c for c in db.FACTIONS if db.FACTIONS[c]["side"] == "blue"] + reds = [c for c in db.FACTIONS if db.FACTIONS[c]["side"] == "red"] + + factions = LabelFrame(body, text="Factions", **STYLES["label-frame"]) + factions.grid(row=0, column=0, sticky=NW, padx=5) + + Label(factions, text="Blue Faction", **STYLES["widget"]).grid(row=1, column=0, sticky=SE) + + self.selected_blue_faction.set(blues[0]) + blue_select = OptionMenu(factions, self.selected_blue_faction, *blues) + blue_select.configure(**STYLES["btn-primary"]) + blue_select.grid(row=1, column=1, sticky=W) + + self.selected_red_faction.set(reds[1]) + Label(factions, text="Red Faction", **STYLES["widget"]).grid(row=2, column=0, sticky=W) + red_select = OptionMenu(factions, self.selected_red_faction, *reds) + red_select.configure(**STYLES["btn-primary"]) + red_select.grid(row=2, column=1, sticky=W) # Terrain Selection terrain = LabelFrame(body, text="Terrain", **STYLES["label-frame"]) diff --git a/ui/overviewcanvas.py b/ui/overviewcanvas.py index c1cdce07..01d305d4 100644 --- a/ui/overviewcanvas.py +++ b/ui/overviewcanvas.py @@ -367,6 +367,7 @@ class OverviewCanvas: if self.display_ground_targets.get(): for ground_object in cp.ground_objects: + pygame.draw.line(surface, RED, self._transform_point(cp.position), self._transform_point(ground_object.position), 1) self.draw_ground_object(ground_object, surface, cp.captured, mouse_pos) if self.display_bases.get(): diff --git a/ui/window.py b/ui/window.py index bed38fb8..bffd5cf1 100644 --- a/ui/window.py +++ b/ui/window.py @@ -89,8 +89,8 @@ class Window: def start_new_game(self, player_name: str, enemy_name: str, terrain: str, sams: bool, midgame: bool, multiplier: float, period:datetime): - player_country = db.UNIT_BY_COUNTRY[player_name]["country"] - enemy_country = db.UNIT_BY_COUNTRY[enemy_name]["country"] + player_country = db.FACTIONS[player_name]["country"] + enemy_country = db.FACTIONS[enemy_name]["country"] if terrain == "persiangulf": conflicttheater = persiangulf.PersianGulfTheater()