diff --git a/game/db.py b/game/db.py index 2026ee47..422f00c2 100644 --- a/game/db.py +++ b/game/db.py @@ -486,6 +486,7 @@ def task_name(task) -> str: def choose_units(for_task: Task, factor: float, count: int, country: str) -> typing.Collection[UnitType]: suitable_unittypes = find_unittype(for_task, country) + suitable_unittypes = [x for x in suitable_unittypes if x not in helicopter_map.values()] suitable_unittypes.sort(key=lambda x: PRICES[x]) idx = int(len(suitable_unittypes) * factor) diff --git a/game/event/convoystrike.py b/game/event/convoystrike.py index d6ce9798..4b9c2cc8 100644 --- a/game/event/convoystrike.py +++ b/game/event/convoystrike.py @@ -15,7 +15,7 @@ DEFENDERS_AMOUNT_FACTOR = 4 class ConvoyStrikeEvent(Event): - SUCCESS_FACTOR = 0.7 + SUCCESS_FACTOR = 0.6 STRENGTH_INFLUENCE = 0.25 targets = None # type: db.ArmorDict diff --git a/game/event/strike.py b/game/event/strike.py index cf6a0c53..949cbdb9 100644 --- a/game/event/strike.py +++ b/game/event/strike.py @@ -8,7 +8,7 @@ class StrikeEvent(Event): SINGLE_OBJECT_STRENGTH_INFLUENCE = 0.05 def __str__(self): - return "Strike" + return "Strike / SEAD" def is_successfull(self, debriefing: Debriefing): return True diff --git a/gen/conflictgen.py b/gen/conflictgen.py index bf169aaf..c4d09f7e 100644 --- a/gen/conflictgen.py +++ b/gen/conflictgen.py @@ -327,11 +327,15 @@ class Conflict: if not frontline_position: assert False - heading = _heading_sum(frontline_heading, +45) - starting_position = Conflict._find_ground_position(frontline_position.point_from_heading(heading, 15000), + heading = frontline_heading + starting_position = Conflict._find_ground_position(frontline_position.point_from_heading(heading, 7000), GROUND_INTERCEPT_SPREAD, _opposite_heading(heading), theater) - destination_position = frontline_position + if not starting_position: + starting_position = frontline_position + destination_position = frontline_position + else: + destination_position = frontline_position return cls( position=destination_position, diff --git a/theater/start_generator.py b/theater/start_generator.py index d14a6e63..e118ef58 100644 --- a/theater/start_generator.py +++ b/theater/start_generator.py @@ -73,9 +73,16 @@ def generate_groundobjects(theater: ConflictTheater): group_id = 0 for cp in theater.controlpoints: - for _ in range(0, random.randrange(2, 4)): - available_categories = list(tpls) + ["aa", "aa"] - tpl_category = random.choice(available_categories) + if cp.is_global: + continue + + amount = random.randrange(5, 7) + for i in range(0, amount): + available_categories = list(tpls) + if i >= amount - 2: + tpl_category = "aa" + else: + tpl_category = random.choice(available_categories) tpl = random.choice(list(tpls[tpl_category].values())) @@ -85,13 +92,6 @@ def generate_groundobjects(theater: ConflictTheater): print("Couldn't find point for {}".format(cp)) continue - """ - dist = point.distance_to_point(cp.position) - 15000 - for another_cp in theater.enemy_points(): - if another_cp.position.distance_to_point(point) < dist: - cp = another_cp - """ - group_id += 1 object_id = 0 diff --git a/ui/mainmenu.py b/ui/mainmenu.py index e3527793..79f95cfb 100644 --- a/ui/mainmenu.py +++ b/ui/mainmenu.py @@ -25,87 +25,11 @@ class MainMenu(Menu): def display(self): persistency.save_game(self.game) - self.window.clear_right_pane() self.upd.update() - # Header : header = Frame(self.frame, **STYLES["header"]) - Button(header, text="Configuration", command=self.configuration_menu, **STYLES["btn-primary"]).grid(column=0, row=0, sticky=NW) - Label(header, text="Budget: {}m (+{}m)".format(self.game.budget, self.game.budget_reward_amount), **STYLES["strong"]).grid(column=1, row=0, sticky=N+EW, padx=50) - Button(header, text="Pass turn", command=self.pass_turn, **STYLES["btn-primary"]).grid(column=2, row=0, sticky=NE) - header.grid(column=0, row=0, sticky=N+EW) - - content = Frame(self.frame, **STYLES["body"]) - content.grid(column=0, row=1, sticky=NSEW) - column = 0 - row = 0 - - """ - def label(text): - nonlocal row, body - frame = LabelFrame(body, **STYLES["label-frame"]) - frame.grid(row=row, sticky=N+EW, columnspan=2) - Label(frame, text=text, **STYLES["widget"]).grid(row=row, sticky=NS) - row += 1 - - def event_button(event): - nonlocal row, body - frame = LabelFrame(body, **STYLES["label-frame"]) - frame.grid(row=row, sticky=N+EW) - Message(frame, text="{}".format( - event - ), aspect=1600, **STYLES["widget"]).grid(column=0, row=0, sticky=N+EW) - Button(body, text=">", command=self.start_event(event), **STYLES["btn-primary"]).grid(column=1, row=row, sticky=E) - row += 1 - - def departure_header(text, style="strong"): - nonlocal row, body - Label(body, text=text, **STYLES[style]).grid(column=0, columnspan=2, row=row, sticky=N+EW, pady=(0, 5)) - row += 1 - - def destination_header(text): - nonlocal row, body - Label(body, text=text, **STYLES["substrong"]).grid(column=0, columnspan=2, row=row, sticky=N+EW) - row += 1 - - events = self.game.events - events.sort(key=lambda x: x.to_cp.name) - events.sort(key=lambda x: x.from_cp.name) - events.sort(key=lambda x: x.informational and 1 or (self.game.is_player_attack(x) and 2 or 0)) - - destination = None - departure = None - - for event in events: - if event.informational: - new_departure = "Deliveries" - elif not self.game.is_player_attack(event): - new_departure = "Enemy attack" - else: - new_departure = event.from_cp.name - - if new_departure != departure: - body = Frame(content, **STYLES["body"]) - body.grid(column=column, row=1, sticky=N+EW) - row = 0 - column += 1 - - departure = new_departure - departure_header(new_departure, style="strong" if self.game.is_player_attack(event) else "supstrong") - destination = None - - if not event.informational: - new_destination = "At {}".format(event.to_cp.name) - if destination != new_destination: - destination_header(new_destination) - destination = new_destination - - if event.informational: - label(str(event)) - else: - event_button(event) - """ + header.grid(column=0, row=0, sticky=NSEW) def pass_turn(self): self.game.pass_turn(no_action=True) diff --git a/ui/overviewcanvas.py b/ui/overviewcanvas.py index 07fb2fe7..0d545fd0 100644 --- a/ui/overviewcanvas.py +++ b/ui/overviewcanvas.py @@ -33,7 +33,7 @@ class OverviewCanvas: WIDTH = 1066 HEIGHT = 600 - MAP_PADDING = 0 + MAP_PADDING = 100 started = None ground_assets_icons = None # type: typing.Dict[str, pygame.Surface] @@ -99,30 +99,15 @@ class OverviewCanvas: if self.screen: self.redraw_required = True self.draw() - col = 0 - Label(self.options, text="Bases", **STYLES["widget"]).grid(row=0, column=col, sticky=W) - Checkbutton(self.options, variable=self.display_bases, **STYLES["radiobutton"]).grid(row=0, column=col + 1, - sticky=E) - Separator(self.options, orient=VERTICAL).grid(row=0, column=col + 2, sticky=NS) - col += 3 - Label(self.options, text="Roads", **STYLES["widget"]).grid(row=0, column=col, sticky=W) - Checkbutton(self.options, variable=self.display_road, **STYLES["radiobutton"]).grid(row=0, column=col + 1, - sticky=E) - Separator(self.options, orient=VERTICAL).grid(row=0, column=col + 2, sticky=NS) - col += 3 - Label(self.options, text="Strike targets", **STYLES["widget"]).grid(row=0, column=col, sticky=W) - Checkbutton(self.options, variable=self.display_ground_targets, **STYLES["radiobutton"]).grid(row=0, - column=col + 1, - sticky=E) - Separator(self.options, orient=VERTICAL).grid(row=0, column=col + 2, sticky=NS) - col += 3 - Label(self.options, text="Forces", **STYLES["widget"]).grid(row=0, column=col, sticky=W) - Checkbutton(self.options, variable=self.display_forces, **STYLES["radiobutton"]).grid(row=0, column=col + 1, - sticky=E) - Separator(self.options, orient=VERTICAL).grid(row=0, column=col + 2, sticky=NS) - col += 4 - Button(self.options, text="Toggle size", command=lambda: self.map_size_toggle(), **STYLES["btn-primary"]).grid(row=0, column=col, sticky=E, padx=(10,10)) + Button(self.options, text="Configuration", command=None, **STYLES["btn-primary"]).grid(column=col, row=0, sticky=NE) + col += 1 + + Label(self.options, text="Budget: {}m (+{}m)".format(self.game.budget, self.game.budget_reward_amount), **STYLES["widget"]).grid(column=col, row=0, sticky=N+EW) + col += 1 + + Button(self.options, text="Pass turn", command=None, **STYLES["btn-primary"]).grid(column=col, row=0, sticky=NE) + col += 1 def map_size_toggle(self): if self.expanded: @@ -249,8 +234,8 @@ class OverviewCanvas: if self.zoom <= 0.5: self.zoom = 0.5 - elif self.zoom > 10: - self.zoom = 10 + elif self.zoom > 3: + self.zoom = 3 if self.redraw_required: # Fill @@ -288,16 +273,6 @@ class OverviewCanvas: for cp in self.game.theater.controlpoints: coords = self._transform_point(cp.position) - if self.display_ground_targets.get(): - if cp.captured: - color = self._player_color() - else: - color = self._enemy_color() - for ground_object in cp.ground_objects: - x, y = self._transform_point(ground_object.position) - pygame.draw.line(surface, color, coords, (x + 8, y + 8), 1) - self.draw_ground_object(ground_object, surface, color, mouse_pos) - if self.display_road.get(): for connected_cp in cp.connected_points: connected_coords = self._transform_point(connected_cp.position) @@ -327,6 +302,10 @@ class OverviewCanvas: pygame.draw.line(surface, color, start_coords, end_coords, 4) + if self.display_ground_targets.get(): + for ground_object in cp.ground_objects: + self.draw_ground_object(ground_object, surface, cp.captured, mouse_pos) + if self.display_bases.get(): mouse_down = self.draw_bases(mouse_pos, mouse_down) @@ -367,7 +346,7 @@ class OverviewCanvas: self.draw_base_info(self.overlay, cp, (0, 0)) if self.selected_event_info: if self._cp_available_for_selected_event(cp): - pygame.draw.line(self.surface, self.WHITE, point, self.selected_event_info[1]) + pygame.draw.line(self.surface, self.WHITE, rect.center, self.selected_event_info[1]) else: self.surface.blit(label, (coords[0] - label.get_width() / 2 + 1, coords[1] + 1)) @@ -424,11 +403,35 @@ class OverviewCanvas: surface.blit(aircraft, (pos[0] + 4, 4 + pos[1] + lineheight * 3 + 15)) surface.blit(aa, (pos[0] + 4, 4 + pos[1] + lineheight * 4 + 20)) - def draw_ground_object(self, ground_object: TheaterGroundObject, surface: pygame.Surface, color, mouse_pos): + def draw_selected_event_info(self): + event = self.selected_event_info[0] + title = self.font.render(str(event), self.ANTIALIASING, self.BLACK, self.GREEN) + hint = self.font.render("Select CP to depart from.", self.ANTIALIASING, (225, 225, 225), self.BLACK) + + w = hint.get_width() + h = title.get_height() + hint.get_height() + 20 + + pos = self.overlay.get_width() / 2 - w / 2, self.overlay.get_height() - h + + # Draw frame + pygame.draw.rect(self.overlay, self.GREEN, (pos[0], pos[1], w + 8, h + 8)) + pygame.draw.rect(self.overlay, self.BLACK, (pos[0] + 2, pos[1] + 2, w + 4, h + 4)) + pygame.draw.rect(self.overlay, self.GREEN, (pos[0] + 2, pos[1], w + 4, title.get_height() + 4)) + + # Title + self.overlay.blit(title, (pos[0] + 4, 4 + pos[1])) + self.overlay.blit(hint, (pos[0] + 4, 4 + pos[1] + title.get_height() + 5)) + + def draw_ground_object(self, ground_object: TheaterGroundObject, surface: pygame.Surface, captured: bool, mouse_pos): + if captured: + color = self._player_color() + else: + color = self._enemy_color() + x, y = self._transform_point(ground_object.position) rect = pygame.Rect(x, y, 16, 16) - if ground_object.is_dead: + if ground_object.is_dead or captured: surface.blit(self.ground_assets_icons["cleared"], (x, y)) else: if ground_object.category in self.ground_assets_icons.keys(): @@ -507,6 +510,9 @@ class OverviewCanvas: if label_to_draw: surface.blit(*label_to_draw) + if self.selected_event_info: + self.draw_selected_event_info() + return mouse_down def _selected_cp(self, cp): @@ -588,6 +594,7 @@ class OverviewCanvas: return self.game.player == "USA" and self.RED or self.BLUE def update(self): + self.redraw_required = True self.draw() def compute_display_rules(self):