Culling optimizations + fixed some aircraft icons
51
game/game.py
@ -72,6 +72,7 @@ class Game:
|
|||||||
self.ground_planners = {}
|
self.ground_planners = {}
|
||||||
self.informations = []
|
self.informations = []
|
||||||
self.informations.append(Information("Game Start", "-" * 40, 0))
|
self.informations.append(Information("Game Start", "-" * 40, 0))
|
||||||
|
self.__culling_points = self.compute_conflicts_position()
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -187,6 +188,7 @@ class Game:
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
def pass_turn(self, no_action=False, ignored_cps: typing.Collection[ControlPoint] = None):
|
def pass_turn(self, no_action=False, ignored_cps: typing.Collection[ControlPoint] = None):
|
||||||
|
|
||||||
logging.info("Pass turn")
|
logging.info("Pass turn")
|
||||||
self.informations.append(Information("End of turn #" + str(self.turn), "-" * 40, 0))
|
self.informations.append(Information("End of turn #" + str(self.turn), "-" * 40, 0))
|
||||||
self.turn = self.turn + 1
|
self.turn = self.turn + 1
|
||||||
@ -202,7 +204,7 @@ class Game:
|
|||||||
self._enemy_reinforcement()
|
self._enemy_reinforcement()
|
||||||
self._budget_player()
|
self._budget_player()
|
||||||
|
|
||||||
if not no_action:
|
if not no_action and self.turn > 1:
|
||||||
for cp in self.theater.player_points():
|
for cp in self.theater.player_points():
|
||||||
cp.base.affect_strength(+PLAYER_BASE_STRENGTH_RECOVERY)
|
cp.base.affect_strength(+PLAYER_BASE_STRENGTH_RECOVERY)
|
||||||
else:
|
else:
|
||||||
@ -221,6 +223,7 @@ class Game:
|
|||||||
self.game_stats.update(self)
|
self.game_stats.update(self)
|
||||||
|
|
||||||
# Plan flights & combat for next turn
|
# Plan flights & combat for next turn
|
||||||
|
self.__culling_points = self.compute_conflicts_position()
|
||||||
self.planners = {}
|
self.planners = {}
|
||||||
self.ground_planners = {}
|
self.ground_planners = {}
|
||||||
for cp in self.theater.controlpoints:
|
for cp in self.theater.controlpoints:
|
||||||
@ -326,3 +329,49 @@ class Game:
|
|||||||
"""
|
"""
|
||||||
self.current_group_id += 1
|
self.current_group_id += 1
|
||||||
return self.current_group_id
|
return self.current_group_id
|
||||||
|
|
||||||
|
def compute_conflicts_position(self):
|
||||||
|
"""
|
||||||
|
Compute the current conflict center position(s), mainly used for culling calculation
|
||||||
|
:return: List of points of interests
|
||||||
|
"""
|
||||||
|
points = []
|
||||||
|
|
||||||
|
# By default, use the existing frontline conflict position
|
||||||
|
for conflict in self.theater.conflicts():
|
||||||
|
points.append(Conflict.frontline_position(self.theater, conflict[0], conflict[1])[0])
|
||||||
|
|
||||||
|
# If there is no conflict take the center point between the two nearest opposing bases
|
||||||
|
if len(points) == 0:
|
||||||
|
cpoint = None
|
||||||
|
min_distance = sys.maxsize
|
||||||
|
for cp in self.theater.player_points():
|
||||||
|
for cp2 in self.theater.enemy_points():
|
||||||
|
d = cp.position.distance_to_point(cp2.position)
|
||||||
|
if d < min_distance:
|
||||||
|
min_distance = d
|
||||||
|
cpoint = Point((cp.position.x + cp2.position.x) / 2, (cp.position.y + cp2.position.y) / 2)
|
||||||
|
if cpoint is not None:
|
||||||
|
points.append(cpoint)
|
||||||
|
|
||||||
|
# Else 0,0, since we need a default value
|
||||||
|
# (in this case this means the whole map is owned by the same player, so it is not an issue)
|
||||||
|
if len(points) == 0:
|
||||||
|
points.append(Point(0, 0))
|
||||||
|
|
||||||
|
return points
|
||||||
|
|
||||||
|
def position_culled(self, pos):
|
||||||
|
"""
|
||||||
|
Check if unit can be generated at given position depending on culling performance settings
|
||||||
|
:param pos: Position you are tryng to spawn stuff at
|
||||||
|
:return: True if units can not be added at given position
|
||||||
|
"""
|
||||||
|
if self.settings.perf_culling == False:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
for c in self.__culling_points:
|
||||||
|
if c.distance_to_point(pos) < self.settings.perf_culling_distance * 1000:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|||||||
@ -25,4 +25,8 @@ class Settings:
|
|||||||
perf_infantry = True
|
perf_infantry = True
|
||||||
perf_ai_parking_start = True
|
perf_ai_parking_start = True
|
||||||
|
|
||||||
|
# Performance culling
|
||||||
|
perf_culling = False
|
||||||
|
perf_culling_distance = 0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -230,6 +230,11 @@ class AircraftConflictGenerator:
|
|||||||
def generate_flights(self, cp, country, flight_planner:FlightPlanner):
|
def generate_flights(self, cp, country, flight_planner:FlightPlanner):
|
||||||
|
|
||||||
for flight in flight_planner.flights:
|
for flight in flight_planner.flights:
|
||||||
|
|
||||||
|
if flight.client_count == 0 and self.game.position_culled(flight.from_cp.position):
|
||||||
|
logging.info("Flight not generated : culled")
|
||||||
|
continue
|
||||||
|
|
||||||
group = self.generate_planned_flight(cp, country, flight)
|
group = self.generate_planned_flight(cp, country, flight)
|
||||||
if flight.flight_type == FlightType.INTERCEPTION:
|
if flight.flight_type == FlightType.INTERCEPTION:
|
||||||
self.setup_group_as_intercept_flight(group, flight)
|
self.setup_group_as_intercept_flight(group, flight)
|
||||||
|
|||||||
@ -61,9 +61,12 @@ class GroundObjectsGenerator:
|
|||||||
|
|
||||||
for ground_object in cp.ground_objects:
|
for ground_object in cp.ground_objects:
|
||||||
if ground_object.dcs_identifier == "AA":
|
if ground_object.dcs_identifier == "AA":
|
||||||
|
|
||||||
|
if self.game.position_culled(ground_object.position):
|
||||||
|
continue
|
||||||
|
|
||||||
for g in ground_object.groups:
|
for g in ground_object.groups:
|
||||||
if len(g.units) > 0:
|
if len(g.units) > 0:
|
||||||
|
|
||||||
utype = unit_type_from_name(g.units[0].type)
|
utype = unit_type_from_name(g.units[0].type)
|
||||||
|
|
||||||
if not ground_object.sea_object:
|
if not ground_object.sea_object:
|
||||||
@ -125,6 +128,10 @@ class GroundObjectsGenerator:
|
|||||||
sg.points[0].tasks.append(ActivateICLSCommand(cp.icls, unit_id=sg.units[0].id))
|
sg.points[0].tasks.append(ActivateICLSCommand(cp.icls, unit_id=sg.units[0].id))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
|
if self.game.position_culled(ground_object.position):
|
||||||
|
continue
|
||||||
|
|
||||||
static_type = None
|
static_type = None
|
||||||
if ground_object.dcs_identifier in warehouse_map:
|
if ground_object.dcs_identifier in warehouse_map:
|
||||||
static_type = warehouse_map[ground_object.dcs_identifier]
|
static_type = warehouse_map[ground_object.dcs_identifier]
|
||||||
@ -160,34 +167,4 @@ class GroundObjectsGenerator:
|
|||||||
dead=ground_object.is_dead,
|
dead=ground_object.is_dead,
|
||||||
)
|
)
|
||||||
|
|
||||||
logging.info("generated {}object identifier {} with mission id {}".format("dead " if ground_object.is_dead else "", group.name, group.id))
|
logging.info("generated {}object identifier {} with mission id {}".format("dead " if ground_object.is_dead else "", group.name, group.id))
|
||||||
|
|
||||||
|
|
||||||
def farp_aa(mission_obj, country, name, position: mapping.Point):
|
|
||||||
"""
|
|
||||||
Add AAA to a FARP :)
|
|
||||||
:param mission_obj:
|
|
||||||
:param country:
|
|
||||||
:param name:
|
|
||||||
:param position:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
vg = unitgroup.VehicleGroup(mission_obj.next_group_id(), mission_obj.string(name))
|
|
||||||
|
|
||||||
units = [
|
|
||||||
AirDefence.SPAAA_ZSU_23_4_Shilka,
|
|
||||||
AirDefence.AAA_ZU_23_Closed,
|
|
||||||
]
|
|
||||||
|
|
||||||
v = mission_obj.vehicle(name + "_AAA", random.choice(units))
|
|
||||||
v.position.x = position.x - random.randint(5, 30)
|
|
||||||
v.position.y = position.y - random.randint(5, 30)
|
|
||||||
v.heading = random.randint(0, 359)
|
|
||||||
vg.add_unit(v)
|
|
||||||
|
|
||||||
wp = vg.add_waypoint(vg.units[0].position, PointAction.OffRoad, 0)
|
|
||||||
wp.ETA_locked = True
|
|
||||||
|
|
||||||
country.add_vehicle_group(vg)
|
|
||||||
return vg
|
|
||||||
|
|
||||||
@ -1,13 +1,14 @@
|
|||||||
from PySide2.QtCore import QSize, Qt, QItemSelectionModel, QPoint
|
from PySide2.QtCore import QSize, Qt, QItemSelectionModel, QPoint
|
||||||
from PySide2.QtGui import QStandardItemModel, QStandardItem
|
from PySide2.QtGui import QStandardItemModel, QStandardItem
|
||||||
from PySide2.QtWidgets import QLabel, QDialog, QGridLayout, QListView, QStackedLayout, QComboBox, QWidget, \
|
from PySide2.QtWidgets import QLabel, QDialog, QGridLayout, QListView, QStackedLayout, QComboBox, QWidget, \
|
||||||
QAbstractItemView, QPushButton, QGroupBox, QCheckBox, QVBoxLayout
|
QAbstractItemView, QPushButton, QGroupBox, QCheckBox, QVBoxLayout, QSpinBox
|
||||||
from dcs.forcedoptions import ForcedOptions
|
from dcs.forcedoptions import ForcedOptions
|
||||||
|
|
||||||
import qt_ui.uiconstants as CONST
|
import qt_ui.uiconstants as CONST
|
||||||
from game.game import Game
|
from game.game import Game
|
||||||
from game.infos.information import Information
|
from game.infos.information import Information
|
||||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||||
|
from qt_ui.windows.finances.QFinancesMenu import QHorizontalSeparationLine
|
||||||
|
|
||||||
|
|
||||||
class QSettingsWindow(QDialog):
|
class QSettingsWindow(QDialog):
|
||||||
@ -199,6 +200,16 @@ class QSettingsWindow(QDialog):
|
|||||||
self.ai_parking_start.setChecked(self.game.settings.perf_ai_parking_start)
|
self.ai_parking_start.setChecked(self.game.settings.perf_ai_parking_start)
|
||||||
self.ai_parking_start.toggled.connect(self.applySettings)
|
self.ai_parking_start.toggled.connect(self.applySettings)
|
||||||
|
|
||||||
|
self.culling = QCheckBox()
|
||||||
|
self.culling.setChecked(self.game.settings.perf_culling)
|
||||||
|
self.culling.toggled.connect(self.applySettings)
|
||||||
|
|
||||||
|
self.culling_distance = QSpinBox()
|
||||||
|
self.culling_distance.setMinimum(50)
|
||||||
|
self.culling_distance.setMaximum(10000)
|
||||||
|
self.culling_distance.setValue(self.game.settings.perf_culling_distance)
|
||||||
|
self.culling_distance.valueChanged.connect(self.applySettings())
|
||||||
|
|
||||||
self.performanceLayout.addWidget(QLabel("Smoke visual effect on frontline"), 0, 0)
|
self.performanceLayout.addWidget(QLabel("Smoke visual effect on frontline"), 0, 0)
|
||||||
self.performanceLayout.addWidget(self.smoke, 0, 1, alignment=Qt.AlignRight)
|
self.performanceLayout.addWidget(self.smoke, 0, 1, alignment=Qt.AlignRight)
|
||||||
self.performanceLayout.addWidget(QLabel("SAM starts in RED alert mode"), 1, 0)
|
self.performanceLayout.addWidget(QLabel("SAM starts in RED alert mode"), 1, 0)
|
||||||
@ -212,6 +223,12 @@ class QSettingsWindow(QDialog):
|
|||||||
self.performanceLayout.addWidget(QLabel("AI planes parking start (AI starts in flight if disabled)"), 5, 0)
|
self.performanceLayout.addWidget(QLabel("AI planes parking start (AI starts in flight if disabled)"), 5, 0)
|
||||||
self.performanceLayout.addWidget(self.ai_parking_start, 5, 1, alignment=Qt.AlignRight)
|
self.performanceLayout.addWidget(self.ai_parking_start, 5, 1, alignment=Qt.AlignRight)
|
||||||
|
|
||||||
|
self.performanceLayout.addWidget(QHorizontalSeparationLine(), 6, 0, 1, 2)
|
||||||
|
self.performanceLayout.addWidget(QLabel("Culling of distant units enabled"), 7, 0)
|
||||||
|
self.performanceLayout.addWidget(self.culling, 7, 1, alignment=Qt.AlignRight)
|
||||||
|
self.performanceLayout.addWidget(QLabel("Culling distance (km)"), 8, 0)
|
||||||
|
self.performanceLayout.addWidget(self.culling_distance, 8, 1, alignment=Qt.AlignRight)
|
||||||
|
|
||||||
self.generatorLayout.addWidget(self.gameplay)
|
self.generatorLayout.addWidget(self.gameplay)
|
||||||
self.generatorLayout.addWidget(QLabel("Disabling settings below may improve performance, but will impact the overall quality of the experience."))
|
self.generatorLayout.addWidget(QLabel("Disabling settings below may improve performance, but will impact the overall quality of the experience."))
|
||||||
self.generatorLayout.addWidget(self.performance)
|
self.generatorLayout.addWidget(self.performance)
|
||||||
@ -277,6 +294,9 @@ class QSettingsWindow(QDialog):
|
|||||||
self.game.settings.perf_infantry = self.infantry.isChecked()
|
self.game.settings.perf_infantry = self.infantry.isChecked()
|
||||||
self.game.settings.perf_ai_parking_start = self.ai_parking_start.isChecked()
|
self.game.settings.perf_ai_parking_start = self.ai_parking_start.isChecked()
|
||||||
|
|
||||||
|
self.game.settings.perf_culling = self.culling.isChecked()
|
||||||
|
self.game.settings.perf_culling_distance = int(self.culling_distance.value())
|
||||||
|
|
||||||
GameUpdateSignal.get_instance().updateGame(self.game)
|
GameUpdateSignal.get_instance().updateGame(self.game)
|
||||||
|
|
||||||
def onSelectionChanged(self):
|
def onSelectionChanged(self):
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
resources/ui/units/aircrafts/P-51D-30-NA_24.jpg
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
resources/ui/units/aircrafts/SpitfireLFMkIX_24.jpg
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
@ -1,12 +1,10 @@
|
|||||||
import typing
|
import typing
|
||||||
import itertools
|
|
||||||
|
|
||||||
import dcs
|
import dcs
|
||||||
from dcs.mapping import Point
|
from dcs.mapping import Point
|
||||||
|
|
||||||
from .landmap import Landmap, poly_contains
|
|
||||||
from .controlpoint import ControlPoint
|
from .controlpoint import ControlPoint
|
||||||
from .theatergroundobject import TheaterGroundObject
|
from .landmap import poly_contains
|
||||||
|
|
||||||
SIZE_TINY = 150
|
SIZE_TINY = 150
|
||||||
SIZE_SMALL = 600
|
SIZE_SMALL = 600
|
||||||
@ -66,7 +64,7 @@ class ConflictTheater:
|
|||||||
self.land_poly = self.land_poly.difference(geometry.Polygon(x))
|
self.land_poly = self.land_poly.difference(geometry.Polygon(x))
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def add_controlpoint(self, point: ControlPoint, connected_to: typing.Collection[ControlPoint] = []):
|
def add_controlpoint(self, point: ControlPoint, connected_to: [ControlPoint] = []):
|
||||||
for connected_point in connected_to:
|
for connected_point in connected_to:
|
||||||
point.connect(to=connected_point)
|
point.connect(to=connected_point)
|
||||||
|
|
||||||
@ -118,3 +116,5 @@ class ConflictTheater:
|
|||||||
|
|
||||||
def enemy_points(self) -> typing.Collection[ControlPoint]:
|
def enemy_points(self) -> typing.Collection[ControlPoint]:
|
||||||
return [point for point in self.controlpoints if not point.captured]
|
return [point for point in self.controlpoints if not point.captured]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -52,30 +52,30 @@ class PersianGulfTheater(ConflictTheater):
|
|||||||
self.east_carrier = ControlPoint.carrier("East carrier", Point(59514.324335475, 28165.517980635))
|
self.east_carrier = ControlPoint.carrier("East carrier", Point(59514.324335475, 28165.517980635))
|
||||||
|
|
||||||
self.add_controlpoint(self.liwa, connected_to=[self.al_dhafra])
|
self.add_controlpoint(self.liwa, connected_to=[self.al_dhafra])
|
||||||
self.add_controlpoint(self.al_dhafra, connected_to=[self.liwa, self.sir_abu_nuayr, self.al_maktoum, self.al_ain])
|
self.add_controlpoint(self.al_dhafra, connected_to=[self.liwa, self.al_maktoum, self.al_ain])
|
||||||
self.add_controlpoint(self.al_ain, connected_to=[self.al_dhafra, self.al_maktoum])
|
self.add_controlpoint(self.al_ain, connected_to=[self.al_dhafra, self.al_maktoum])
|
||||||
self.add_controlpoint(self.al_maktoum, connected_to=[self.al_dhafra, self.al_minhad, self.sir_abu_nuayr, self.al_ain])
|
self.add_controlpoint(self.al_maktoum, connected_to=[self.al_dhafra, self.al_minhad, self.al_ain])
|
||||||
self.add_controlpoint(self.al_minhad, connected_to=[self.al_maktoum, self.dubai])
|
self.add_controlpoint(self.al_minhad, connected_to=[self.al_maktoum, self.dubai])
|
||||||
self.add_controlpoint(self.dubai, connected_to=[self.al_minhad, self.sharjah, self.fujairah])
|
self.add_controlpoint(self.dubai, connected_to=[self.al_minhad, self.sharjah, self.fujairah])
|
||||||
self.add_controlpoint(self.sharjah, connected_to=[self.dubai, self.ras_al_khaimah])
|
self.add_controlpoint(self.sharjah, connected_to=[self.dubai, self.ras_al_khaimah])
|
||||||
self.add_controlpoint(self.ras_al_khaimah, connected_to=[self.sharjah, self.khasab])
|
self.add_controlpoint(self.ras_al_khaimah, connected_to=[self.sharjah, self.khasab])
|
||||||
self.add_controlpoint(self.fujairah, connected_to=[self.dubai, self.khasab])
|
self.add_controlpoint(self.fujairah, connected_to=[self.dubai, self.khasab])
|
||||||
self.add_controlpoint(self.khasab, connected_to=[self.ras_al_khaimah, self.fujairah, self.tunb_island])
|
self.add_controlpoint(self.khasab, connected_to=[self.ras_al_khaimah, self.fujairah])
|
||||||
|
|
||||||
self.add_controlpoint(self.sir_abu_nuayr, connected_to=[self.al_dhafra, self.al_maktoum, self.sirri])
|
self.add_controlpoint(self.sir_abu_nuayr, connected_to=[])
|
||||||
self.add_controlpoint(self.sirri, connected_to=[self.sir_abu_nuayr, self.abu_musa])
|
self.add_controlpoint(self.sirri, connected_to=[])
|
||||||
self.add_controlpoint(self.abu_musa, connected_to=[self.sirri, self.sir_abu_nuayr])
|
self.add_controlpoint(self.abu_musa, connected_to=[])
|
||||||
self.add_controlpoint(self.tunb_kochak, connected_to=[self.sirri, self.abu_musa, self.tunb_island])
|
self.add_controlpoint(self.tunb_kochak, connected_to=[])
|
||||||
|
|
||||||
self.add_controlpoint(self.tunb_island, connected_to=[self.khasab, self.qeshm, self.tunb_kochak])
|
self.add_controlpoint(self.tunb_island, connected_to=[])
|
||||||
self.add_controlpoint(self.bandar_lengeh, connected_to=[self.tunb_island, self.lar, self.qeshm])
|
self.add_controlpoint(self.bandar_lengeh, connected_to=[self.lar, self.qeshm])
|
||||||
self.add_controlpoint(self.qeshm, connected_to=[self.bandar_lengeh, self.havadarya, self.tunb_island])
|
self.add_controlpoint(self.qeshm, connected_to=[self.bandar_lengeh, self.havadarya])
|
||||||
self.add_controlpoint(self.havadarya, connected_to=[self.lar, self.qeshm, self.bandar_abbas])
|
self.add_controlpoint(self.havadarya, connected_to=[self.lar, self.qeshm, self.bandar_abbas])
|
||||||
self.add_controlpoint(self.bandar_abbas, connected_to=[self.havadarya, self.kerman])
|
self.add_controlpoint(self.bandar_abbas, connected_to=[self.havadarya, self.kerman])
|
||||||
|
|
||||||
self.add_controlpoint(self.shiraz, connected_to=[self.lar, self.kerman])
|
self.add_controlpoint(self.shiraz, connected_to=[self.lar, self.kerman])
|
||||||
self.add_controlpoint(self.kerman, connected_to=[self.lar, self.shiraz, self.bandar_abbas])
|
self.add_controlpoint(self.kerman, connected_to=[self.lar, self.shiraz, self.bandar_abbas])
|
||||||
self.add_controlpoint(self.lar, connected_to=[self.bandar_lengeh, self.havadarya, self.shiraz, self.kerman])
|
self.add_controlpoint(self.lar, connected_to=[self.havadarya, self.shiraz, self.kerman])
|
||||||
|
|
||||||
self.add_controlpoint(self.west_carrier)
|
self.add_controlpoint(self.west_carrier)
|
||||||
self.add_controlpoint(self.east_carrier)
|
self.add_controlpoint(self.east_carrier)
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import typing
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from game.data.building_data import DEFAULT_AVAILABLE_BUILDINGS
|
from game.data.building_data import DEFAULT_AVAILABLE_BUILDINGS
|
||||||
from gen import namegen
|
from gen import namegen, TheaterGroundObject
|
||||||
from gen.defenses.armor_group_generator import generate_armor_group
|
from gen.defenses.armor_group_generator import generate_armor_group
|
||||||
from gen.fleet.ship_group_generator import generate_carrier_group, generate_lha_group, generate_ship_group
|
from gen.fleet.ship_group_generator import generate_carrier_group, generate_lha_group, generate_ship_group
|
||||||
from gen.missiles.missiles_group_generator import generate_missile_group
|
from gen.missiles.missiles_group_generator import generate_missile_group
|
||||||
|
|||||||