mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
new frontline position finding method; AA for strikes; other minor fixes and adjustments
This commit is contained in:
parent
35a7da2816
commit
0015667829
@ -35,6 +35,17 @@ class StrikeOperation(Operation):
|
|||||||
conflict=conflict)
|
conflict=conflict)
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
|
for global_cp in self.game.theater.controlpoints:
|
||||||
|
if not global_cp.is_global:
|
||||||
|
continue
|
||||||
|
|
||||||
|
ship = self.shipgen.generate_carrier(type=db.find_unittype(Carriage, self.game.player)[0],
|
||||||
|
country=self.game.player,
|
||||||
|
at=global_cp.at)
|
||||||
|
|
||||||
|
if global_cp == self.from_cp and not self.is_quick:
|
||||||
|
self.attackers_starting_position = ship
|
||||||
|
|
||||||
targets = [] # type: typing.List[typing.Tuple[str, Point]]
|
targets = [] # type: typing.List[typing.Tuple[str, Point]]
|
||||||
category_counters = {} # type: typing.Dict[str, int]
|
category_counters = {} # type: typing.Dict[str, int]
|
||||||
processed_groups = []
|
processed_groups = []
|
||||||
|
|||||||
@ -155,7 +155,7 @@ class Conflict:
|
|||||||
return from_cp.has_frontline and to_cp.has_frontline
|
return from_cp.has_frontline and to_cp.has_frontline
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def frontline_position(cls, from_cp: ControlPoint, to_cp: ControlPoint) -> typing.Tuple[Point, int]:
|
def frontline_position0(cls, from_cp: ControlPoint, to_cp: ControlPoint) -> typing.Tuple[Point, int]:
|
||||||
cp_distance = from_cp.position.distance_to_point(to_cp.position)
|
cp_distance = from_cp.position.distance_to_point(to_cp.position)
|
||||||
cp_distance -= cp_distance * to_cp.frontline_offset + cp_distance * from_cp.frontline_offset
|
cp_distance -= cp_distance * to_cp.frontline_offset + cp_distance * from_cp.frontline_offset
|
||||||
|
|
||||||
@ -164,8 +164,45 @@ class Conflict:
|
|||||||
return to_cp.position.point_from_heading(heading, distance), heading
|
return to_cp.position.point_from_heading(heading, distance), heading
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def frontline_vector(cls, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater) -> typing.Tuple[Point, int, int]:
|
def frontline_position2(cls, theater: ConflictTheater, from_cp: ControlPoint, to_cp: ControlPoint) -> typing.Optional[typing.Tuple[Point, int]]:
|
||||||
center_position, heading = cls.frontline_position(from_cp, to_cp)
|
attack_heading = from_cp.position.heading_between_point(to_cp.position)
|
||||||
|
attack_starting_position = cls._find_ground_position(from_cp.position, 200000, attack_heading, theater)
|
||||||
|
if not attack_starting_position:
|
||||||
|
return None
|
||||||
|
|
||||||
|
attack_ending_position = cls._find_ground_position(to_cp.position, 200000, _opposite_heading(attack_heading), theater)
|
||||||
|
if not attack_ending_position:
|
||||||
|
return None
|
||||||
|
|
||||||
|
attack_distance = attack_ending_position.distance_to_point(attack_starting_position)
|
||||||
|
strength_delta = (from_cp.base.strength - to_cp.base.strength) / 1.0
|
||||||
|
middle_position = attack_starting_position.point_from_heading(attack_heading, attack_distance / 2)
|
||||||
|
|
||||||
|
return middle_position.point_from_heading(attack_heading, strength_delta * attack_distance), _opposite_heading(attack_heading)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def frontline_position(cls, theater: ConflictTheater, from_cp: ControlPoint, to_cp: ControlPoint) -> typing.Optional[typing.Tuple[Point, int]]:
|
||||||
|
attack_heading = from_cp.position.heading_between_point(to_cp.position)
|
||||||
|
attack_distance = from_cp.position.distance_to_point(to_cp.position)
|
||||||
|
middle_point = from_cp.position.point_from_heading(attack_heading, attack_distance / 2)
|
||||||
|
|
||||||
|
strength_delta = (from_cp.base.strength - to_cp.base.strength) / 1.0
|
||||||
|
position = middle_point.point_from_heading(attack_heading, strength_delta * attack_distance / 2 - FRONTLINE_MIN_CP_DISTANCE)
|
||||||
|
ground_position = cls._find_ground_position(position, attack_distance / 2 - FRONTLINE_MIN_CP_DISTANCE, attack_heading, theater)
|
||||||
|
if ground_position:
|
||||||
|
return ground_position, attack_heading
|
||||||
|
else:
|
||||||
|
print(from_cp, to_cp)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def frontline_vector(cls, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater) -> typing.Optional[typing.Tuple[Point, int, int]]:
|
||||||
|
frontline = cls.frontline_position(theater, from_cp, to_cp)
|
||||||
|
if not frontline:
|
||||||
|
return None
|
||||||
|
|
||||||
|
center_position, heading = frontline
|
||||||
left_position, right_position = None, None
|
left_position, right_position = None, None
|
||||||
|
|
||||||
if not theater.is_on_land(center_position):
|
if not theater.is_on_land(center_position):
|
||||||
@ -401,7 +438,7 @@ class Conflict:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def transport_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater):
|
def transport_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater):
|
||||||
frontline_position, heading = cls.frontline_position(from_cp, to_cp)
|
frontline_position, heading = cls.frontline_position(theater, from_cp, to_cp)
|
||||||
initial_dest = frontline_position.point_from_heading(heading, TRANSPORT_FRONTLINE_DIST)
|
initial_dest = frontline_position.point_from_heading(heading, TRANSPORT_FRONTLINE_DIST)
|
||||||
dest = cls._find_ground_position(initial_dest, from_cp.position.distance_to_point(to_cp.position) / 3, heading, theater)
|
dest = cls._find_ground_position(initial_dest, from_cp.position.distance_to_point(to_cp.position) / 3, heading, theater)
|
||||||
if not dest:
|
if not dest:
|
||||||
|
|||||||
@ -98,7 +98,11 @@ 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)
|
frontline = Conflict.frontline_position(self.game.theater, from_cp, to_cp)
|
||||||
|
if not frontline:
|
||||||
|
continue
|
||||||
|
|
||||||
|
point, heading = frontline
|
||||||
plane_start = point.point_from_heading(turn_heading(heading, 90), FRONTLINE_LENGTH / 2)
|
plane_start = point.point_from_heading(turn_heading(heading, 90), FRONTLINE_LENGTH / 2)
|
||||||
|
|
||||||
for offset in range(0, FRONTLINE_LENGTH, FRONT_SMOKE_SPACING):
|
for offset in range(0, FRONTLINE_LENGTH, FRONT_SMOKE_SPACING):
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -11,7 +11,7 @@ def load_templates():
|
|||||||
temp_mis = Mission()
|
temp_mis = Mission()
|
||||||
temp_mis.load_file("resources/tools/groundobject_templates.miz")
|
temp_mis.load_file("resources/tools/groundobject_templates.miz")
|
||||||
|
|
||||||
groups = {} # type: typing.Dict[str, typing.Dict[int, typing.Collection[Static]]]
|
groups = {} # type: typing.Dict[str, typing.Dict[int, typing.List[Static]]]
|
||||||
|
|
||||||
for static_group in temp_mis.country("USA").static_group:
|
for static_group in temp_mis.country("USA").static_group:
|
||||||
for static in static_group.units:
|
for static in static_group.units:
|
||||||
@ -42,6 +42,7 @@ def load_templates():
|
|||||||
"heading": static.heading,
|
"heading": static.heading,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
tpls["aa"] = {0: [{"type": "AA", "offset": Point(0, 0), "heading": 0}]}
|
||||||
return tpls
|
return tpls
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -3,18 +3,20 @@ import typing
|
|||||||
import math
|
import math
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
from game import db
|
|
||||||
from theater.controlpoint import ControlPoint
|
|
||||||
|
|
||||||
from dcs.planes import *
|
from dcs.planes import *
|
||||||
from dcs.vehicles import *
|
from dcs.vehicles import *
|
||||||
from dcs.task import *
|
from dcs.task import *
|
||||||
|
|
||||||
|
from game import db
|
||||||
|
|
||||||
STRENGTH_AA_ASSEMBLE_MIN = 0.2
|
STRENGTH_AA_ASSEMBLE_MIN = 0.2
|
||||||
PLANES_SCRAMBLE_MIN_BASE = 4
|
PLANES_SCRAMBLE_MIN_BASE = 4
|
||||||
PLANES_SCRAMBLE_MAX_BASE = 8
|
PLANES_SCRAMBLE_MAX_BASE = 8
|
||||||
PLANES_SCRAMBLE_FACTOR = 0.6
|
PLANES_SCRAMBLE_FACTOR = 0.6
|
||||||
|
|
||||||
|
BASE_MAX_STRENGTH = 1
|
||||||
|
BASE_MIN_STRENGTH = 0
|
||||||
|
|
||||||
|
|
||||||
class Base:
|
class Base:
|
||||||
aircraft = {} # type: typing.Dict[PlaneType, int]
|
aircraft = {} # type: typing.Dict[PlaneType, int]
|
||||||
@ -136,10 +138,10 @@ class Base:
|
|||||||
|
|
||||||
def affect_strength(self, amount):
|
def affect_strength(self, amount):
|
||||||
self.strength += amount
|
self.strength += amount
|
||||||
if self.strength > 1:
|
if self.strength > BASE_MAX_STRENGTH:
|
||||||
self.strength = 1
|
self.strength = BASE_MAX_STRENGTH
|
||||||
elif self.strength < 0:
|
elif self.strength <= 0:
|
||||||
self.strength = 0.001
|
self.strength = BASE_MIN_STRENGTH
|
||||||
|
|
||||||
def scramble_count(self, multiplier: float, task: Task = None) -> int:
|
def scramble_count(self, multiplier: float, task: Task = None) -> int:
|
||||||
if task:
|
if task:
|
||||||
|
|||||||
@ -25,12 +25,12 @@ class CaucasusTheater(ConflictTheater):
|
|||||||
kutaisi = ControlPoint.from_airport(caucasus.Kutaisi, LAND, SIZE_SMALL, IMPORTANCE_LOW)
|
kutaisi = ControlPoint.from_airport(caucasus.Kutaisi, LAND, SIZE_SMALL, IMPORTANCE_LOW)
|
||||||
senaki = ControlPoint.from_airport(caucasus.Senaki_Kolkhi, LAND, SIZE_REGULAR, IMPORTANCE_LOW)
|
senaki = ControlPoint.from_airport(caucasus.Senaki_Kolkhi, LAND, SIZE_REGULAR, IMPORTANCE_LOW)
|
||||||
kobuleti = ControlPoint.from_airport(caucasus.Kobuleti, COAST_A_E, SIZE_SMALL, 1.1)
|
kobuleti = ControlPoint.from_airport(caucasus.Kobuleti, COAST_A_E, SIZE_SMALL, 1.1)
|
||||||
batumi = ControlPoint.from_airport(caucasus.Batumi, COAST_DL_E, SIZE_SMALL, 1.3)
|
batumi = ControlPoint.from_airport(caucasus.Batumi, COAST_DL_E, SIZE_SMALL, 1.3, has_frontline=False)
|
||||||
sukhumi = ControlPoint.from_airport(caucasus.Sukhumi_Babushara, COAST_DR_E, SIZE_REGULAR, 1.2)
|
sukhumi = ControlPoint.from_airport(caucasus.Sukhumi_Babushara, COAST_DR_E, SIZE_REGULAR, 1.2)
|
||||||
gudauta = ControlPoint.from_airport(caucasus.Gudauta, COAST_DR_E, SIZE_REGULAR, 1.2)
|
gudauta = ControlPoint.from_airport(caucasus.Gudauta, COAST_DR_E, SIZE_REGULAR, 1.2, has_frontline=False)
|
||||||
sochi = ControlPoint.from_airport(caucasus.Sochi_Adler, COAST_DR_E, SIZE_BIG, IMPORTANCE_HIGH)
|
sochi = ControlPoint.from_airport(caucasus.Sochi_Adler, COAST_DR_E, SIZE_BIG, IMPORTANCE_HIGH, has_frontline=False)
|
||||||
|
|
||||||
gelendzhik = ControlPoint.from_airport(caucasus.Gelendzhik, COAST_DR_E, SIZE_BIG, 1.1)
|
gelendzhik = ControlPoint.from_airport(caucasus.Gelendzhik, COAST_DR_E, SIZE_BIG, 1.1, has_frontline=False)
|
||||||
maykop = ControlPoint.from_airport(caucasus.Maykop_Khanskaya, LAND, SIZE_LARGE, IMPORTANCE_HIGH)
|
maykop = ControlPoint.from_airport(caucasus.Maykop_Khanskaya, LAND, SIZE_LARGE, IMPORTANCE_HIGH)
|
||||||
krasnodar = ControlPoint.from_airport(caucasus.Krasnodar_Center, LAND, SIZE_LARGE, IMPORTANCE_HIGH)
|
krasnodar = ControlPoint.from_airport(caucasus.Krasnodar_Center, LAND, SIZE_LARGE, IMPORTANCE_HIGH)
|
||||||
novorossiysk = ControlPoint.from_airport(caucasus.Novorossiysk, COAST_DR_E, SIZE_BIG, 1.2)
|
novorossiysk = ControlPoint.from_airport(caucasus.Novorossiysk, COAST_DR_E, SIZE_BIG, 1.2)
|
||||||
@ -75,6 +75,7 @@ class CaucasusTheater(ConflictTheater):
|
|||||||
|
|
||||||
self.carrier_1.captured = True
|
self.carrier_1.captured = True
|
||||||
self.soganlug.captured = True
|
self.soganlug.captured = True
|
||||||
|
self.gudauta.captured = True
|
||||||
|
|
||||||
def add_controlpoint(self, point: ControlPoint, connected_to: typing.Collection[ControlPoint] = []):
|
def add_controlpoint(self, point: ControlPoint, connected_to: typing.Collection[ControlPoint] = []):
|
||||||
point.name = " ".join(re.split(r"[ -]", point.name)[:1])
|
point.name = " ".join(re.split(r"[ -]", point.name)[:1])
|
||||||
|
|||||||
@ -49,7 +49,7 @@ class ControlPoint:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def carrier(cls, name: str, at: Point):
|
def carrier(cls, name: str, at: Point):
|
||||||
import theater.conflicttheater
|
import theater.conflicttheater
|
||||||
return cls(0, name, at, at, theater.conflicttheater.LAND, theater.conflicttheater.SIZE_SMALL, 1)
|
return cls(0, name, at, at, theater.conflicttheater.LAND, theater.conflicttheater.SIZE_SMALL, 1, has_frontline=False)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class NevadaTheater(ConflictTheater):
|
|||||||
daytime_map = {
|
daytime_map = {
|
||||||
"dawn": (4, 6),
|
"dawn": (4, 6),
|
||||||
"day": (6, 17),
|
"day": (6, 17),
|
||||||
"dusk": (17, 19),
|
"dusk": (17, 18),
|
||||||
"night": (0, 5),
|
"night": (0, 5),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -59,7 +59,7 @@ def generate_groundobjects(theater: ConflictTheater):
|
|||||||
group_id = 0
|
group_id = 0
|
||||||
for cp in theater.enemy_points():
|
for cp in theater.enemy_points():
|
||||||
for _ in range(0, random.randrange(3, 6)):
|
for _ in range(0, random.randrange(3, 6)):
|
||||||
available_categories = list(tpls)
|
available_categories = list(tpls) + ["aa", "aa", "aa"]
|
||||||
tpl_category = random.choice(available_categories)
|
tpl_category = random.choice(available_categories)
|
||||||
|
|
||||||
tpl = random.choice(list(tpls[tpl_category].values()))
|
tpl = random.choice(list(tpls[tpl_category].values()))
|
||||||
@ -87,7 +87,7 @@ def generate_groundobjects(theater: ConflictTheater):
|
|||||||
g.cp_id = cp.id
|
g.cp_id = cp.id
|
||||||
|
|
||||||
g.dcs_identifier = object["type"]
|
g.dcs_identifier = object["type"]
|
||||||
g.heading = object["heading"],
|
g.heading = object["heading"]
|
||||||
g.position = Point(point.x + object["offset"].x, point.y + object["offset"].y)
|
g.position = Point(point.x + object["offset"].x, point.y + object["offset"].y)
|
||||||
|
|
||||||
cp.ground_objects.append(g)
|
cp.ground_objects.append(g)
|
||||||
|
|||||||
@ -80,8 +80,16 @@ 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):
|
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)
|
frontline = Conflict.frontline_vector(cp, connected_cp, self.game.theater)
|
||||||
distance = max(distance, 1000)
|
if not frontline:
|
||||||
|
print(cp, connected_cp)
|
||||||
|
continue
|
||||||
|
|
||||||
|
frontline_pos, heading, distance = frontline
|
||||||
|
if distance < 10000:
|
||||||
|
frontline_pos = frontline_pos.point_from_heading(heading + 180, 5000)
|
||||||
|
distance = 10000
|
||||||
|
|
||||||
start_coords = self.transform_point(frontline_pos, treshold=10)
|
start_coords = self.transform_point(frontline_pos, treshold=10)
|
||||||
end_coords = self.transform_point(frontline_pos.point_from_heading(heading, distance), treshold=60)
|
end_coords = self.transform_point(frontline_pos.point_from_heading(heading, distance), treshold=60)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user