frontline attack ops

This commit is contained in:
Vasyl Horbachenko 2018-07-16 23:58:01 +03:00
parent 1fbf4e292a
commit e4c3f8bce2
19 changed files with 205 additions and 206 deletions

View File

@ -17,45 +17,6 @@ from theater import start_generator
from userdata import persistency
"""
from dcs.lua.parse import *
a = loads(open("build/mission", "r").read())
b = loads(open("build/mission_workin.lua", "r").read())
def get(a, k):
b = a
for x in k.strip().split(" "):
if isinstance(a, dict):
y = a
a = a.get(x, None)
if a is None:
try:
a = y.get(int(x), None)
except:
pass
else:
break
if a is None:
pass
return a
def cycle(kk, ref, v):
if isinstance(v, dict):
for k, v in v.items():
cycle(kk + " " + str(k), ref, v)
elif isinstance(v, list):
for i, v in enumerate(v):
cycle(kk + " " + str(i), ref, v)
else:
if get(ref, kk) != v:
print(kk, v)
print(get(ref, kk))
cycle("", a, b)
sys.exit(0)
"""
persistency.setup(sys.argv[1])
dcs.planes.FlyingType.payload_dirs.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "resources\\payloads"))

View File

@ -448,6 +448,11 @@ def unitdict_split(unit_dict: UnitsDict, count: int):
if len(buffer_dict):
yield buffer_dict
def unitdict_restrict_count(unit_dict: UnitsDict, total_count: int) -> UnitsDict:
return list(unitdict_split(unit_dict, total_count))[0]
def _validate_db():
# check unit by task uniquity
total_set = set()

View File

@ -1,8 +1,8 @@
from .event import *
from .frontlinecas import *
from .frontlineattack import *
from .intercept import *
from .capture import *
from .baseattack import *
from .navalintercept import *
from .antiaastrike import *
from .groundattack import *
from .insurgentattack import *
from .infantrytransport import *

View File

@ -4,13 +4,13 @@ import random
from dcs.task import *
from game import db
from game.operation.capture import CaptureOperation
from game.operation.baseattack import BaseAttackOperation
from userdata.debriefing import Debriefing
from .event import Event
class CaptureEvent(Event):
class BaseAttackEvent(Event):
silent = True
BONUS_BASE = 15
STRENGTH_RECOVERY = 0.55
@ -28,7 +28,7 @@ class CaptureEvent(Event):
return not attackers_success
def commit(self, debriefing: Debriefing):
super(CaptureEvent, self).commit(debriefing)
super(BaseAttackEvent, self).commit(debriefing)
if self.is_successfull(debriefing):
if self.from_cp.captured:
self.to_cp.captured = True
@ -49,13 +49,13 @@ class CaptureEvent(Event):
escort = self.from_cp.base.scramble_sweep(self.game.settings.multiplier)
attackers = self.from_cp.base.armor
op = CaptureOperation(game=self.game,
attacker_name=self.attacker_name,
defender_name=self.defender_name,
attacker_clients={},
defender_clients=clients,
from_cp=self.from_cp,
to_cp=self.to_cp)
op = BaseAttackOperation(game=self.game,
attacker_name=self.attacker_name,
defender_name=self.defender_name,
attacker_clients={},
defender_clients=clients,
from_cp=self.from_cp,
to_cp=self.to_cp)
op.setup(cas=cas,
escort=escort,
@ -67,13 +67,13 @@ class CaptureEvent(Event):
self.operation = op
def player_attacking(self, cas: db.PlaneDict, escort: db.PlaneDict, armor: db.ArmorDict, clients: db.PlaneDict):
op = CaptureOperation(game=self.game,
attacker_name=self.attacker_name,
defender_name=self.defender_name,
attacker_clients=clients,
defender_clients={},
from_cp=self.from_cp,
to_cp=self.to_cp)
op = BaseAttackOperation(game=self.game,
attacker_name=self.attacker_name,
defender_name=self.defender_name,
attacker_clients=clients,
defender_clients={},
from_cp=self.from_cp,
to_cp=self.to_cp)
defenders = self.to_cp.base.scramble_sweep(self.game.settings.multiplier)
defenders.update(self.to_cp.base.scramble_cas(self.game.settings.multiplier))

View File

@ -0,0 +1,76 @@
import math
import random
from dcs.task import *
from dcs.vehicles import AirDefence
from game import *
from game.event import *
from game.operation.frontlineattack import FrontlineAttackOperation
from userdata.debriefing import Debriefing
class FrontlineAttackEvent(Event):
TARGET_VARIETY = 2
TARGET_AMOUNT_FACTOR = 0.5
ATTACKER_AMOUNT_FACTOR = 0.4
ATTACKER_DEFENDER_FACTOR = 0.7
STRENGTH_INFLUENCE = 0.3
SUCCESS_MIN_TARGETS = 3
defenders = None # type: db.ArmorDict
@property
def threat_description(self):
return "{} vehicles".format(self.to_cp.base.assemble_count())
def __str__(self):
return "Frontline attack from {} at {}".format(self.from_cp, self.to_cp)
def is_successfull(self, debriefing: Debriefing):
total_targets = sum(self.defenders.values())
destroyed_targets = 0
for unit, count in debriefing.destroyed_units[self.defender_name].items():
if unit in self.defenders:
destroyed_targets += count
if self.from_cp.captured:
return float(destroyed_targets) >= min(self.SUCCESS_MIN_TARGETS, total_targets)
else:
return float(destroyed_targets) < min(self.SUCCESS_MIN_TARGETS, total_targets)
def commit(self, debriefing: Debriefing):
super(FrontlineAttackEvent, self).commit(debriefing)
if self.from_cp.captured:
if self.is_successfull(debriefing):
self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
else:
self.to_cp.base.affect_strength(+self.STRENGTH_INFLUENCE)
else:
if self.is_successfull(debriefing):
self.from_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
else:
self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
def skip(self):
if self.to_cp.captured:
self.to_cp.base.affect_strength(-0.1)
def player_attacking(self, armor: db.ArmorDict, strikegroup: db.PlaneDict, clients: db.PlaneDict):
self.defenders = self.to_cp.base.assemble_cap()
op = FrontlineAttackOperation(game=self.game,
attacker_name=self.attacker_name,
defender_name=self.defender_name,
attacker_clients=clients,
defender_clients={},
from_cp=self.from_cp,
to_cp=self.to_cp)
op.setup(target=self.defenders,
attackers=db.unitdict_restrict_count(armor, sum(self.defenders.values())),
strikegroup=strikegroup)
self.operation = op

View File

@ -1,91 +0,0 @@
import math
import random
from dcs.task import *
from dcs.vehicles import AirDefence
from game import *
from game.event import *
from game.operation.frontlinecas import FrontlineCASOperation
from userdata.debriefing import Debriefing
class FrontlineCASEvent(Event):
TARGET_VARIETY = 2
TARGET_AMOUNT_FACTOR = 0.5
ATTACKER_AMOUNT_FACTOR = 0.4
STRENGTH_INFLUENCE = 0.3
SUCCESS_MIN_TARGETS = 3
targets = None # type: db.ArmorDict
@property
def threat_description(self):
if not self.game.is_player_attack(self):
return "{} aicraft".format(self.from_cp.base.scramble_count(self.game.settings.multiplier, CAS))
else:
return super(FrontlineCASEvent, self).threat_description
def __str__(self):
return "Frontline CAS from {} at {}".format(self.from_cp, self.to_cp)
def is_successfull(self, debriefing: Debriefing):
total_targets = sum(self.targets.values())
destroyed_targets = 0
for unit, count in debriefing.destroyed_units[self.defender_name].items():
if unit in self.targets:
destroyed_targets += count
if self.from_cp.captured:
return float(destroyed_targets) >= min(self.SUCCESS_MIN_TARGETS, total_targets)
else:
return float(destroyed_targets) < min(self.SUCCESS_MIN_TARGETS, total_targets)
def commit(self, debriefing: Debriefing):
super(FrontlineCASEvent, self).commit(debriefing)
if self.from_cp.captured:
if self.is_successfull(debriefing):
self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
else:
self.to_cp.base.affect_strength(+self.STRENGTH_INFLUENCE)
else:
if self.is_successfull(debriefing):
self.from_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
else:
self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
def skip(self):
if self.to_cp.captured:
self.to_cp.base.affect_strength(-0.1)
def player_attacking(self, strikegroup: db.PlaneDict, clients: db.PlaneDict):
suitable_armor_targets = db.find_unittype(PinpointStrike, self.defender_name)
random.shuffle(suitable_armor_targets)
target_types = suitable_armor_targets[:self.TARGET_VARIETY]
typecount = max(math.floor(self.to_cp.base.assemble_count() * self.TARGET_AMOUNT_FACTOR), 1)
self.targets = {unittype: typecount for unittype in target_types}
defense_aa_unit = random.choice(self.game.commision_unit_types(self.to_cp, AirDefence))
self.targets[defense_aa_unit] = 1
suitable_armor_attackers = db.find_unittype(PinpointStrike, self.attacker_name)
random.shuffle(suitable_armor_attackers)
attacker_types = suitable_armor_attackers[:self.TARGET_VARIETY]
typecount = max(math.floor(self.from_cp.base.assemble_count() * self.ATTACKER_AMOUNT_FACTOR), 1)
attackers = {unittype: typecount for unittype in attacker_types}
op = FrontlineCASOperation(game=self.game,
attacker_name=self.attacker_name,
defender_name=self.defender_name,
attacker_clients=clients,
defender_clients={},
from_cp=self.from_cp,
to_cp=self.to_cp)
op.setup(target=self.targets,
attackers=attackers,
strikegroup=strikegroup)
self.operation = op

View File

@ -5,11 +5,11 @@ from dcs.task import *
from game import *
from game.event import *
from game.event.frontlinecas import FrontlineCASEvent
from game.operation.groundattack import GroundAttackOperation
from game.event.frontlineattack import FrontlineAttackEvent
from game.operation.insurgentattack import InsurgentAttackOperation
class GroundAttackEvent(FrontlineCASEvent):
class InsurgentAttackEvent(FrontlineAttackEvent):
def __str__(self):
return "Destroy insurgents at {}".format(self.to_cp)
@ -24,13 +24,13 @@ class GroundAttackEvent(FrontlineCASEvent):
typecount = max(math.floor(self.difficulty * self.TARGET_AMOUNT_FACTOR), 1)
self.targets = {unittype: typecount for unittype in unittypes}
op = GroundAttackOperation(game=self.game,
attacker_name=self.attacker_name,
defender_name=self.defender_name,
attacker_clients={},
defender_clients=clients,
from_cp=self.from_cp,
to_cp=self.to_cp)
op = InsurgentAttackOperation(game=self.game,
attacker_name=self.attacker_name,
defender_name=self.defender_name,
attacker_clients={},
defender_clients=clients,
from_cp=self.from_cp,
to_cp=self.to_cp)
op.setup(target=self.targets,
strikegroup=strikegroup)

View File

@ -39,17 +39,17 @@ For the enemy events, only 1 event of each type could be generated for a turn.
Events:
* CaptureEvent - capture base
* InterceptEvent - air intercept
* FrontlineCASEvent - frontline CAS
* FrontlineAttack - frontline attack
* GroundAttackEvent - destroy insurgents
* NavalInterceptEvent - naval intercept
* AntiAAStrikeEvent - anti-AA strike
* InfantryTransportEvent - helicopter infantry transport
"""
EVENT_PROBABILITIES = {
CaptureEvent: [100, 10],
BaseAttackEvent: [100, 10],
InterceptEvent: [25, 10],
FrontlineCASEvent: [250, 0],
GroundAttackEvent: [0, 10],
FrontlineAttackEvent: [100, 0],
InsurgentAttackEvent: [0, 10],
NavalInterceptEvent: [25, 10],
AntiAAStrikeEvent: [25, 10],
InfantryTransportEvent: [25, 0],
@ -130,7 +130,7 @@ class Game:
if event_class == NavalInterceptEvent:
if player_cp.radials == LAND:
continue
elif event_class == CaptureEvent:
elif event_class == BaseAttackEvent:
if enemy_cap_generated:
continue
if enemy_cp.base.total_armor == 0:

View File

@ -12,7 +12,7 @@ from gen.visualgen import *
from .operation import Operation
class CaptureOperation(Operation):
class BaseAttackOperation(Operation):
cas = None # type: db.PlaneDict
escort = None # type: db.PlaneDict
intercept = None # type: db.PlaneDict
@ -37,7 +37,7 @@ class CaptureOperation(Operation):
self.aa = aa
def prepare(self, terrain: dcs.terrain.Terrain, is_quick: bool):
super(CaptureOperation, self).prepare(terrain, is_quick)
super(BaseAttackOperation, self).prepare(terrain, is_quick)
self.defenders_starting_position = None
if self.game.player == self.defender_name:
@ -63,5 +63,5 @@ class CaptureOperation(Operation):
self.airgen.generate_strikegroup_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(BaseAttackOperation, self).generate()

View File

@ -18,7 +18,7 @@ from .operation import Operation
MAX_DISTANCE_BETWEEN_GROUPS = 12000
class FrontlineCASOperation(Operation):
class FrontlineAttackOperation(Operation):
attackers = None # type: db.ArmorDict
strikegroup = None # type: db.PlaneDict
target = None # type: db.ArmorDict
@ -32,7 +32,7 @@ class FrontlineCASOperation(Operation):
self.attackers = attackers
def prepare(self, terrain: Terrain, is_quick: bool):
super(FrontlineCASOperation, self).prepare(terrain, is_quick)
super(FrontlineAttackOperation, self).prepare(terrain, is_quick)
if self.defender_name == self.game.player:
self.attackers_starting_position = None
self.defenders_starting_position = None
@ -51,4 +51,4 @@ class FrontlineCASOperation(Operation):
def generate(self):
self.armorgen.generate_vec(self.attackers, self.target)
self.airgen.generate_cas_strikegroup(self.strikegroup, clients=self.attacker_clients, at=self.attackers_starting_position)
super(FrontlineCASOperation, self).generate()
super(FrontlineAttackOperation, self).generate()

View File

@ -13,7 +13,7 @@ from gen.conflictgen import Conflict
from .operation import Operation
class GroundAttackOperation(Operation):
class InsurgentAttackOperation(Operation):
strikegroup = None # type: db.PlaneDict
target = None # type: db.ArmorDict
@ -24,7 +24,7 @@ class GroundAttackOperation(Operation):
self.target = target
def prepare(self, terrain: Terrain, is_quick: bool):
super(GroundAttackOperation, self).prepare(terrain, is_quick)
super(InsurgentAttackOperation, self).prepare(terrain, is_quick)
conflict = Conflict.ground_attack_conflict(
attacker=self.mission.country(self.attacker_name),
@ -41,4 +41,4 @@ class GroundAttackOperation(Operation):
self.airgen.generate_defense(self.strikegroup, self.defender_clients, self.defenders_starting_position)
self.armorgen.generate(self.target, {})
super(GroundAttackOperation, self).generate()
super(InsurgentAttackOperation, self).generate()

View File

@ -1,3 +1,4 @@
from random import randint
from itertools import zip_longest
from game import db
@ -13,6 +14,10 @@ from dcs.country import *
SPREAD_DISTANCE_FACTOR = 0.1, 0.3
SPREAD_DISTANCE_SIZE_FACTOR = 0.1
FRONTLINE_CAS_FIGHTS_COUNT = 4, 8
FRONTLINE_CAS_GROUP_MIN = 1, 2
FRONTLINE_CAS_PADDING = 12000
class ArmorConflictGenerator:
def __init__(self, mission: Mission, conflict: Conflict):
@ -50,7 +55,7 @@ class ArmorConflictGenerator:
side=self.conflict.attackers_side,
unit=type,
count=count,
at=position.point_from_heading(self.conflict.heading - 90, 600),
at=position.point_from_heading(self.conflict.heading - 90, 5000),
to=position)
if defenders:
@ -59,7 +64,7 @@ class ArmorConflictGenerator:
side=self.conflict.defenders_side,
unit=type,
count=count,
at=position.point_from_heading(self.conflict.heading + 90, 600),
at=position.point_from_heading(self.conflict.heading + 90, 1000),
to=position)
def generate(self, attackers: db.ArmorDict, defenders: db.ArmorDict):
@ -78,16 +83,16 @@ class ArmorConflictGenerator:
at=self.conflict.ground_defenders_location)
def generate_vec(self, attackers: db.ArmorDict, defenders: db.ArmorDict):
defender_groups = list(db.unitdict_split(defenders, 6))
distance_between_groups = min(self.conflict.distance / len(defender_groups), 12000)
total_distance = distance_between_groups * len(defender_groups)
fights_count = randint(*FRONTLINE_CAS_FIGHTS_COUNT)
single_fight_defenders_count = min(int(sum(defenders.values()) / fights_count), randint(*FRONTLINE_CAS_GROUP_MIN))
defender_groups = list(db.unitdict_split(defenders, single_fight_defenders_count))
attacker_groups = list(db.unitdict_split(attackers,
int(sum(attackers.values()) / len(defender_groups))))
single_fight_attackers_count = min(int(sum(attackers.values()) / len(defender_groups)), randint(*FRONTLINE_CAS_GROUP_MIN))
attacker_groups = list(db.unitdict_split(attackers, single_fight_attackers_count))
position = self.conflict.center.point_from_heading(self.conflict.opposite_heading, total_distance / 2)
for attacker_group_dict, target_group_dict in zip_longest(attacker_groups, defender_groups):
position = position.point_from_heading(self.conflict.heading, distance_between_groups)
position = self.conflict.position.point_from_heading(self.conflict.heading,
random.randint(FRONTLINE_CAS_PADDING, int(self.conflict.distance - FRONTLINE_CAS_PADDING)))
self._generate_fight_at(attacker_group_dict, target_group_dict, position)
def generate_passengers(self, count: int):

View File

@ -38,8 +38,9 @@ NAVAL_INTERCEPT_DISTANCE_FACTOR = 1
NAVAL_INTERCEPT_DISTANCE_MAX = 40000
NAVAL_INTERCEPT_STEP = 5000
FRONT_SMOKE_MIN_DISTANCE = 5000
FRONT_SMOKE_DISTANCE_FACTOR = 0.5
FRONTLINE_LENGTH = 80000
FRONTLINE_MIN_CP_DISTANCE = 5000
FRONTLINE_DISTANCE_STRENGTH_FACTOR = 0.7
def _opposite_heading(h):
@ -127,7 +128,7 @@ class Conflict:
@classmethod
def frontline_position(cls, from_cp: ControlPoint, to_cp: ControlPoint) -> typing.Tuple[Point, int]:
distance = max(from_cp.position.distance_to_point(to_cp.position) * FRONT_SMOKE_DISTANCE_FACTOR * to_cp.base.strength, FRONT_SMOKE_MIN_DISTANCE)
distance = max(from_cp.position.distance_to_point(to_cp.position) * FRONTLINE_DISTANCE_STRENGTH_FACTOR * to_cp.base.strength, FRONTLINE_MIN_CP_DISTANCE)
heading = to_cp.position.heading_between_point(from_cp.position)
return to_cp.position.point_from_heading(heading, distance), heading
@ -136,7 +137,7 @@ class Conflict:
center_position, heading = cls.frontline_position(from_cp, to_cp)
left_position = center_position
for offset in range(0, 80000, 1000):
for offset in range(0, int(FRONTLINE_LENGTH / 2), 1000):
pos = center_position.point_from_heading(_heading_sum(heading, -90), offset)
if not theater.is_on_land(pos):
break
@ -144,7 +145,7 @@ class Conflict:
left_position = pos
right_position = center_position
for offset in range(0, 80000, 1000):
for offset in range(0, int(FRONTLINE_LENGTH / 2), 1000):
pos = center_position.point_from_heading(_heading_sum(heading, 90), offset)
if not theater.is_on_land(pos):
break

View File

@ -62,7 +62,6 @@ def __monkey_static_dict(self: Static):
__original_static_dict = Static.dict
Static.dict = __monkey_static_dict
FRONT_SMOKE_LENGTH = 80000
FRONT_SMOKE_SPACING = 800
FRONT_SMOKE_RANDOM_SPREAD = 4000
FRONT_SMOKE_TYPE_CHANCES = {
@ -100,9 +99,9 @@ class VisualGenerator:
def _generate_frontline_smokes(self):
for from_cp, to_cp in self.game.theater.conflicts():
point, heading = Conflict.frontline_position(from_cp, to_cp)
plane_start = point.point_from_heading(turn_heading(heading, 90), FRONT_SMOKE_LENGTH / 2)
plane_start = point.point_from_heading(turn_heading(heading, 90), FRONTLINE_LENGTH / 2)
for offset in range(0, FRONT_SMOKE_LENGTH, FRONT_SMOKE_SPACING):
for offset in range(0, FRONTLINE_LENGTH, FRONT_SMOKE_SPACING):
position = plane_start.point_from_heading(turn_heading(heading, - 90), offset)
for k, v in FRONT_SMOKE_TYPE_CHANCES.items():

View File

@ -0,0 +1,39 @@
from dcs.lua.parse import *
a = loads(open("build/mission", "r").read())
b = loads(open("build/mission_workin.lua", "r").read())
def get(a, k):
b = a
for x in k.strip().split(" "):
if isinstance(a, dict):
y = a
a = a.get(x, None)
if a is None:
try:
a = y.get(int(x), None)
except:
pass
else:
break
if a is None:
pass
return a
def cycle(kk, ref, v):
if isinstance(v, dict):
for k, v in v.items():
cycle(kk + " " + str(k), ref, v)
elif isinstance(v, list):
for i, v in enumerate(v):
cycle(kk + " " + str(i), ref, v)
else:
if get(ref, kk) != v:
print(kk, v)
print(get(ref, kk))
cycle("", a, b)

View File

@ -150,7 +150,7 @@ class Base:
return min(min(max(count, PLANES_SCRAMBLE_MIN_BASE), int(PLANES_SCRAMBLE_MAX_BASE * multiplier)), count)
def assemble_count(self):
return int(self.total_armor * min(self.strength + 0.5, 1))
return int(self.total_armor * 0.5)
def assemble_aa_count(self) -> int:
if self.strength > STRENGTH_AA_ASSEMBLE_MIN:
@ -171,7 +171,8 @@ class Base:
return self._find_best_armor(PinpointStrike, self.assemble_count())
def assemble_defense(self) -> typing.Dict[Armor, int]:
return self._find_best_armor(PinpointStrike, self.assemble_count())
count = int(self.total_armor * min(self.strength + 0.5, 1))
return self._find_best_armor(PinpointStrike, count)
def assemble_aa(self, count=None) -> typing.Dict[AirDefence, int]:
return self._find_best_unit(self.aa, AirDefence, count and min(count, self.total_aa) or self.assemble_aa_count())

View File

@ -172,8 +172,8 @@ class EventMenu(Menu):
if amount > 0:
scrambled_armor[unit_type] = amount
if type(self.event) is CaptureEvent:
e = self.event # type: CaptureEvent
if type(self.event) is BaseAttackEvent:
e = self.event # type: BaseAttackEvent
if self.game.is_player_attack(self.event):
e.player_attacking(cas=scrambled_cas,
escort=scrambled_sweep,
@ -190,12 +190,9 @@ class EventMenu(Menu):
else:
e.player_defending(escort=scrambled_aircraft,
clients=scrambled_clients)
elif type(self.event) is FrontlineCASEvent:
e = self.event # type: FrontlineCASEvent
if self.game.is_player_attack(self.event):
e.player_attacking(strikegroup=scrambled_aircraft, clients=scrambled_clients)
else:
e.player_defending(interceptors=scrambled_aircraft, clients=scrambled_clients)
elif type(self.event) is FrontlineAttackEvent:
e = self.event # type: FrontlineAttackEvent
e.player_attacking(armor=scrambled_armor, strikegroup=scrambled_aircraft, clients=scrambled_clients)
elif type(self.event) is NavalInterceptEvent:
e = self.event # type: NavalInterceptEvent
@ -209,8 +206,8 @@ class EventMenu(Menu):
e.player_attacking(strikegroup=scrambled_aircraft, clients=scrambled_clients)
else:
e.player_defending(interceptors=scrambled_aircraft, clients=scrambled_clients)
elif type(self.event) is GroundAttackEvent:
e = self.event # type: GroundAttackEvent
elif type(self.event) is InsurgentAttackEvent:
e = self.event # type: InsurgentAttackEvent
if self.game.is_player_attack(self.event):
assert False
else:

View File

@ -6,6 +6,7 @@ from tkinter.ttk import *
from ui.window import *
from game.game import *
from gen.conflictgen import Conflict
from theater.conflicttheater import *
@ -44,7 +45,7 @@ class OverviewCanvas:
def create_cp_title(self, coords, cp: ControlPoint):
title = cp.name
font = ("Helvetica", 13)
font = ("Helvetica", 10)
id = self.canvas.create_text(coords[0]+1, coords[1]+1, text=title, fill='white', font=font)
self.canvas.tag_bind(id, "<Button-1>", self.display(cp))
@ -74,9 +75,14 @@ class OverviewCanvas:
self.canvas.create_line((coords[0], coords[1], connected_coords[0], connected_coords[1]), width=2, fill=color)
if cp.captured and not connected_cp.captured and Conflict.has_frontline_between(cp, connected_cp):
frontline_pos, heading, distance = Conflict.frontline_vector(cp, connected_cp, self.game.theater)
start_coords, end_coords = self.transform_point(frontline_pos), self.transform_point(frontline_pos.point_from_heading(heading, distance))
self.canvas.create_line((*start_coords, *end_coords), width=2, fill=color)
for cp in self.game.theater.controlpoints:
coords = self.transform_point(cp.position)
arc_size = 22 * math.pow(cp.importance, 1)
arc_size = 16 * math.pow(cp.importance, 1)
extent = max(cp.base.strength * 180, 10)
start = (180 - extent) / 2

View File

@ -19,7 +19,7 @@ def base_path() -> str:
if os.path.exists(openbeta_path):
return openbeta_path
else:
return os.path.join(_user_folder, "Saved Games" , "DCS")
return os.path.join(_user_folder, "Saved Games", "DCS")
def _save_file() -> str: