diff --git a/game/db.py b/game/db.py index 77e03707..249117ff 100644 --- a/game/db.py +++ b/game/db.py @@ -26,7 +26,7 @@ x_map = { } from this example `Identifier` should be used (which may or may not include category of the unit and dot + underscore characters). -For example, player accessible Hornet is called `FA_18C_hornet`, and MANPAD Igla is called `AirDefence.SAM_SA_18_Igla_MANPADS` +For example, player accessible Hornet is called `FA_18C_hornet`, and MANPAD Igla is called `AirDefence.SAM_SA_18_Igla_S_MANPADS` """ """ @@ -98,7 +98,7 @@ PRICES = { AirDefence.SAM_Patriot_ICC: 15, AirDefence.AAA_ZU_23_on_Ural_375: 5, - AirDefence.SAM_SA_18_Igla_MANPADS: 8, + AirDefence.SAM_SA_18_Igla_S_MANPADS: 8, AirDefence.SAM_SA_19_Tunguska_2S6: 10, AirDefence.SAM_SA_8_Osa_9A33: 15, @@ -174,8 +174,7 @@ UNIT_BY_TASK = { 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_19_Tunguska_2S6, AirDefence.SAM_SA_19_Tunguska_2S6, AirDefence.SAM_SA_8_Osa_9A33, ], @@ -252,7 +251,7 @@ UNIT_BY_COUNTRY = { Mi_8MT, AirDefence.AAA_ZU_23_on_Ural_375, - AirDefence.SAM_SA_18_Igla_MANPADS, + AirDefence.SAM_SA_18_Igla_S_MANPADS, AirDefence.SAM_SA_19_Tunguska_2S6, AirDefence.SAM_SA_8_Osa_9A33, diff --git a/game/game.py b/game/game.py index 3bbcf6f1..ffa37bca 100644 --- a/game/game.py +++ b/game/game.py @@ -46,12 +46,12 @@ Events: * InfantryTransportEvent - helicopter infantry transport """ EVENT_PROBABILITIES = { - CaptureEvent: [100, 6], - InterceptEvent: [25, 9], - GroundInterceptEvent: [25, 9], - GroundAttackEvent: [0, 9], - NavalInterceptEvent: [25, 9], - AntiAAStrikeEvent: [25, 9], + CaptureEvent: [100, 8], + InterceptEvent: [25, 12], + GroundInterceptEvent: [25, 12], + GroundAttackEvent: [0, 12], + NavalInterceptEvent: [25, 12], + AntiAAStrikeEvent: [25, 12], InfantryTransportEvent: [25, 0], } diff --git a/game/operation/navalintercept.py b/game/operation/navalintercept.py index b5ef999c..3dac0cf4 100644 --- a/game/operation/navalintercept.py +++ b/game/operation/navalintercept.py @@ -8,6 +8,7 @@ class NavalInterceptionOperation(Operation): strikegroup = None # type: db.PlaneDict interceptors = None # type: db.PlaneDict targets = None # type: db.ShipDict + trigger_radius = TRIGGER_RADIUS_LARGE def setup(self, strikegroup: db.PlaneDict, diff --git a/gen/aircraft.py b/gen/aircraft.py index e9775359..dc4a09f5 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -2,6 +2,7 @@ from game import db from game.settings import Settings from .conflictgen import * from .naming import * +from .triggergen import TRIGGER_WAYPOINT_OFFSET from dcs.mission import * from dcs.unitgroup import * @@ -14,21 +15,26 @@ ESCORT_ENGAGEMENT_MAX_DIST = 100000 WORKAROUND_WAYP_DIST = 1000 WARM_START_ALTITUDE = 3000 +WARM_START_AIRSPEED = 550 + INTERCEPTION_ALT = 3000 +INTERCEPTION_AIRSPEED = 1000 + +ATTACK_CIRCLE_ALT = 5000 +ATTACK_CIRCLE_DURATION = 15 + CAS_ALTITUDE = 1000 RTB_ALTITUDE = 1000 -TRANSPORT_LANDING_ALT = 1000 HELI_ALT = 900 -WARM_START_AIRSPEED = 550 -INTERCEPTION_AIRSPEED = 1000 +TRANSPORT_LANDING_ALT = 1000 DEFENCE_ENGAGEMENT_MAX_DISTANCE = 60000 INTERCEPT_MAX_DISTANCE = 200000 class AircraftConflictGenerator: - escort_targets = [] # type: typing.List[PlaneGroup] + escort_targets = [] # type: typing.List[typing.Tuple[PlaneGroup, int]] def __init__(self, mission: Mission, conflict: Conflict, settings: Settings): self.m = mission @@ -168,7 +174,7 @@ class AircraftConflictGenerator: else: assert False - def _generate_escort(self, side: Country, units: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition): + def _generate_escort(self, side: Country, units: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition, is_quick=False, should_orbit=False): groups = [] for flying_type, count, client_count in self._split_to_groups(units, clients): group = self._generate_group( @@ -184,14 +190,22 @@ class AircraftConflictGenerator: heading = group.position.heading_between_point(self.conflict.position) 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, client_count) - for group in self.escort_targets: - wayp.tasks.append(EscortTaskAction(group.id, engagement_max_dist=ESCORT_ENGAGEMENT_MAX_DIST)) + for escorted_group, waypoint_index in self.escort_targets: + waypoint_index += 1 + if not is_quick: + waypoint_index += TRIGGER_WAYPOINT_OFFSET - group.add_waypoint(self.conflict.from_cp.position, RTB_ALTITUDE) - group.land_at(self.conflict.from_cp.at) + wayp.tasks.append(EscortTaskAction(escorted_group.id, engagement_max_dist=ESCORT_ENGAGEMENT_MAX_DIST, lastwpt=waypoint_index)) + + if should_orbit: + orbit_task = ControlledTask(OrbitAction(ATTACK_CIRCLE_ALT, pattern=OrbitAction.OrbitPattern.Circle)) + orbit_task.stop_after_duration(ATTACK_CIRCLE_DURATION * 60) + + orbit_waypoint = group.add_waypoint(self.conflict.position, CAS_ALTITUDE) + orbit_waypoint.tasks.append(orbit_task) + orbit_waypoint.tasks.append(EngageTargets(max_distance=DEFENCE_ENGAGEMENT_MAX_DISTANCE)) groups.append(group) return groups @@ -207,11 +221,11 @@ class AircraftConflictGenerator: count=count, client_count=client_count, at=at and at or self._group_point(self.conflict.air_attackers_location)) - self.escort_targets.append(group) - group.add_waypoint(self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED) + waypoint = group.add_waypoint(self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED) group.task = CAS.name self._setup_group(group, CAS, client_count) + self.escort_targets.append((group, group.points.index(waypoint))) group.add_waypoint(self.conflict.from_cp.position, RTB_ALTITUDE) group.land_at(self.conflict.from_cp.at) @@ -227,7 +241,6 @@ class AircraftConflictGenerator: count=count, client_count=client_count, at=at and at or self._group_point(self.conflict.air_attackers_location)) - self.escort_targets.append(group) wayp = group.add_waypoint(self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED) for target_group in target_groups: @@ -235,6 +248,7 @@ class AircraftConflictGenerator: group.task = AntishipStrike.name self._setup_group(group, AntishipStrike, client_count) + self.escort_targets.append((group, group.points.index(wayp))) group.add_waypoint(self.conflict.from_cp.position, RTB_ALTITUDE) group.land_at(self.conflict.from_cp.at) @@ -244,9 +258,10 @@ class AircraftConflictGenerator: side=self.conflict.attackers_side, units=attackers, clients=clients, - at=at and at or self._group_point(self.conflict.air_attackers_location)): + at=at and at or self._group_point(self.conflict.air_attackers_location), + is_quick=at is None, + should_orbit=True): g.add_waypoint(self.conflict.position, WARM_START_ALTITUDE) - g.add_waypoint(self.conflict.from_cp.position, RTB_ALTITUDE) g.land_at(self.conflict.from_cp.at) def generate_transport_escort(self, escort: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): @@ -254,7 +269,9 @@ class AircraftConflictGenerator: side=self.conflict.defenders_side, units=escort, clients=clients, - at=at and at or self._group_point(self.conflict.air_defenders_location)): + at=at and at or self._group_point(self.conflict.air_defenders_location), + is_quick=at is None, + should_orbit=False): g.add_waypoint(self.conflict.to_cp.position, RTB_ALTITUDE) g.land_at(self.conflict.to_cp.at) @@ -271,7 +288,7 @@ 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=DEFENCE_ENGAGEMENT_MAX_DISTANCE)) - wayp.tasks.append(dcs.task.OrbitAction()) + wayp.tasks.append(dcs.task.OrbitAction(ATTACK_CIRCLE_ALT, pattern=OrbitAction.OrbitPattern.Circle)) self._setup_group(group, CAP, client_count) group.add_waypoint(self.conflict.to_cp.position, RTB_ALTITUDE) @@ -289,10 +306,10 @@ class AircraftConflictGenerator: client_count=client_count, at=self._group_point(self.conflict.air_defenders_location)) - group.task = Transport.name + waypoint = group.add_waypoint(destination.position.random_point_within(0, 0), TRANSPORT_LANDING_ALT) + self.escort_targets.append((group, group.points.index(waypoint))) - self.escort_targets.append(group) - group.add_waypoint(destination.position.random_point_within(0, 0), TRANSPORT_LANDING_ALT) + group.task = Transport.name group.land_at(destination) def generate_interception(self, interceptors: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): diff --git a/gen/conflictgen.py b/gen/conflictgen.py index c94c3551..e0bf85b2 100644 --- a/gen/conflictgen.py +++ b/gen/conflictgen.py @@ -198,9 +198,6 @@ class Conflict: defense_heading = to_cp.find_radial(from_cp.position.heading_between_point(to_cp.position), ignored_radial=attack_heading) distance = to_cp.size * GROUND_DISTANCE_FACTOR - attackers_location = position.point_from_heading(attack_heading, distance) - attackers_location = Conflict._find_ground_location(attackers_location, distance * 2, _heading_sum(attack_heading, 180), theater) - defenders_location = position.point_from_heading(defense_heading, distance) defenders_location = Conflict._find_ground_location(defenders_location, distance * 2, _heading_sum(defense_heading, 180), theater) @@ -213,7 +210,7 @@ class Conflict: defenders_side=defender, ground_attackers_location=None, ground_defenders_location=defenders_location, - air_attackers_location=position.point_from_heading(attack_heading, INTERCEPT_ATTACKERS_DISTANCE), + air_attackers_location=position.point_from_heading(attack_heading, AIR_DISTANCE), air_defenders_location=position ) diff --git a/gen/triggergen.py b/gen/triggergen.py index 56b85c20..c49ea74d 100644 --- a/gen/triggergen.py +++ b/gen/triggergen.py @@ -19,10 +19,11 @@ PUSH_TRIGGER_SIZE = 3000 REGROUP_ZONE_DISTANCE = 12000 REGROUP_ALT = 5000 +TRIGGER_WAYPOINT_OFFSET = 2 TRIGGER_MIN_DISTANCE_FROM_START = 10000 TRIGGER_RADIUS_MINIMUM = 25000 -TRIGGER_RADIUS_SMALL = 40000 +TRIGGER_RADIUS_SMALL = 30000 TRIGGER_RADIUS_MEDIUM = 100000 TRIGGER_RADIUS_LARGE = 150000 @@ -51,7 +52,7 @@ class TriggersGenerator: activate_by_trigger.append(vehicle_group) conflict_distance = self.conflict.from_cp.position.distance_to_point(self.conflict.position) - minimum_radius = min(conflict_distance - TRIGGER_MIN_DISTANCE_FROM_START, conflict_distance - TRIGGER_RADIUS_MINIMUM) + minimum_radius = max(conflict_distance - TRIGGER_MIN_DISTANCE_FROM_START, TRIGGER_RADIUS_MINIMUM) if minimum_radius < 0: minimum_radius = 0 @@ -147,3 +148,4 @@ class TriggersGenerator: # TODO: waypoint parts of this should not be post-hacked but added in airgen self._gen_activation_trigger(activation_trigger_radius, player_coalition, enemy_coalition) self._gen_push_trigger(player_coalition) + diff --git a/theater/base.py b/theater/base.py index 4652532f..eeed269d 100644 --- a/theater/base.py +++ b/theater/base.py @@ -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 * self.strength) + return int(self.total_armor * min(self.strength + 0.5, 1)) def assemble_aa_count(self) -> int: if self.strength > STRENGTH_AA_ASSEMBLE_MIN: diff --git a/theater/persiangulf.py b/theater/persiangulf.py index 737c5d52..a7c3fcb6 100644 --- a/theater/persiangulf.py +++ b/theater/persiangulf.py @@ -41,7 +41,6 @@ class PersianGulfTheater(ConflictTheater): bandar_abbas = ControlPoint.from_airport(persiangulf.Bandar_Abbas_Intl, LAND, SIZE_BIG, IMPORTANCE_HIGH) lar = ControlPoint.from_airport(persiangulf.Lar_Airbase, LAND, SIZE_REGULAR, IMPORTANCE_HIGH) - east_carrier = ControlPoint.carrier("West carrier", Point(-91023.430176, -159467.078125)) west_carrier = ControlPoint.carrier("East carrier", Point(-100531.972946, 60939.275818)) def __init__(self): @@ -67,10 +66,8 @@ class PersianGulfTheater(ConflictTheater): self.add_controlpoint(self.bandar_abbas, connected_to=[self.havadarya]) self.add_controlpoint(self.lar, connected_to=[self.bandar_lengeh, self.qeshm, self.havadarya]) - self.add_controlpoint(self.east_carrier) self.add_controlpoint(self.west_carrier) - self.east_carrier.captured = True self.west_carrier.captured = True self.al_dhafra.captured = True