Channel map support.

This commit is contained in:
Khopa 2020-06-12 19:10:58 +02:00
parent c708abafc8
commit 601375d06f
16 changed files with 304 additions and 79 deletions

View File

@ -3,7 +3,10 @@
##Features/Improvements :
* **[Units/Factions]** Added P-47D-30 for factions allies_1944
* **[Campaign/Map]** Added support for The Channel map [TODO]
* **[Campaign/Map]** Added a campaign in the Channel map
* **[Campaign/Map]** Changed the Normandy campaign map
* **[Campaign/Map]** Added new campaign Normandy Small
* **[Mission Generator]** AI Flight generator has been reworked
* **[Mission Generator]** Add PP points for JF-17 on STRIKE missions
@ -18,34 +21,40 @@
* **[Flight Planner]** Added SEAD mission generator
* **[Flight Planner]** Added STRIKE mission generator
* **[Flight Planner]** Added buttons to add autogenerated waypoints (ASCEND, DESCEND, RTB)
* **[Flight Planner]** Improved waypoint list [TODO]
* **[Flight Planner]** Improved waypoint list
* **[Settings]** Added settings to disallow external views
* **[Settings]** Added settings to choose F10 Map mode (All, Allies only, Player only, Fog of War, Map Only)
* **[Settings]** Added settings to choose whether to auto-generate objective marks on the map
* **[Settings]** Added settings to choose whether to auto-generate objective marks on the F10 map
* **[Info Panel]** Added information about destroyed buildings in info panel
* **[Info Panel]** Added information about destroyed units at SAM site in info panel
* **[Debriefing]** Added information about units destroyed outside the frontline in the debriefing window
* **[Debriefing]** Added information about buildings destroyed in the debriefing window
* **[Debriefing]** Added destroyed buildings in the debriefing window
* **[Map]** Tooltip now contains the list of building for Strike targets on the map
* **[Map]** Added "Oil derrick" building
* **[Map]** Added "ww2 bunker" building (WW2)
* **[Map]** Added "ally camp" building (WW2)
* **[Misc]** Made it possible to setup DCS Saved Games directory and DCS installation directory manually at first start
##Fixed issues :
* **[Units/Factions]** Replaced S3-B Tanker by KC130 for most factions (More fuel)
* **[Units/Factions]** WW2 factions will not have offshore oil station and other modern buildings generated. No more third-reich operated offshore stations will spawn on normandy's coast.
* **[Mission Generator]** When playing as RED the activation trigger would not be properly generated
* **[Mission Generator]** FW-190A8 is now properly considered as a flyable aircraft
* **[Mission Generator]** Changed "strike" payload for Su-24M that was innefective
* **[Mission Generator]** Changed "strike" payload for JF-17 to use LS-6 bombs instead of GBU
* **[Mission Generator]** Change power station template. (Buildings could end up superposed).
* **[Maps/Campaign]** Now using Vasiani airbase instead of Soganlung airport in North Caucasus campaign (More parking slots)
* **[Info Panel]** Message displayed on base capture event stated that the ennemy captured an airbase, while it was the player who captured it.
* **[Map View]** Graphical glitch on map when one building of an objective was destroyed, but not the others
* **[Map View]**

View File

@ -13,9 +13,11 @@ from dcs.unit import *
from dcs.unittype import *
from dcs.unitgroup import *
from game.factions.bluefor_coldwar import BLUEFOR_COLDWAR
from game.factions.china_2000 import China_2000
from game.factions.france_1995 import France_1995
from game.factions.france_2005 import France_2005
from game.factions.germany_1944_easy import Germany_1944_Easy
from game.factions.germany_1990 import Germany_1990
from game.factions.insurgent import Insurgent
from game.factions.iran_2015 import Iran_2015
@ -609,14 +611,18 @@ FACTIONS = {
"China 2000": China_2000,
"North Korea 2000": NorthKorea_2000,
"Insurgent": Insurgent,
"Germany 1944 (WW2 Pack)": Germany_1944,
"Germany 1944 Easy (WW2 Pack)": Germany_1944_Easy,
"Bluefor Modern": BLUEFOR_MODERN,
"Bluefor Cold War 1970s": BLUEFOR_COLDWAR,
"USA 2005": USA_2005,
"USA 1990": USA_1990,
"USA 1965": USA_1965,
"USA 1960": USA_1960,
"USA 1955 (Require WW2 Pack)": USA_1955,
"Allies 1944 (Require WW2 Pack)": USA_1944,
"Bluefor Modern": BLUEFOR_MODERN,
"USA 1955 (WW2 Pack)": USA_1955,
"Allies 1944 (WW2 Pack)": USA_1944,
"France 2005": France_2005,
"France 1995": France_1995,
"Germany 1990": Germany_1990,
@ -631,7 +637,7 @@ FACTIONS = {
"Israel 2000": Israel_2000,
"Turkey 2005": Turkey_2005,
"United Arab Emirates 2005": UAE_2005,
"Germany 1944 (Require WW2 Pack)": Germany_1944
}
BLUEFOR_FACTIONS = [FACTIONS[f]["country"] for f in FACTIONS if FACTIONS[f]["side"] == "blue"]
print(BLUEFOR_FACTIONS)

View File

@ -0,0 +1,61 @@
from dcs.vehicles import *
from dcs.ships import *
from dcs.planes import *
from dcs.helicopters import *
BLUEFOR_COLDWAR = {
"country": "USA",
"side": "blue",
"units": [
F_14B,
F_4E,
F_5E_3,
A_10A,
AJS37,
KC_135,
KC130,
C_130,
E_3A,
UH_1H,
SA342M,
SA342L,
Armor.MBT_M60A3_Patton,
Armor.APC_M113,
Unarmed.Transport_M818,
Infantry.Infantry_M4,
Infantry.Soldier_M249,
AirDefence.SAM_Hawk_PCP,
AirDefence.SAM_Chaparral_M48,
CVN_74_John_C__Stennis,
LHA_1_Tarawa,
Armed_speedboat,
], "shorad": [
AirDefence.AAA_Vulcan_M163,
], "aircraft_carrier": [
CVN_74_John_C__Stennis,
], "helicopter_carrier": [
LHA_1_Tarawa,
], "destroyer": [
Oliver_Hazzard_Perry_class,
], "cruiser": [
Ticonderoga_class,
], "carrier_names": [
"CVN-71 Theodore Roosevelt",
"CVN-72 Abraham Lincoln",
"CVN-73 George Washington",
"CVN-74 John C. Stennis",
], "lhanames": [
"LHA-1 Tarawa",
"LHA-2 Saipan",
"LHA-3 Belleau Wood",
"LHA-4 Nassau",
"LHA-5 Peleliu"
]
}

View File

@ -31,6 +31,8 @@ BLUEFOR_MODERN = {
UH_1H,
AH_64D,
Ka_50,
SA342M,
SA342L,
Armor.MBT_M1A2_Abrams,
Armor.MBT_Leopard_2,

View File

@ -0,0 +1,35 @@
from dcs.planes import *
from dcs.vehicles import *
from game.data.building_data import WW2_GERMANY_BUILDINGS
Germany_1944_Easy = {
"country": "Third Reich",
"side": "red",
"units": [
FW_190A8,
FW_190D9,
Bf_109K_4,
Ju_88A4,
Armor.MT_Pz_Kpfw_IV_Ausf_H,
Armor.APC_Sd_Kfz_251,
Armor.IFV_Sd_Kfz_234_2_Puma,
Artillery.Sturmpanzer_IV_Brummbär,
Unarmed.Sd_Kfz_2,
Unarmed.Sd_Kfz_7,
Unarmed.Kübelwagen_82,
Infantry.Infantry_Mauser_98,
AirDefence.AAA_8_8cm_Flak_36,
],
"shorad":[
AirDefence.AAA_8_8cm_Flak_36,
],
"objects": WW2_GERMANY_BUILDINGS,
"doctrine": {
# TODO
}
}

View File

@ -144,7 +144,7 @@ class Game:
self.events.remove(event)
def initiate_event(self, event: Event):
assert event in self.events
#assert event in self.events
logging.info("Generating {} (regular)".format(event))
event.generate()

View File

@ -54,6 +54,7 @@ def load_icons():
ICONS["Terrain_Persian_Gulf"] = QPixmap("./resources/ui/terrain_pg.gif")
ICONS["Terrain_Nevada"] = QPixmap("./resources/ui/terrain_nevada.gif")
ICONS["Terrain_Normandy"] = QPixmap("./resources/ui/terrain_normandy.gif")
ICONS["Terrain_Channel"] = QPixmap("./resources/ui/terrain_channel.gif")
ICONS["Dawn"] = QPixmap("./resources/ui/daytime/dawn.png")
ICONS["Day"] = QPixmap("./resources/ui/daytime/day.png")

View File

@ -1,6 +1,7 @@
import typing
from typing import Dict
from PySide2 import QtCore
from PySide2.QtCore import Qt, QRect, QPointF
from PySide2.QtGui import QPixmap, QBrush, QColor, QWheelEvent, QPen, QFont
from PySide2.QtWidgets import QGraphicsView, QFrame, QGraphicsOpacityEffect
@ -64,12 +65,60 @@ class QLiberationMap(QGraphicsView):
if self.game is not None:
self.reload_scene()
"""
Uncomment to set up theather reference points
def keyPressEvent(self, event):
#super(QLiberationMap, self).keyPressEvent(event)
numpad_mod = int(event.modifiers()) & QtCore.Qt.KeypadModifier
i = 0
for k,v in self.game.theater.reference_points.items():
if i == 0:
point_0 = k
else:
point_1 = k
i = i + 1
if event.key() == QtCore.Qt.Key_Down:
self.game.theater.reference_points[point_0] = self.game.theater.reference_points[point_0][0] + 100, self.game.theater.reference_points[point_0][1]
if event.key() == QtCore.Qt.Key_Up:
self.game.theater.reference_points[point_0] = self.game.theater.reference_points[point_0][0] - 100, self.game.theater.reference_points[point_0][1]
if event.key() == QtCore.Qt.Key_Left:
self.game.theater.reference_points[point_0] = self.game.theater.reference_points[point_0][0], self.game.theater.reference_points[point_0][1] + 100
if event.key() == QtCore.Qt.Key_Right:
self.game.theater.reference_points[point_0] = self.game.theater.reference_points[point_0][0], self.game.theater.reference_points[point_0][1] - 100
if event.key() == QtCore.Qt.Key_2 and numpad_mod:
self.game.theater.reference_points[point_1] = self.game.theater.reference_points[point_1][0] + 100, self.game.theater.reference_points[point_1][1]
if event.key() == QtCore.Qt.Key_8 and numpad_mod:
self.game.theater.reference_points[point_1] = self.game.theater.reference_points[point_1][0] - 100, self.game.theater.reference_points[point_1][1]
if event.key() == QtCore.Qt.Key_4 and numpad_mod:
self.game.theater.reference_points[point_1] = self.game.theater.reference_points[point_1][0], self.game.theater.reference_points[point_1][1] + 100
if event.key() == QtCore.Qt.Key_6 and numpad_mod:
self.game.theater.reference_points[point_1] = self.game.theater.reference_points[point_1][0], self.game.theater.reference_points[point_1][1] - 100
print(self.game.theater.reference_points)
self.reload_scene()
"""
def reload_scene(self):
scene = self.scene()
scene.clear()
self.addBackground()
#self.add_game_events()
# Uncomment below to help set up theater reference points
#for i, r in enumerate(self.game.theater.reference_points.items()):
# text = scene.addText(str(r), font=QFont("Trebuchet MS", 10, weight=5, italic=False))
# text.setPos(0, i * 24)
for cp in self.game.theater.controlpoints:
@ -252,56 +301,6 @@ class QLiberationMap(QGraphicsView):
return X > treshold and X or treshold, Y > treshold and Y or treshold
def add_game_events(self):
occupied_rects = []
for cp in self.game.theater.controlpoints:
point = self._transform_point(cp.position)
occupied_rects.append(QRect(point[0] - 16, point[1] - 16, 32, 48))
def _location_to_rect(location: Point) -> QRect:
nonlocal occupied_rects
point = self._transform_point(location)
rect = QRect(point[0] - 16, point[1] - 16, 32, 32)
i = 0
while True:
result = True
for occupied_rect in occupied_rects:
if rect.intersects(occupied_rect):
i += 1
if i % 2:
rect.setY(rect.y() + occupied_rect.height())
else:
rect.setX(rect.x() + occupied_rect.width())
result = False
break
if result:
break
occupied_rects.append(rect)
return rect
def _events_priority_key(event: Event) -> int:
priority_list = [InfantryTransportEvent, StrikeEvent, BaseAttackEvent, UnitsDeliveryEvent]
if type(event) not in priority_list:
return 0
else:
return priority_list.index(type(event)) + 1
scene = self.scene()
events = self.game.events
events.sort(key=_events_priority_key, reverse=True)
for event in events:
location = event.location
if type(event) in [FrontlineAttackEvent, FrontlinePatrolEvent, ConvoyStrikeEvent]:
location = self._frontline_center(event.from_cp, event.to_cp)
rect = _location_to_rect(location)
scene.addItem(QMapEvent(self, rect.x(), rect.y(), 32, 32, event))
def addBackground(self):
scene = self.scene()

View File

@ -8,7 +8,7 @@ from dcs.task import CAP, CAS
import qt_ui.uiconstants as CONST
from game import db, Game
from gen import namegen
from theater import start_generator, persiangulf, nevada, caucasus, ConflictTheater, normandy
from theater import start_generator, persiangulf, nevada, caucasus, ConflictTheater, normandy, thechannel
from userdata.logging import version_string
@ -41,6 +41,8 @@ class NewGameWizard(QtWidgets.QWizard):
isTerrainCaucasusNorth= self.field("isTerrainCaucasusNorth")
isIranianCampaignTheater = self.field("isIranianCampaignTheater")
isTerrainNormandy = self.field("isTerrainNormandy")
isTerrainNormandySmall = self.field("isTerrainNormandySmall")
isTerrainChannel = self.field("isTerrainChannel")
isTerrainEmirates = self.field("isTerrainEmirates")
timePeriod = db.TIME_PERIODS[list(db.TIME_PERIODS.keys())[self.field("timePeriod")]]
midGame = self.field("midGame")
@ -65,6 +67,10 @@ class NewGameWizard(QtWidgets.QWizard):
conflicttheater = persiangulf.Emirates()
elif isTerrainNormandy:
conflicttheater = normandy.NormandyTheater()
elif isTerrainNormandySmall:
conflicttheater = normandy.NormandySmall()
elif isTerrainChannel:
conflicttheater = thechannel.ChannelTheater()
else:
conflicttheater = caucasus.CaucasusTheater()
@ -238,8 +244,12 @@ class TheaterConfiguration(QtWidgets.QWizardPage):
terrainEmirates.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Persian_Gulf"]))
terrainNttr = QtWidgets.QRadioButton("Nevada - North Nevada [RECOMMENDED]")
terrainNttr.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Nevada"]))
terrainNormandy = QtWidgets.QRadioButton("Normandy [Alpha]")
terrainNormandy = QtWidgets.QRadioButton("Normandy")
terrainNormandy.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Normandy"]))
terrainNormandySmall = QtWidgets.QRadioButton("Normandy Small")
terrainNormandySmall.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Normandy"]))
terrainChannel = QtWidgets.QRadioButton("Channel")
terrainChannel.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Channel"]))
terrainCaucasusSmall.setChecked(True)
# Time Period
@ -261,6 +271,8 @@ class TheaterConfiguration(QtWidgets.QWizardPage):
self.registerField('isTerrainEmirates', terrainEmirates)
self.registerField('isTerrainNttr', terrainNttr)
self.registerField('isTerrainNormandy', terrainNormandy)
self.registerField('isTerrainNormandySmall', terrainNormandySmall)
self.registerField('isTerrainChannel', terrainChannel)
self.registerField('timePeriod', timePeriodSelect)
# Build layout
@ -274,6 +286,8 @@ class TheaterConfiguration(QtWidgets.QWizardPage):
terrainGroupLayout.addWidget(terrainPg)
terrainGroupLayout.addWidget(terrainNttr)
terrainGroupLayout.addWidget(terrainNormandy)
terrainGroupLayout.addWidget(terrainNormandySmall)
terrainGroupLayout.addWidget(terrainChannel)
terrainGroup.setLayout(terrainGroupLayout)
timeGroupLayout = QtWidgets.QGridLayout()

View File

@ -124,10 +124,14 @@ class QMissionPlanning(QDialog):
def on_start(self):
# TODO : refactor this nonsense
self.gameEvent = None
for event in self.game.events:
if isinstance(event, FrontlineAttackEvent) and event.is_player_attacking:
self.gameEvent = event
if self.gameEvent is None:
self.gameEvent = FrontlineAttackEvent(self.game, self.game.theater.controlpoints[0], self.game.theater.controlpoints[0],
self.game.theater.controlpoints[0].position, self.game.player_name, self.game.enemy_name)
#if self.awacs_checkbox.isChecked() == 1:
# self.gameEvent.is_awacs_enabled = True
# self.game.awacs_expense_commit()

BIN
resources/channellandmap.p Normal file

Binary file not shown.

Binary file not shown.

View File

@ -3,7 +3,7 @@ import pickle
from dcs.mission import Mission
from dcs.planes import A_10C
for terrain in ["cau", "gulf", "nev", "normandy"]:
for terrain in ["cau", "gulf", "nev", "channel"]:
print("Terrain " + terrain)
m = Mission()
m.load_file("./{}_terrain.miz".format(terrain))

Binary file not shown.

View File

@ -20,18 +20,60 @@ class NormandyTheater(ConflictTheater):
def __init__(self):
super(NormandyTheater, self).__init__()
self.st_pierre = ControlPoint.from_airport(normandy.Saint_Pierre_du_Mont, LAND, SIZE_REGULAR, IMPORTANCE_MEDIUM)
self.maupertus = ControlPoint.from_airport(normandy.Maupertus, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.azeville = ControlPoint.from_airport(normandy.Azeville, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.needOarPoint = ControlPoint.from_airport(normandy.Needs_Oar_Point, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.chailey = ControlPoint.from_airport(normandy.Chailey, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.deuxjumeaux = ControlPoint.from_airport(normandy.Deux_Jumeaux, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.lignerolles = ControlPoint.from_airport(normandy.Lignerolles, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.carpiquet = ControlPoint.from_airport(normandy.Carpiquet, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.lessay = ControlPoint.from_airport(normandy.Lessay, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.meautis = ControlPoint.from_airport(normandy.Meautis, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.chippelle = ControlPoint.from_airport(normandy.Chippelle, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.maupertus = ControlPoint.from_airport(normandy.Maupertus, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.evreux = ControlPoint.from_airport(normandy.Evreux, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.add_controlpoint(self.st_pierre, connected_to=[self.chippelle])
self.add_controlpoint(self.maupertus, connected_to=[self.azeville])
self.add_controlpoint(self.azeville, connected_to=[self.meautis, self.maupertus])
self.add_controlpoint(self.lessay, connected_to=[self.meautis])
self.add_controlpoint(self.meautis, connected_to=[self.chippelle, self.lessay, self.azeville])
self.add_controlpoint(self.chippelle, connected_to=[self.st_pierre, self.meautis])
self.add_controlpoint(self.chailey, connected_to=[self.needOarPoint])
self.add_controlpoint(self.needOarPoint, connected_to=[self.chailey])
self.st_pierre.captured = True
self.add_controlpoint(self.deuxjumeaux, connected_to=[self.lignerolles])
self.add_controlpoint(self.lignerolles, connected_to=[self.deuxjumeaux, self.lessay, self.carpiquet])
self.add_controlpoint(self.lessay, connected_to=[self.lignerolles, self.maupertus])
self.add_controlpoint(self.carpiquet, connected_to=[self.lignerolles, self.evreux])
self.add_controlpoint(self.maupertus, connected_to=[self.lessay])
self.add_controlpoint(self.evreux, connected_to=[self.carpiquet])
self.deuxjumeaux.captured = True
self.chailey.captured = True
self.needOarPoint.captured = True
class NormandySmall(ConflictTheater):
terrain = dcs.terrain.Normandy()
overview_image = "normandy.gif"
reference_points = {(normandy.Needs_Oar_Point.position.x, normandy.Needs_Oar_Point.position.y): (-170, -1000),
(normandy.Evreux.position.x, normandy.Evreux.position.y): (2020, 500)}
landmap = load_landmap("resources\\normandylandmap.p")
daytime_map = {
"dawn": (6, 8),
"day": (10, 17),
"dusk": (17, 18),
"night": (0, 5),
}
def __init__(self):
super(NormandySmall, self).__init__()
self.needOarPoint = ControlPoint.from_airport(normandy.Needs_Oar_Point, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.deuxjumeaux = ControlPoint.from_airport(normandy.Deux_Jumeaux, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.lignerolles = ControlPoint.from_airport(normandy.Lignerolles, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.carpiquet = ControlPoint.from_airport(normandy.Carpiquet, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.evreux = ControlPoint.from_airport(normandy.Evreux, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.add_controlpoint(self.needOarPoint, connected_to=[self.needOarPoint])
self.add_controlpoint(self.deuxjumeaux, connected_to=[self.lignerolles])
self.add_controlpoint(self.lignerolles, connected_to=[self.deuxjumeaux, self.carpiquet])
self.add_controlpoint(self.carpiquet, connected_to=[self.lignerolles, self.evreux])
self.add_controlpoint(self.evreux, connected_to=[self.carpiquet])
self.deuxjumeaux.captured = True
self.needOarPoint.captured = True

52
theater/thechannel.py Normal file
View File

@ -0,0 +1,52 @@
from dcs.terrain import thechannel
from .conflicttheater import *
from .landmap import *
class ChannelTheater(ConflictTheater):
terrain = dcs.terrain.TheChannel()
overview_image = "thechannel.gif"
reference_points = {(thechannel.Abbeville_Drucat.position.x, thechannel.Abbeville_Drucat.position.y): (2400, 4100),
(thechannel.Detling.position.x, thechannel.Detling.position.y): (1100, 2000)}
landmap = load_landmap("resources\\channellandmap.p")
daytime_map = {
"dawn": (6, 8),
"day": (10, 17),
"dusk": (17, 18),
"night": (0, 5),
}
def __init__(self):
super(ChannelTheater, self).__init__()
self.abeville = ControlPoint.from_airport(thechannel.Abbeville_Drucat, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.detling = ControlPoint.from_airport(thechannel.Detling, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.stomer = ControlPoint.from_airport(thechannel.Saint_Omer_Longuenesse, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.dunkirk = ControlPoint.from_airport(thechannel.Dunkirk_Mardyck, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.hawkinge = ControlPoint.from_airport(thechannel.Hawkinge, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.highhalden = ControlPoint.from_airport(thechannel.High_Halden, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.lympne = ControlPoint.from_airport(thechannel.Lympne, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.manston = ControlPoint.from_airport(thechannel.Manston, LAND, SIZE_SMALL, IMPORTANCE_LOW)
self.merville = ControlPoint.from_airport(thechannel.Merville_Calonne, LAND, SIZE_SMALL, IMPORTANCE_LOW)
# England
self.add_controlpoint(self.detling, connected_to=[self.highhalden])
self.add_controlpoint(self.hawkinge, connected_to=[self.lympne, self.manston])
self.add_controlpoint(self.highhalden, connected_to=[self.detling, self.lympne])
self.add_controlpoint(self.lympne, connected_to=[self.highhalden, self.hawkinge])
self.add_controlpoint(self.manston, connected_to=[self.hawkinge])
# France
self.add_controlpoint(self.dunkirk, connected_to=[self.stomer])
self.add_controlpoint(self.stomer, connected_to=[self.dunkirk, self.merville, self.abeville])
self.add_controlpoint(self.merville, connected_to=[self.stomer])
self.add_controlpoint(self.abeville, connected_to=[self.stomer])
self.detling.captured = True
self.hawkinge.captured = True
self.highhalden.captured = True
self.lympne.captured = True
self.manston.captured = True