diff --git a/changelog.md b/changelog.md index 606f6ff2..093156bf 100644 --- a/changelog.md +++ b/changelog.md @@ -20,7 +20,7 @@ * **[Mission Generator]** Carrier will sail into the wind, not in the same direction * **[Mission Generator]** Carrier cold start was not working (flight was starting warm even when cold was selected) * **[Mission Generator]** Carrier group ships are more spread out -* **[Mission Generator]** Fixed radio frequency for german WW2 warbirds +* **[Mission Generator]** Fixed wrong radio frequency for german WW2 warbirds * **[Mission Generator]** Fixed FW-190A8 spawning with bomb rack for CAP missions * **[Mission Generator]** Fixed A-20G spawning with no payload * **[Mission Generator]** Fixed Su-33 spawning too heavy to take off from carrier diff --git a/game/db.py b/game/db.py index bd066198..50173a1d 100644 --- a/game/db.py +++ b/game/db.py @@ -18,7 +18,7 @@ from game.factions.bluefor_coldwar import BLUEFOR_COLDWAR from game.factions.bluefor_coldwar_a4 import BLUEFOR_COLDWAR_A4 from game.factions.bluefor_coldwar_mods import BLUEFOR_COLDWAR_MODS from game.factions.canada_2005 import Canada_2005 -from game.factions.china_2000 import China_2000 +from game.factions.china_2010 import China_2010 from game.factions.france_1995 import France_1995 from game.factions.france_2005 import France_2005 from game.factions.france_modded import France_2005_Modded @@ -759,7 +759,7 @@ FACTIONS = { "Israel 2000": Israel_2000, - "China 2000": China_2000, + "China 2010": China_2010, "Sweden 1990": Sweden_1990, diff --git a/game/factions/china_2000.py b/game/factions/china_2010.py similarity index 82% rename from game/factions/china_2000.py rename to game/factions/china_2010.py index cb3b0a7c..88763281 100644 --- a/game/factions/china_2000.py +++ b/game/factions/china_2010.py @@ -3,7 +3,7 @@ from dcs.planes import * from dcs.ships import * from dcs.vehicles import * -China_2000 = { +China_2010 = { "country": "China", "side": "red", "units": [ @@ -58,10 +58,20 @@ China_2000 = { Type_052C_Destroyer ], "cruiser": [ Type_054A_Frigate, + ], "helicopter_carrier": [ + Type_071_Amphibious_Transport_Dock, + ], "lhanames": [ + "Kunlun Shan", + "Jinggang Shan", + "Changbai Shan", + "Yimeng Shan", + "Longhu Shan", + "Wuzhi Shan", + "Wudang Shan" ], "carrier_names": [ "001 Liaoning", "002 Shandong", ], "boat":[ - "ChineseNavyGroupGenerator", "Type54GroupGenerator" + "Type54GroupGenerator" ] } \ No newline at end of file diff --git a/game/game.py b/game/game.py index df42fe2e..d0e846d2 100644 --- a/game/game.py +++ b/game/game.py @@ -56,8 +56,8 @@ class Game: current_unit_id = 0 current_group_id = 0 - def __init__(self, player_name: str, enemy_name: str, theater: ConflictTheater, start_date: datetime): - self.settings = Settings() + def __init__(self, player_name: str, enemy_name: str, theater: ConflictTheater, start_date: datetime, settings): + self.settings = settings self.events = [] self.theater = theater self.player_name = player_name diff --git a/game/settings.py b/game/settings.py index 4ec598ed..263bfc06 100644 --- a/game/settings.py +++ b/game/settings.py @@ -1,33 +1,41 @@ class Settings: - # Difficulty settings - player_skill = "Good" - enemy_skill = "Average" - enemy_vehicle_skill = "Average" - map_coalition_visibility = "All Units" - labels = "Full" - only_player_takeoff = True # Legacy parameter do not use - night_disabled = False - external_views_allowed = True - supercarrier = False - multiplier = 1 - generate_marks = True - sams = True # Legacy parameter do not use - cold_start = False # Legacy parameter do not use - version = None + def __init__(self): + # Generator settings + self.inverted = False + self.do_not_generate_carrier = False # TODO : implement + self.do_not_generate_lha = False # TODO : implement + self.do_not_generate_player_navy = True # TODO : implement + self.do_not_generate_enemy_navy = True # TODO : implement - # Performance oriented - perf_red_alert_state = True - perf_smoke_gen = True - perf_artillery = True - perf_moving_units = True - perf_infantry = True - perf_ai_parking_start = True - perf_destroyed_units = True + # Difficulty settings + self.player_skill = "Good" + self.enemy_skill = "Average" + self.enemy_vehicle_skill = "Average" + self.map_coalition_visibility = "All Units" + self.labels = "Full" + self.only_player_takeoff = True # Legacy parameter do not use + self.night_disabled = False + self.external_views_allowed = True + self.supercarrier = False + self.multiplier = 1 + self.generate_marks = True + self.sams = True # Legacy parameter do not use + self.cold_start = False # Legacy parameter do not use + self.version = None - # Performance culling - perf_culling = False - perf_culling_distance = 100 + # Performance oriented + self.perf_red_alert_state = True + self.perf_smoke_gen = True + self.perf_artillery = True + self.perf_moving_units = True + self.perf_infantry = True + self.perf_ai_parking_start = True + self.perf_destroyed_units = True + + # Performance culling + self.perf_culling = False + self.perf_culling_distance = 100 diff --git a/gen/aircraft.py b/gen/aircraft.py index 8ee9ddb9..695e5fa4 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -303,7 +303,7 @@ class AircraftConflictGenerator: def setup_interceptor_triggers(self, group, flight, activation_trigger): - detection_zone = self.m.triggers.add_triggerzone(flight.from_cp.position, radius=200000, hidden=False, name="ITZ") + detection_zone = self.m.triggers.add_triggerzone(flight.from_cp.position, radius=25000, hidden=False, name="ITZ") if flight.from_cp.captured: activation_trigger.add_condition(PartOfCoalitionInZone(self.game.get_enemy_color(), detection_zone.id)) # TODO : support unit type in part of coalition activation_trigger.add_action(MessageToAll(String("WARNING : Enemy aircrafts have been detected in the vicinity of " + flight.from_cp.name + ". Interceptors are taking off."), 20)) diff --git a/qt_ui/windows/QNewGameWizard.py b/qt_ui/windows/QNewGameWizard.py index 9b5291f7..13eedaf5 100644 --- a/qt_ui/windows/QNewGameWizard.py +++ b/qt_ui/windows/QNewGameWizard.py @@ -3,10 +3,12 @@ from __future__ import unicode_literals import datetime from PySide2 import QtGui, QtWidgets +from PySide2.QtWidgets import QHBoxLayout, QVBoxLayout from dcs.task import CAP, CAS import qt_ui.uiconstants as CONST from game import db, Game +from game.settings import Settings from gen import namegen from theater import start_generator, persiangulf, nevada, caucasus, ConflictTheater, normandy, thechannel @@ -46,6 +48,12 @@ class NewGameWizard(QtWidgets.QWizard): timePeriod = db.TIME_PERIODS[list(db.TIME_PERIODS.keys())[self.field("timePeriod")]] midGame = self.field("midGame") multiplier = self.field("multiplier") + no_carrier = self.field("no_carrier") + no_lha = self.field("no_lha") + supercarrier = self.field("supercarrier") + no_player_navy = self.field("no_player_navy") + no_enemy_navy = self.field("no_enemy_navy") + invertMap = self.field("invertMap") player_name = blueFaction enemy_name = redFaction @@ -75,20 +83,25 @@ class NewGameWizard(QtWidgets.QWizard): else: conflicttheater = caucasus.CaucasusTheater() + settings = Settings() + settings.inverted = invertMap + settings.supercarrier = supercarrier + settings.do_not_generate_carrier = no_carrier + settings.do_not_generate_lha = no_lha + settings.do_not_generate_player_navy = no_player_navy + settings.do_not_generate_enemy_navy = no_enemy_navy + self.generatedGame = self.start_new_game(player_name, enemy_name, conflicttheater, midGame, multiplier, - timePeriod) + timePeriod, settings) super(NewGameWizard, self).accept() def start_new_game(self, player_name: str, enemy_name: str, conflicttheater: ConflictTheater, - midgame: bool, multiplier: float, period: datetime): - - if midgame: - for i in range(0, int(len(conflicttheater.controlpoints) / 2)): - conflicttheater.controlpoints[i].captured = True + midgame: bool, multiplier: float, period: datetime, settings:Settings): # Reset name generator namegen.reset() + start_generator.prepare_theater(conflicttheater, settings, midgame) print("-- Starting New Game Generator") print("Enemy name : " + enemy_name) @@ -100,7 +113,8 @@ class NewGameWizard(QtWidgets.QWizard): game = Game(player_name=player_name, enemy_name=enemy_name, theater=conflicttheater, - start_date=period) + start_date=period, + settings=settings) print("-- Game Object generated") start_generator.generate_groundobjects(conflicttheater, game) @@ -240,9 +254,6 @@ class FactionSelection(QtWidgets.QWizardPage): self.requiredMods.setText(self.requiredMods.text() + "
  • None
  • \n") - - - class TheaterConfiguration(QtWidgets.QWizardPage): def __init__(self, parent=None): super(TheaterConfiguration, self).__init__(parent) @@ -281,6 +292,15 @@ class TheaterConfiguration(QtWidgets.QWizardPage): terrainChannelComplete.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Channel"])) terrainCaucasusSmall.setChecked(True) + # Campaign settings + mapSettingsGroup = QtWidgets.QGroupBox("Map Settings") + invertMap = QtWidgets.QCheckBox() + self.registerField('invertMap', invertMap) + mapSettingsLayout = QtWidgets.QGridLayout() + mapSettingsLayout.addWidget(QtWidgets.QLabel("Invert Map"), 1, 0) + mapSettingsLayout.addWidget(invertMap, 1, 1) + mapSettingsGroup.setLayout(mapSettingsLayout) + # Time Period timeGroup = QtWidgets.QGroupBox("Time Period") timePeriod = QtWidgets.QLabel("Start date :") @@ -329,6 +349,7 @@ class TheaterConfiguration(QtWidgets.QWizardPage): layout = QtWidgets.QGridLayout() layout.setColumnMinimumWidth(0, 20) layout.addWidget(terrainGroup) + layout.addWidget(mapSettingsGroup) layout.addWidget(timeGroup) self.setLayout(layout) @@ -348,15 +369,47 @@ class MiscOptions(QtWidgets.QWizardPage): multiplier.setMinimum(1) multiplier.setMaximum(5) + miscSettingsGroup = QtWidgets.QGroupBox("Misc Settings") self.registerField('midGame', midGame) self.registerField('multiplier', multiplier) + # Campaign settings + generatorSettingsGroup = QtWidgets.QGroupBox("Generator Settings") + no_carrier = QtWidgets.QCheckBox() + self.registerField('no_carrier', no_carrier) + no_lha = QtWidgets.QCheckBox() + self.registerField('no_lha', no_lha) + supercarrier = QtWidgets.QCheckBox() + self.registerField('supercarrier', supercarrier) + no_player_navy= QtWidgets.QCheckBox() + self.registerField('no_player_navy', no_player_navy) + no_enemy_navy = QtWidgets.QCheckBox() + self.registerField('no_enemy_navy', no_enemy_navy) + + generatorLayout = QtWidgets.QGridLayout() + generatorLayout.addWidget(QtWidgets.QLabel("No Aircraft Carriers"), 1, 0) + generatorLayout.addWidget(no_carrier, 1, 1) + generatorLayout.addWidget(QtWidgets.QLabel("No LHA"), 2, 0) + generatorLayout.addWidget(no_lha, 2, 1) + generatorLayout.addWidget(QtWidgets.QLabel("Use Supercarrier module"), 3, 0) + generatorLayout.addWidget(supercarrier, 3, 1) + generatorLayout.addWidget(QtWidgets.QLabel("No Player Navy"), 4, 0) + generatorLayout.addWidget(no_player_navy, 4, 1) + generatorLayout.addWidget(QtWidgets.QLabel("No Enemy Navy"), 5, 0) + generatorLayout.addWidget(no_enemy_navy, 5, 1) + generatorSettingsGroup.setLayout(generatorLayout) + layout = QtWidgets.QGridLayout() layout.addWidget(QtWidgets.QLabel("Start at mid game"), 1, 0) layout.addWidget(midGame, 1, 1) layout.addWidget(QtWidgets.QLabel("Ennemy forces multiplier [Disabled for Now]"), 2, 0) layout.addWidget(multiplier, 2, 1) - self.setLayout(layout) + miscSettingsGroup.setLayout(layout) + + mlayout = QVBoxLayout() + mlayout.addWidget(miscSettingsGroup) + mlayout.addWidget(generatorSettingsGroup) + self.setLayout(mlayout) class ConclusionPage(QtWidgets.QWizardPage): diff --git a/theater/caucasus.py b/theater/caucasus.py index ebc4e781..8c46d5d3 100644 --- a/theater/caucasus.py +++ b/theater/caucasus.py @@ -1,11 +1,8 @@ -import re - -from dcs.terrain import caucasus from dcs import mapping +from dcs.terrain import caucasus -from .landmap import * from .conflicttheater import * -from .base import * +from .landmap import * class CaucasusTheater(ConflictTheater): @@ -63,15 +60,17 @@ class CaucasusTheater(ConflictTheater): self.add_controlpoint(self.gudauta, connected_to=[self.sochi, self.sukhumi]) self.add_controlpoint(self.sochi, connected_to=[self.gudauta, self.gelendzhik]) - self.add_controlpoint(self.gelendzhik, connected_to=[self.sochi, ]) - self.add_controlpoint(self.krymsk, connected_to=[self.anapa, self.krasnodar]) + self.add_controlpoint(self.gelendzhik, connected_to=[self.sochi, self.krymsk]) + self.add_controlpoint(self.krymsk, connected_to=[self.anapa, self.krasnodar, self.gelendzhik]) self.add_controlpoint(self.anapa, connected_to=[self.krymsk]) self.add_controlpoint(self.krasnodar, connected_to=[self.krymsk, self.maykop]) self.add_controlpoint(self.carrier_1) self.carrier_1.captured = True + self.carrier_1.captured_invert = True self.batumi.captured = True + self.anapa.captured_invert = True """ @@ -113,7 +112,9 @@ class WesternGeorgia(ConflictTheater): self.add_controlpoint(self.carrier_1) self.carrier_1.captured = True + self.carrier_1.captured_invert = True self.kobuleti.captured = True + self.sochi.captured_invert = True """ @@ -158,8 +159,6 @@ class WesternGeorgiaInverted(ConflictTheater): self.sochi.captured = True - - class NorthCaucasus(ConflictTheater): terrain = caucasus.Caucasus() overview_image = "caumap.gif" @@ -203,3 +202,7 @@ class NorthCaucasus(ConflictTheater): self.carrier_1.captured = True self.vaziani.captured = True self.kutaisi.captured = True + + self.carrier_1.captured_invert = True + self.maykop.captured_invert = True + self.mineralnye.captured_invert = True diff --git a/theater/controlpoint.py b/theater/controlpoint.py index f8d4380f..49da85b4 100644 --- a/theater/controlpoint.py +++ b/theater/controlpoint.py @@ -4,7 +4,7 @@ from enum import Enum from dcs.mapping import * from dcs.terrain import Airport -from dcs.ships import CVN_74_John_C__Stennis, LHA_1_Tarawa, CV_1143_5_Admiral_Kuznetsov +from dcs.ships import CVN_74_John_C__Stennis, LHA_1_Tarawa, CV_1143_5_Admiral_Kuznetsov, Type_071_Amphibious_Transport_Dock from game import db from gen.ground_forces.combat_stance import CombatStance @@ -55,6 +55,7 @@ class ControlPoint: self.size = size self.importance = importance self.captured = False + self.captured_invert = False self.has_frontline = has_frontline self.radials = radials self.connected_points = [] @@ -148,7 +149,7 @@ class ControlPoint: if g.dcs_identifier in ["CARRIER", "LHA"]: for group in g.groups: for u in group.units: - if db.unit_type_from_name(u.type) in [CVN_74_John_C__Stennis, LHA_1_Tarawa, CV_1143_5_Admiral_Kuznetsov]: + if db.unit_type_from_name(u.type) in [CVN_74_John_C__Stennis, LHA_1_Tarawa, CV_1143_5_Admiral_Kuznetsov, Type_071_Amphibious_Transport_Dock]: return True return False elif self.cptype in [ControlPointType.AIRBASE, ControlPointType.FARP]: diff --git a/theater/nevada.py b/theater/nevada.py index cfc440ad..8f970458 100644 --- a/theater/nevada.py +++ b/theater/nevada.py @@ -46,4 +46,5 @@ class NevadaTheater(ConflictTheater): self.add_controlpoint(self.mesquite, connected_to=[self.lincoln_conty, self.groom_lake, self.creech]) self.tonopah.captured = True + self.mesquite.captured_invert = True diff --git a/theater/normandy.py b/theater/normandy.py index 5364db4b..dd67e9a6 100644 --- a/theater/normandy.py +++ b/theater/normandy.py @@ -44,6 +44,8 @@ class NormandyTheater(ConflictTheater): self.chailey.captured = True self.needOarPoint.captured = True + self.evreux.captured_invert = True + class NormandySmall(ConflictTheater): terrain = dcs.terrain.Normandy() @@ -77,3 +79,5 @@ class NormandySmall(ConflictTheater): self.deuxjumeaux.captured = True self.needOarPoint.captured = True + + self.evreux.captured_invert = True diff --git a/theater/persiangulf.py b/theater/persiangulf.py index 4f05b051..6826369b 100644 --- a/theater/persiangulf.py +++ b/theater/persiangulf.py @@ -84,6 +84,10 @@ class PersianGulfTheater(ConflictTheater): self.east_carrier.captured = True self.liwa.captured = True + self.west_carrier.captured_invert = True + self.east_carrier.captured_invert = True + self.shiraz.captured_invert = True + class IranianCampaign(ConflictTheater): @@ -154,6 +158,8 @@ class IranianCampaign(ConflictTheater): self.havadarya.captured = True self.bandar_abbas.captured = True + self.shiraz.captured_invert = True + class Emirates(ConflictTheater): terrain = dcs.terrain.PersianGulf() @@ -199,3 +205,7 @@ class Emirates(ConflictTheater): self.tarawa_carrier.captured = True self.east_carrier.captured = True self.fujairah.captured = True + + self.tarawa_carrier.captured_invert = True + self.east_carrier.captured_invert = True + self.fujairah.captured_invert = True diff --git a/theater/start_generator.py b/theater/start_generator.py index 977bea8f..670be6b3 100644 --- a/theater/start_generator.py +++ b/theater/start_generator.py @@ -5,6 +5,7 @@ import typing import logging from game.data.building_data import DEFAULT_AVAILABLE_BUILDINGS +from game.settings import Settings from gen import namegen, TheaterGroundObject from gen.defenses.armor_group_generator import generate_armor_group from gen.fleet.ship_group_generator import generate_carrier_group, generate_lha_group, generate_ship_group @@ -153,8 +154,15 @@ def generate_groundobjects(theater: ConflictTheater, game): for ground_object in cp.ground_objects: logging.info(ground_object.groups) + # Generate navy groups if "boat" in db.FACTIONS[faction_name].keys(): + if cp.captured and game.settings.do_not_generate_player_navy: + continue + + if not cp.captured and game.settings.do_not_generate_enemy_navy: + continue + boat_count = 1 if "boat_count" in db.FACTIONS[faction_name].keys(): boat_count = int(db.FACTIONS[faction_name]["boat_count"]) @@ -378,3 +386,37 @@ def generate_cp_ground_points(cp: ControlPoint, theater, game, group_id, templat cp.ground_objects.append(g) return group_id + + +def prepare_theater(theater: ConflictTheater, settings:Settings, midgame): + + to_remove = [] + + # autocapture half the base if midgame + if midgame: + for i in range(0, int(len(theater.controlpoints) / 2)): + theater.controlpoints[i].captured = True + + # Remove carrier and lha, invert situation if needed + for cp in theater.controlpoints: + if cp.cptype is ControlPointType.AIRCRAFT_CARRIER_GROUP and settings.do_not_generate_carrier: + to_remove.append(cp) + elif cp.cptype is ControlPointType.LHA_GROUP and settings.do_not_generate_lha: + to_remove.append(cp) + + if settings.inverted: + cp.captured = cp.captured_invert + + # do remove + for cp in to_remove: + theater.controlpoints.remove(cp) + + # reapply midgame inverted if needed + if midgame and settings.inverted: + for i, cp in enumerate(reversed(theater.controlpoints)): + if i > len(theater.controlpoints): + break + else: + cp.captured = True + + diff --git a/theater/thechannel.py b/theater/thechannel.py index 97132d20..18b1a617 100644 --- a/theater/thechannel.py +++ b/theater/thechannel.py @@ -50,6 +50,12 @@ class ChannelTheater(ConflictTheater): self.lympne.captured = True self.manston.captured = True + self.manston.captured_invert = True + self.dunkirk.captured_invert = True + self.stomer.captured_invert = True + self.merville.captured_invert = True + self.abeville.captured_invert = True + class ChannelTheaterComplete(ConflictTheater): terrain = dcs.terrain.TheChannel() @@ -95,4 +101,9 @@ class ChannelTheaterComplete(ConflictTheater): #self.dunkirk.captured = True self.highhalden.captured = True self.lympne.captured = True - self.manston.captured = True \ No newline at end of file + self.manston.captured = True + + self.dunkirk.captured_invert = True + self.stomer.captured_invert = True + self.merville.captured_invert = True + self.abeville.captured_invert = True