frontline attack ops

This commit is contained in:
Vasyl Horbachenko 2018-07-16 23:58:01 +03:00 committed by Vasyl Horbachenko
parent 6f5835a2b8
commit 820820eb92
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 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]) persistency.setup(sys.argv[1])
dcs.planes.FlyingType.payload_dirs.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "resources\\payloads")) 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): if len(buffer_dict):
yield 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(): def _validate_db():
# check unit by task uniquity # check unit by task uniquity
total_set = set() total_set = set()

View File

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

View File

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

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 import *
from game.event import * from game.event import *
from game.event.frontlinecas import FrontlineCASEvent from game.event.frontlineattack import FrontlineAttackEvent
from game.operation.groundattack import GroundAttackOperation from game.operation.insurgentattack import InsurgentAttackOperation
class GroundAttackEvent(FrontlineCASEvent): class InsurgentAttackEvent(FrontlineAttackEvent):
def __str__(self): def __str__(self):
return "Destroy insurgents at {}".format(self.to_cp) return "Destroy insurgents at {}".format(self.to_cp)
@ -24,7 +24,7 @@ class GroundAttackEvent(FrontlineCASEvent):
typecount = max(math.floor(self.difficulty * self.TARGET_AMOUNT_FACTOR), 1) typecount = max(math.floor(self.difficulty * self.TARGET_AMOUNT_FACTOR), 1)
self.targets = {unittype: typecount for unittype in unittypes} self.targets = {unittype: typecount for unittype in unittypes}
op = GroundAttackOperation(game=self.game, op = InsurgentAttackOperation(game=self.game,
attacker_name=self.attacker_name, attacker_name=self.attacker_name,
defender_name=self.defender_name, defender_name=self.defender_name,
attacker_clients={}, attacker_clients={},

View File

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

View File

@ -12,7 +12,7 @@ from gen.visualgen import *
from .operation import Operation from .operation import Operation
class CaptureOperation(Operation): class BaseAttackOperation(Operation):
cas = None # type: db.PlaneDict cas = None # type: db.PlaneDict
escort = None # type: db.PlaneDict escort = None # type: db.PlaneDict
intercept = None # type: db.PlaneDict intercept = None # type: db.PlaneDict
@ -37,7 +37,7 @@ class CaptureOperation(Operation):
self.aa = aa self.aa = aa
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(BaseAttackOperation, self).prepare(terrain, is_quick)
self.defenders_starting_position = None self.defenders_starting_position = None
if self.game.player == self.defender_name: 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.airgen.generate_strikegroup_escort(self.escort, clients=self.attacker_clients, at=self.attackers_starting_position)
self.visualgen.generate_target_smokes(self.to_cp) 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 MAX_DISTANCE_BETWEEN_GROUPS = 12000
class FrontlineCASOperation(Operation): class FrontlineAttackOperation(Operation):
attackers = None # type: db.ArmorDict attackers = None # type: db.ArmorDict
strikegroup = None # type: db.PlaneDict strikegroup = None # type: db.PlaneDict
target = None # type: db.ArmorDict target = None # type: db.ArmorDict
@ -32,7 +32,7 @@ class FrontlineCASOperation(Operation):
self.attackers = attackers self.attackers = attackers
def prepare(self, terrain: Terrain, is_quick: bool): 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: if self.defender_name == self.game.player:
self.attackers_starting_position = None self.attackers_starting_position = None
self.defenders_starting_position = None self.defenders_starting_position = None
@ -51,4 +51,4 @@ class FrontlineCASOperation(Operation):
def generate(self): def generate(self):
self.armorgen.generate_vec(self.attackers, self.target) self.armorgen.generate_vec(self.attackers, self.target)
self.airgen.generate_cas_strikegroup(self.strikegroup, clients=self.attacker_clients, at=self.attackers_starting_position) 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 from .operation import Operation
class GroundAttackOperation(Operation): class InsurgentAttackOperation(Operation):
strikegroup = None # type: db.PlaneDict strikegroup = None # type: db.PlaneDict
target = None # type: db.ArmorDict target = None # type: db.ArmorDict
@ -24,7 +24,7 @@ class GroundAttackOperation(Operation):
self.target = target self.target = target
def prepare(self, terrain: Terrain, is_quick: bool): 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( conflict = Conflict.ground_attack_conflict(
attacker=self.mission.country(self.attacker_name), 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.airgen.generate_defense(self.strikegroup, self.defender_clients, self.defenders_starting_position)
self.armorgen.generate(self.target, {}) 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 itertools import zip_longest
from game import db from game import db
@ -13,6 +14,10 @@ from dcs.country import *
SPREAD_DISTANCE_FACTOR = 0.1, 0.3 SPREAD_DISTANCE_FACTOR = 0.1, 0.3
SPREAD_DISTANCE_SIZE_FACTOR = 0.1 SPREAD_DISTANCE_SIZE_FACTOR = 0.1
FRONTLINE_CAS_FIGHTS_COUNT = 4, 8
FRONTLINE_CAS_GROUP_MIN = 1, 2
FRONTLINE_CAS_PADDING = 12000
class ArmorConflictGenerator: class ArmorConflictGenerator:
def __init__(self, mission: Mission, conflict: Conflict): def __init__(self, mission: Mission, conflict: Conflict):
@ -50,7 +55,7 @@ class ArmorConflictGenerator:
side=self.conflict.attackers_side, side=self.conflict.attackers_side,
unit=type, unit=type,
count=count, count=count,
at=position.point_from_heading(self.conflict.heading - 90, 600), at=position.point_from_heading(self.conflict.heading - 90, 5000),
to=position) to=position)
if defenders: if defenders:
@ -59,7 +64,7 @@ class ArmorConflictGenerator:
side=self.conflict.defenders_side, side=self.conflict.defenders_side,
unit=type, unit=type,
count=count, count=count,
at=position.point_from_heading(self.conflict.heading + 90, 600), at=position.point_from_heading(self.conflict.heading + 90, 1000),
to=position) to=position)
def generate(self, attackers: db.ArmorDict, defenders: db.ArmorDict): def generate(self, attackers: db.ArmorDict, defenders: db.ArmorDict):
@ -78,16 +83,16 @@ class ArmorConflictGenerator:
at=self.conflict.ground_defenders_location) at=self.conflict.ground_defenders_location)
def generate_vec(self, attackers: db.ArmorDict, defenders: db.ArmorDict): def generate_vec(self, attackers: db.ArmorDict, defenders: db.ArmorDict):
defender_groups = list(db.unitdict_split(defenders, 6)) fights_count = randint(*FRONTLINE_CAS_FIGHTS_COUNT)
distance_between_groups = min(self.conflict.distance / len(defender_groups), 12000) single_fight_defenders_count = min(int(sum(defenders.values()) / fights_count), randint(*FRONTLINE_CAS_GROUP_MIN))
total_distance = distance_between_groups * len(defender_groups) defender_groups = list(db.unitdict_split(defenders, single_fight_defenders_count))
attacker_groups = list(db.unitdict_split(attackers, single_fight_attackers_count = min(int(sum(attackers.values()) / len(defender_groups)), randint(*FRONTLINE_CAS_GROUP_MIN))
int(sum(attackers.values()) / len(defender_groups)))) 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): 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) self._generate_fight_at(attacker_group_dict, target_group_dict, position)
def generate_passengers(self, count: int): def generate_passengers(self, count: int):

View File

@ -38,8 +38,9 @@ NAVAL_INTERCEPT_DISTANCE_FACTOR = 1
NAVAL_INTERCEPT_DISTANCE_MAX = 40000 NAVAL_INTERCEPT_DISTANCE_MAX = 40000
NAVAL_INTERCEPT_STEP = 5000 NAVAL_INTERCEPT_STEP = 5000
FRONT_SMOKE_MIN_DISTANCE = 5000 FRONTLINE_LENGTH = 80000
FRONT_SMOKE_DISTANCE_FACTOR = 0.5 FRONTLINE_MIN_CP_DISTANCE = 5000
FRONTLINE_DISTANCE_STRENGTH_FACTOR = 0.7
def _opposite_heading(h): def _opposite_heading(h):
@ -127,7 +128,7 @@ class Conflict:
@classmethod @classmethod
def frontline_position(cls, from_cp: ControlPoint, to_cp: ControlPoint) -> typing.Tuple[Point, int]: 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) heading = to_cp.position.heading_between_point(from_cp.position)
return to_cp.position.point_from_heading(heading, distance), heading 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) center_position, heading = cls.frontline_position(from_cp, to_cp)
left_position = center_position 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) pos = center_position.point_from_heading(_heading_sum(heading, -90), offset)
if not theater.is_on_land(pos): if not theater.is_on_land(pos):
break break
@ -144,7 +145,7 @@ class Conflict:
left_position = pos left_position = pos
right_position = center_position 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) pos = center_position.point_from_heading(_heading_sum(heading, 90), offset)
if not theater.is_on_land(pos): if not theater.is_on_land(pos):
break break

View File

@ -62,7 +62,6 @@ def __monkey_static_dict(self: Static):
__original_static_dict = Static.dict __original_static_dict = Static.dict
Static.dict = __monkey_static_dict Static.dict = __monkey_static_dict
FRONT_SMOKE_LENGTH = 80000
FRONT_SMOKE_SPACING = 800 FRONT_SMOKE_SPACING = 800
FRONT_SMOKE_RANDOM_SPREAD = 4000 FRONT_SMOKE_RANDOM_SPREAD = 4000
FRONT_SMOKE_TYPE_CHANCES = { FRONT_SMOKE_TYPE_CHANCES = {
@ -100,9 +99,9 @@ class VisualGenerator:
def _generate_frontline_smokes(self): def _generate_frontline_smokes(self):
for from_cp, to_cp in self.game.theater.conflicts(): for from_cp, to_cp in self.game.theater.conflicts():
point, heading = Conflict.frontline_position(from_cp, to_cp) 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) position = plane_start.point_from_heading(turn_heading(heading, - 90), offset)
for k, v in FRONT_SMOKE_TYPE_CHANCES.items(): 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) return min(min(max(count, PLANES_SCRAMBLE_MIN_BASE), int(PLANES_SCRAMBLE_MAX_BASE * multiplier)), count)
def assemble_count(self): 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: def assemble_aa_count(self) -> int:
if self.strength > STRENGTH_AA_ASSEMBLE_MIN: if self.strength > STRENGTH_AA_ASSEMBLE_MIN:
@ -171,7 +171,8 @@ class Base:
return self._find_best_armor(PinpointStrike, self.assemble_count()) return self._find_best_armor(PinpointStrike, self.assemble_count())
def assemble_defense(self) -> typing.Dict[Armor, int]: 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]: 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()) 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: if amount > 0:
scrambled_armor[unit_type] = amount scrambled_armor[unit_type] = amount
if type(self.event) is CaptureEvent: if type(self.event) is BaseAttackEvent:
e = self.event # type: CaptureEvent e = self.event # type: BaseAttackEvent
if self.game.is_player_attack(self.event): if self.game.is_player_attack(self.event):
e.player_attacking(cas=scrambled_cas, e.player_attacking(cas=scrambled_cas,
escort=scrambled_sweep, escort=scrambled_sweep,
@ -190,12 +190,9 @@ class EventMenu(Menu):
else: else:
e.player_defending(escort=scrambled_aircraft, e.player_defending(escort=scrambled_aircraft,
clients=scrambled_clients) clients=scrambled_clients)
elif type(self.event) is FrontlineCASEvent: elif type(self.event) is FrontlineAttackEvent:
e = self.event # type: FrontlineCASEvent e = self.event # type: FrontlineAttackEvent
if self.game.is_player_attack(self.event): e.player_attacking(armor=scrambled_armor, strikegroup=scrambled_aircraft, clients=scrambled_clients)
e.player_attacking(strikegroup=scrambled_aircraft, clients=scrambled_clients)
else:
e.player_defending(interceptors=scrambled_aircraft, clients=scrambled_clients)
elif type(self.event) is NavalInterceptEvent: elif type(self.event) is NavalInterceptEvent:
e = self.event # type: NavalInterceptEvent e = self.event # type: NavalInterceptEvent
@ -209,8 +206,8 @@ class EventMenu(Menu):
e.player_attacking(strikegroup=scrambled_aircraft, clients=scrambled_clients) e.player_attacking(strikegroup=scrambled_aircraft, clients=scrambled_clients)
else: else:
e.player_defending(interceptors=scrambled_aircraft, clients=scrambled_clients) e.player_defending(interceptors=scrambled_aircraft, clients=scrambled_clients)
elif type(self.event) is GroundAttackEvent: elif type(self.event) is InsurgentAttackEvent:
e = self.event # type: GroundAttackEvent e = self.event # type: InsurgentAttackEvent
if self.game.is_player_attack(self.event): if self.game.is_player_attack(self.event):
assert False assert False
else: else:

View File

@ -6,6 +6,7 @@ from tkinter.ttk import *
from ui.window import * from ui.window import *
from game.game import * from game.game import *
from gen.conflictgen import Conflict
from theater.conflicttheater import * from theater.conflicttheater import *
@ -44,7 +45,7 @@ class OverviewCanvas:
def create_cp_title(self, coords, cp: ControlPoint): def create_cp_title(self, coords, cp: ControlPoint):
title = cp.name 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) 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)) 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) 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: for cp in self.game.theater.controlpoints:
coords = self.transform_point(cp.position) 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) extent = max(cp.base.strength * 180, 10)
start = (180 - extent) / 2 start = (180 - extent) / 2