mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
gulf & nevada maps integration; updates to commisioning/start generation units logic; mission gen updates; carriers always on map
This commit is contained in:
parent
56c9f97417
commit
92e5514e8d
14
__init__.py
14
__init__.py
@ -1,5 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
import theater.caucasus
|
||||
import theater.persiangulf
|
||||
import theater.nevada
|
||||
|
||||
import ui.window
|
||||
import ui.mainmenu
|
||||
import ui.newgamemenu
|
||||
@ -19,10 +22,15 @@ game = persistency.restore_game()
|
||||
if not game:
|
||||
new_game_menu = None # type: NewGameMenu
|
||||
|
||||
def start_new_game(player_name: str, enemy_name: str):
|
||||
conflicttheater = theater.caucasus.CaucasusTheater()
|
||||
start_generator.generate_initial(conflicttheater, enemy_name)
|
||||
def start_new_game(player_name: str, enemy_name: str, terrain: str):
|
||||
if terrain == "persiangulf":
|
||||
conflicttheater = theater.persiangulf.PersianGulfTheater()
|
||||
elif terrain == "nevada":
|
||||
conflicttheater = theater.nevada.NevadaTheater()
|
||||
else:
|
||||
conflicttheater = theater.caucasus.CaucasusTheater()
|
||||
|
||||
start_generator.generate_initial(conflicttheater, enemy_name)
|
||||
proceed_to_main_menu(Game(player_name=player_name,
|
||||
enemy_name=enemy_name,
|
||||
theater=conflicttheater))
|
||||
|
||||
207
game/db.py
207
game/db.py
@ -8,33 +8,46 @@ from dcs.task import *
|
||||
from dcs.unittype import *
|
||||
|
||||
PRICES = {
|
||||
# planes
|
||||
|
||||
Su_25T: 11,
|
||||
Su_25: 11,
|
||||
A_10A: 18,
|
||||
A_10C: 20,
|
||||
|
||||
FA_18C_hornet: 18,
|
||||
AV8BNA: 15,
|
||||
|
||||
# fighter
|
||||
C_101CC: 10,
|
||||
AJS37: 15,
|
||||
F_5E: 12,
|
||||
MiG_23MLD: 15,
|
||||
MiG_25PD: 20,
|
||||
MiG_31: 30,
|
||||
Su_27: 30,
|
||||
Su_33: 33,
|
||||
F_15C: 30,
|
||||
M_2000C: 11,
|
||||
|
||||
MiG_15bis: 8,
|
||||
MiG_21Bis: 13,
|
||||
MiG_29A: 23,
|
||||
FA_18C_hornet: 18,
|
||||
AV8BNA: 15,
|
||||
F_15C: 30,
|
||||
M_2000C: 15,
|
||||
|
||||
# bomber
|
||||
Su_25T: 15,
|
||||
Su_24M: 18,
|
||||
Su_17M4: 13,
|
||||
L_39ZA: 10,
|
||||
MiG_29G: 18,
|
||||
Su_34: 22,
|
||||
|
||||
A_10A: 18,
|
||||
A_10C: 20,
|
||||
|
||||
# special
|
||||
IL_76MD: 13,
|
||||
An_26B: 13,
|
||||
An_30M: 13,
|
||||
Yak_40: 13,
|
||||
S_3B_Tanker: 13,
|
||||
|
||||
A_50: 8,
|
||||
E_3A: 8,
|
||||
C_130: 8,
|
||||
|
||||
# armor
|
||||
|
||||
Armor.MBT_T_55: 4,
|
||||
Armor.MBT_T_80U: 8,
|
||||
Armor.MBT_T_90: 10,
|
||||
@ -45,49 +58,142 @@ PRICES = {
|
||||
Armor.ATGM_M1134_Stryker: 6,
|
||||
Armor.APC_BTR_80: 6,
|
||||
|
||||
AirDefence.AAA_ZU_23_on_Ural_375: 4,
|
||||
AirDefence.AAA_Vulcan_M163: 5,
|
||||
AirDefence.SAM_Avenger_M1097: 10,
|
||||
AirDefence.SAM_Patriot_ICC: 15,
|
||||
|
||||
AirDefence.AAA_ZU_23_on_Ural_375: 5,
|
||||
AirDefence.SAM_SA_18_Igla_MANPADS: 8,
|
||||
AirDefence.SAM_SA_19_Tunguska_2S6: 10,
|
||||
AirDefence.SAM_SA_8_Osa_9A33: 15,
|
||||
|
||||
# ship
|
||||
CV_1143_5_Admiral_Kuznetsov: 100,
|
||||
CVN_74_John_C__Stennis: 100,
|
||||
}
|
||||
|
||||
UNIT_BY_TASK = {
|
||||
FighterSweep: [Su_27, Su_33, FA_18C_hornet, F_15C, MiG_21Bis, MiG_29A, F_A_18C, AV8BNA, ],
|
||||
CAS: [Su_25T, A_10A, A_10C, ],
|
||||
Transport: [IL_76MD, S_3B_Tanker, ],
|
||||
FighterSweep: [
|
||||
C_101CC,
|
||||
AJS37,
|
||||
F_5E,
|
||||
MiG_23MLD,
|
||||
MiG_25PD,
|
||||
MiG_31,
|
||||
Su_27,
|
||||
Su_33,
|
||||
MiG_15bis,
|
||||
MiG_21Bis,
|
||||
MiG_29A,
|
||||
FA_18C_hornet,
|
||||
AV8BNA,
|
||||
F_15C,
|
||||
M_2000C,
|
||||
],
|
||||
CAS: [
|
||||
A_10A,
|
||||
A_10C,
|
||||
Su_25T,
|
||||
Su_24M,
|
||||
Su_17M4,
|
||||
L_39ZA,
|
||||
MiG_29G,
|
||||
Su_34,
|
||||
],
|
||||
|
||||
Transport: [
|
||||
IL_76MD,
|
||||
An_26B,
|
||||
An_30M,
|
||||
Yak_40,
|
||||
|
||||
S_3B_Tanker,
|
||||
C_130,
|
||||
],
|
||||
AWACS: [E_3A, A_50, ],
|
||||
|
||||
CAP: [Armor.MBT_T_90, Armor.MBT_T_80U, Armor.MBT_T_55, Armor.MBT_M1A2_Abrams, Armor.MBT_M60A3_Patton, Armor.ATGM_M1134_Stryker, Armor.APC_BTR_80, ],
|
||||
AirDefence: [AirDefence.AAA_ZU_23_on_Ural_375, AirDefence.SAM_Avenger_M1097 ],
|
||||
AirDefence: [
|
||||
AirDefence.AAA_Vulcan_M163,
|
||||
AirDefence.SAM_Avenger_M1097,
|
||||
AirDefence.SAM_Patriot_ICC,
|
||||
|
||||
AirDefence.AAA_ZU_23_on_Ural_375,
|
||||
AirDefence.SAM_SA_18_Igla_MANPADS,
|
||||
AirDefence.SAM_SA_19_Tunguska_2S6,
|
||||
AirDefence.SAM_SA_8_Osa_9A33,
|
||||
],
|
||||
Carriage: [CVN_74_John_C__Stennis, CV_1143_5_Admiral_Kuznetsov, ],
|
||||
}
|
||||
|
||||
UNIT_BY_COUNTRY = {
|
||||
"Russia": [
|
||||
Su_25T,
|
||||
C_101CC,
|
||||
AJS37,
|
||||
F_5E,
|
||||
MiG_23MLD,
|
||||
MiG_25PD,
|
||||
MiG_31,
|
||||
Su_27,
|
||||
Su_33,
|
||||
Su_25,
|
||||
MiG_15bis,
|
||||
MiG_21Bis,
|
||||
MiG_29A,
|
||||
M_2000C,
|
||||
|
||||
A_10A,
|
||||
A_10C,
|
||||
Su_25T,
|
||||
Su_24M,
|
||||
Su_17M4,
|
||||
L_39ZA,
|
||||
MiG_29G,
|
||||
Su_34,
|
||||
|
||||
IL_76MD,
|
||||
An_26B,
|
||||
An_30M,
|
||||
Yak_40,
|
||||
A_50,
|
||||
|
||||
AirDefence.AAA_ZU_23_on_Ural_375,
|
||||
AirDefence.SAM_SA_18_Igla_MANPADS,
|
||||
AirDefence.SAM_SA_19_Tunguska_2S6,
|
||||
AirDefence.SAM_SA_8_Osa_9A33,
|
||||
|
||||
Armor.APC_BTR_80,
|
||||
Armor.MBT_T_90,
|
||||
Armor.MBT_T_80U,
|
||||
Armor.MBT_T_55,
|
||||
IL_76MD,
|
||||
CV_1143_5_Admiral_Kuznetsov],
|
||||
|
||||
"USA": [F_15C,
|
||||
A_10C,
|
||||
FA_18C_hornet,
|
||||
AV8BNA,
|
||||
E_3A,
|
||||
Armor.MBT_M1A2_Abrams,
|
||||
Armor.MBT_M60A3_Patton,
|
||||
Armor.ATGM_M1134_Stryker,
|
||||
S_3B_Tanker,
|
||||
AirDefence.SAM_Avenger_M1097,
|
||||
CVN_74_John_C__Stennis],
|
||||
"USA": [
|
||||
F_15C,
|
||||
FA_18C_hornet,
|
||||
AV8BNA,
|
||||
AJS37,
|
||||
F_5E,
|
||||
M_2000C,
|
||||
MiG_21Bis,
|
||||
MiG_15bis,
|
||||
|
||||
A_10A,
|
||||
A_10C,
|
||||
|
||||
S_3B_Tanker,
|
||||
C_130,
|
||||
E_3A,
|
||||
|
||||
Armor.MBT_M1A2_Abrams,
|
||||
Armor.MBT_M60A3_Patton,
|
||||
Armor.ATGM_M1134_Stryker,
|
||||
|
||||
AirDefence.AAA_Vulcan_M163,
|
||||
AirDefence.SAM_Avenger_M1097,
|
||||
AirDefence.SAM_Patriot_ICC,
|
||||
|
||||
CVN_74_John_C__Stennis,
|
||||
],
|
||||
}
|
||||
|
||||
PLANE_PAYLOAD_OVERRIDES = {
|
||||
@ -132,3 +238,38 @@ def task_name(task) -> str:
|
||||
return "AirDefence"
|
||||
else:
|
||||
return task.name
|
||||
|
||||
|
||||
def choose_units(for_task: Task, factor: float, count: int, country: str) -> typing.Collection[UnitType]:
|
||||
suitable_unittypes = find_unittype(for_task, country)
|
||||
suitable_unittypes.sort(key=lambda x: PRICES[x])
|
||||
|
||||
idx = int(len(suitable_unittypes) * factor)
|
||||
variety = int(count + count * factor / 2)
|
||||
|
||||
index_start = min(idx, len(suitable_unittypes) - variety)
|
||||
index_end = min(idx + variety, len(suitable_unittypes))
|
||||
return suitable_unittypes[index_start:index_end]
|
||||
|
||||
|
||||
def _validate_db():
|
||||
# check unit by task uniquity
|
||||
total_set = set()
|
||||
for t, unit_collection in UNIT_BY_TASK.items():
|
||||
for unit_type in unit_collection:
|
||||
assert unit_type not in total_set, "{} is duplicate".format(unit_type)
|
||||
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():
|
||||
if unit_type in country_units_list:
|
||||
did_find = True
|
||||
assert did_find, "{} not in country list".format(unit_type)
|
||||
|
||||
# check prices
|
||||
for unit_type in total_set:
|
||||
assert unit_type in PRICES, "{} not in prices".format(unit_type)
|
||||
|
||||
_validate_db()
|
||||
@ -26,13 +26,13 @@ class Event:
|
||||
|
||||
def generate(self):
|
||||
self.operation.is_awacs_enabled = self.is_awacs_enabled
|
||||
self.operation.prepare(is_quick=False)
|
||||
self.operation.prepare(self.game.theater.terrain, is_quick=False)
|
||||
self.operation.generate()
|
||||
self.operation.mission.save("build/nextturn.miz")
|
||||
|
||||
def generate_quick(self):
|
||||
self.operation.is_awacs_enabled = self.is_awacs_enabled
|
||||
self.operation.prepare(is_quick=True)
|
||||
self.operation.prepare(self.game.theater.terrain, is_quick=True)
|
||||
self.operation.generate()
|
||||
self.operation.mission.save('build/nextturn_quick.miz')
|
||||
|
||||
@ -88,7 +88,7 @@ class GroundInterceptEvent(Event):
|
||||
else:
|
||||
pass
|
||||
|
||||
def player_attacking(self, position: Point, strikegroup: db.PlaneDict, clients: db.PlaneDict):
|
||||
def player_attacking(self, strikegroup: db.PlaneDict, clients: db.PlaneDict):
|
||||
suitable_unittypes = db.find_unittype(CAP, self.defender_name)
|
||||
random.shuffle(suitable_unittypes)
|
||||
unittypes = suitable_unittypes[:self.TARGET_VARIETY]
|
||||
@ -100,9 +100,9 @@ class GroundInterceptEvent(Event):
|
||||
defender_name=self.defender_name,
|
||||
attacker_clients=clients,
|
||||
defender_clients={},
|
||||
from_cp=self.from_cp)
|
||||
op.setup(position=position,
|
||||
target=self.targets,
|
||||
from_cp=self.from_cp,
|
||||
to_cp=self.to_cp)
|
||||
op.setup(target=self.targets,
|
||||
strikegroup=strikegroup)
|
||||
|
||||
self.operation = op
|
||||
|
||||
11
game/game.py
11
game/game.py
@ -9,6 +9,7 @@ COMMISION_LIMITS_FACTORS = {
|
||||
}
|
||||
|
||||
COMMISION_AMOUNTS_SCALE = 2
|
||||
COMMISION_UNIT_VARIETY = 4
|
||||
COMMISION_AMOUNTS_FACTORS = {
|
||||
CAP: 0.6,
|
||||
CAS: 0.3,
|
||||
@ -85,7 +86,6 @@ class Game:
|
||||
enemy_interception = True
|
||||
break
|
||||
|
||||
|
||||
if to_cp in self.theater.conflicts(False):
|
||||
continue
|
||||
|
||||
@ -120,8 +120,10 @@ class Game:
|
||||
break
|
||||
|
||||
def _generate_globalinterceptions(self):
|
||||
global_count = len([x for x in self.theater.player_points() if x.is_global])
|
||||
for from_cp in [x for x in self.theater.player_points() if x.is_global]:
|
||||
probability = PLAYER_INTERCEPT_GLOBAL_PROBABILITY_BASE * math.log(len(self.theater.player_points()) + 1, PLAYER_INTERCEPT_GLOBAL_PROBABILITY_LOG)
|
||||
probability_base = max(PLAYER_INTERCEPT_GLOBAL_PROBABILITY_BASE / global_count, 1)
|
||||
probability = probability_base * math.log(len(self.theater.player_points()) + 1, PLAYER_INTERCEPT_GLOBAL_PROBABILITY_LOG)
|
||||
if self._roll(probability, from_cp.base.strength):
|
||||
to_cp = random.choice([x for x in self.theater.enemy_points() if x not in self.theater.conflicts()])
|
||||
self.events.append(InterceptEvent(attacker_name=self.player,
|
||||
@ -139,8 +141,9 @@ class Game:
|
||||
awarded_points = COMMISION_AMOUNTS_FACTORS[for_task] * math.pow(cp.importance, COMMISION_AMOUNTS_SCALE)
|
||||
points_to_spend = cp.base.append_commision_points(for_task, awarded_points)
|
||||
if points_to_spend > 0:
|
||||
unit_type = random.choice(db.find_unittype(for_task, self.enemy))
|
||||
cp.base.commision_units({unit_type: points_to_spend})
|
||||
importance_factor = (cp.importance - IMPORTANCE_LOW) / (IMPORTANCE_HIGH - IMPORTANCE_LOW)
|
||||
unittypes = db.choose_units(for_task, importance_factor, COMMISION_UNIT_VARIETY, self.enemy)
|
||||
cp.base.commision_units({random.choice(unittypes): points_to_spend})
|
||||
|
||||
@property
|
||||
def budget_reward_amount(self):
|
||||
|
||||
@ -58,7 +58,8 @@ class Operation:
|
||||
enemy_name = self.from_cp.captured and self.defender_name or self.attacker_name
|
||||
self.extra_aagen = ExtraAAConflictGenerator(mission, conflict, self.game, player_name, enemy_name)
|
||||
|
||||
def prepare(self, is_quick: bool):
|
||||
def prepare(self, terrain: dcs.terrain.Terrain, is_quick: bool):
|
||||
self.mission = dcs.Mission(terrain)
|
||||
self.is_quick = is_quick
|
||||
|
||||
if is_quick:
|
||||
@ -66,14 +67,25 @@ class Operation:
|
||||
self.defenders_starting_position = None
|
||||
else:
|
||||
self.attackers_starting_position = self.from_cp.at
|
||||
self.defenders_starting_position = self.to_cp and self.to_cp.at or None
|
||||
self.defenders_starting_position = self.to_cp.at
|
||||
|
||||
def generate(self):
|
||||
self.extra_aagen.generate()
|
||||
self.envgen.generate(self.is_quick)
|
||||
if self.is_awacs_enabled:
|
||||
self.awacsgen.generate()
|
||||
|
||||
self.extra_aagen.generate()
|
||||
self.envgen.generate(self.is_quick)
|
||||
|
||||
for global_cp in self.game.theater.controlpoints:
|
||||
if not global_cp.is_global:
|
||||
continue
|
||||
|
||||
ship = self.shipgen.generate(type=db.find_unittype(Carriage, self.attacker_name)[0],
|
||||
at=global_cp.at)
|
||||
|
||||
if global_cp == self.from_cp and not self.is_quick:
|
||||
self.attackers_starting_position = ship
|
||||
|
||||
def units_of(self, country_name: str) -> typing.Collection[UnitType]:
|
||||
return []
|
||||
|
||||
@ -103,14 +115,12 @@ class CaptureOperation(Operation):
|
||||
self.defense = defense
|
||||
self.aa = aa
|
||||
|
||||
def prepare(self, is_quick: bool):
|
||||
super(CaptureOperation, self).prepare(is_quick)
|
||||
mission = dcs.Mission()
|
||||
|
||||
self.initialize(mission=mission,
|
||||
def prepare(self, terrain: dcs.terrain.Terrain, is_quick: bool):
|
||||
super(CaptureOperation, self).prepare(terrain, is_quick)
|
||||
self.initialize(mission=self.mission,
|
||||
conflict=self.to_cp.conflict_attack(self.from_cp,
|
||||
mission.country(self.attacker_name),
|
||||
mission.country(self.defender_name)))
|
||||
self.mission.country(self.attacker_name),
|
||||
self.mission.country(self.defender_name)))
|
||||
|
||||
def generate(self):
|
||||
self.armorgen.generate(self.attack, self.defense)
|
||||
@ -140,18 +150,16 @@ class InterceptOperation(Operation):
|
||||
self.airdefense = airdefense
|
||||
self.interceptors = interceptors
|
||||
|
||||
def prepare(self, is_quick: bool):
|
||||
super(InterceptOperation, self).prepare(is_quick)
|
||||
mission = dcs.Mission()
|
||||
|
||||
def prepare(self, terrain: dcs.terrain.Terrain, is_quick: bool):
|
||||
super(InterceptOperation, self).prepare(terrain, is_quick)
|
||||
conflict = Conflict.intercept_conflict(
|
||||
attacker=mission.country(self.attacker_name),
|
||||
defender=mission.country(self.defender_name),
|
||||
attacker=self.mission.country(self.attacker_name),
|
||||
defender=self.mission.country(self.defender_name),
|
||||
from_cp=self.from_cp,
|
||||
to_cp=self.to_cp
|
||||
)
|
||||
|
||||
self.initialize(mission=mission,
|
||||
self.initialize(mission=self.mission,
|
||||
conflict=conflict)
|
||||
|
||||
def generate(self):
|
||||
@ -159,40 +167,30 @@ class InterceptOperation(Operation):
|
||||
self.airgen.generate_transport_escort(self.escort, clients=self.defender_clients)
|
||||
|
||||
if self.from_cp.is_global:
|
||||
starting_ship = self.shipgen.generate(type=db.find_unittype(Carriage, self.attacker_name)[0],
|
||||
at=self.from_cp.at)
|
||||
|
||||
if self.is_quick:
|
||||
starting_ship = None
|
||||
|
||||
self.airgen.generate_interception(self.interceptors, clients=self.attacker_clients, at=starting_ship)
|
||||
super(InterceptOperation, self).generate()
|
||||
self.airgen.generate_interception(self.interceptors, clients=self.attacker_clients, at=self.attackers_starting_position)
|
||||
else:
|
||||
self.airgen.generate_interception(self.interceptors, clients=self.attacker_clients, at=self.attackers_starting_position)
|
||||
|
||||
super(InterceptOperation, self).generate()
|
||||
super(InterceptOperation, self).generate()
|
||||
|
||||
|
||||
class GroundInterceptOperation(Operation):
|
||||
def setup(self,
|
||||
position: Point,
|
||||
target: db.ArmorDict,
|
||||
strikegroup: db.PlaneDict):
|
||||
self.position = position
|
||||
self.strikegroup = strikegroup
|
||||
self.target = target
|
||||
|
||||
def prepare(self, is_quick: bool):
|
||||
super(GroundInterceptOperation, self).prepare(is_quick)
|
||||
mission = dcs.Mission()
|
||||
def prepare(self, terrain: dcs.terrain.Terrain, is_quick: bool):
|
||||
super(GroundInterceptOperation, self).prepare(terrain, is_quick)
|
||||
conflict = Conflict.ground_intercept_conflict(
|
||||
attacker=mission.country(self.attacker_name),
|
||||
defender=mission.country(self.defender_name),
|
||||
position=self.position,
|
||||
heading=randint(0, 360),
|
||||
radials=ALL_RADIALS
|
||||
attacker=self.mission.country(self.attacker_name),
|
||||
defender=self.mission.country(self.defender_name),
|
||||
heading=self.to_cp.position.heading_between_point(self.from_cp.position),
|
||||
cp=self.to_cp
|
||||
)
|
||||
|
||||
self.initialize(mission=mission,
|
||||
self.initialize(mission=self.mission,
|
||||
conflict=conflict)
|
||||
|
||||
def generate(self):
|
||||
|
||||
@ -7,8 +7,8 @@ from .naming import *
|
||||
from dcs.mission import *
|
||||
|
||||
DISTANCE_FACTOR = 4, 5
|
||||
EXTRA_AA_MIN_DISTANCE = 70000
|
||||
EXTRA_AA_POSITION_FROM_CP = 10000
|
||||
EXTRA_AA_MIN_DISTANCE = 35000
|
||||
EXTRA_AA_POSITION_FROM_CP = 550
|
||||
|
||||
class AAConflictGenerator:
|
||||
def __init__(self, mission: Mission, conflict: Conflict):
|
||||
|
||||
@ -72,6 +72,8 @@ class AircraftConflictGenerator:
|
||||
for unit_instance in group.units:
|
||||
unit_instance.livery_id = db.PLANE_LIVERY_OVERRIDES[unit_type]
|
||||
|
||||
print("AC: {} {}".format(unit_type, len(group.units)))
|
||||
|
||||
def _generate_at_airport(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, airport: Airport = None) -> FlyingGroup:
|
||||
assert count > 0
|
||||
assert unit is not None
|
||||
|
||||
@ -8,6 +8,9 @@ from dcs.unittype import *
|
||||
from dcs.task import *
|
||||
from dcs.terrain.terrain import NoParkingSlotError
|
||||
|
||||
AWACS_DISTANCE = 150000
|
||||
AWACS_ALT = 10000
|
||||
|
||||
|
||||
class AWACSConflictGenerator:
|
||||
def __init__(self, mission: Mission, conflict: Conflict, game):
|
||||
@ -22,5 +25,6 @@ class AWACSConflictGenerator:
|
||||
country=self.conflict.attackers_side,
|
||||
name=namegen.next_awacs_group_name(),
|
||||
plane_type=plane,
|
||||
altitude=AWACS_ALT,
|
||||
airport=None,
|
||||
position=self.conflict.position)
|
||||
position=self.conflict.position.random_point_within(AWACS_DISTANCE, AWACS_DISTANCE))
|
||||
|
||||
@ -14,10 +14,8 @@ from dcs.point import *
|
||||
from dcs.task import *
|
||||
from dcs.country import *
|
||||
|
||||
def _opposite_heading(h):
|
||||
return h+180
|
||||
|
||||
GROUND_DISTANCE_FACTOR = 2
|
||||
GROUNDINTERCEPT_DISTANCE_FACTOR = 6
|
||||
AIR_DISTANCE = 32000
|
||||
|
||||
INTERCEPT_ATTACKERS_HEADING = -45, 45
|
||||
@ -28,6 +26,10 @@ INTERCEPT_MAX_DISTANCE = 80000
|
||||
INTERCEPT_MIN_DISTANCE = 45000
|
||||
|
||||
|
||||
def _opposite_heading(h):
|
||||
return h+180
|
||||
|
||||
|
||||
class Conflict:
|
||||
attackers_side = None # type: Country
|
||||
defenders_side = None # type: Country
|
||||
@ -81,18 +83,18 @@ class Conflict:
|
||||
return instance
|
||||
|
||||
@classmethod
|
||||
def ground_intercept_conflict(self, attacker: Country, defender: Country, position: Point, heading: int, radials: typing.List[int]):
|
||||
def ground_intercept_conflict(self, attacker: Country, defender: Country, heading: int, cp):
|
||||
from theater.conflicttheater import SIZE_SMALL
|
||||
|
||||
instance = self()
|
||||
instance.attackers_side = attacker
|
||||
instance.defenders_side = defender
|
||||
|
||||
instance.position = position
|
||||
instance.size = SIZE_SMALL
|
||||
instance.radials = radials
|
||||
instance.position = cp.position
|
||||
instance.size = cp.size
|
||||
instance.radials = cp.radials
|
||||
|
||||
instance.air_attackers_location = instance.position.point_from_heading(random.randint(*INTERCEPT_ATTACKERS_HEADING) + heading, AIR_DISTANCE)
|
||||
instance.ground_defenders_location = instance.position
|
||||
instance.ground_defenders_location = instance.position.point_from_heading(random.choice(cp.radials), instance.size * GROUNDINTERCEPT_DISTANCE_FACTOR)
|
||||
|
||||
return instance
|
||||
|
||||
@ -6,6 +6,7 @@ from dcs.mission import Mission
|
||||
from dcs.triggers import *
|
||||
from dcs.condition import *
|
||||
from dcs.action import *
|
||||
from dcs.task import *
|
||||
|
||||
from theater.weatherforecast import WeatherForecast
|
||||
from theater.conflicttheater import Conflict
|
||||
@ -14,18 +15,17 @@ ACTIVATION_TRIGGER_SIZE = 80000
|
||||
ACTIVATION_TRIGGER_MIN_DISTANCE = 5000
|
||||
|
||||
RANDOM_TIME = {
|
||||
"night": 0,
|
||||
"dusk": 5,
|
||||
"dawn": 35,
|
||||
"noon": 75,
|
||||
"night": 5,
|
||||
"dusk": 30,
|
||||
"dawn": 30,
|
||||
"day": 100,
|
||||
}
|
||||
|
||||
RANDOM_WEATHER = {
|
||||
0: 0, # thunderstorm
|
||||
1: 5, # heavy rain
|
||||
2: 20, # rain
|
||||
3: 40, # random dynamic
|
||||
0: 5, # thunderstorm
|
||||
1: 20, # heavy rain
|
||||
2: 30, # rain
|
||||
3: 100, # random dynamic
|
||||
}
|
||||
|
||||
|
||||
@ -36,17 +36,7 @@ class EnvironmentSettingsGenerator:
|
||||
self.game = game
|
||||
|
||||
def _gen_random_time(self):
|
||||
time_roll = random.randint(0, 100)
|
||||
time_period = None
|
||||
for k, v in RANDOM_TIME.items():
|
||||
if v >= time_roll:
|
||||
time_period = k
|
||||
break
|
||||
|
||||
self.mission.random_daytime(time_period)
|
||||
|
||||
def _gen_random_time_2(self):
|
||||
start_time = datetime.now(self.mission.start_time.tzinfo).date()
|
||||
start_time = datetime.today()
|
||||
daytime_map = {
|
||||
"day": timedelta(hours=random.randrange(9, 18)),
|
||||
"night": timedelta(hours=random.randrange(-3, 6)),
|
||||
@ -54,24 +44,24 @@ class EnvironmentSettingsGenerator:
|
||||
"dawn": timedelta(hours=random.randrange(6, 9)),
|
||||
}
|
||||
|
||||
time_roll = random.randint(0, 100)
|
||||
time_period = None
|
||||
for k, v in RANDOM_TIME.items():
|
||||
if v >= time_roll:
|
||||
if random.randint(0, 100) <= v:
|
||||
time_period = k
|
||||
break
|
||||
|
||||
print("generated {}".format(time_period))
|
||||
start_time += daytime_map[time_period]
|
||||
self.mission.start_time = start_time
|
||||
|
||||
def _gen_random_weather(self):
|
||||
weather_roll = random.randint(0, 100)
|
||||
weather_type = None
|
||||
for k, v in RANDOM_TIME.items():
|
||||
if v >= weather_roll:
|
||||
for k, v in RANDOM_WEATHER.items():
|
||||
if random.randint(0, 100) <= v:
|
||||
weather_type = k
|
||||
break
|
||||
|
||||
print("generated weather {}".format(weather_type))
|
||||
if weather_type == 0:
|
||||
self.mission.weather.random_thunderstorm()
|
||||
elif weather_type == 1:
|
||||
@ -116,9 +106,10 @@ class EnvironmentSettingsGenerator:
|
||||
player_coalition = self.game.player == "USA" and "blue" or "red"
|
||||
enemy_coalition = player_coalition == "blue" and "red" or "blue"
|
||||
|
||||
self.mission.coalition[player_coalition].bullseye = self.conflict.position
|
||||
self.mission.coalition[player_coalition].bullseye = {"x": self.conflict.position.x,
|
||||
"y": self.conflict.position.y}
|
||||
|
||||
self._gen_random_time_2()
|
||||
self._gen_random_time()
|
||||
self._gen_random_weather()
|
||||
self._set_allegiances(player_coalition, enemy_coalition)
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@ from .base import *
|
||||
|
||||
|
||||
class CaucasusTheater(ConflictTheater):
|
||||
terrain = caucasus.Caucasus()
|
||||
overview_image = "caumap.gif"
|
||||
reference_points = {(-317948.32727306, 635639.37385346): (282.5, 319),
|
||||
(-355692.3067714, 617269.96285781): (269, 352), }
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import dcs
|
||||
|
||||
from .controlpoint import *
|
||||
|
||||
SIZE_TINY = 150
|
||||
SIZE_SMALL = 600
|
||||
SIZE_REGULAR = 1000
|
||||
SIZE_BIG = 2000
|
||||
@ -29,6 +30,7 @@ class ConflictTheater:
|
||||
terrain = None # type: dcs.terrain.Terrain
|
||||
controlpoints = None # type: typing.Collection[ControlPoint]
|
||||
reference_points = None # type: typing.Dict
|
||||
overview_image = None # type: str
|
||||
|
||||
def __init__(self):
|
||||
self.controlpoints = []
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import typing
|
||||
import re
|
||||
|
||||
from dcs.mapping import *
|
||||
from dcs.country import *
|
||||
@ -17,7 +18,8 @@ class ControlPoint:
|
||||
def __init__(self, name: str, position: Point, at, radials: typing.Collection[int], size: int, importance: int):
|
||||
import theater.base
|
||||
|
||||
self.name = name.split("-")[0]
|
||||
self.name = " ".join(re.split(r" |-", name)[:2])
|
||||
self.full_name = name
|
||||
self.position = position
|
||||
self.at = at
|
||||
|
||||
@ -30,6 +32,7 @@ class ControlPoint:
|
||||
|
||||
@classmethod
|
||||
def from_airport(cls, airport: Airport, radials: typing.Collection[int], size: int, importance: int):
|
||||
assert airport
|
||||
return cls(airport.name, airport.position, airport, radials, size, importance)
|
||||
|
||||
@classmethod
|
||||
|
||||
@ -6,6 +6,11 @@ from .base import *
|
||||
|
||||
|
||||
class NevadaTheater(ConflictTheater):
|
||||
terrain = dcs.terrain.Nevada()
|
||||
overview_image = "nevada.gif"
|
||||
reference_points = {(nevada.Mina_Airport_3Q0.position.x, nevada.Mina_Airport_3Q0.position.y): (45, -360),
|
||||
(nevada.Laughlin_Airport.position.x, nevada.Laughlin_Airport.position.y): (440, 80), }
|
||||
|
||||
mina = ControlPoint.from_airport(nevada.Mina_Airport_3Q0, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW)
|
||||
tonopah = ControlPoint.from_airport(nevada.Tonopah_Airport, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW)
|
||||
tonopah_test_range = ControlPoint.from_airport(nevada.Tonopah_Test_Range_Airfield, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW)
|
||||
|
||||
@ -6,46 +6,65 @@ from .base import *
|
||||
|
||||
|
||||
class PersianGulfTheater(ConflictTheater):
|
||||
terrain = dcs.terrain.PersianGulf()
|
||||
overview_image = "persiangulf.gif"
|
||||
reference_points = {(persiangulf.Sir_Abu_Nuayr.position.x, persiangulf.Sir_Abu_Nuayr.position.y): (351, 115),
|
||||
(persiangulf.Sirri_Island.position.x, persiangulf.Sirri_Island.position.y): (389, 22), }
|
||||
|
||||
al_dhafra = ControlPoint.from_airport(persiangulf.Al_Dhafra_AB, ALL_RADIALS, SIZE_BIG, IMPORTANCE_LOW)
|
||||
al_maktoum = ControlPoint.from_airport(persiangulf.Al_Maktoum_Intl, ALL_RADIALS, SIZE_BIG, IMPORTANCE_LOW)
|
||||
al_minhad = ControlPoint.from_airport(persiangulf.Al_Minhad_AB, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_LOW)
|
||||
sir_abu_nuayr = ControlPoint.from_airport(persiangulf.Sir_Abu_Nuayr, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW)
|
||||
sir_abu_nuayr = ControlPoint.from_airport(persiangulf.Sir_Abu_Nuayr, [330], SIZE_SMALL, IMPORTANCE_LOW)
|
||||
|
||||
dubai = ControlPoint.from_airport(persiangulf.Dubai_Intl, COAST_SWNE, SIZE_LARGE, IMPORTANCE_MEDIUM)
|
||||
sharjah = ControlPoint.from_airport(persiangulf.Sharjah_Intl, ALL_RADIALS, SIZE_BIG, IMPORTANCE_MEDIUM)
|
||||
fujairah = ControlPoint.from_airport(persiangulf.Fujairah_Intl, COAST_NS_E, SIZE_REGULAR, IMPORTANCE_MEDIUM)
|
||||
fujairah = ControlPoint.from_airport(persiangulf.Fujairah_Intl, COAST_NS_W, SIZE_REGULAR, IMPORTANCE_MEDIUM)
|
||||
khasab = ControlPoint.from_airport(persiangulf.Khasab, COAST_EW_S, SIZE_SMALL, IMPORTANCE_MEDIUM)
|
||||
|
||||
sirri = ControlPoint.from_airport(persiangulf.Sirri_Island, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_MEDIUM)
|
||||
abu_musa = ControlPoint.from_airport(persiangulf.Abu_Musa_Island_Airport, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_MEDIUM)
|
||||
tunb_island = ControlPoint.from_airport(persiangulf.Tunb_Island_AFB, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_HIGH)
|
||||
sirri = ControlPoint.from_airport(persiangulf.Sirri_Island, ALL_RADIALS, SIZE_TINY, IMPORTANCE_MEDIUM)
|
||||
abu_musa = ControlPoint.from_airport(persiangulf.Abu_Musa_Island_Airport, ALL_RADIALS, SIZE_TINY, IMPORTANCE_MEDIUM)
|
||||
tunb_island = ControlPoint.from_airport(persiangulf.Tunb_Island_AFB, COAST_EW_N, SIZE_SMALL, IMPORTANCE_HIGH)
|
||||
tunb_kochak = ControlPoint.from_airport(persiangulf.Tunb_Kochak, COAST_EW_S, SIZE_TINY, IMPORTANCE_HIGH)
|
||||
|
||||
bandar_lengeh = ControlPoint.from_airport(persiangulf.Bandar_Lengeh, COAST_EW_N, SIZE_SMALL, IMPORTANCE_HIGH)
|
||||
qeshm = ControlPoint.from_airport(persiangulf.Qeshm_Island, COAST_EW_N, SIZE_SMALL, IMPORTANCE_HIGH)
|
||||
|
||||
havadarya = ControlPoint.from_airport(persiangulf.Havadarya, COAST_SWNE, SIZE_REGULAR, IMPORTANCE_HIGH)
|
||||
havadarya = ControlPoint.from_airport(persiangulf.Havadarya, COAST_EW_N, SIZE_REGULAR, IMPORTANCE_HIGH)
|
||||
bandar_abbas = ControlPoint.from_airport(persiangulf.Bandar_Abbas_Intl, COAST_EW_N, SIZE_BIG, IMPORTANCE_HIGH)
|
||||
lar = ControlPoint.from_airport(persiangulf.Lar_Airbase, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_HIGH)
|
||||
|
||||
east_carrier = ControlPoint.carrier("West carrier", Point(-91023.430176, -159467.078125))
|
||||
west_carrier = ControlPoint.carrier("East carrier", Point(-100531.972946, 60939.275818))
|
||||
north_carrier = ControlPoint.carrier("North carrier", Point(70531.972946, 60939.275818))
|
||||
|
||||
def __init__(self):
|
||||
super(PersianGulfTheater, self).__init__()
|
||||
|
||||
self.add_controlpoint(self.al_dhafra, connected_to=[self.sir_abu_nuayr, self.al_maktoum])
|
||||
self.add_controlpoint(self.al_maktoum, connected_to=[self.al_dhafra, self.al_minhad, self.sir_abu_nuayr])
|
||||
self.add_controlpoint(self.dubai, connected_to=[self.sir_abu_nuayr, self.al_minhad, self.sharjah])
|
||||
self.add_controlpoint(self.al_minhad, connected_to=[self.al_maktoum, self.dubai])
|
||||
self.add_controlpoint(self.dubai, connected_to=[self.al_minhad, self.sharjah])
|
||||
self.add_controlpoint(self.sharjah, connected_to=[self.dubai, self.khasab])
|
||||
self.add_controlpoint(self.fujairah, connected_to=[self.dubai, self.khasab])
|
||||
self.add_controlpoint(self.khasab, connected_to=[self.sharjah, self.fujairah, self.tunb_island])
|
||||
|
||||
self.add_controlpoint(self.sir_abu_nuayr, connected_to=[self.al_dhafra, self.al_maktoum, self.dubai])
|
||||
self.add_controlpoint(self.sirri, connected_to=[self.sir_abu_nuayr, self.abu_musa, self.tunb_island])
|
||||
self.add_controlpoint(self.abu_musa, connected_to=[self.sirri, self.sir_abu_nuayr, self.tunb_island])
|
||||
self.add_controlpoint(self.sir_abu_nuayr, connected_to=[self.al_dhafra, self.al_maktoum, self.sirri])
|
||||
self.add_controlpoint(self.sirri, connected_to=[self.sir_abu_nuayr, self.abu_musa])
|
||||
self.add_controlpoint(self.abu_musa, connected_to=[self.sirri, self.sir_abu_nuayr])
|
||||
self.add_controlpoint(self.tunb_kochak, connected_to=[self.sirri, self.abu_musa, self.tunb_island])
|
||||
|
||||
self.add_controlpoint(self.tunb_island, connected_to=[self.khasab, self.abu_musa, self.sirri, self.qeshm])
|
||||
self.add_controlpoint(self.tunb_island, connected_to=[self.khasab, self.qeshm, self.tunb_kochak])
|
||||
self.add_controlpoint(self.bandar_lengeh, connected_to=[self.tunb_island, self.lar, self.qeshm])
|
||||
self.add_controlpoint(self.qeshm, connected_to=[self.bandar_lengeh, self.havadarya, self.tunb_island])
|
||||
self.add_controlpoint(self.havadarya, connected_to=[self.lar, self.qeshm, self.bandar_abbas])
|
||||
self.add_controlpoint(self.bandar_abbas, connected_to=[self.havadarya])
|
||||
self.add_controlpoint(self.lar, connected_to=[self.bandar_lengeh, self.qeshm, self.havadarya])
|
||||
|
||||
self.add_controlpoint(self.east_carrier)
|
||||
self.add_controlpoint(self.west_carrier)
|
||||
self.add_controlpoint(self.north_carrier)
|
||||
|
||||
self.east_carrier.captured = True
|
||||
self.west_carrier.captured = True
|
||||
self.north_carrier.captured = True
|
||||
self.al_dhafra.captured = True
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
from theater.base import *
|
||||
from theater.conflicttheater import *
|
||||
|
||||
UNIT_VARIETY = 2
|
||||
UNIT_AMOUNT_FACTOR = 0.25
|
||||
UNIT_VARIETY = 3
|
||||
UNIT_AMOUNT_FACTOR = 16
|
||||
|
||||
|
||||
def generate_initial(theater: ConflictTheater, enemy: str):
|
||||
@ -11,19 +11,14 @@ def generate_initial(theater: ConflictTheater, enemy: str):
|
||||
continue
|
||||
|
||||
for task in [CAP, FighterSweep, CAS, AirDefence]:
|
||||
suitable_unittypes = db.find_unittype(task, enemy)
|
||||
suitable_unittypes.sort(key=lambda x: db.PRICES[x], reverse=True)
|
||||
assert cp.importance <= IMPORTANCE_HIGH, "invalid importance {}".format(cp.importance)
|
||||
assert cp.importance >= IMPORTANCE_LOW, "invalid importance {}".format(cp.importance)
|
||||
|
||||
importance = cp.importance * 10
|
||||
reversed_importance = IMPORTANCE_HIGH * 10 - cp.importance * 10
|
||||
units_idx_start = int(reversed_importance)
|
||||
units_idx_end = units_idx_start + UNIT_VARIETY
|
||||
importance_factor = (cp.importance - IMPORTANCE_LOW) / (IMPORTANCE_HIGH - IMPORTANCE_LOW)
|
||||
variety = int(UNIT_VARIETY + UNIT_VARIETY * importance_factor / 2)
|
||||
unittypes = db.choose_units(task, importance_factor, variety, enemy)
|
||||
|
||||
range_start = min(len(suitable_unittypes)-1, units_idx_start)
|
||||
range_end = min(len(suitable_unittypes), units_idx_end)
|
||||
unittypes = suitable_unittypes[range_start:range_end]
|
||||
|
||||
typecount = max(math.floor(importance * UNIT_AMOUNT_FACTOR), 1)
|
||||
#print("{} - {}-{} {}, {}".format(cp.name, units_idx_start, units_idx_end, unittypes, typecount))
|
||||
units = {unittype: typecount for unittype in unittypes}
|
||||
cp.base.commision_units(units)
|
||||
count = max(int(importance_factor * UNIT_AMOUNT_FACTOR), 1)
|
||||
count_per_type = max(int(float(count) / len(unittypes)), 1)
|
||||
for unit_type in unittypes:
|
||||
cp.base.commision_units({unit_type: count_per_type})
|
||||
|
||||
@ -143,7 +143,7 @@ class EventMenu(Menu):
|
||||
clients=scrambled_clients)
|
||||
elif type(self.event) is GroundInterceptEvent:
|
||||
e = self.event # type: GroundInterceptEvent
|
||||
e.player_attacking(e.to_cp.position.random_point_within(30000), strikegroup=scrambled_aircraft, clients=scrambled_clients)
|
||||
e.player_attacking(strikegroup=scrambled_aircraft, clients=scrambled_clients)
|
||||
|
||||
self.game.initiate_event(self.event)
|
||||
EventResultsMenu(self.window, self.parent, self.game, self.event).display()
|
||||
|
||||
@ -21,6 +21,9 @@ class EventResultsMenu(Menu):
|
||||
self.window.clear_right_pane()
|
||||
|
||||
if not self.finished:
|
||||
"""
|
||||
For debugging purposes
|
||||
|
||||
Button(self.frame, text="no losses, succ", command=self.simulate_result(0, 1)).grid()
|
||||
Button(self.frame, text="no losses, fail", command=self.simulate_result(0, 1)).grid(row=1, column=1)
|
||||
|
||||
@ -29,6 +32,7 @@ class EventResultsMenu(Menu):
|
||||
|
||||
Button(self.frame, text="full losses, succ", command=self.simulate_result(1, 0)).grid(row=3, )
|
||||
Button(self.frame, text="full losses, fail", command=self.simulate_result(1, 0)).grid(row=3, column=1)
|
||||
"""
|
||||
|
||||
Label(self.frame, text="Play the mission and save debriefing to {}".format(debriefing_directory_location())).grid(row=0, column=0)
|
||||
else:
|
||||
|
||||
@ -6,6 +6,7 @@ from ui.window import *
|
||||
|
||||
class NewGameMenu(Menu):
|
||||
selected_country = None # type: IntVar
|
||||
selected_terrain = None # type: IntVar
|
||||
|
||||
def __init__(self, window: Window, callback: typing.Callable):
|
||||
super(NewGameMenu, self).__init__(window, None, None)
|
||||
@ -15,6 +16,9 @@ class NewGameMenu(Menu):
|
||||
self.selected_country = IntVar()
|
||||
self.selected_country.set(0)
|
||||
|
||||
self.selected_terrain = IntVar()
|
||||
self.selected_terrain.set(0)
|
||||
|
||||
@property
|
||||
def player_country_name(self):
|
||||
if self.selected_country.get() == 0:
|
||||
@ -29,13 +33,27 @@ class NewGameMenu(Menu):
|
||||
else:
|
||||
return "Russia"
|
||||
|
||||
@property
|
||||
def terrain_name(self) -> str:
|
||||
if self.selected_terrain.get() == 0:
|
||||
return "caucasus"
|
||||
elif self.selected_terrain.get() == 1:
|
||||
return "nevada"
|
||||
else:
|
||||
return "persiangulf"
|
||||
|
||||
def display(self):
|
||||
self.window.clear_right_pane()
|
||||
|
||||
Label(self.frame, text="Player country").grid(row=0, column=0)
|
||||
Radiobutton(self.frame, text="USA", variable=self.selected_country, value=0).grid(row=1, column=0)
|
||||
Radiobutton(self.frame, text="Russia", variable=self.selected_country, value=1).grid(row=2, column=0)
|
||||
Button(self.frame, text="Proceed", command=self.proceed).grid(row=3, column=0)
|
||||
|
||||
Label(self.frame, text="Terrain").grid(row=0, column=1)
|
||||
Radiobutton(self.frame, text="Caucasus", variable=self.selected_terrain, value=0).grid(row=1, column=1)
|
||||
Radiobutton(self.frame, text="Nevada", variable=self.selected_terrain, value=1).grid(row=2, column=1)
|
||||
Radiobutton(self.frame, text="Persian Gulf", variable=self.selected_terrain, value=2).grid(row=3, column=1)
|
||||
Button(self.frame, text="Proceed", command=self.proceed).grid(row=4, column=0, columnspan=2)
|
||||
|
||||
def proceed(self):
|
||||
self.callback(self.player_country_name, self.enemy_country_name)
|
||||
self.callback(self.player_country_name, self.enemy_country_name, self.terrain_name)
|
||||
|
||||
@ -11,14 +11,14 @@ class OverviewCanvas:
|
||||
mainmenu = None # type: ui.mainmenu.MainMenu
|
||||
|
||||
def __init__(self, frame: Frame, parent, game: Game):
|
||||
self.canvas = Canvas(frame, width=616, height=350)
|
||||
self.canvas.grid(column=0, row=0, sticky=NSEW)
|
||||
self.image = PhotoImage(file="resources/caumap.gif")
|
||||
self.parent = parent
|
||||
|
||||
self.game = game
|
||||
|
||||
def cp_coordinates(self, cp: ControlPoint) -> (int, int):
|
||||
self.image = PhotoImage(file=os.path.join("resources", game.theater.overview_image))
|
||||
self.canvas = Canvas(frame, width=self.image.width(), height=self.image.height())
|
||||
self.canvas.grid(column=0, row=0, sticky=NSEW)
|
||||
|
||||
def transform_point(self, p: Point) -> (int, int):
|
||||
point_a = list(self.game.theater.reference_points.keys())[0]
|
||||
point_a_img = self.game.theater.reference_points[point_a]
|
||||
|
||||
@ -35,8 +35,8 @@ class OverviewCanvas:
|
||||
y_scale = float(y_dist) / float(lat_dist)
|
||||
|
||||
# ---
|
||||
x_offset = cp.position.x - point_a[0]
|
||||
y_offset = cp.position.y - point_a[1]
|
||||
x_offset = p.x - point_a[0]
|
||||
y_offset = p.y - point_a[1]
|
||||
|
||||
return point_b_img[1] + y_offset * y_scale, point_a_img[0] - x_offset * x_scale
|
||||
|
||||
@ -54,9 +54,9 @@ class OverviewCanvas:
|
||||
self.canvas.create_image((self.image.width()/2, self.image.height()/2), image=self.image)
|
||||
|
||||
for cp in self.game.theater.controlpoints:
|
||||
coords = self.cp_coordinates(cp)
|
||||
coords = self.transform_point(cp.position)
|
||||
for connected_cp in cp.connected_points:
|
||||
connected_coords = self.cp_coordinates(connected_cp)
|
||||
connected_coords = self.transform_point(connected_cp.position)
|
||||
if connected_cp.captured != cp.captured:
|
||||
color = "red"
|
||||
elif connected_cp.captured and cp.captured:
|
||||
@ -67,7 +67,7 @@ class OverviewCanvas:
|
||||
self.canvas.create_line((coords[0], coords[1], connected_coords[0], connected_coords[1]), width=2, fill=color)
|
||||
|
||||
for cp in self.game.theater.controlpoints:
|
||||
coords = self.cp_coordinates(cp)
|
||||
coords = self.transform_point(cp.position)
|
||||
arc_size = 22 * math.pow(cp.importance, 1)
|
||||
extent = max(cp.base.strength * 180, 10)
|
||||
start = (180 - extent) / 2
|
||||
@ -79,6 +79,15 @@ class OverviewCanvas:
|
||||
style=PIESLICE,
|
||||
start=start,
|
||||
extent=extent)
|
||||
|
||||
"""
|
||||
For debugging purposes
|
||||
|
||||
for r in cp.radials:
|
||||
p = self.transform_point(cp.position.point_from_heading(r, 20000))
|
||||
self.canvas.create_text(p[0], p[1], text="{}".format(r))
|
||||
"""
|
||||
|
||||
self.canvas.tag_bind(cp_id, "<Button-1>", self.display(cp))
|
||||
self.create_cp_title((coords[0] + arc_size/4, coords[1] + arc_size/4), cp)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user