mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
new options, landmaps, mission settings generation update & frontlike smokes generation
This commit is contained in:
parent
92e5514e8d
commit
e54e548bdd
@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
import os
|
||||||
|
import dcs
|
||||||
|
|
||||||
import theater.caucasus
|
import theater.caucasus
|
||||||
import theater.persiangulf
|
import theater.persiangulf
|
||||||
import theater.nevada
|
import theater.nevada
|
||||||
@ -11,6 +14,8 @@ from game.game import Game
|
|||||||
from theater import start_generator
|
from theater import start_generator
|
||||||
from userdata import persistency
|
from userdata import persistency
|
||||||
|
|
||||||
|
dcs.planes.FlyingType.payload_dirs.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "resources\\payloads"))
|
||||||
|
|
||||||
|
|
||||||
def proceed_to_main_menu(game: Game):
|
def proceed_to_main_menu(game: Game):
|
||||||
m = ui.mainmenu.MainMenu(w, None, game)
|
m = ui.mainmenu.MainMenu(w, None, game)
|
||||||
@ -22,7 +27,7 @@ game = persistency.restore_game()
|
|||||||
if not game:
|
if not game:
|
||||||
new_game_menu = None # type: NewGameMenu
|
new_game_menu = None # type: NewGameMenu
|
||||||
|
|
||||||
def start_new_game(player_name: str, enemy_name: str, terrain: str):
|
def start_new_game(player_name: str, enemy_name: str, terrain: str, sams: bool):
|
||||||
if terrain == "persiangulf":
|
if terrain == "persiangulf":
|
||||||
conflicttheater = theater.persiangulf.PersianGulfTheater()
|
conflicttheater = theater.persiangulf.PersianGulfTheater()
|
||||||
elif terrain == "nevada":
|
elif terrain == "nevada":
|
||||||
@ -30,7 +35,7 @@ if not game:
|
|||||||
else:
|
else:
|
||||||
conflicttheater = theater.caucasus.CaucasusTheater()
|
conflicttheater = theater.caucasus.CaucasusTheater()
|
||||||
|
|
||||||
start_generator.generate_initial(conflicttheater, enemy_name)
|
start_generator.generate_initial(conflicttheater, enemy_name, sams)
|
||||||
proceed_to_main_menu(Game(player_name=player_name,
|
proceed_to_main_menu(Game(player_name=player_name,
|
||||||
enemy_name=enemy_name,
|
enemy_name=enemy_name,
|
||||||
theater=conflicttheater))
|
theater=conflicttheater))
|
||||||
|
|||||||
18
game/db.py
18
game/db.py
@ -115,10 +115,17 @@ UNIT_BY_TASK = {
|
|||||||
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, ],
|
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: [
|
||||||
AirDefence.AAA_Vulcan_M163,
|
AirDefence.AAA_Vulcan_M163,
|
||||||
|
AirDefence.AAA_Vulcan_M163,
|
||||||
|
AirDefence.AAA_Vulcan_M163,
|
||||||
|
AirDefence.SAM_Avenger_M1097,
|
||||||
AirDefence.SAM_Avenger_M1097,
|
AirDefence.SAM_Avenger_M1097,
|
||||||
AirDefence.SAM_Patriot_ICC,
|
AirDefence.SAM_Patriot_ICC,
|
||||||
|
|
||||||
AirDefence.AAA_ZU_23_on_Ural_375,
|
AirDefence.AAA_ZU_23_on_Ural_375,
|
||||||
|
AirDefence.AAA_ZU_23_on_Ural_375,
|
||||||
|
AirDefence.AAA_ZU_23_on_Ural_375,
|
||||||
|
AirDefence.AAA_ZU_23_on_Ural_375,
|
||||||
|
AirDefence.SAM_SA_18_Igla_MANPADS,
|
||||||
AirDefence.SAM_SA_18_Igla_MANPADS,
|
AirDefence.SAM_SA_18_Igla_MANPADS,
|
||||||
AirDefence.SAM_SA_19_Tunguska_2S6,
|
AirDefence.SAM_SA_19_Tunguska_2S6,
|
||||||
AirDefence.SAM_SA_8_Osa_9A33,
|
AirDefence.SAM_SA_8_Osa_9A33,
|
||||||
@ -126,6 +133,14 @@ UNIT_BY_TASK = {
|
|||||||
Carriage: [CVN_74_John_C__Stennis, CV_1143_5_Admiral_Kuznetsov, ],
|
Carriage: [CVN_74_John_C__Stennis, CV_1143_5_Admiral_Kuznetsov, ],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SAM_BAN = [
|
||||||
|
AirDefence.SAM_Avenger_M1097,
|
||||||
|
AirDefence.SAM_Patriot_ICC,
|
||||||
|
|
||||||
|
AirDefence.SAM_SA_19_Tunguska_2S6,
|
||||||
|
AirDefence.SAM_SA_8_Osa_9A33,
|
||||||
|
]
|
||||||
|
|
||||||
UNIT_BY_COUNTRY = {
|
UNIT_BY_COUNTRY = {
|
||||||
"Russia": [
|
"Russia": [
|
||||||
C_101CC,
|
C_101CC,
|
||||||
@ -256,7 +271,7 @@ def _validate_db():
|
|||||||
# check unit by task uniquity
|
# check unit by task uniquity
|
||||||
total_set = set()
|
total_set = set()
|
||||||
for t, unit_collection in UNIT_BY_TASK.items():
|
for t, unit_collection in UNIT_BY_TASK.items():
|
||||||
for unit_type in unit_collection:
|
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".format(unit_type)
|
||||||
total_set.add(unit_type)
|
total_set.add(unit_type)
|
||||||
|
|
||||||
@ -272,4 +287,5 @@ def _validate_db():
|
|||||||
for unit_type in total_set:
|
for unit_type in total_set:
|
||||||
assert unit_type in PRICES, "{} not in prices".format(unit_type)
|
assert unit_type in PRICES, "{} not in prices".format(unit_type)
|
||||||
|
|
||||||
|
|
||||||
_validate_db()
|
_validate_db()
|
||||||
@ -258,7 +258,7 @@ class CaptureEvent(Event):
|
|||||||
attack=armor,
|
attack=armor,
|
||||||
intercept=interceptors,
|
intercept=interceptors,
|
||||||
defense=self.to_cp.base.armor,
|
defense=self.to_cp.base.armor,
|
||||||
aa=self.to_cp.base.aa)
|
aa=self.to_cp.base.assemble_aa())
|
||||||
|
|
||||||
self.operation = op
|
self.operation = op
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ COMMISION_LIMITS_FACTORS = {
|
|||||||
CAP: 2,
|
CAP: 2,
|
||||||
CAS: 1,
|
CAS: 1,
|
||||||
FighterSweep: 3,
|
FighterSweep: 3,
|
||||||
AirDefence: 2,
|
AirDefence: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMISION_AMOUNTS_SCALE = 2
|
COMMISION_AMOUNTS_SCALE = 2
|
||||||
@ -39,6 +39,8 @@ class Game:
|
|||||||
budget = PLAYER_BUDGET_INITIAL
|
budget = PLAYER_BUDGET_INITIAL
|
||||||
events = None # type: typing.List[Event]
|
events = None # type: typing.List[Event]
|
||||||
pending_transfers = None # type: typing.Dict[]
|
pending_transfers = None # type: typing.Dict[]
|
||||||
|
player_skill = "Good"
|
||||||
|
enemy_skill = "Average"
|
||||||
|
|
||||||
def __init__(self, player_name: str, enemy_name: str, theater: ConflictTheater):
|
def __init__(self, player_name: str, enemy_name: str, theater: ConflictTheater):
|
||||||
self.events = []
|
self.events = []
|
||||||
|
|||||||
@ -7,8 +7,9 @@ from gen.aircraft import *
|
|||||||
from gen.aaa import *
|
from gen.aaa import *
|
||||||
from gen.shipgen import *
|
from gen.shipgen import *
|
||||||
from gen.conflictgen import *
|
from gen.conflictgen import *
|
||||||
from gen.envsettingsgen import *
|
from gen.settingsgen import *
|
||||||
from gen.awacsgen import *
|
from gen.awacsgen import *
|
||||||
|
from gen.visualgen import *
|
||||||
|
|
||||||
|
|
||||||
class Operation:
|
class Operation:
|
||||||
@ -21,8 +22,9 @@ class Operation:
|
|||||||
aagen = None # type: AAConflictGenerator
|
aagen = None # type: AAConflictGenerator
|
||||||
extra_aagen = None # type: ExtraAAConflictGenerator
|
extra_aagen = None # type: ExtraAAConflictGenerator
|
||||||
shipgen = None # type: ShipGenerator
|
shipgen = None # type: ShipGenerator
|
||||||
envgen = None # type: EnvironmentSettingsGenerator
|
envgen = None # type: SettingsGenerator
|
||||||
awacsgen = None # type: AWACSConflictGenerator
|
awacsgen = None # type: AWACSConflictGenerator
|
||||||
|
visualgen = None # type: VisualGenerator
|
||||||
|
|
||||||
is_awacs_enabled = False
|
is_awacs_enabled = False
|
||||||
|
|
||||||
@ -52,7 +54,8 @@ class Operation:
|
|||||||
self.aagen = AAConflictGenerator(mission, conflict)
|
self.aagen = AAConflictGenerator(mission, conflict)
|
||||||
self.shipgen = ShipGenerator(mission, conflict)
|
self.shipgen = ShipGenerator(mission, conflict)
|
||||||
self.awacsgen = AWACSConflictGenerator(mission, conflict, self.game)
|
self.awacsgen = AWACSConflictGenerator(mission, conflict, self.game)
|
||||||
self.envgen = EnvironmentSettingsGenerator(mission, conflict, self.game)
|
self.envgen = SettingsGenerator(mission, conflict, self.game)
|
||||||
|
self.visualgen = VisualGenerator(mission, conflict, self.game)
|
||||||
|
|
||||||
player_name = self.from_cp.captured and self.attacker_name or self.defender_name
|
player_name = self.from_cp.captured and self.attacker_name or self.defender_name
|
||||||
enemy_name = self.from_cp.captured and self.defender_name or self.attacker_name
|
enemy_name = self.from_cp.captured and self.defender_name or self.attacker_name
|
||||||
@ -70,6 +73,8 @@ class Operation:
|
|||||||
self.defenders_starting_position = self.to_cp.at
|
self.defenders_starting_position = self.to_cp.at
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
|
self.visualgen.generate()
|
||||||
|
|
||||||
if self.is_awacs_enabled:
|
if self.is_awacs_enabled:
|
||||||
self.awacsgen.generate()
|
self.awacsgen.generate()
|
||||||
|
|
||||||
@ -117,6 +122,11 @@ class CaptureOperation(Operation):
|
|||||||
|
|
||||||
def prepare(self, terrain: dcs.terrain.Terrain, is_quick: bool):
|
def prepare(self, terrain: dcs.terrain.Terrain, is_quick: bool):
|
||||||
super(CaptureOperation, self).prepare(terrain, is_quick)
|
super(CaptureOperation, self).prepare(terrain, is_quick)
|
||||||
|
|
||||||
|
self.defenders_starting_position = None
|
||||||
|
if self.game.player == self.defender_name:
|
||||||
|
self.attackers_starting_position = None
|
||||||
|
|
||||||
self.initialize(mission=self.mission,
|
self.initialize(mission=self.mission,
|
||||||
conflict=self.to_cp.conflict_attack(self.from_cp,
|
conflict=self.to_cp.conflict_attack(self.from_cp,
|
||||||
self.mission.country(self.attacker_name),
|
self.mission.country(self.attacker_name),
|
||||||
@ -131,6 +141,7 @@ class CaptureOperation(Operation):
|
|||||||
self.airgen.generate_cas(self.cas, clients=self.attacker_clients, at=self.attackers_starting_position)
|
self.airgen.generate_cas(self.cas, clients=self.attacker_clients, at=self.attackers_starting_position)
|
||||||
self.airgen.generate_cas_escort(self.escort, clients=self.attacker_clients, at=self.attackers_starting_position)
|
self.airgen.generate_cas_escort(self.escort, clients=self.attacker_clients, at=self.attackers_starting_position)
|
||||||
|
|
||||||
|
self.visualgen.generate_target_smokes(self.to_cp)
|
||||||
super(CaptureOperation, self).generate()
|
super(CaptureOperation, self).generate()
|
||||||
|
|
||||||
|
|
||||||
@ -152,6 +163,8 @@ class InterceptOperation(Operation):
|
|||||||
|
|
||||||
def prepare(self, terrain: dcs.terrain.Terrain, is_quick: bool):
|
def prepare(self, terrain: dcs.terrain.Terrain, is_quick: bool):
|
||||||
super(InterceptOperation, self).prepare(terrain, is_quick)
|
super(InterceptOperation, self).prepare(terrain, is_quick)
|
||||||
|
self.defenders_starting_position = None
|
||||||
|
|
||||||
conflict = Conflict.intercept_conflict(
|
conflict = Conflict.intercept_conflict(
|
||||||
attacker=self.mission.country(self.attacker_name),
|
attacker=self.mission.country(self.attacker_name),
|
||||||
defender=self.mission.country(self.defender_name),
|
defender=self.mission.country(self.defender_name),
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
import typing
|
import typing
|
||||||
import random
|
import random
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, time
|
||||||
|
|
||||||
from dcs.mission import Mission
|
from dcs.mission import Mission
|
||||||
from dcs.triggers import *
|
from dcs.triggers import *
|
||||||
from dcs.condition import *
|
from dcs.condition import *
|
||||||
from dcs.action import *
|
from dcs.action import *
|
||||||
from dcs.task import *
|
from dcs.unit import Skill
|
||||||
|
|
||||||
|
from game import db
|
||||||
from theater.weatherforecast import WeatherForecast
|
from theater.weatherforecast import WeatherForecast
|
||||||
from theater.conflicttheater import Conflict
|
from theater.conflicttheater import Conflict
|
||||||
|
|
||||||
@ -23,35 +24,27 @@ RANDOM_TIME = {
|
|||||||
|
|
||||||
RANDOM_WEATHER = {
|
RANDOM_WEATHER = {
|
||||||
0: 5, # thunderstorm
|
0: 5, # thunderstorm
|
||||||
1: 20, # heavy rain
|
1: 10, # heavy rain
|
||||||
2: 30, # rain
|
2: 20, # rain
|
||||||
3: 100, # random dynamic
|
3: 100, # random dynamic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class EnvironmentSettingsGenerator:
|
class SettingsGenerator:
|
||||||
def __init__(self, mission: Mission, conflict: Conflict, game):
|
def __init__(self, mission: Mission, conflict: Conflict, game):
|
||||||
self.mission = mission
|
self.mission = mission
|
||||||
self.conflict = conflict
|
self.conflict = conflict
|
||||||
self.game = game
|
self.game = game
|
||||||
|
|
||||||
def _gen_random_time(self):
|
def _gen_random_time(self):
|
||||||
start_time = datetime.today()
|
start_time = datetime.combine(datetime.today(), time())
|
||||||
daytime_map = {
|
time_range = None
|
||||||
"day": timedelta(hours=random.randrange(9, 18)),
|
|
||||||
"night": timedelta(hours=random.randrange(-3, 6)),
|
|
||||||
"dusk": timedelta(hours=random.randrange(18, 21)),
|
|
||||||
"dawn": timedelta(hours=random.randrange(6, 9)),
|
|
||||||
}
|
|
||||||
|
|
||||||
time_period = None
|
|
||||||
for k, v in RANDOM_TIME.items():
|
for k, v in RANDOM_TIME.items():
|
||||||
if random.randint(0, 100) <= v:
|
if random.randint(0, 100) <= v:
|
||||||
time_period = k
|
time_range = self.game.theater.daytime_map[k]
|
||||||
break
|
break
|
||||||
|
|
||||||
print("generated {}".format(time_period))
|
start_time += timedelta(hours=random.randint(*time_range))
|
||||||
start_time += daytime_map[time_period]
|
|
||||||
self.mission.start_time = start_time
|
self.mission.start_time = start_time
|
||||||
|
|
||||||
def _gen_random_weather(self):
|
def _gen_random_weather(self):
|
||||||
@ -102,6 +95,16 @@ class EnvironmentSettingsGenerator:
|
|||||||
continue
|
continue
|
||||||
self.mission.terrain.airport_by_id(cp.at.id).set_coalition(cp.captured and player_coalition or enemy_coalition)
|
self.mission.terrain.airport_by_id(cp.at.id).set_coalition(cp.captured and player_coalition or enemy_coalition)
|
||||||
|
|
||||||
|
def _set_skill(self, player_coalition: str, enemy_coalition: str):
|
||||||
|
for coalition_name, coalition in self.mission.coalition.items():
|
||||||
|
skill_level = player_coalition == coalition_name and self.game.player_skill or self.game.enemy_skill
|
||||||
|
for country in coalition.countries.values():
|
||||||
|
for plane_group in country.plane_group:
|
||||||
|
plane_group.set_skill(Skill(skill_level))
|
||||||
|
|
||||||
|
for vehicle_group in country.vehicle_group:
|
||||||
|
vehicle_group.set_skill(Skill(skill_level))
|
||||||
|
|
||||||
def generate(self, is_quick: bool):
|
def generate(self, is_quick: bool):
|
||||||
player_coalition = self.game.player == "USA" and "blue" or "red"
|
player_coalition = self.game.player == "USA" and "blue" or "red"
|
||||||
enemy_coalition = player_coalition == "blue" and "red" or "blue"
|
enemy_coalition = player_coalition == "blue" and "red" or "blue"
|
||||||
@ -111,6 +114,7 @@ class EnvironmentSettingsGenerator:
|
|||||||
|
|
||||||
self._gen_random_time()
|
self._gen_random_time()
|
||||||
self._gen_random_weather()
|
self._gen_random_weather()
|
||||||
|
self._set_skill(player_coalition, enemy_coalition)
|
||||||
self._set_allegiances(player_coalition, enemy_coalition)
|
self._set_allegiances(player_coalition, enemy_coalition)
|
||||||
|
|
||||||
if not is_quick:
|
if not is_quick:
|
||||||
126
gen/visualgen.py
Normal file
126
gen/visualgen.py
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
import typing
|
||||||
|
import random
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
from dcs.mission import Mission
|
||||||
|
from dcs.statics import *
|
||||||
|
from dcs.unit import Static
|
||||||
|
|
||||||
|
from theater.conflicttheater import Conflict
|
||||||
|
#from game.game import Game
|
||||||
|
|
||||||
|
|
||||||
|
class Smoke(unittype.StaticType):
|
||||||
|
id = "big_smoke"
|
||||||
|
category = "Effects"
|
||||||
|
name = "big_smoke"
|
||||||
|
shape_name = 2
|
||||||
|
rate = 100
|
||||||
|
|
||||||
|
|
||||||
|
class BigSmoke(unittype.StaticType):
|
||||||
|
id = "big_smoke"
|
||||||
|
category = "Effects"
|
||||||
|
name = "big_smoke"
|
||||||
|
shape_name = 3
|
||||||
|
rate = 100
|
||||||
|
|
||||||
|
|
||||||
|
class MassiveSmoke(unittype.StaticType):
|
||||||
|
id = "big_smoke"
|
||||||
|
category = "Effects"
|
||||||
|
name = "big_smoke"
|
||||||
|
shape_name = 4
|
||||||
|
rate = 100
|
||||||
|
|
||||||
|
|
||||||
|
def __monkey_static_dict(self: Static):
|
||||||
|
global __original_static_dict
|
||||||
|
|
||||||
|
d = __original_static_dict(self)
|
||||||
|
if self.type == "big_smoke":
|
||||||
|
d["effectPreset"] = self.shape_name
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
__original_static_dict = Static.dict
|
||||||
|
Static.dict = __monkey_static_dict
|
||||||
|
|
||||||
|
FRONT_SMOKE_MIN_DISTANCE = 10000
|
||||||
|
FRONT_SMOKE_DISTANCE_FACTOR = 0.75
|
||||||
|
FRONT_SMOKE_LENGTH = 80000
|
||||||
|
FRONT_SMOKE_SPACING = 600
|
||||||
|
FRONT_SMOKE_RANDOM_SPREAD = 1200
|
||||||
|
FRONT_SMOKE_TYPE_CHANCES = {
|
||||||
|
5: MassiveSmoke,
|
||||||
|
40: BigSmoke,
|
||||||
|
100: Smoke,
|
||||||
|
}
|
||||||
|
|
||||||
|
DESTINATION_SMOKE_AMOUNT_FACTOR = 0.03
|
||||||
|
DESTINATION_SMOKE_DISTANCE_FACTOR = 1
|
||||||
|
DESTINATION_SMOKE_TYPE_CHANCES = {
|
||||||
|
5: BigSmoke,
|
||||||
|
100: Smoke,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def turn_heading(heading, fac):
|
||||||
|
heading += fac
|
||||||
|
if heading > 359:
|
||||||
|
heading = heading - 359
|
||||||
|
if heading < 0:
|
||||||
|
heading = 359 + heading
|
||||||
|
return heading
|
||||||
|
|
||||||
|
|
||||||
|
class VisualGenerator:
|
||||||
|
game = None # type: Game
|
||||||
|
|
||||||
|
def __init__(self, mission: Mission, conflict: Conflict, game):
|
||||||
|
self.mission = mission
|
||||||
|
self.conflict = conflict
|
||||||
|
self.game = game
|
||||||
|
|
||||||
|
def _generate_frontline_smokes(self):
|
||||||
|
for from_cp, to_cp in self.game.theater.conflicts():
|
||||||
|
distance = max(from_cp.position.distance_to_point(to_cp.position) * FRONT_SMOKE_DISTANCE_FACTOR * to_cp.base.strength, FRONT_SMOKE_MIN_DISTANCE)
|
||||||
|
heading = to_cp.position.heading_between_point(from_cp.position)
|
||||||
|
point = to_cp.position.point_from_heading(heading, distance)
|
||||||
|
plane_start = point.point_from_heading(turn_heading(heading, 90), FRONT_SMOKE_LENGTH / 2)
|
||||||
|
|
||||||
|
for offset in range(0, FRONT_SMOKE_LENGTH, FRONT_SMOKE_SPACING):
|
||||||
|
position = plane_start.point_from_heading(turn_heading(heading, - 90), offset)
|
||||||
|
|
||||||
|
for k, v in FRONT_SMOKE_TYPE_CHANCES.items():
|
||||||
|
if random.randint(0, 100) <= k:
|
||||||
|
pos = position.random_point_within(FRONT_SMOKE_RANDOM_SPREAD, FRONT_SMOKE_RANDOM_SPREAD)
|
||||||
|
if not self.game.theater.is_on_land(pos):
|
||||||
|
break
|
||||||
|
|
||||||
|
self.mission.static_group(
|
||||||
|
self.mission.country(self.game.enemy),
|
||||||
|
"",
|
||||||
|
_type=v,
|
||||||
|
position=pos)
|
||||||
|
break
|
||||||
|
|
||||||
|
def generate_target_smokes(self, target):
|
||||||
|
spread = target.size * DESTINATION_SMOKE_DISTANCE_FACTOR
|
||||||
|
for _ in range(0, int(target.size * DESTINATION_SMOKE_AMOUNT_FACTOR * (1.1 - target.base.strength))):
|
||||||
|
for k, v in DESTINATION_SMOKE_TYPE_CHANCES.items():
|
||||||
|
if random.randint(0, 100) <= k:
|
||||||
|
position = target.position.random_point_within(0, spread)
|
||||||
|
if not self.game.theater.is_on_land(position):
|
||||||
|
break
|
||||||
|
|
||||||
|
self.mission.static_group(
|
||||||
|
self.mission.country(self.game.enemy),
|
||||||
|
"",
|
||||||
|
_type=v,
|
||||||
|
position=position)
|
||||||
|
|
||||||
|
break
|
||||||
|
|
||||||
|
def generate(self):
|
||||||
|
self._generate_frontline_smokes()
|
||||||
BIN
resources/cau_terrain.miz
Normal file
BIN
resources/cau_terrain.miz
Normal file
Binary file not shown.
BIN
resources/caulandmap.p
Normal file
BIN
resources/caulandmap.p
Normal file
Binary file not shown.
14
resources/generate_landmap.py
Normal file
14
resources/generate_landmap.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import pickle
|
||||||
|
|
||||||
|
from dcs.mission import Mission
|
||||||
|
from dcs.terrain import PersianGulf
|
||||||
|
|
||||||
|
m = Mission()
|
||||||
|
m.load_file("./gulf_terrain.miz")
|
||||||
|
|
||||||
|
landmap = []
|
||||||
|
for plane_group in m.country("USA").plane_group:
|
||||||
|
landmap.append([(x.position.x, x.position.y) for x in plane_group.points])
|
||||||
|
|
||||||
|
with open("gulflandmap.p", "wb") as f:
|
||||||
|
pickle.dump(landmap, f)
|
||||||
BIN
resources/gulf_terrain.miz
Normal file
BIN
resources/gulf_terrain.miz
Normal file
Binary file not shown.
BIN
resources/gulflandmap.p
Normal file
BIN
resources/gulflandmap.p
Normal file
Binary file not shown.
BIN
resources/nevada.gif
Normal file
BIN
resources/nevada.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 117 KiB |
BIN
resources/persiangulf.gif
Normal file
BIN
resources/persiangulf.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 80 KiB |
@ -127,7 +127,6 @@ class Base:
|
|||||||
|
|
||||||
def commit_losses(self, units_lost: typing.Dict[typing.Any, int]):
|
def commit_losses(self, units_lost: typing.Dict[typing.Any, int]):
|
||||||
for unit_type, count in units_lost.items():
|
for unit_type, count in units_lost.items():
|
||||||
target_array = None
|
|
||||||
if unit_type in self.aircraft:
|
if unit_type in self.aircraft:
|
||||||
target_array = self.aircraft
|
target_array = self.aircraft
|
||||||
elif unit_type in self.armor:
|
elif unit_type in self.armor:
|
||||||
@ -164,3 +163,7 @@ class Base:
|
|||||||
|
|
||||||
def assemble_defense(self, factor: float) -> typing.Dict[Armor, int]:
|
def assemble_defense(self, factor: float) -> typing.Dict[Armor, int]:
|
||||||
return self._find_best_armor(CAP, math.ceil(self.total_armor * factor * self.strength))
|
return self._find_best_armor(CAP, math.ceil(self.total_armor * factor * self.strength))
|
||||||
|
|
||||||
|
def assemble_aa(self) -> typing.Dict[AirDefence, int]:
|
||||||
|
count = int(self.total_aa * (self.strength > 0.2 and self.strength or 0))
|
||||||
|
return self._find_best_unit(self.aa, AirDefence, count)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
from dcs.terrain import caucasus
|
from dcs.terrain import caucasus
|
||||||
from dcs import mapping
|
from dcs import mapping
|
||||||
|
|
||||||
|
from .landmap import *
|
||||||
from .conflicttheater import *
|
from .conflicttheater import *
|
||||||
from .base import *
|
from .base import *
|
||||||
|
|
||||||
@ -10,6 +11,13 @@ class CaucasusTheater(ConflictTheater):
|
|||||||
overview_image = "caumap.gif"
|
overview_image = "caumap.gif"
|
||||||
reference_points = {(-317948.32727306, 635639.37385346): (282.5, 319),
|
reference_points = {(-317948.32727306, 635639.37385346): (282.5, 319),
|
||||||
(-355692.3067714, 617269.96285781): (269, 352), }
|
(-355692.3067714, 617269.96285781): (269, 352), }
|
||||||
|
landmap_poly = load_poly("resources\\caulandmap.p")
|
||||||
|
daytime_map = {
|
||||||
|
"dawn": (6, 9),
|
||||||
|
"day": (9, 18),
|
||||||
|
"dusk": (18, 21),
|
||||||
|
"night": (0, 5),
|
||||||
|
}
|
||||||
|
|
||||||
soganlug = ControlPoint.from_airport(caucasus.Soganlug, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW)
|
soganlug = ControlPoint.from_airport(caucasus.Soganlug, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW)
|
||||||
kutaisi = ControlPoint.from_airport(caucasus.Kutaisi, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW)
|
kutaisi = ControlPoint.from_airport(caucasus.Kutaisi, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW)
|
||||||
@ -32,7 +40,7 @@ class CaucasusTheater(ConflictTheater):
|
|||||||
mineralnye = ControlPoint.from_airport(caucasus.Mineralnye_Vody, ALL_RADIALS, SIZE_BIG, IMPORTANCE_MEDIUM)
|
mineralnye = ControlPoint.from_airport(caucasus.Mineralnye_Vody, ALL_RADIALS, SIZE_BIG, IMPORTANCE_MEDIUM)
|
||||||
mozdok = ControlPoint.from_airport(caucasus.Mozdok, ALL_RADIALS, SIZE_BIG, IMPORTANCE_MEDIUM)
|
mozdok = ControlPoint.from_airport(caucasus.Mozdok, ALL_RADIALS, SIZE_BIG, IMPORTANCE_MEDIUM)
|
||||||
|
|
||||||
carrier_1 = ControlPoint.carrier("Carrier", mapping.Point(-355810.6875, 516399.1875))
|
carrier_1 = ControlPoint.carrier("Carrier", mapping.Point(-305810.6875, 406399.1875))
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(CaucasusTheater, self).__init__()
|
super(CaucasusTheater, self).__init__()
|
||||||
@ -63,3 +71,9 @@ class CaucasusTheater(ConflictTheater):
|
|||||||
self.carrier_1.captured = True
|
self.carrier_1.captured = True
|
||||||
self.soganlug.captured = True
|
self.soganlug.captured = True
|
||||||
|
|
||||||
|
self.sukhumi.captured = True
|
||||||
|
self.gudauta.base.strength = 0.5
|
||||||
|
|
||||||
|
self.kobuleti.captured = True
|
||||||
|
self.batumi.base.strength = 0.15
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import itertools
|
|||||||
|
|
||||||
import dcs
|
import dcs
|
||||||
|
|
||||||
|
from .landmap import ray_tracing
|
||||||
from .controlpoint import *
|
from .controlpoint import *
|
||||||
|
|
||||||
SIZE_TINY = 150
|
SIZE_TINY = 150
|
||||||
@ -31,6 +32,8 @@ class ConflictTheater:
|
|||||||
controlpoints = None # type: typing.Collection[ControlPoint]
|
controlpoints = None # type: typing.Collection[ControlPoint]
|
||||||
reference_points = None # type: typing.Dict
|
reference_points = None # type: typing.Dict
|
||||||
overview_image = None # type: str
|
overview_image = None # type: str
|
||||||
|
landmap_poly = None
|
||||||
|
daytime_map = None # type: typing.Dict[str, typing.Tuple[int, int]]
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.controlpoints = []
|
self.controlpoints = []
|
||||||
@ -41,6 +44,15 @@ class ConflictTheater:
|
|||||||
|
|
||||||
self.controlpoints.append(point)
|
self.controlpoints.append(point)
|
||||||
|
|
||||||
|
def is_on_land(self, point: Point) -> bool:
|
||||||
|
if not self.landmap_poly:
|
||||||
|
return True
|
||||||
|
|
||||||
|
for poly in self.landmap_poly:
|
||||||
|
return ray_tracing(point.x, point.y, poly)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def player_points(self) -> typing.Collection[ControlPoint]:
|
def player_points(self) -> typing.Collection[ControlPoint]:
|
||||||
return [point for point in self.controlpoints if point.captured]
|
return [point for point in self.controlpoints if point.captured]
|
||||||
|
|
||||||
|
|||||||
24
theater/landmap.py
Normal file
24
theater/landmap.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import pickle
|
||||||
|
|
||||||
|
|
||||||
|
def load_poly(filename: str):
|
||||||
|
with open(filename, "rb") as f:
|
||||||
|
return pickle.load(f)
|
||||||
|
|
||||||
|
|
||||||
|
def ray_tracing(x, y, poly):
|
||||||
|
n = len(poly)
|
||||||
|
inside = False
|
||||||
|
xints = 0.0
|
||||||
|
p1x, p1y = poly[0]
|
||||||
|
for i in range(n+1):
|
||||||
|
p2x, p2y = poly[i % n]
|
||||||
|
if y > min(p1y, p2y):
|
||||||
|
if y <= max(p1y, p2y):
|
||||||
|
if x <= max(p1x, p2x):
|
||||||
|
if p1y != p2y:
|
||||||
|
xints = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
|
||||||
|
if p1x == p2x or x <= xints:
|
||||||
|
inside = not inside
|
||||||
|
p1x, p1y = p2x, p2y
|
||||||
|
return inside
|
||||||
@ -10,6 +10,12 @@ class NevadaTheater(ConflictTheater):
|
|||||||
overview_image = "nevada.gif"
|
overview_image = "nevada.gif"
|
||||||
reference_points = {(nevada.Mina_Airport_3Q0.position.x, nevada.Mina_Airport_3Q0.position.y): (45, -360),
|
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), }
|
(nevada.Laughlin_Airport.position.x, nevada.Laughlin_Airport.position.y): (440, 80), }
|
||||||
|
daytime_map = {
|
||||||
|
"dawn": (4, 6),
|
||||||
|
"day": (6, 17),
|
||||||
|
"dusk": (17, 19),
|
||||||
|
"night": (0, 5),
|
||||||
|
}
|
||||||
|
|
||||||
mina = ControlPoint.from_airport(nevada.Mina_Airport_3Q0, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW)
|
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 = ControlPoint.from_airport(nevada.Tonopah_Airport, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW)
|
||||||
@ -45,3 +51,5 @@ class NevadaTheater(ConflictTheater):
|
|||||||
self.add_controlpoint(self.laughlin, connected_to=[self.jean, self.las_vegas])
|
self.add_controlpoint(self.laughlin, connected_to=[self.jean, self.las_vegas])
|
||||||
|
|
||||||
self.mina.captured = True
|
self.mina.captured = True
|
||||||
|
self.pahute_mesa.captured = True
|
||||||
|
self.groom_lake.captured = True
|
||||||
|
|||||||
@ -3,6 +3,7 @@ from dcs import mapping
|
|||||||
|
|
||||||
from .conflicttheater import *
|
from .conflicttheater import *
|
||||||
from .base import *
|
from .base import *
|
||||||
|
from .landmap import load_poly
|
||||||
|
|
||||||
|
|
||||||
class PersianGulfTheater(ConflictTheater):
|
class PersianGulfTheater(ConflictTheater):
|
||||||
@ -10,6 +11,13 @@ class PersianGulfTheater(ConflictTheater):
|
|||||||
overview_image = "persiangulf.gif"
|
overview_image = "persiangulf.gif"
|
||||||
reference_points = {(persiangulf.Sir_Abu_Nuayr.position.x, persiangulf.Sir_Abu_Nuayr.position.y): (351, 115),
|
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), }
|
(persiangulf.Sirri_Island.position.x, persiangulf.Sirri_Island.position.y): (389, 22), }
|
||||||
|
landmap_poly = load_poly("resources\\gulflandmap.p")
|
||||||
|
daytime_map = {
|
||||||
|
"dawn": (5, 7),
|
||||||
|
"day": (7, 17),
|
||||||
|
"dusk": (17, 19),
|
||||||
|
"night": (0, 5),
|
||||||
|
}
|
||||||
|
|
||||||
al_dhafra = ControlPoint.from_airport(persiangulf.Al_Dhafra_AB, ALL_RADIALS, SIZE_BIG, IMPORTANCE_LOW)
|
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_maktoum = ControlPoint.from_airport(persiangulf.Al_Maktoum_Intl, ALL_RADIALS, SIZE_BIG, IMPORTANCE_LOW)
|
||||||
|
|||||||
@ -1,11 +1,20 @@
|
|||||||
|
import math
|
||||||
|
|
||||||
from theater.base import *
|
from theater.base import *
|
||||||
from theater.conflicttheater import *
|
from theater.conflicttheater import *
|
||||||
|
|
||||||
UNIT_VARIETY = 3
|
UNIT_VARIETY = 3
|
||||||
UNIT_AMOUNT_FACTOR = 16
|
UNIT_AMOUNT_FACTOR = 16
|
||||||
|
|
||||||
|
COUNT_BY_TASK = {
|
||||||
|
CAP: 12,
|
||||||
|
FighterSweep: 16,
|
||||||
|
CAS: 8,
|
||||||
|
AirDefence: 0.5,
|
||||||
|
}
|
||||||
|
|
||||||
def generate_initial(theater: ConflictTheater, enemy: str):
|
|
||||||
|
def generate_initial(theater: ConflictTheater, enemy: str, sams: bool):
|
||||||
for cp in theater.enemy_points():
|
for cp in theater.enemy_points():
|
||||||
if cp.captured:
|
if cp.captured:
|
||||||
continue
|
continue
|
||||||
@ -15,10 +24,14 @@ def generate_initial(theater: ConflictTheater, enemy: str):
|
|||||||
assert cp.importance >= IMPORTANCE_LOW, "invalid importance {}".format(cp.importance)
|
assert cp.importance >= IMPORTANCE_LOW, "invalid importance {}".format(cp.importance)
|
||||||
|
|
||||||
importance_factor = (cp.importance - IMPORTANCE_LOW) / (IMPORTANCE_HIGH - IMPORTANCE_LOW)
|
importance_factor = (cp.importance - IMPORTANCE_LOW) / (IMPORTANCE_HIGH - IMPORTANCE_LOW)
|
||||||
variety = int(UNIT_VARIETY + UNIT_VARIETY * importance_factor / 2)
|
variety = int(UNIT_VARIETY)
|
||||||
unittypes = db.choose_units(task, importance_factor, variety, enemy)
|
unittypes = db.choose_units(task, importance_factor, variety, enemy)
|
||||||
|
|
||||||
count = max(int(importance_factor * UNIT_AMOUNT_FACTOR), 1)
|
if not sams:
|
||||||
|
unittypes = [x for x in unittypes if x not in db.SAM_BAN]
|
||||||
|
|
||||||
|
count = max(COUNT_BY_TASK[task] * importance_factor, 1)
|
||||||
count_per_type = max(int(float(count) / len(unittypes)), 1)
|
count_per_type = max(int(float(count) / len(unittypes)), 1)
|
||||||
for unit_type in unittypes:
|
for unit_type in unittypes:
|
||||||
|
print("{} - {} {}".format(cp.name, db.unit_type_name(unit_type), count_per_type))
|
||||||
cp.base.commision_units({unit_type: count_per_type})
|
cp.base.commision_units({unit_type: count_per_type})
|
||||||
|
|||||||
@ -7,3 +7,26 @@ from ui.window import *
|
|||||||
class ConfigurationMenu(Menu):
|
class ConfigurationMenu(Menu):
|
||||||
def __init__(self, window: Window, parent, game: Game):
|
def __init__(self, window: Window, parent, game: Game):
|
||||||
super(ConfigurationMenu, self).__init__(window, parent, game)
|
super(ConfigurationMenu, self).__init__(window, parent, game)
|
||||||
|
self.frame = window.right_pane
|
||||||
|
self.player_skill_var = StringVar()
|
||||||
|
self.player_skill_var.set(self.game.player_skill)
|
||||||
|
|
||||||
|
self.enemy_skill_var = StringVar()
|
||||||
|
self.enemy_skill_var.set(self.game.enemy_skill)
|
||||||
|
|
||||||
|
def dismiss(self):
|
||||||
|
self.game.player_skill = self.player_skill_var.get()
|
||||||
|
self.game.enemy_skill = self.enemy_skill_var.get()
|
||||||
|
super(ConfigurationMenu, self).dismiss()
|
||||||
|
|
||||||
|
def display(self):
|
||||||
|
self.window.clear_right_pane()
|
||||||
|
|
||||||
|
Label(self.frame, text="Player coalition skill").grid(row=0, column=0)
|
||||||
|
Label(self.frame, text="Enemy coalition skill").grid(row=1, column=0)
|
||||||
|
|
||||||
|
OptionMenu(self.frame, self.player_skill_var, "Average", "Good", "High", "Excellent").grid(row=0, column=1)
|
||||||
|
OptionMenu(self.frame, self.enemy_skill_var, "Average", "Good", "High", "Excellent").grid(row=1, column=1)
|
||||||
|
|
||||||
|
Button(self.frame, text="Back", command=self.dismiss).grid(row=2, column=0, columnspan=1)
|
||||||
|
|
||||||
|
|||||||
@ -30,9 +30,9 @@ class EventMenu(Menu):
|
|||||||
self.window.clear_right_pane()
|
self.window.clear_right_pane()
|
||||||
row = 0
|
row = 0
|
||||||
|
|
||||||
def label(text, _row=None, _column=None):
|
def label(text, _row=None, _column=None, sticky=None):
|
||||||
nonlocal row
|
nonlocal row
|
||||||
Label(self.frame, text=text).grid(row=_row and _row or row, column=_column and _column or 0)
|
Label(self.frame, text=text).grid(row=_row and _row or row, column=_column and _column or 0, sticky=sticky)
|
||||||
|
|
||||||
if _row is None:
|
if _row is None:
|
||||||
row += 1
|
row += 1
|
||||||
@ -62,7 +62,12 @@ class EventMenu(Menu):
|
|||||||
|
|
||||||
row += 1
|
row += 1
|
||||||
|
|
||||||
Checkbutton(self.frame, text="AWACS", var=self.awacs).grid(row=row, column=2)
|
Button(self.frame, text="Commit", command=self.start).grid(column=1, row=row, sticky=E)
|
||||||
|
Button(self.frame, text="Back", command=self.dismiss).grid(column=2, row=row, sticky=E)
|
||||||
|
|
||||||
|
awacs_enabled = self.game.budget >= AWACS_BUDGET_COST and NORMAL or DISABLED
|
||||||
|
Checkbutton(self.frame, text="AWACS ({}m)".format(AWACS_BUDGET_COST), var=self.awacs, state=awacs_enabled).grid(row=row, column=0, sticky=W)
|
||||||
|
|
||||||
row += 1
|
row += 1
|
||||||
|
|
||||||
label("Aircraft")
|
label("Aircraft")
|
||||||
@ -76,17 +81,14 @@ class EventMenu(Menu):
|
|||||||
scrable_row(unit_type, count)
|
scrable_row(unit_type, count)
|
||||||
|
|
||||||
if not self.base.total_planes:
|
if not self.base.total_planes:
|
||||||
label("None")
|
label("None", sticky=W)
|
||||||
|
|
||||||
label("Armor")
|
label("Armor")
|
||||||
for unit_type, count in self.base.armor.items():
|
for unit_type, count in self.base.armor.items():
|
||||||
scramble_armor_row(unit_type, count)
|
scramble_armor_row(unit_type, count)
|
||||||
|
|
||||||
if not self.base.total_armor:
|
if not self.base.total_armor:
|
||||||
label("None")
|
label("None", sticky=W)
|
||||||
|
|
||||||
Button(self.frame, text="Commit", command=self.start).grid(column=0, row=row)
|
|
||||||
Button(self.frame, text="Back", command=self.dismiss).grid(column=2, row=row)
|
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
if self.awacs.get() == 1:
|
if self.awacs.get() == 1:
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import pickle
|
|||||||
|
|
||||||
from ui.basemenu import *
|
from ui.basemenu import *
|
||||||
from ui.overviewcanvas import *
|
from ui.overviewcanvas import *
|
||||||
|
from ui.configurationmenu import *
|
||||||
|
|
||||||
from game.game import *
|
from game.game import *
|
||||||
from userdata import persistency
|
from userdata import persistency
|
||||||
@ -41,7 +42,8 @@ class MainMenu(Menu):
|
|||||||
row += 1
|
row += 1
|
||||||
Separator(self.frame, orient='horizontal').grid(row=row, sticky=EW); row += 1
|
Separator(self.frame, orient='horizontal').grid(row=row, sticky=EW); row += 1
|
||||||
|
|
||||||
Button(self.frame, text="Pass turn", command=self.pass_turn).grid(column=0, row=0, sticky=NE)
|
Button(self.frame, text="Configuration", command=self.configuration_menu).grid(column=0, row=0, sticky=NE)
|
||||||
|
Button(self.frame, text="Pass turn", command=self.pass_turn).grid(column=0, row=0, sticky=N)
|
||||||
Label(self.frame, text="Budget: {}m (+{}m)".format(self.game.budget, self.game.budget_reward_amount)).grid(column=0, row=0, sticky=NW)
|
Label(self.frame, text="Budget: {}m (+{}m)".format(self.game.budget, self.game.budget_reward_amount)).grid(column=0, row=0, sticky=NW)
|
||||||
Separator(self.frame, orient='horizontal').grid(row=row, sticky=EW); row += 1
|
Separator(self.frame, orient='horizontal').grid(row=row, sticky=EW); row += 1
|
||||||
|
|
||||||
@ -58,10 +60,16 @@ class MainMenu(Menu):
|
|||||||
self.game.pass_turn(no_action=True)
|
self.game.pass_turn(no_action=True)
|
||||||
self.display()
|
self.display()
|
||||||
|
|
||||||
|
def configuration_menu(self):
|
||||||
|
ConfigurationMenu(self.window, self, self.game).display()
|
||||||
|
|
||||||
def start_event(self, event) -> typing.Callable:
|
def start_event(self, event) -> typing.Callable:
|
||||||
return lambda: EventMenu(self.window, self, self.game, event).display()
|
return lambda: EventMenu(self.window, self, self.game, event).display()
|
||||||
|
|
||||||
def go_cp(self, cp: ControlPoint):
|
def go_cp(self, cp: ControlPoint):
|
||||||
|
if not cp.captured:
|
||||||
|
return
|
||||||
|
|
||||||
if self.basemenu:
|
if self.basemenu:
|
||||||
self.basemenu.dismiss()
|
self.basemenu.dismiss()
|
||||||
self.basemenu = None
|
self.basemenu = None
|
||||||
|
|||||||
@ -7,6 +7,7 @@ from ui.window import *
|
|||||||
class NewGameMenu(Menu):
|
class NewGameMenu(Menu):
|
||||||
selected_country = None # type: IntVar
|
selected_country = None # type: IntVar
|
||||||
selected_terrain = None # type: IntVar
|
selected_terrain = None # type: IntVar
|
||||||
|
sams = True
|
||||||
|
|
||||||
def __init__(self, window: Window, callback: typing.Callable):
|
def __init__(self, window: Window, callback: typing.Callable):
|
||||||
super(NewGameMenu, self).__init__(window, None, None)
|
super(NewGameMenu, self).__init__(window, None, None)
|
||||||
@ -19,6 +20,9 @@ class NewGameMenu(Menu):
|
|||||||
self.selected_terrain = IntVar()
|
self.selected_terrain = IntVar()
|
||||||
self.selected_terrain.set(0)
|
self.selected_terrain.set(0)
|
||||||
|
|
||||||
|
self.sams = BooleanVar()
|
||||||
|
self.sams.set(1)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def player_country_name(self):
|
def player_country_name(self):
|
||||||
if self.selected_country.get() == 0:
|
if self.selected_country.get() == 0:
|
||||||
@ -53,7 +57,11 @@ class NewGameMenu(Menu):
|
|||||||
Radiobutton(self.frame, text="Caucasus", variable=self.selected_terrain, value=0).grid(row=1, 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="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)
|
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)
|
|
||||||
|
Label(self.frame, text="Options").grid(row=1, column=2)
|
||||||
|
Checkbutton(self.frame, text="SAMs", variable=self.sams).grid(row=1, column=2)
|
||||||
|
|
||||||
|
Button(self.frame, text="Proceed", command=self.proceed).grid(row=4, column=0, columnspan=3)
|
||||||
|
|
||||||
def proceed(self):
|
def proceed(self):
|
||||||
self.callback(self.player_country_name, self.enemy_country_name, self.terrain_name)
|
self.callback(self.player_country_name, self.enemy_country_name, self.terrain_name, bool(self.sams.get()))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user