mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
balance improvements; general fixes
This commit is contained in:
parent
002ee75a26
commit
fab2968825
@ -53,7 +53,6 @@ class Event:
|
||||
|
||||
def commit(self, debriefing: Debriefing):
|
||||
for country, losses in debriefing.destroyed_units.items():
|
||||
cp = None # type: ControlPoint
|
||||
if country == self.attacker_name:
|
||||
cp = self.from_cp
|
||||
else:
|
||||
@ -69,7 +68,7 @@ class GroundInterceptEvent(Event):
|
||||
BONUS_BASE = 3
|
||||
TARGET_AMOUNT_FACTOR = 2
|
||||
TARGET_VARIETY = 2
|
||||
STRENGTH_INFLUENCE = 0.1
|
||||
STRENGTH_INFLUENCE = 0.3
|
||||
SUCCESS_TARGETS_HIT_PERCENTAGE = 0.5
|
||||
|
||||
targets = None # type: db.ArmorDict
|
||||
@ -84,7 +83,7 @@ class GroundInterceptEvent(Event):
|
||||
if unit in self.targets:
|
||||
destroyed_targets += count
|
||||
|
||||
return (float(destroyed_targets) / float(total_targets)) > self.SUCCESS_TARGETS_HIT_PERCENTAGE
|
||||
return (float(destroyed_targets) / float(total_targets)) >= self.SUCCESS_TARGETS_HIT_PERCENTAGE
|
||||
|
||||
def commit(self, debriefing: Debriefing):
|
||||
super(GroundInterceptEvent, self).commit(debriefing)
|
||||
@ -125,8 +124,8 @@ class GroundInterceptEvent(Event):
|
||||
|
||||
class InterceptEvent(Event):
|
||||
BONUS_BASE = 5
|
||||
STRENGTH_INFLUENCE = 0.25
|
||||
GLOBAL_STRENGTH_INFLUENCE = 0.05
|
||||
STRENGTH_INFLUENCE = 0.3
|
||||
GLOBAL_STRENGTH_INFLUENCE = 0.3
|
||||
AIRDEFENSE_COUNT = 3
|
||||
|
||||
transport_unit = None # type: FlyingType
|
||||
@ -148,14 +147,17 @@ class InterceptEvent(Event):
|
||||
def commit(self, debriefing: Debriefing):
|
||||
super(InterceptEvent, self).commit(debriefing)
|
||||
|
||||
if self.is_successfull(debriefing):
|
||||
if self.from_cp.is_global:
|
||||
for cp in self.game.theater.enemy_points():
|
||||
cp.base.affect_strength(-self.GLOBAL_STRENGTH_INFLUENCE)
|
||||
if self.attacker_name == self.game.player:
|
||||
if self.is_successfull(debriefing):
|
||||
self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
|
||||
else:
|
||||
self.to_cp.base.affect_strength(self.STRENGTH_INFLUENCE * float(self.from_cp.captured and -1 or 1))
|
||||
self.from_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
|
||||
else:
|
||||
self.to_cp.base.affect_strength(self.STRENGTH_INFLUENCE * float(self.from_cp.captured and 1 or -1))
|
||||
# enemy attacking
|
||||
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:
|
||||
|
||||
19
game/game.py
19
game/game.py
@ -19,17 +19,17 @@ COMMISION_AMOUNTS_FACTORS = {
|
||||
|
||||
|
||||
ENEMY_INTERCEPT_PROBABILITY_BASE = 8
|
||||
ENEMY_INTERCEPT_GLOBAL_PROBABILITY_BASE = 3
|
||||
ENEMY_INTERCEPT_GLOBAL_PROBABILITY_BASE = 5
|
||||
ENEMY_CAPTURE_PROBABILITY_BASE = 4
|
||||
|
||||
PLAYER_INTERCEPT_PROBABILITY_BASE = 30
|
||||
PLAYER_GROUNDINTERCEPT_PROBABILITY_BASE = 30
|
||||
PLAYER_INTERCEPT_PROBABILITY_BASE = 35
|
||||
PLAYER_GROUNDINTERCEPT_PROBABILITY_BASE = 35
|
||||
|
||||
PLAYER_INTERCEPT_GLOBAL_PROBABILITY_BASE = 10
|
||||
PLAYER_INTERCEPT_GLOBAL_PROBABILITY_BASE = 20
|
||||
PLAYER_INTERCEPT_GLOBAL_PROBABILITY_LOG = 2
|
||||
|
||||
PLAYER_BUDGET_INITIAL = 90
|
||||
PLAYER_BUDGET_BASE = 30
|
||||
PLAYER_BUDGET_BASE = 20
|
||||
PLAYER_BUDGET_IMPORTANCE_LOG = 2
|
||||
|
||||
AWACS_BUDGET_COST = 4
|
||||
@ -60,11 +60,14 @@ class Game:
|
||||
to_cp=to_cp,
|
||||
game=self))
|
||||
|
||||
def _generate_enemy_caps(self):
|
||||
def _generate_enemy_caps(self, ignored_cps: typing.Collection[ControlPoint] = None):
|
||||
for from_cp, to_cp in self.theater.conflicts(False):
|
||||
if from_cp.base.total_planes == 0 or from_cp.base.total_armor == 0:
|
||||
continue
|
||||
|
||||
if ignored_cps and to_cp in ignored_cps:
|
||||
continue
|
||||
|
||||
if self._roll(ENEMY_CAPTURE_PROBABILITY_BASE, from_cp.base.strength):
|
||||
self.events.append(CaptureEvent(attacker_name=self.enemy,
|
||||
defender_name=self.player,
|
||||
@ -191,7 +194,7 @@ class Game:
|
||||
def is_player_attack(self, event: Event):
|
||||
return event.attacker_name == self.player
|
||||
|
||||
def pass_turn(self, no_action=False):
|
||||
def pass_turn(self, no_action=False, ignored_cps: typing.Collection[ControlPoint]=None):
|
||||
for event in self.events:
|
||||
event.skip()
|
||||
|
||||
@ -202,7 +205,7 @@ class Game:
|
||||
|
||||
self.events = [] # type: typing.List[Event]
|
||||
self._fill_cap_events()
|
||||
self._generate_enemy_caps()
|
||||
self._generate_enemy_caps(ignored_cps=ignored_cps)
|
||||
self._generate_interceptions()
|
||||
self._generate_globalinterceptions()
|
||||
self._generate_groundinterceptions()
|
||||
|
||||
@ -128,10 +128,14 @@ class CaptureOperation(Operation):
|
||||
if self.game.player == self.defender_name:
|
||||
self.attackers_starting_position = None
|
||||
|
||||
conflict = Conflict.capture_conflict(
|
||||
attacker=self.mission.country(self.attacker_name),
|
||||
defender=self.mission.country(self.defender_name),
|
||||
from_cp=self.from_cp,
|
||||
to_cp=self.to_cp
|
||||
)
|
||||
self.initialize(mission=self.mission,
|
||||
conflict=self.to_cp.conflict_attack(self.from_cp,
|
||||
self.mission.country(self.attacker_name),
|
||||
self.mission.country(self.defender_name)))
|
||||
conflict=conflict)
|
||||
|
||||
def generate(self):
|
||||
self.armorgen.generate(self.attack, self.defense)
|
||||
@ -203,7 +207,8 @@ class GroundInterceptOperation(Operation):
|
||||
attacker=self.mission.country(self.attacker_name),
|
||||
defender=self.mission.country(self.defender_name),
|
||||
heading=self.to_cp.position.heading_between_point(self.from_cp.position),
|
||||
cp=self.to_cp
|
||||
from_cp=self.from_cp,
|
||||
to_cp=self.to_cp
|
||||
)
|
||||
|
||||
self.initialize(mission=self.mission,
|
||||
|
||||
@ -6,10 +6,11 @@ from .naming import *
|
||||
|
||||
from dcs.mission import *
|
||||
|
||||
DISTANCE_FACTOR = 4, 5
|
||||
DISTANCE_FACTOR = 2, 4
|
||||
EXTRA_AA_MIN_DISTANCE = 35000
|
||||
EXTRA_AA_POSITION_FROM_CP = 550
|
||||
|
||||
|
||||
class AAConflictGenerator:
|
||||
def __init__(self, mission: Mission, conflict: Conflict):
|
||||
self.m = mission
|
||||
|
||||
@ -20,9 +20,9 @@ TRANSPORT_LANDING_ALT = 500
|
||||
|
||||
INTERCEPTION_ALT = 3600
|
||||
CAS_ALTITUDE = 1000
|
||||
RTB_ALTITUDE = 1000
|
||||
|
||||
INTERCEPT_MAX_DISTANCE_FACTOR = 15
|
||||
|
||||
INTERCEPT_MAX_DISTANCE = 80000
|
||||
|
||||
class AircraftConflictGenerator:
|
||||
escort_targets = [] # type: typing.List[PlaneGroup]
|
||||
@ -54,7 +54,7 @@ class AircraftConflictGenerator:
|
||||
count -= group_size
|
||||
client_count -= client_size
|
||||
|
||||
def _setup_group(self, group: FlyingGroup, for_task: Task):
|
||||
def _setup_group(self, group: FlyingGroup, for_task: Task, clients: db.PlaneDict):
|
||||
did_load_loadout = False
|
||||
unit_type = group.units[0].unit_type
|
||||
if unit_type in db.PLANE_PAYLOAD_OVERRIDES:
|
||||
@ -77,11 +77,19 @@ class AircraftConflictGenerator:
|
||||
for unit_instance in group.units:
|
||||
unit_instance.livery_id = db.PLANE_LIVERY_OVERRIDES[unit_type]
|
||||
|
||||
single_client = sum(clients.values()) == 1
|
||||
client_count = clients.get(unit_type, 0)
|
||||
for idx in range(min(client_count, len(group.units))):
|
||||
if single_client:
|
||||
group.units[idx].set_player()
|
||||
else:
|
||||
group.units[idx].set_client()
|
||||
|
||||
def _generate_at_airport(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, airport: Airport = None) -> FlyingGroup:
|
||||
assert count > 0
|
||||
assert unit is not None
|
||||
|
||||
group = self.m.flight_group_from_airport(
|
||||
return self.m.flight_group_from_airport(
|
||||
country=side,
|
||||
name=name,
|
||||
aircraft_type=unit_type,
|
||||
@ -91,16 +99,11 @@ class AircraftConflictGenerator:
|
||||
group_size=count,
|
||||
parking_slots=None)
|
||||
|
||||
for idx in range(client_count):
|
||||
group.units[idx].set_client()
|
||||
|
||||
return group
|
||||
|
||||
def _generate_inflight(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, at: Point) -> FlyingGroup:
|
||||
assert count > 0
|
||||
assert unit is not None
|
||||
|
||||
group = self.m.flight_group(
|
||||
return self.m.flight_group(
|
||||
country=side,
|
||||
name=name,
|
||||
aircraft_type=unit_type,
|
||||
@ -112,16 +115,11 @@ class AircraftConflictGenerator:
|
||||
start_type=StartType.Warm,
|
||||
group_size=count)
|
||||
|
||||
for idx in range(client_count):
|
||||
group.units[idx].set_client()
|
||||
|
||||
return group
|
||||
|
||||
def _generate_at_carrier(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, at: ShipGroup) -> FlyingGroup:
|
||||
assert count > 0
|
||||
assert unit is not None
|
||||
|
||||
group = self.m.flight_group_from_unit(
|
||||
return self.m.flight_group_from_unit(
|
||||
country=side,
|
||||
name=name,
|
||||
aircraft_type=unit_type,
|
||||
@ -130,11 +128,6 @@ class AircraftConflictGenerator:
|
||||
start_type=StartType.Warm,
|
||||
group_size=count)
|
||||
|
||||
for idx in range(client_count):
|
||||
group.units[idx].set_client()
|
||||
|
||||
return group
|
||||
|
||||
def _generate_group(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, at: db.StartingPosition):
|
||||
if isinstance(at, Point):
|
||||
return self._generate_inflight(name, side, unit_type, count, client_count, at)
|
||||
@ -148,10 +141,18 @@ class AircraftConflictGenerator:
|
||||
else:
|
||||
assert False
|
||||
|
||||
def _generate_escort(self, side: Country, units: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition):
|
||||
if len(self.escort_targets) == 0:
|
||||
return
|
||||
def _at_position(self, at) -> Point:
|
||||
if isinstance(at, Point):
|
||||
return at
|
||||
elif isinstance(at, ShipGroup):
|
||||
return at.position
|
||||
elif issubclass(at, Airport):
|
||||
return at.position
|
||||
else:
|
||||
assert False
|
||||
|
||||
def _generate_escort(self, side: Country, units: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition):
|
||||
groups = []
|
||||
for flying_type, count, client_count in self._split_to_groups(units, clients):
|
||||
group = self._generate_group(
|
||||
name=namegen.next_escort_group_name(),
|
||||
@ -167,11 +168,14 @@ class AircraftConflictGenerator:
|
||||
position = group.position # type: Point
|
||||
wayp = group.add_waypoint(position.point_from_heading(heading, WORKAROUND_WAYP_DIST), CAS_ALTITUDE, WARM_START_AIRSPEED)
|
||||
|
||||
self._setup_group(group, CAP)
|
||||
self._setup_group(group, CAP, clients)
|
||||
|
||||
for group in self.escort_targets:
|
||||
wayp.tasks.append(EscortTaskAction(group.id, engagement_max_dist=ESCORT_MAX_DIST))
|
||||
|
||||
groups.append(group)
|
||||
return groups
|
||||
|
||||
def generate_cas(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
||||
assert len(self.escort_targets) == 0
|
||||
|
||||
@ -187,21 +191,25 @@ class AircraftConflictGenerator:
|
||||
|
||||
group.add_waypoint(self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED)
|
||||
group.task = CAS.name
|
||||
self._setup_group(group, CAS)
|
||||
self._setup_group(group, CAS, clients)
|
||||
|
||||
group.add_waypoint(self.conflict.from_cp.position, RTB_ALTITUDE)
|
||||
|
||||
def generate_cas_escort(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
||||
self._generate_escort(
|
||||
side=self.conflict.attackers_side,
|
||||
units=attackers,
|
||||
clients=clients,
|
||||
at=at and at or self._group_point(self.conflict.air_attackers_location))
|
||||
for g in self._generate_escort(
|
||||
side=self.conflict.attackers_side,
|
||||
units=attackers,
|
||||
clients=clients,
|
||||
at=at and at or self._group_point(self.conflict.air_attackers_location)):
|
||||
g.add_waypoint(self.conflict.from_cp.position, RTB_ALTITUDE)
|
||||
|
||||
def generate_transport_escort(self, escort: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
||||
self._generate_escort(
|
||||
side=self.conflict.defenders_side,
|
||||
units=escort,
|
||||
clients=clients,
|
||||
at=at and at or self._group_point(self.conflict.air_defenders_location))
|
||||
for g in self._generate_escort(
|
||||
side=self.conflict.defenders_side,
|
||||
units=escort,
|
||||
clients=clients,
|
||||
at=at and at or self._group_point(self.conflict.air_defenders_location)):
|
||||
g.add_waypoint(self.conflict.to_cp.position, RTB_ALTITUDE)
|
||||
|
||||
def generate_defense(self, defenders: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
||||
for flying_type, count, client_count in self._split_to_groups(defenders, clients):
|
||||
@ -215,9 +223,11 @@ class AircraftConflictGenerator:
|
||||
|
||||
group.task = CAP.name
|
||||
wayp = group.add_waypoint(self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED)
|
||||
wayp.tasks.append(dcs.task.EngageTargets(max_distance=self.conflict.size * INTERCEPT_MAX_DISTANCE_FACTOR))
|
||||
wayp.tasks.append(dcs.task.EngageTargets(max_distance=INTERCEPT_MAX_DISTANCE))
|
||||
wayp.tasks.append(dcs.task.OrbitAction())
|
||||
self._setup_group(group, CAP)
|
||||
self._setup_group(group, CAP, clients)
|
||||
|
||||
group.add_waypoint(self.conflict.to_cp.position, RTB_ALTITUDE)
|
||||
|
||||
def generate_transport(self, transport: db.PlaneDict, destination: Airport):
|
||||
assert len(self.escort_targets) == 0
|
||||
@ -251,8 +261,10 @@ class AircraftConflictGenerator:
|
||||
|
||||
heading = group.position.heading_between_point(self.conflict.position)
|
||||
initial_wayp = group.add_waypoint(group.position.point_from_heading(heading, WORKAROUND_WAYP_DIST), INTERCEPTION_ALT, INTERCEPTION_AIRSPEED)
|
||||
initial_wayp.tasks.append(EngageTargets())
|
||||
initial_wayp.tasks.append(EngageTargets(max_distance=INTERCEPT_MAX_DISTANCE))
|
||||
|
||||
wayp = group.add_waypoint(self.conflict.position, 0)
|
||||
wayp.tasks.append(EngageTargets())
|
||||
self._setup_group(group, CAP)
|
||||
wayp.tasks.append(EngageTargets(max_distance=INTERCEPT_MAX_DISTANCE))
|
||||
self._setup_group(group, CAP, clients)
|
||||
|
||||
group.add_waypoint(self.conflict.from_cp.position, RTB_ALTITUDE)
|
||||
|
||||
@ -34,7 +34,7 @@ class ArmorConflictGenerator:
|
||||
position=self._group_point(at),
|
||||
group_size=1,
|
||||
move_formation=PointAction.OffRoad)
|
||||
wayp = group.add_waypoint(self.conflict.position)
|
||||
wayp = group.add_waypoint(self.conflict.position.point_from_heading(0, 500))
|
||||
wayp.tasks = []
|
||||
|
||||
def generate(self, attackers: db.ArmorDict, defenders: db.ArmorDict):
|
||||
|
||||
@ -14,8 +14,8 @@ from dcs.point import *
|
||||
from dcs.task import *
|
||||
from dcs.country import *
|
||||
|
||||
GROUND_DISTANCE_FACTOR = 2
|
||||
GROUNDINTERCEPT_DISTANCE_FACTOR = 6
|
||||
GROUND_DISTANCE_FACTOR = 0.8
|
||||
GROUNDINTERCEPT_DISTANCE_FACTOR = 3
|
||||
AIR_DISTANCE = 32000
|
||||
|
||||
INTERCEPT_ATTACKERS_HEADING = -45, 45
|
||||
@ -43,6 +43,8 @@ def _heading_sum(h, a) -> int:
|
||||
class Conflict:
|
||||
attackers_side = None # type: Country
|
||||
defenders_side = None # type: Country
|
||||
from_cp = None # type: ControlPoint
|
||||
to_cp = None # type: ControlPoint
|
||||
position = None # type: Point
|
||||
size = None # type: int
|
||||
radials = None # type: typing.List[int]
|
||||
@ -53,13 +55,19 @@ class Conflict:
|
||||
air_defenders_location = None # type: Point
|
||||
|
||||
@classmethod
|
||||
def capture_conflict(self, attacker: Country, attack_heading: int, defender: Country, defense_heading: int, position: Point, size: int, radials: typing.Collection[int]):
|
||||
def capture_conflict(self, attacker: Country, defender: Country, from_cp, to_cp):
|
||||
attack_heading = to_cp.find_radial(to_cp.position.heading_between_point(from_cp.position))
|
||||
defense_heading = to_cp.find_radial(from_cp.position.heading_between_point(to_cp.position), ignored_radial=attack_heading)
|
||||
position = to_cp.position
|
||||
|
||||
instance = self()
|
||||
instance.attackers_side = attacker
|
||||
instance.defenders_side = defender
|
||||
instance.from_cp = from_cp
|
||||
instance.to_cp = to_cp
|
||||
instance.position = position
|
||||
instance.size = size
|
||||
instance.radials = radials
|
||||
instance.size = to_cp.size
|
||||
instance.radials = to_cp.radials
|
||||
|
||||
instance.ground_attackers_location = instance.position.point_from_heading(attack_heading, instance.size * GROUND_DISTANCE_FACTOR)
|
||||
instance.ground_defenders_location = instance.position.point_from_heading(defense_heading, instance.size * GROUND_DISTANCE_FACTOR)
|
||||
@ -74,12 +82,15 @@ class Conflict:
|
||||
from theater.conflicttheater import SIZE_REGULAR
|
||||
from theater.conflicttheater import ALL_RADIALS
|
||||
|
||||
heading = _heading_sum(from_cp.position.heading_between_point(to_cp.position), +90)
|
||||
raw_distance = from_cp.position.distance_to_point(to_cp.position) / 2.5
|
||||
heading = _heading_sum(from_cp.position.heading_between_point(to_cp.position), random.choice([-1, 1]) * random.randint(60, 100))
|
||||
|
||||
raw_distance = from_cp.position.distance_to_point(to_cp.position) * 0.4
|
||||
distance = max(min(raw_distance, INTERCEPT_MAX_DISTANCE), INTERCEPT_MIN_DISTANCE)
|
||||
position = from_cp.position.point_from_heading(heading, distance)
|
||||
|
||||
instance = self()
|
||||
instance.from_cp = from_cp
|
||||
instance.to_cp = to_cp
|
||||
instance.attackers_side = attacker
|
||||
instance.defenders_side = defender
|
||||
|
||||
@ -93,18 +104,18 @@ class Conflict:
|
||||
return instance
|
||||
|
||||
@classmethod
|
||||
def ground_intercept_conflict(self, attacker: Country, defender: Country, heading: int, cp):
|
||||
from theater.conflicttheater import SIZE_SMALL
|
||||
|
||||
def ground_intercept_conflict(self, attacker: Country, defender: Country, heading: int, from_cp, to_cp):
|
||||
instance = self()
|
||||
instance.from_cp = from_cp
|
||||
instance.to_cp = to_cp
|
||||
instance.attackers_side = attacker
|
||||
instance.defenders_side = defender
|
||||
|
||||
instance.position = cp.position
|
||||
instance.size = cp.size
|
||||
instance.radials = cp.radials
|
||||
instance.position = to_cp.position
|
||||
instance.size = to_cp.size
|
||||
instance.radials = to_cp.radials
|
||||
|
||||
instance.air_attackers_location = instance.position.point_from_heading(random.randint(*INTERCEPT_ATTACKERS_HEADING) + heading, AIR_DISTANCE)
|
||||
instance.ground_defenders_location = instance.position.point_from_heading(random.choice(cp.radials), instance.size * GROUNDINTERCEPT_DISTANCE_FACTOR)
|
||||
instance.ground_defenders_location = instance.position.point_from_heading(random.choice(to_cp.radials), instance.size * GROUNDINTERCEPT_DISTANCE_FACTOR)
|
||||
|
||||
return instance
|
||||
|
||||
@ -52,8 +52,8 @@ FRONT_SMOKE_LENGTH = 80000
|
||||
FRONT_SMOKE_SPACING = 600
|
||||
FRONT_SMOKE_RANDOM_SPREAD = 1200
|
||||
FRONT_SMOKE_TYPE_CHANCES = {
|
||||
5: MassiveSmoke,
|
||||
40: BigSmoke,
|
||||
10: MassiveSmoke,
|
||||
60: BigSmoke,
|
||||
100: Smoke,
|
||||
}
|
||||
|
||||
@ -119,7 +119,6 @@ class VisualGenerator:
|
||||
"",
|
||||
_type=v,
|
||||
position=position)
|
||||
|
||||
break
|
||||
|
||||
def generate(self):
|
||||
|
||||
@ -12,6 +12,7 @@ from dcs.task import *
|
||||
PLANES_IN_GROUP = 2
|
||||
|
||||
PLANES_SCRAMBLE_MIN = 4
|
||||
PLANES_SCRAMBLE_MAX = 8
|
||||
PLANES_SCRAMBLE_FACTOR = 0.5
|
||||
|
||||
|
||||
@ -151,7 +152,7 @@ class Base:
|
||||
|
||||
def scramble_count(self) -> int:
|
||||
count = int(self.total_planes * PLANES_SCRAMBLE_FACTOR * self.strength)
|
||||
return min(max(count, PLANES_SCRAMBLE_MIN), self.total_planes)
|
||||
return min(min(max(count, PLANES_SCRAMBLE_MIN), PLANES_SCRAMBLE_MAX), self.total_planes)
|
||||
|
||||
def assemble_count(self):
|
||||
return self.total_armor * self.strength
|
||||
|
||||
@ -68,10 +68,11 @@ class ControlPoint:
|
||||
attack_radial = self.find_radial(self.position.heading_between_point(from_cp.position))
|
||||
defense_radial = self.find_radial(from_cp.position.heading_between_point(self.position), ignored_radial=attack_radial)
|
||||
|
||||
pos = self.position.point_from_heading(0, 1000)
|
||||
return Conflict.capture_conflict(attacker=attacker,
|
||||
attack_heading=attack_radial,
|
||||
defender=defender,
|
||||
defense_heading=defense_radial,
|
||||
position=self.position,
|
||||
position=pos,
|
||||
size=self.size,
|
||||
radials=self.radials)
|
||||
|
||||
@ -13,9 +13,9 @@ class PersianGulfTheater(ConflictTheater):
|
||||
(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),
|
||||
"dawn": (6, 8),
|
||||
"day": (8, 16),
|
||||
"dusk": (16, 18),
|
||||
"night": (0, 5),
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ class PersianGulfTheater(ConflictTheater):
|
||||
|
||||
sirri = ControlPoint.from_airport(persiangulf.Sirri_Island, ALL_RADIALS, SIZE_TINY, IMPORTANCE_MEDIUM)
|
||||
abu_musa = ControlPoint.from_airport(persiangulf.Abu_Musa_Island_Airport, ALL_RADIALS, SIZE_TINY, IMPORTANCE_MEDIUM)
|
||||
tunb_island = ControlPoint.from_airport(persiangulf.Tunb_Island_AFB, COAST_EW_N, SIZE_SMALL, IMPORTANCE_HIGH)
|
||||
tunb_island = ControlPoint.from_airport(persiangulf.Tunb_Island_AFB, [0, 270, 330], SIZE_SMALL, IMPORTANCE_HIGH)
|
||||
tunb_kochak = ControlPoint.from_airport(persiangulf.Tunb_Kochak, COAST_EW_S, SIZE_TINY, IMPORTANCE_HIGH)
|
||||
|
||||
bandar_lengeh = ControlPoint.from_airport(persiangulf.Bandar_Lengeh, COAST_EW_N, SIZE_SMALL, IMPORTANCE_HIGH)
|
||||
@ -72,4 +72,17 @@ class PersianGulfTheater(ConflictTheater):
|
||||
|
||||
self.east_carrier.captured = True
|
||||
self.west_carrier.captured = True
|
||||
|
||||
self.al_dhafra.captured = True
|
||||
|
||||
"""
|
||||
Mid game:
|
||||
"""
|
||||
|
||||
self.al_maktoum.captured = True
|
||||
self.al_minhad.captured = True
|
||||
self.dubai.captured = True
|
||||
self.sharjah.captured = True
|
||||
self.fujairah.captured = True
|
||||
self.khasab.captured = True
|
||||
self.sir_abu_nuayr.captured = True
|
||||
|
||||
@ -7,7 +7,7 @@ UNIT_VARIETY = 3
|
||||
UNIT_AMOUNT_FACTOR = 16
|
||||
|
||||
COUNT_BY_TASK = {
|
||||
PinpointStrike: 12,
|
||||
PinpointStrike: 24,
|
||||
CAP: 16,
|
||||
CAS: 8,
|
||||
AirDefence: 0.5,
|
||||
|
||||
@ -29,4 +29,7 @@ class ConfigurationMenu(Menu):
|
||||
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)
|
||||
Button(self.frame, text="Cheat +200m", command=self.cheat_money).grid(row=3, column=0)
|
||||
|
||||
def cheat_money(self):
|
||||
self.game.budget += 200
|
||||
|
||||
@ -68,7 +68,7 @@ class EventResultsMenu(Menu):
|
||||
enemy_name=self.game.enemy)
|
||||
|
||||
self.game.finish_event(event=self.event, debriefing=debriefing)
|
||||
self.game.pass_turn()
|
||||
self.game.pass_turn(ignored_cps=[self.event.to_cp, ])
|
||||
|
||||
self.finished = True
|
||||
self.player_losses = debriefing.destroyed_units.get(self.game.player, {})
|
||||
|
||||
@ -113,5 +113,8 @@ def _poll_new_debriefing_log(snapshot: typing.Dict[str, float], callback: typing
|
||||
|
||||
|
||||
def wait_for_debriefing(callback: typing.Callable):
|
||||
if not os.path.exists(debriefing_directory_location()):
|
||||
os.mkdir(debriefing_directory_location())
|
||||
|
||||
threading.Thread(target=_poll_new_debriefing_log, args=(_logfiles_snapshot(), callback)).start()
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user