mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
WIP
This commit is contained in:
parent
ccf2cd3425
commit
6f4b7e0f1a
@ -25,12 +25,13 @@
|
||||
* **[Mission Generator]** Fixed A-20G spawning with no payload
|
||||
* **[Mission Generator]** Fixed Su-33 spawning too heavy to take off from carrier
|
||||
* **[Mission Generator]** Base defense units were not controllable with Combined Arms
|
||||
* **[Mission Script/Performance]** Mission lua script will not listen to weapons fired event anymore and register every fired weapons. This should improve performance especially in WW2 scenarios or when rocket artillery is firing.
|
||||
* **[Campaign Generator]** Carrier name will now not appear for faction who do not have carriers
|
||||
|
||||
* **[Units/Factions]** Remove JF-17 from USA 2005 faction
|
||||
* **[Units/Factions]** Removed Oliver Hazard Perry from cold war factions (too powerful sam system)
|
||||
* **[Bug]** On the persian gulf full map campaign, the two carriers were sharing the same id, this was causing a lot of bugs
|
||||
* **[Performance]** Tuned the culling setting so that you cannot run into situation where no AI flights are generated
|
||||
* **[Performance]** Tuned the culling setting so that you cannot run into situation where no friendly or enemy AI flights are generated
|
||||
|
||||
* **[Other]** Application doesn't gracefully exit.
|
||||
* **[Other]** Other minor fixes
|
||||
|
||||
33
game/data/cap_capabilities_db.py
Normal file
33
game/data/cap_capabilities_db.py
Normal file
@ -0,0 +1,33 @@
|
||||
from dcs.planes import *
|
||||
from pydcs_extensions.a4ec.a4ec import A_4E_C
|
||||
|
||||
"""
|
||||
This list contains the aircraft that do not use the guns as the last resort weapons, but as a main weapon
|
||||
They'll RTB when they don't have gun ammo left
|
||||
"""
|
||||
GUNFIGHTERS = [
|
||||
|
||||
# Cold War
|
||||
MiG_15bis,
|
||||
MiG_19P,
|
||||
MiG_21Bis,
|
||||
F_86F_Sabre,
|
||||
A_4E_C,
|
||||
F_5E_3,
|
||||
|
||||
# Trainers
|
||||
C_101CC,
|
||||
L_39ZA,
|
||||
|
||||
# WW2
|
||||
P_51D_30_NA,
|
||||
P_51D,
|
||||
P_47D_30,
|
||||
SpitfireLFMkIXCW,
|
||||
SpitfireLFMkIX,
|
||||
Bf_109K_4,
|
||||
FW_190D9,
|
||||
FW_190A8,
|
||||
I_16,
|
||||
|
||||
]
|
||||
16
game/game.py
16
game/game.py
@ -76,6 +76,22 @@ class Game:
|
||||
self.__frontlineData = []
|
||||
self.__destroyed_units = []
|
||||
|
||||
self.sanitize_sides()
|
||||
|
||||
|
||||
def sanitize_sides(self):
|
||||
"""
|
||||
Make sure the opposing factions are using different countries
|
||||
:return:
|
||||
"""
|
||||
if self.player_country == self.enemy_country:
|
||||
if self.player_country == "USA":
|
||||
self.enemy_country = "USAF Aggressors"
|
||||
elif self.player_country == "Russia":
|
||||
self.enemy_country = "USSR"
|
||||
else:
|
||||
self.enemy_country = "Russia"
|
||||
|
||||
@property
|
||||
def player_faction(self):
|
||||
return db.FACTIONS[self.player_name]
|
||||
|
||||
@ -91,15 +91,6 @@ class Operation:
|
||||
|
||||
p_country = self.game.player_country
|
||||
e_country = self.game.enemy_country
|
||||
if self.game.player_country == self.game.enemy_country:
|
||||
if self.game.player_country != "USAF Aggresors":
|
||||
e_country = "USAF Aggresors"
|
||||
else:
|
||||
if self.game.player_country != "Russia":
|
||||
e_country = "Russia"
|
||||
else:
|
||||
e_country = "USA"
|
||||
|
||||
self.current_mission.coalition["blue"].add_country(country_dict[db.country_id_from_name(p_country)]())
|
||||
self.current_mission.coalition["red"].add_country(country_dict[db.country_id_from_name(e_country)]())
|
||||
|
||||
|
||||
66
gen/armor.py
66
gen/armor.py
@ -1,5 +1,5 @@
|
||||
from dcs.action import AITaskPush, AITaskSet
|
||||
from dcs.condition import TimeAfter, UnitDamaged, Or
|
||||
from dcs.condition import TimeAfter, UnitDamaged, Or, GroupLifeLess
|
||||
from dcs.task import *
|
||||
from dcs.triggers import TriggerOnce, Event
|
||||
|
||||
@ -93,13 +93,11 @@ class GroundConflictGenerator:
|
||||
|
||||
self.gen_infantry_group_for_group(g, False, self.mission.country(self.game.enemy_country), self.conflict.heading - 90)
|
||||
|
||||
|
||||
# Plan combat actions for groups
|
||||
self.plan_action_for_groups(self.player_stance, player_groups, enemy_groups, self.conflict.heading + 90, self.conflict.from_cp, self.conflict.to_cp)
|
||||
self.plan_action_for_groups(self.enemy_stance, enemy_groups, player_groups, self.conflict.heading - 90, self.conflict.to_cp, self.conflict.from_cp)
|
||||
|
||||
|
||||
|
||||
def gen_infantry_group_for_group(self, group, is_player, side:Country, forward_heading):
|
||||
|
||||
# Disable infantry unit gen if disabled
|
||||
@ -161,8 +159,7 @@ class GroundConflictGenerator:
|
||||
dcs_group.add_trigger_action(hold_task)
|
||||
|
||||
# Artillery strike random start
|
||||
artillery_trigger = TriggerOnce(Event.NoEvent,
|
||||
"ArtilleryFireTask #" + str(dcs_group.id))
|
||||
artillery_trigger = TriggerOnce(Event.NoEvent, "ArtilleryFireTask #" + str(dcs_group.id))
|
||||
artillery_trigger.add_condition(TimeAfter(seconds=random.randint(1, 45)* 60))
|
||||
|
||||
fire_task = FireAtPoint(target, len(group.units) * 10, 100)
|
||||
@ -179,7 +176,7 @@ class GroundConflictGenerator:
|
||||
|
||||
# Hold position
|
||||
dcs_group.points[0].tasks.append(Hold())
|
||||
retreat = self.find_retreat_point(dcs_group, forward_heading)
|
||||
retreat = self.find_retreat_point(dcs_group, forward_heading, (int)(RETREAT_DISTANCE/8))
|
||||
dcs_group.add_waypoint(dcs_group.position.point_from_heading(forward_heading, 1), PointAction.OffRoad)
|
||||
dcs_group.points[1].tasks.append(Hold())
|
||||
dcs_group.add_waypoint(retreat, PointAction.OffRoad)
|
||||
@ -190,12 +187,15 @@ class GroundConflictGenerator:
|
||||
if i < len(dcs_group.units) - 1:
|
||||
artillery_fallback.add_condition(Or())
|
||||
|
||||
hold_2 = Hold()
|
||||
hold_2.number = 3
|
||||
dcs_group.add_trigger_action(hold_2)
|
||||
|
||||
retreat_task = GoToWaypoint(toIndex=3)
|
||||
retreat_task.number = 3
|
||||
retreat_task.number = 4
|
||||
dcs_group.add_trigger_action(retreat_task)
|
||||
|
||||
artillery_fallback.add_action(AITaskSet(dcs_group.id, len(dcs_group.tasks)))
|
||||
artillery_fallback.add_action(AITaskPush(dcs_group.id, len(dcs_group.tasks)))
|
||||
self.mission.triggerrules.triggers.append(artillery_fallback)
|
||||
|
||||
for u in dcs_group.units:
|
||||
@ -232,12 +232,16 @@ class GroundConflictGenerator:
|
||||
i = 1
|
||||
for target in targets:
|
||||
rand_offset = Point(random.randint(-RANDOM_OFFSET_ATTACK, RANDOM_OFFSET_ATTACK), random.randint(-RANDOM_OFFSET_ATTACK, RANDOM_OFFSET_ATTACK))
|
||||
dcs_group.add_waypoint(target.points[0].position+rand_offset,PointAction.OffRoad)
|
||||
dcs_group.add_waypoint(target.points[0].position+rand_offset, PointAction.OffRoad)
|
||||
dcs_group.points[i].tasks.append(AttackGroup(target.id))
|
||||
i = i + 1
|
||||
if to_cp.position.distance_to_point(dcs_group.points[0].position) <= AGGRESIVE_MOVE_DISTANCE:
|
||||
attack_point = to_cp.position.random_point_within(500, 0)
|
||||
dcs_group.add_waypoint(attack_point)
|
||||
|
||||
if stance != CombatStance.RETREAT:
|
||||
self.add_morale_trigger(dcs_group, forward_heading)
|
||||
|
||||
elif group.role in [CombatGroupRole.APC, CombatGroupRole.ATGM]:
|
||||
|
||||
if stance in [CombatStance.AGGRESIVE, CombatStance.BREAKTHROUGH, CombatStance.ELIMINATION]:
|
||||
@ -248,6 +252,9 @@ class GroundConflictGenerator:
|
||||
attack_point = self.find_offensive_point(dcs_group, forward_heading, AGGRESIVE_MOVE_DISTANCE)
|
||||
dcs_group.add_waypoint(attack_point, PointAction.OnRoad)
|
||||
|
||||
if stance != CombatStance.RETREAT:
|
||||
self.add_morale_trigger(dcs_group, forward_heading)
|
||||
|
||||
if stance == CombatStance.RETREAT:
|
||||
# In retreat mode, the units will fall back
|
||||
# If the ally base is close enough, the units will even regroup there
|
||||
@ -260,14 +267,51 @@ class GroundConflictGenerator:
|
||||
dcs_group.add_waypoint(reposition_point, PointAction.OffRoad)
|
||||
|
||||
|
||||
def find_retreat_point(self, dcs_group, frontline_heading):
|
||||
def add_morale_trigger(self, dcs_group, forward_heading):
|
||||
"""
|
||||
This add a trigger to manage units fleeing whenever their group is hit hard, or being engaged by CAS
|
||||
"""
|
||||
|
||||
if len(dcs_group.units) == 1:
|
||||
return
|
||||
|
||||
# Units should hold position on last waypoint
|
||||
dcs_group.points[len(dcs_group.points) - 1].tasks.append(Hold())
|
||||
|
||||
# Force unit heading
|
||||
for unit in dcs_group.units:
|
||||
unit.heading = forward_heading
|
||||
dcs_group.manualHeading = True
|
||||
|
||||
# We add a new retreat waypoint
|
||||
dcs_group.add_waypoint(self.find_retreat_point(dcs_group, forward_heading, (int)(RETREAT_DISTANCE / 8)), PointAction.OffRoad)
|
||||
|
||||
# Fallback task
|
||||
fallback = ControlledTask(GoToWaypoint(toIndex=len(dcs_group.points)))
|
||||
fallback.enabled = False
|
||||
dcs_group.add_trigger_action(Hold())
|
||||
dcs_group.add_trigger_action(fallback)
|
||||
|
||||
# Create trigger
|
||||
fallback = TriggerOnce(Event.NoEvent, "Morale manager #" + str(dcs_group.id))
|
||||
|
||||
# Usually more than 50% casualties = RETREAT
|
||||
fallback.add_condition(GroupLifeLess(dcs_group.id, random.randint(51, 76)))
|
||||
|
||||
# Do retreat to the configured retreat waypoint
|
||||
fallback.add_action(AITaskPush(dcs_group.id, len(dcs_group.tasks)))
|
||||
|
||||
self.mission.triggerrules.triggers.append(fallback)
|
||||
|
||||
|
||||
def find_retreat_point(self, dcs_group, frontline_heading, distance=RETREAT_DISTANCE):
|
||||
"""
|
||||
Find a point to retreat to
|
||||
:param dcs_group: DCS mission group we are searching a retreat point for
|
||||
:param frontline_heading: Heading of the frontline
|
||||
:return: dcs.mapping.Point object with the desired position
|
||||
"""
|
||||
return dcs_group.points[0].position.point_from_heading(frontline_heading-180, RETREAT_DISTANCE)
|
||||
return dcs_group.points[0].position.point_from_heading(frontline_heading-180, distance)
|
||||
|
||||
def find_offensive_point(self, dcs_group, frontline_heading, distance):
|
||||
"""
|
||||
|
||||
@ -45,12 +45,6 @@ class GroundObjectsGenerator:
|
||||
|
||||
def generate(self):
|
||||
|
||||
cp = None # type: ControlPoint
|
||||
if self.conflict.attackers_country.name == self.game.player_country:
|
||||
cp = self.conflict.to_cp
|
||||
else:
|
||||
cp = self.conflict.from_cp
|
||||
|
||||
for cp in self.game.theater.controlpoints:
|
||||
|
||||
if cp.captured:
|
||||
|
||||
@ -21,10 +21,11 @@ from userdata import liberation_install, persistency, liberation_theme
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1" # Potential fix for 4K screens
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
# init the theme and load the stylesheet based on the theme index
|
||||
liberation_theme.init();
|
||||
liberation_theme.init()
|
||||
css = ""
|
||||
with open("./resources/stylesheets/"+liberation_theme.get_theme_css_file()) as stylesheet:
|
||||
app.setStyleSheet(stylesheet.read())
|
||||
|
||||
@ -35,8 +35,8 @@ class QBaseMenu2(QDialog):
|
||||
|
||||
self.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||
self.setMinimumSize(300, 200)
|
||||
self.setMinimumWidth(680)
|
||||
self.setMaximumWidth(680)
|
||||
self.setMinimumWidth(800)
|
||||
self.setMaximumWidth(800)
|
||||
self.setModal(True)
|
||||
self.initUi()
|
||||
|
||||
@ -50,7 +50,7 @@ class QBaseMenu2(QDialog):
|
||||
|
||||
header = QLabel(self)
|
||||
header.setGeometry(0, 0, 655, 106)
|
||||
pixmap = QPixmap("./resources/ui/airbase.png")
|
||||
pixmap = QPixmap(self.get_base_image())
|
||||
header.setPixmap(pixmap)
|
||||
|
||||
title = QLabel("<b>" + self.cp.name + "</b>")
|
||||
@ -75,7 +75,6 @@ class QBaseMenu2(QDialog):
|
||||
def closeEvent(self, closeEvent:QCloseEvent):
|
||||
GameUpdateSignal.get_instance().updateGame(self.game)
|
||||
|
||||
|
||||
def get_base_image(self):
|
||||
if self.cp.cptype == ControlPointType.AIRCRAFT_CARRIER_GROUP:
|
||||
return "./resources/ui/carrier.png"
|
||||
|
||||
@ -33,10 +33,12 @@ class QMissionPlanning(QDialog):
|
||||
self.select_airbase = QChooseAirbase(self.game)
|
||||
self.select_airbase.selected_airbase_changed.connect(self.on_departure_cp_changed)
|
||||
self.planned_flight_view = QPlannedFlightsView(None)
|
||||
self.available_aircraft_at_selected_location = {}
|
||||
if self.captured_cp[0].id in self.game.planners.keys():
|
||||
self.planner = self.game.planners[self.captured_cp[0].id]
|
||||
self.planned_flight_view.set_flight_planner(self.planner)
|
||||
self.selected_cp = self.captured_cp[0]
|
||||
self.available_aircraft_at_selected_location = self.planner.get_available_aircraft()
|
||||
|
||||
self.planned_flight_view.selectionModel().setCurrentIndex(self.planned_flight_view.indexAt(QPoint(1, 1)), QItemSelectionModel.Rows)
|
||||
self.planned_flight_view.selectionModel().selectionChanged.connect(self.on_flight_selection_change)
|
||||
@ -82,8 +84,10 @@ class QMissionPlanning(QDialog):
|
||||
if len(cps) == 1:
|
||||
self.selected_cp = cps[0]
|
||||
self.planner = self.game.planners[cps[0].id]
|
||||
self.available_aircraft_at_selected_location = self.planner.get_available_aircraft()
|
||||
self.planned_flight_view.set_flight_planner(self.planner)
|
||||
else:
|
||||
self.available_aircraft_at_selected_location = {}
|
||||
self.planned_flight_view.set_flight_planner(None)
|
||||
|
||||
def on_flight_selection_change(self):
|
||||
|
||||
@ -40,7 +40,8 @@ class QFlightCreator(QDialog):
|
||||
for aircraft_type in self.planner.get_available_aircraft().keys():
|
||||
print(aircraft_type)
|
||||
print(aircraft_type.name)
|
||||
self.select_type_aircraft.addItem(aircraft_type.id, userData=aircraft_type)
|
||||
if self.available[aircraft_type] > 0:
|
||||
self.select_type_aircraft.addItem(aircraft_type.id, userData=aircraft_type)
|
||||
self.select_type_aircraft.setCurrentIndex(0)
|
||||
|
||||
self.select_flight_type = QComboBox()
|
||||
@ -61,6 +62,11 @@ class QFlightCreator(QDialog):
|
||||
self.select_count_of_aircraft.setMaximum(4)
|
||||
self.select_count_of_aircraft.setValue(2)
|
||||
|
||||
aircraft_type = self.select_type_aircraft.currentData()
|
||||
if aircraft_type is not None:
|
||||
self.select_count_of_aircraft.setValue(min(self.available[aircraft_type], 2))
|
||||
self.select_count_of_aircraft.setMaximum(min(self.available[aircraft_type], 4))
|
||||
|
||||
self.add_button = QPushButton("Add")
|
||||
self.add_button.clicked.connect(self.create_flight)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user