mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
display events on map
This commit is contained in:
parent
af5cd57094
commit
355cd3e0e4
@ -9,6 +9,7 @@ from dcs.unittype import UnitType
|
||||
from game import *
|
||||
from theater import *
|
||||
from gen.environmentgen import EnvironmentSettings
|
||||
from gen.conflictgen import Conflict
|
||||
from game.db import assigned_units_from, unitdict_from
|
||||
|
||||
from userdata.debriefing import Debriefing
|
||||
|
||||
@ -10,6 +10,11 @@ class InterceptEvent(Event):
|
||||
|
||||
transport_unit = None # type: FlyingType
|
||||
|
||||
def __init__(self, game, from_cp: ControlPoint, target_cp: ControlPoint, location: Point, attacker_name: str,
|
||||
defender_name: str):
|
||||
super().__init__(game, from_cp, target_cp, location, attacker_name, defender_name)
|
||||
self.location = Conflict.intercept_position(self.from_cp, self.to_cp)
|
||||
|
||||
def __str__(self):
|
||||
return "Air Intercept"
|
||||
|
||||
@ -74,7 +79,8 @@ class InterceptEvent(Event):
|
||||
from_cp=self.departure_cp,
|
||||
to_cp=self.to_cp)
|
||||
|
||||
op.setup(escort=assigned_units_from(escort),
|
||||
op.setup(location=self.location,
|
||||
escort=assigned_units_from(escort),
|
||||
transport={self.transport_unit: 1},
|
||||
airdefense={airdefense_unit: self.AIRDEFENSE_COUNT},
|
||||
interceptors=flights[CAP])
|
||||
|
||||
@ -9,6 +9,11 @@ class NavalInterceptEvent(Event):
|
||||
|
||||
targets = None # type: db.ShipDict
|
||||
|
||||
def __init__(self, game, from_cp: ControlPoint, target_cp: ControlPoint, location: Point, attacker_name: str,
|
||||
defender_name: str):
|
||||
super().__init__(game, from_cp, target_cp, location, attacker_name, defender_name)
|
||||
self.location = Conflict.naval_intercept_position(from_cp, target_cp, game.theater)
|
||||
|
||||
def _targets_count(self) -> int:
|
||||
from gen.conflictgen import IMPORTANCE_LOW
|
||||
factor = (self.to_cp.importance - IMPORTANCE_LOW + 0.1) * 20
|
||||
@ -83,7 +88,8 @@ class NavalInterceptEvent(Event):
|
||||
to_cp=self.to_cp
|
||||
)
|
||||
|
||||
op.setup(strikegroup=flights[CAS],
|
||||
op.setup(location=self.location,
|
||||
strikegroup=flights[CAS],
|
||||
interceptors={},
|
||||
targets=self.targets)
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ Events:
|
||||
EVENT_PROBABILITIES = {
|
||||
# events always present; only for the player
|
||||
FrontlineAttackEvent: [100, 0],
|
||||
FrontlinePatrolEvent: [100, 0],
|
||||
#FrontlinePatrolEvent: [100, 0],
|
||||
StrikeEvent: [100, 0],
|
||||
|
||||
# events randomly present; only for the player
|
||||
@ -169,10 +169,10 @@ class Game:
|
||||
if not Conflict.has_frontline_between(player_cp, enemy_cp):
|
||||
continue
|
||||
|
||||
if player_probability == 100 or self._roll(player_probability, player_cp.base.strength):
|
||||
if player_probability == 100 or player_probability > 0 and self._roll(player_probability, player_cp.base.strength):
|
||||
self._generate_player_event(event_class, player_cp, enemy_cp)
|
||||
|
||||
if enemy_probability == 100 or self._roll(enemy_probability, enemy_cp.base.strength):
|
||||
if enemy_probability == 100 or enemy_probability > 0 and self._roll(enemy_probability, enemy_cp.base.strength):
|
||||
self._generate_enemy_event(event_class, player_cp, enemy_cp)
|
||||
|
||||
def commision_unit_types(self, cp: ControlPoint, for_task: Task) -> typing.Collection[UnitType]:
|
||||
|
||||
@ -4,6 +4,7 @@ from .operation import *
|
||||
|
||||
|
||||
class InterceptOperation(Operation):
|
||||
location = None # type: Point
|
||||
escort = None # type: db.AssignedUnitsDict
|
||||
transport = None # type: db.PlaneDict
|
||||
interceptors = None # type: db.AssignedUnitsDict
|
||||
@ -12,10 +13,12 @@ class InterceptOperation(Operation):
|
||||
trigger_radius = TRIGGER_RADIUS_LARGE
|
||||
|
||||
def setup(self,
|
||||
location: Point,
|
||||
escort: db.AssignedUnitsDict,
|
||||
transport: db.PlaneDict,
|
||||
airdefense: db.AirDefenseDict,
|
||||
interceptors: db.AssignedUnitsDict):
|
||||
self.location = location
|
||||
self.escort = escort
|
||||
self.transport = transport
|
||||
self.airdefense = airdefense
|
||||
@ -30,6 +33,7 @@ class InterceptOperation(Operation):
|
||||
conflict = Conflict.intercept_conflict(
|
||||
attacker=self.current_mission.country(self.attacker_name),
|
||||
defender=self.current_mission.country(self.defender_name),
|
||||
position=self.location,
|
||||
from_cp=self.from_cp,
|
||||
to_cp=self.to_cp,
|
||||
theater=self.game.theater
|
||||
|
||||
@ -4,15 +4,18 @@ from .operation import *
|
||||
|
||||
|
||||
class NavalInterceptionOperation(Operation):
|
||||
location = None # type: Point
|
||||
strikegroup = None # type: db.AssignedUnitsDict
|
||||
interceptors = None # type: db.AssignedUnitsDict
|
||||
targets = None # type: db.ShipDict
|
||||
trigger_radius = TRIGGER_RADIUS_LARGE
|
||||
|
||||
def setup(self,
|
||||
location: Point,
|
||||
strikegroup: db.AssignedUnitsDict,
|
||||
interceptors: db.AssignedUnitsDict,
|
||||
targets: db.ShipDict):
|
||||
self.location = location
|
||||
self.strikegroup = strikegroup
|
||||
self.interceptors = interceptors
|
||||
self.targets = targets
|
||||
@ -25,6 +28,7 @@ class NavalInterceptionOperation(Operation):
|
||||
conflict = Conflict.naval_intercept_conflict(
|
||||
attacker=self.current_mission.country(self.attacker_name),
|
||||
defender=self.current_mission.country(self.defender_name),
|
||||
position=self.location,
|
||||
from_cp=self.from_cp,
|
||||
to_cp=self.to_cp,
|
||||
theater=self.game.theater
|
||||
|
||||
@ -277,13 +277,14 @@ class Conflict:
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def intercept_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater):
|
||||
def intercept_position(cls, from_cp: ControlPoint, to_cp:ControlPoint) -> Point:
|
||||
raw_distance = from_cp.position.distance_to_point(to_cp.position) * 1.5
|
||||
distance = max(min(raw_distance, INTERCEPT_MAX_DISTANCE), INTERCEPT_MIN_DISTANCE)
|
||||
|
||||
heading = _heading_sum(from_cp.position.heading_between_point(to_cp.position), random.choice([-1, 1]) * random.randint(60, 100))
|
||||
position = from_cp.position.point_from_heading(heading, distance)
|
||||
return from_cp.position.point_from_heading(heading, distance)
|
||||
|
||||
@classmethod
|
||||
def intercept_conflict(cls, attacker: Country, defender: Country, position: Point, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater):
|
||||
return cls(
|
||||
position=position.point_from_heading(position.heading_between_point(to_cp.position), INTERCEPT_CONFLICT_DISTANCE),
|
||||
theater=theater,
|
||||
@ -385,7 +386,7 @@ class Conflict:
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def naval_intercept_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater):
|
||||
def naval_intercept_position(cls, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater):
|
||||
radial = random.choice(to_cp.sea_radials)
|
||||
|
||||
initial_distance = min(int(from_cp.position.distance_to_point(to_cp.position) * NAVAL_INTERCEPT_DISTANCE_FACTOR), NAVAL_INTERCEPT_DISTANCE_MAX)
|
||||
@ -395,7 +396,10 @@ class Conflict:
|
||||
|
||||
if not theater.is_on_land(position):
|
||||
break
|
||||
return position
|
||||
|
||||
@classmethod
|
||||
def naval_intercept_conflict(cls, attacker: Country, defender: Country, position: Point, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater):
|
||||
attacker_heading = from_cp.position.heading_between_point(to_cp.position)
|
||||
return cls(
|
||||
position=position,
|
||||
|
||||
@ -18,8 +18,6 @@ IMPORTANCE_LOW = 1
|
||||
IMPORTANCE_MEDIUM = 1.2
|
||||
IMPORTANCE_HIGH = 1.4
|
||||
|
||||
GLOBAL_CP_CONFLICT_DISTANCE_MIN = 340000
|
||||
|
||||
"""
|
||||
ALL_RADIALS = [0, 45, 90, 135, 180, 225, 270, 315, ]
|
||||
COAST_NS_E = [45, 90, 135, ]
|
||||
|
||||
@ -10,7 +10,10 @@ from ui.styles import STYLES
|
||||
from ui.window import *
|
||||
|
||||
|
||||
EVENT_DEPARTURE_MAX_DISTANCE = 250000
|
||||
EVENT_DEPARTURE_MAX_DISTANCE = 340000
|
||||
|
||||
EVENT_COLOR_ATTACK = (100, 100, 255)
|
||||
EVENT_COLOR_DEFENSE = (255, 100, 100)
|
||||
|
||||
|
||||
class OverviewCanvas:
|
||||
@ -30,6 +33,7 @@ class OverviewCanvas:
|
||||
|
||||
WIDTH = 1066
|
||||
HEIGHT = 600
|
||||
MAP_PADDING = 0
|
||||
|
||||
started = None
|
||||
ground_assets_icons = None # type: typing.Dict[str, pygame.Surface]
|
||||
@ -170,7 +174,8 @@ class OverviewCanvas:
|
||||
pygame.draw.rect(self.map, self.WHITE, (0, 0, self.map.get_width(), self.map.get_height()), 5)
|
||||
|
||||
# Create surfaces for drawing
|
||||
self.surface = pygame.Surface((self.map.get_width(), self.map.get_height()))
|
||||
self.surface = pygame.Surface((self.map.get_width() + self.MAP_PADDING * 2,
|
||||
self.map.get_height() + self.MAP_PADDING * 2))
|
||||
self.surface.set_alpha(None)
|
||||
self.overlay = pygame.Surface((self.WIDTH, self.HEIGHT), pygame.SRCALPHA)
|
||||
|
||||
@ -190,10 +195,10 @@ class OverviewCanvas:
|
||||
self.redraw_required = True
|
||||
i = 0
|
||||
while not self.exited:
|
||||
self.clock.tick(60)
|
||||
self.clock.tick(30)
|
||||
self.draw()
|
||||
i += 1
|
||||
if i == 300:
|
||||
if i == 600:
|
||||
self.frontline_vector_cache = {}
|
||||
i = 0
|
||||
print("Stopped SDL app")
|
||||
@ -248,6 +253,7 @@ class OverviewCanvas:
|
||||
if self.redraw_required:
|
||||
# Fill
|
||||
self.screen.fill(self.BACKGROUND)
|
||||
self.surface.fill(self.BACKGROUND)
|
||||
self.overlay.fill(pygame.Color(0, 0, 0, 0))
|
||||
|
||||
# Surface
|
||||
@ -267,7 +273,7 @@ class OverviewCanvas:
|
||||
self.redraw_required = False
|
||||
|
||||
def draw_map(self, surface: pygame.Surface, overlay: pygame.Surface, mouse_pos: (int, int), mouse_down: [bool, bool]):
|
||||
self.surface.blit(self.map, (0, 0))
|
||||
self.surface.blit(self.map, (self.MAP_PADDING, self.MAP_PADDING))
|
||||
|
||||
# Display zoom level on overlay
|
||||
zoom_lvl = self.font.render(" x " + str(self.zoom) + " ", self.ANTIALIASING, self.WHITE, self.DARK_BLUE)
|
||||
@ -436,24 +442,47 @@ class OverviewCanvas:
|
||||
surface.blit(lb, (pos[0] + 18, pos[1]))
|
||||
|
||||
def draw_events(self, surface: pygame.Surface, mouse_pos, mouse_down):
|
||||
occupied_rects = [pygame.Rect(*self._transform_point(x.position), 32, 32) for x in self.game.theater.controlpoints]
|
||||
occupied_rects = []
|
||||
for cp in self.game.theater.controlpoints:
|
||||
point = self._transform_point(cp.position)
|
||||
occupied_rects.append(pygame.Rect(point[0] - 16, point[1] - 16, 32, 48))
|
||||
|
||||
def _location_to_rect(location: Point) -> pygame.Rect:
|
||||
nonlocal occupied_rects
|
||||
point = self._transform_point(location)
|
||||
rect = pygame.Rect(*point, 32, 32)
|
||||
rect = pygame.Rect(point[0] - 16, point[1] - 16, 32, 32)
|
||||
|
||||
i = 0
|
||||
for occupied_rect in occupied_rects:
|
||||
if rect.colliderect(occupied_rect):
|
||||
i += 1
|
||||
if i % 2:
|
||||
rect.y = occupied_rect.y + occupied_rect.height + 3
|
||||
else:
|
||||
rect.x = occupied_rect.x + occupied_rect.width + 3
|
||||
while True:
|
||||
result = True
|
||||
for occupied_rect in occupied_rects:
|
||||
if rect.colliderect(occupied_rect):
|
||||
i += 1
|
||||
|
||||
if i % 2:
|
||||
rect.y += occupied_rect.height
|
||||
else:
|
||||
rect.x += occupied_rect.width
|
||||
|
||||
result = False
|
||||
break
|
||||
if result:
|
||||
break
|
||||
|
||||
occupied_rects.append(rect)
|
||||
return rect
|
||||
|
||||
def _events_priority_key(event: Event) -> int:
|
||||
priority_list = [InfantryTransportEvent, StrikeEvent, BaseAttackEvent]
|
||||
if type(event) not in priority_list:
|
||||
return 0
|
||||
else:
|
||||
return priority_list.index(type(event)) + 1
|
||||
|
||||
events = self.game.events
|
||||
events.sort(key=_events_priority_key, reverse=True)
|
||||
print(events)
|
||||
|
||||
label_to_draw = None
|
||||
for event in self.game.events:
|
||||
location = event.location
|
||||
@ -461,7 +490,7 @@ class OverviewCanvas:
|
||||
location = self._frontline_center(event.from_cp, event.to_cp)
|
||||
|
||||
rect = _location_to_rect(location)
|
||||
pygame.draw.rect(surface, self.RED, rect)
|
||||
pygame.draw.rect(surface, EVENT_COLOR_ATTACK if event.is_player_attacking else EVENT_COLOR_DEFENSE, rect)
|
||||
self.surface.blit(self.event_icons[event.__class__], rect.topleft)
|
||||
|
||||
if rect.collidepoint(*mouse_pos) or self.selected_event_info == (event, rect.center):
|
||||
@ -511,6 +540,9 @@ class OverviewCanvas:
|
||||
X = point_b_img[1] + X_offset * X_scale
|
||||
Y = point_a_img[0] - Y_offset * Y_scale
|
||||
|
||||
X += self.MAP_PADDING
|
||||
Y += self.MAP_PADDING
|
||||
|
||||
return X > treshold and X or treshold, Y > treshold and Y or treshold
|
||||
|
||||
def _frontline_vector(self, from_cp: ControlPoint, to_cp: ControlPoint):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user