Merge pull request #98 from Khopa/develop

2.1.1-alpha-2
This commit is contained in:
C. Perreau 2020-08-23 18:26:14 +02:00 committed by GitHub
commit d213fa1b91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
75 changed files with 904 additions and 139 deletions

107
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,107 @@
name: Release Pipeline
on:
push:
tags: [ '*' ]
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
with:
submodules: true
- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install environment
run: |
py -m venv ./venv
- name: Install dependencies
run: |
./venv/scripts/activate
pip install -r requirements.txt
# For some reason the shiboken2.abi3.dll is not found properly, so I copy it instead
Copy-Item .\venv\Lib\site-packages\shiboken2\shiboken2.abi3.dll .\venv\Lib\site-packages\PySide2\ -Force
- name: Build binaries
run: |
./venv/scripts/activate
$env:PYTHONPATH=".;./pydcs"
pyinstaller pyinstaller.spec
- name: Create Installer
env:
TAG_NAME: ${{ github.ref }}
run: |
$version = ($env:TAG_NAME -split "/") | Select-Object -Last 1
(Get-Content .\installer\dcs_liberation.iss) -replace "{{version}}",$version | Out-File .\build\installer.iss
cd .\installer
iscc.exe ..\build\installer.iss
cd ..
Copy-Item .\changelog.md .\dist
- uses: actions/upload-artifact@v2
with:
name: dcs_liberation
path: dist/
release:
needs: [ build ]
runs-on: windows-latest
steps:
- uses: actions/download-artifact@v2
with:
name: dcs_liberation
- name: "Get Version"
id: version
env:
TAG_NAME: ${{ github.ref }}
run: |
Get-ChildItem -Recurse -Depth 1
$version = ($env:TAG_NAME -split "/") | Select-Object -Last 1
$prerelease = ("2.1.1-alpha3" -match '[^\.\d]').ToString().ToLower()
Write-Host $version
Write-Host $prerelease
Write-Output "::set-output name=number::$version"
Write-Output "::set-output name=prerelease::$prerelease"
$changelog = Get-Content .\changelog.md
$last_change = ($changelog | Select-String -Pattern "^#\s" | Select-Object -Skip 1 -First 1).LineNumber - 2
($changelog | Select-Object -First $last_change) -join "`n" | Out-File .\releasenotes.md
Compress-Archive -Path .\dcs_liberation -DestinationPath "dcs_liberation.$version.zip" -Compression Optimal
- uses: actions/create-release@v1
id: create_release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref }}
body_path: releasenotes.md
draft: false
prerelease: ${{ steps.version.outputs.prerelease }}
- uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./dcs_liberation.exe
asset_name: dcs_liberation.${{ steps.version.outputs.number }}.exe
asset_content_type: application/exe
- uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./dcs_liberation.${{ steps.version.outputs.number }}.zip
asset_name: dcs_liberation.${{ steps.version.outputs.number }}.zip
asset_content_type: application/zip

4
.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "pydcs"]
path = pydcs
url = https://github.com/pydcs/dcs
branch = master

View File

@ -1,3 +1,23 @@
# 2.1.1
## Features/Improvements :
* **[Other]** Added an installer option (thanks to contributor parithon)
* **[Cheat Menu]** Added possibility to replace destroyed SAM and base defenses units for the player (Click on a SAM site to fix it)
* **[Cheat Menu]** Added recon images for buildings on strike targets, click on a Strike target to get detailled informations
* **[Units/Factions]** Added F-16C to USA 1990
* **[Units/Factions]** Added MQ-9 Reaper as CAS unit for USA 2005
* **[Units/Factions]** Added Mig-21, Mig-23, SA-342L to Syria 2011
* **[Cheat Menu]** Added buttons to remove money
## Fixed issues :
* **[UI/UX]** Spelling issues (Thanks to Github contributor steveveepee)
* **[Campaign Generator]** LHA was placed on land in Syrian Civil War campaign
* **[Campaign Generator]** Fixed inverted configuration for Syria full map
* **[Campaign Generator]** Syria "Inherent Resolve" campaign, added Incirlik Air Base
* **[Mission Generator]** AH-1W was not used by AI to generate CAS mission by default
* **[Mission Generator]** Fixed F-16C targeting pod not being added to payload
* **[Mission Generator]** AH-64A and AH-64D payloads fix.
# 2.1.0
## Features/Improvements :

View File

@ -1,12 +1,12 @@
import inspect
import dcs
from pydcs import dcs
DEFAULT_AVAILABLE_BUILDINGS = ['fuel', 'ammo', 'comms', 'oil', 'ware', 'farp', 'fob', 'power', 'factory', 'derrick', 'aa']
WW2_GERMANY_BUILDINGS = ['fuel', 'factory', 'ww2bunker', 'ww2bunker', 'ww2bunker', 'allycamp', 'allycamp', 'aa']
WW2_ALLIES_BUILDINGS = ['fuel', 'factory', 'allycamp', 'allycamp', 'allycamp', 'allycamp', 'allycamp', 'aa']
FORTIFICATION_BUILDINGS = ['Siegfried Line', 'Concertina Wire', 'Czech hedgehogs 1', 'Czech hedgehogs 2',
FORTIFICATION_BUILDINGS = ['Siegfried Line', 'Concertina wire', 'Concertina Wire', 'Czech hedgehogs 1', 'Czech hedgehogs 2',
'Dragonteeth 1', 'Dragonteeth 2', 'Dragonteeth 3', 'Dragonteeth 4', 'Dragonteeth 5',
'Haystack 1', 'Haystack 2', 'Haystack 3', 'Haystack 4', 'Hemmkurvenvenhindernis',
'Log posts 1', 'Log posts 2', 'Log posts 3', 'Log ramps 1', 'Log ramps 2', 'Log ramps 3',

View File

@ -295,23 +295,6 @@ PRICES = {
Unarmed.Transport_M818: 3,
AirDefence.AAA_Vulcan_M163: 5,
AirDefence.SAM_Linebacker_M6: 10,
AirDefence.AAA_ZU_23_Closed: 2,
AirDefence.SPAAA_ZSU_23_4_Shilka: 4,
AirDefence.SAM_SA_9_Strela_1_9P31: 8,
AirDefence.SAM_SA_19_Tunguska_2S6: 15,
AirDefence.SAM_SA_6_Kub_LN_2P25: 22,
AirDefence.SAM_SA_8_Osa_9A33: 12,
AirDefence.SAM_SA_3_S_125_LN_5P73: 20,
AirDefence.SAM_SA_2_LN_SM_90: 15,
AirDefence.SAM_SA_11_Buk_LN_9A310M1: 25,
AirDefence.SAM_Hawk_PCP: 20,
AirDefence.SAM_Patriot_LN_M901: 60,
AirDefence.SAM_SA_10_S_300PS_LN_5P85C: 60,
AirDefence.SAM_Chaparral_M48: 10,
# WW2
Armor.MT_Pz_Kpfw_V_Panther_Ausf_G:24,
Armor.MT_Pz_Kpfw_IV_Ausf_H:16,
@ -332,9 +315,6 @@ PRICES = {
Armor.LAC_M8_Greyhound: 8,
Armor.TD_M10_GMC: 14,
Armor.StuG_III_Ausf__G: 12,
AirDefence.AAA_Bofors_40mm: 8,
AirDefence.AAA_8_8cm_Flak_36: 8,
AirDefence.AAA_8_8cm_Flak_18: 12,
Artillery.M12_GMC: 10,
Artillery.Sturmpanzer_IV_Brummbär: 10,
@ -348,6 +328,79 @@ PRICES = {
Dry_cargo_ship_Ivanov: 10,
Tanker_Elnya_160: 10,
# Air Defence units
AirDefence.SAM_SA_19_Tunguska_2S6: 30,
AirDefence.SAM_SA_6_Kub_LN_2P25: 20,
AirDefence.SAM_SA_3_S_125_LN_5P73: 6,
AirDefence.SAM_SA_10_S_300PS_LN_5P85C: 22,
AirDefence.SAM_SA_10_S_300PS_LN_5P85D: 22,
AirDefence.SAM_SA_11_Buk_LN_9A310M1: 30,
AirDefence.SAM_SA_8_Osa_9A33: 28,
AirDefence.SAM_SA_15_Tor_9A331: 40,
AirDefence.SAM_SA_13_Strela_10M3_9A35M3: 24,
AirDefence.SAM_SA_9_Strela_1_9P31: 16,
AirDefence.SAM_SA_11_Buk_CC_9S470M1: 25,
AirDefence.SAM_SA_8_Osa_LD_9T217: 22,
AirDefence.SAM_Patriot_AMG_AN_MRC_137: 35,
AirDefence.SAM_Patriot_ECS_AN_MSQ_104: 30,
AirDefence.SPAAA_Gepard: 24,
AirDefence.SAM_Hawk_PCP: 14,
AirDefence.AAA_Vulcan_M163: 12,
AirDefence.SAM_Hawk_LN_M192: 8,
AirDefence.SAM_Chaparral_M48: 16,
AirDefence.SAM_Linebacker_M6: 18,
AirDefence.SAM_Patriot_LN_M901: 15,
AirDefence.SAM_Avenger_M1097: 20,
AirDefence.SAM_Patriot_EPP_III: 15,
AirDefence.SAM_Patriot_ICC: 18,
AirDefence.SAM_Roland_ADS: 12,
AirDefence.SAM_SA_10_S_300PS_CP_54K6: 18,
AirDefence.Stinger_MANPADS: 6,
AirDefence.SAM_Stinger_comm_dsr: 4,
AirDefence.SAM_Stinger_comm: 4,
AirDefence.SPAAA_ZSU_23_4_Shilka: 12,
AirDefence.AAA_ZU_23_Closed: 6,
AirDefence.AAA_ZU_23_Emplacement: 6,
AirDefence.AAA_ZU_23_on_Ural_375: 8,
AirDefence.AAA_ZU_23_Insurgent_Closed: 6,
AirDefence.AAA_ZU_23_Insurgent_on_Ural_375: 8,
AirDefence.AAA_ZU_23_Insurgent: 6,
AirDefence.SAM_SA_18_Igla_MANPADS: 10,
AirDefence.SAM_SA_18_Igla_comm: 8,
AirDefence.SAM_SA_18_Igla_S_MANPADS: 12,
AirDefence.SAM_SA_18_Igla_S_comm: 8,
AirDefence.EWR_1L13: 30,
AirDefence.SAM_SA_6_Kub_STR_9S91: 22,
AirDefence.SAM_SA_10_S_300PS_TR_30N6: 24,
AirDefence.SAM_SA_10_S_300PS_SR_5N66M: 30,
AirDefence.EWR_55G6: 30,
AirDefence.SAM_SA_10_S_300PS_SR_64H6E: 30,
AirDefence.SAM_SA_11_Buk_SR_9S18M1: 28,
AirDefence.CP_9S80M1_Sborka: 10,
AirDefence.SAM_Hawk_TR_AN_MPQ_46: 14,
AirDefence.SAM_Hawk_SR_AN_MPQ_50: 18,
AirDefence.SAM_Patriot_STR_AN_MPQ_53: 22,
AirDefence.SAM_Hawk_CWAR_AN_MPQ_55: 20,
AirDefence.SAM_SR_P_19: 14,
AirDefence.SAM_Roland_EWR: 16,
AirDefence.SAM_SA_3_S_125_TR_SNR: 14,
AirDefence.SAM_SA_2_LN_SM_90: 8,
AirDefence.SAM_SA_2_TR_SNR_75_Fan_Song: 12,
AirDefence.Rapier_FSA_Launcher: 6,
AirDefence.Rapier_FSA_Optical_Tracker: 12,
AirDefence.Rapier_FSA_Blindfire_Tracker: 16,
AirDefence.HQ_7_Self_Propelled_LN: 20,
AirDefence.HQ_7_Self_Propelled_STR: 24,
AirDefence.AAA_8_8cm_Flak_18: 6,
AirDefence.AAA_Flak_38: 6,
AirDefence.AAA_8_8cm_Flak_36: 8,
AirDefence.AAA_8_8cm_Flak_37: 10,
AirDefence.AAA_Flak_Vierling_38:6,
AirDefence.AAA_Kdo_G_40: 8,
AirDefence.Flak_Searchlight_37: 4,
AirDefence.Maschinensatz_33: 10,
AirDefence.AAA_8_8cm_Flak_41: 12,
AirDefence.AAA_Bofors_40mm: 8,
# FRENCH PACK MOD
frenchpack.AMX_10RCR: 10,
@ -959,10 +1012,8 @@ PLANE_PAYLOAD_OVERRIDES = {
RQ_1A_Predator: COMMON_OVERRIDE,
WingLoong_I: COMMON_OVERRIDE,
AH_1W: COMMON_OVERRIDE,
AH_64D:{
CAS: "AGM-114K*16"
},
AH_64D: COMMON_OVERRIDE,
AH_64A: COMMON_OVERRIDE,
Su_25TM: {
SEAD: "Kh-31P*2_Kh-25ML*4_R-73*2_L-081_MPS410",

View File

@ -178,9 +178,12 @@ class Event:
for i, ground_object in enumerate(cp.ground_objects):
if ground_object.dcs_identifier in ["AA", "CARRIER", "LHA"]:
for g in ground_object.groups:
if not hasattr(g, "units_losts"):
g.units_losts = []
for u in g.units:
if u.name == destroyed_ground_unit_name:
g.units.remove(u)
g.units_losts.append(u)
destroyed_units = destroyed_units + 1
info.text = u.type
ucount = sum([len(g.units) for g in ground_object.groups])

View File

@ -7,14 +7,20 @@ Syria_2011 = {
"side": "red",
"units": [
MiG_29S,
MiG_21Bis,
MiG_23MLD,
MiG_25PD,
L_39ZA,
Su_24M,
MiG_29S,
Su_17M4,
Su_24M,
L_39ZA,
Mi_24V,
SA342M,
Mi_8MT,
SA342M,
SA342L,
IL_76MD,
IL_78M,

View File

@ -11,12 +11,11 @@ USA_1990 = {
F_15E,
F_14B,
FA_18C_hornet,
F_16C_50,
A_10A,
AV8BNA,
B_1B,
KC_135,
KC130,
C_130,
@ -24,7 +23,6 @@ USA_1990 = {
UH_1H,
AH_64A,
OH_58D,
Armor.MBT_M1A2_Abrams,
Armor.IFV_LAV_25,

View File

@ -14,6 +14,7 @@ USA_2005 = {
F_16C_50,
A_10C,
AV8BNA,
MQ_9_Reaper,
KC_135,
KC130,
@ -22,7 +23,6 @@ USA_2005 = {
UH_1H,
AH_64D,
OH_58D,
Armor.MBT_M1A2_Abrams,
Armor.ATGM_M1134_Stryker,

View File

@ -516,6 +516,10 @@ class AircraftConflictGenerator:
group.points[0].tasks.append(OptRestrictJettison(True))
for point in flight.points:
group.add_waypoint(Point(point.x,point.y), point.alt)
group.add_waypoint(Point(point.x, point.y), point.alt)
def setup_radio_preset(self, flight, group):
pass

View File

@ -1,7 +1,7 @@
import logging
import typing
import pdb
import dcs
from pydcs import dcs
from random import randint
from dcs import Mission

View File

@ -7,7 +7,8 @@ from game.data.doctrine import MODERN_DOCTRINE
from game.data.radar_db import UNITS_WITH_RADAR
from game.utils import meter_to_feet, nm_to_meter
from gen import Conflict
from gen.flights.ai_flight_planner_db import INTERCEPT_CAPABLE, CAP_CAPABLE, CAS_CAPABLE, SEAD_CAPABLE, STRIKE_CAPABLE
from gen.flights.ai_flight_planner_db import INTERCEPT_CAPABLE, CAP_CAPABLE, CAS_CAPABLE, SEAD_CAPABLE, STRIKE_CAPABLE, \
DRONES
from gen.flights.flight import Flight, FlightType, FlightWaypoint, FlightWaypointType
@ -245,8 +246,13 @@ class FlightPlanner:
except IndexError:
break
inventory[unit] = inventory[unit] - 2
flight = Flight(unit, 2, self.from_cp, FlightType.STRIKE)
if unit in DRONES:
count = 1
else:
count = 2
inventory[unit] = inventory[unit] - count
flight = Flight(unit, count, self.from_cp, FlightType.STRIKE)
flight.points = []
flight.scheduled_in = offset + i*random.randint(self.doctrine["STRIKE_EVERY_X_MINUTES"] - 5, self.doctrine["STRIKE_EVERY_X_MINUTES"] + 5)

View File

@ -74,7 +74,7 @@ CAP_CAPABLE = [
Rafale_M,
]
# USed for CAS (Close air support) and BAI (Battlefield Interdiction)
# Used for CAS (Close air support) and BAI (Battlefield Interdiction)
CAS_CAPABLE = [
MiG_15bis,
@ -117,6 +117,8 @@ CAS_CAPABLE = [
AH_64A,
AH_64D,
AH_1W,
UH_1H,

View File

@ -0,0 +1,4 @@
from dcs.unitgroup import FlyingGroup

View File

@ -65,6 +65,40 @@ SAM_MAP = {
AirDefence.HQ_7_Self_Propelled_LN: HQ7Generator
}
SAM_PRICES = {
AirDefence.SAM_Hawk_PCP: 35,
AirDefence.AAA_ZU_23_Emplacement: 10,
AirDefence.AAA_ZU_23_Closed: 10,
AirDefence.AAA_ZU_23_on_Ural_375: 10,
AirDefence.AAA_ZU_23_Insurgent_on_Ural_375: 10,
AirDefence.AAA_ZU_23_Insurgent_Closed: 10,
AirDefence.AAA_ZU_23_Insurgent: 10,
AirDefence.SPAAA_ZSU_23_4_Shilka: 10,
AirDefence.AAA_Vulcan_M163: 15,
AirDefence.SAM_Linebacker_M6: 20,
AirDefence.Rapier_FSA_Launcher: 20,
AirDefence.SAM_Avenger_M1097: 22,
AirDefence.SPAAA_Gepard: 24,
AirDefence.SAM_Roland_ADS: 40,
AirDefence.SAM_Patriot_LN_M901: 85,
AirDefence.SAM_Patriot_EPP_III: 85,
AirDefence.SAM_Chaparral_M48: 25,
AirDefence.AAA_Bofors_40mm: 15,
AirDefence.AAA_8_8cm_Flak_36: 15,
AirDefence.SAM_SA_2_LN_SM_90: 30,
AirDefence.SAM_SA_3_S_125_LN_5P73: 35,
AirDefence.SAM_SA_6_Kub_LN_2P25: 45,
AirDefence.SAM_SA_8_Osa_9A33: 30,
AirDefence.SAM_SA_9_Strela_1_9P31: 25,
AirDefence.SAM_SA_10_S_300PS_LN_5P85C: 80,
AirDefence.SAM_SA_10_S_300PS_CP_54K6: 80,
AirDefence.SAM_SA_11_Buk_LN_9A310M1: 60,
AirDefence.SAM_SA_13_Strela_10M3_9A35M3: 30,
AirDefence.SAM_SA_15_Tor_9A331: 40,
AirDefence.SAM_SA_19_Tunguska_2S6: 35,
AirDefence.HQ_7_Self_Propelled_LN: 35
}
def generate_anti_air_group(game, parent_cp, ground_object, faction:str):
"""
This generate a SAM group

BIN
installer/ISCC.exe Normal file

Binary file not shown.

View File

@ -0,0 +1,51 @@
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "DCS Liberation"
#define MyAppVersion "{{version}}"
#define MyAppPublisher "Khopa"
#define MyAppURL "https://github.com/Khopa/dcs_liberation/wiki"
#define MyAppExeName "liberation_main.exe"
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{6753B352-D281-42CB-9AFA-5E93EB90AA5A}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={autopf}\{#MyAppName}
DefaultGroupName={#MyAppName}
AllowNoIcons=yes
; Remove the following line to run in administrative install mode (install for all users.)
PrivilegesRequired=lowest
PrivilegesRequiredOverridesAllowed=dialog
OutputDir=..\dist
OutputBaseFilename=dcs_liberation
SetupIconFile=..\resources\icon.ico
UninstallDisplayIcon={app}\liberation_main.exe
Compression=lzma
SolidCompression=yes
WizardStyle=modern
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "..\dist\dcs_liberation\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

1
pydcs Submodule

@ -0,0 +1 @@
Subproject commit dcc3d846316af2925c93ae09840c3ab4a1150e59

View File

@ -4,7 +4,7 @@ import logging
import os
import sys
import dcs
from pydcs import dcs
from PySide2 import QtWidgets
from PySide2.QtGui import QPixmap
from PySide2.QtWidgets import QApplication, QSplashScreen

View File

@ -143,7 +143,7 @@ class QLiberationMap(QGraphicsView):
go_pos = self._transform_point(ground_object.position)
if not ground_object.airbase_group:
buildings = self.game.theater.find_ground_objects_by_obj_name(ground_object.obj_name)
scene.addItem(QMapGroundObject(self, go_pos[0], go_pos[1], 12, 12, cp, ground_object, buildings))
scene.addItem(QMapGroundObject(self, go_pos[0], go_pos[1], 14, 12, cp, ground_object, self.game, buildings))
if ground_object.category == "aa" and self.get_display_rule("sam"):
max_range = 0

View File

@ -1,19 +1,22 @@
from PySide2.QtCore import QPoint, QRect, QPointF, Qt
from PySide2.QtGui import QPainter
from PySide2.QtGui import QPainter, QBrush
from PySide2.QtWidgets import QGraphicsRectItem, QGraphicsItem, QGraphicsSceneHoverEvent, QGraphicsSceneMouseEvent
import qt_ui.uiconstants as CONST
from game import db
from game import db, Game
from game.data.building_data import FORTIFICATION_BUILDINGS
from qt_ui.windows.groundobject.QGroundObjectMenu import QGroundObjectMenu
from theater import TheaterGroundObject, ControlPoint
class QMapGroundObject(QGraphicsRectItem):
def __init__(self, parent, x: float, y: float, w: float, h: float, cp: ControlPoint, model: TheaterGroundObject, buildings=[]):
def __init__(self, parent, x: float, y: float, w: float, h: float, cp: ControlPoint, model: TheaterGroundObject, game:Game, buildings=[]):
super(QMapGroundObject, self).__init__(x, y, w, h)
self.model = model
self.cp = cp
self.parent = parent
self.game = game
self.setAcceptHoverEvents(True)
self.setZValue(2)
self.buildings = buildings
@ -39,6 +42,8 @@ class QMapGroundObject(QGraphicsRectItem):
tooltip = tooltip + str(building.dcs_identifier) + "\n"
self.setToolTip(tooltip[:-1])
def mousePressEvent(self, event:QGraphicsSceneMouseEvent):
self.openEditionMenu()
def paint(self, painter, option, widget=None):
#super(QMapControlPoint, self).paint(painter, option, widget)
@ -53,14 +58,49 @@ class QMapGroundObject(QGraphicsRectItem):
if cat == "aa" and self.model.sea_object:
cat = "ship"
if not self.model.is_dead and not self.cp.captured:
painter.drawPixmap(option.rect, CONST.ICONS[cat + enemyIcons])
elif not self.model.is_dead:
painter.drawPixmap(option.rect, CONST.ICONS[cat + playerIcons])
rect = QRect(option.rect.x()+2,option.rect.y(),option.rect.width()-2,option.rect.height())
is_dead = self.model.is_dead
for building in self.buildings:
if not building.is_dead:
is_dead = False
break
if not is_dead and not self.cp.captured:
painter.drawPixmap(rect, CONST.ICONS[cat + enemyIcons])
elif not is_dead:
painter.drawPixmap(rect, CONST.ICONS[cat + playerIcons])
else:
painter.drawPixmap(option.rect, CONST.ICONS["destroyed"])
painter.drawPixmap(rect, CONST.ICONS["destroyed"])
self.drawHealthGauge(painter, option)
painter.restore()
def drawHealthGauge(self, painter, option):
units_alive = 0
units_dead = 0
if len(self.model.groups) == 0:
for building in self.buildings:
if building.dcs_identifier in FORTIFICATION_BUILDINGS:
continue
if building.is_dead:
units_dead += 1
else:
units_alive += 1
for g in self.model.groups:
units_alive += len(g.units)
if hasattr(g, "units_losts"):
units_dead += len(g.units_losts)
if units_dead + units_alive > 0:
ratio = float(units_alive)/(float(units_dead) + float(units_alive))
bar_height = ratio * option.rect.height()
painter.fillRect(option.rect.x(), option.rect.y(), 2, option.rect.height(), QBrush(CONST.COLORS["dark_red"]))
painter.fillRect(option.rect.x(), option.rect.y(), 2, bar_height, QBrush(CONST.COLORS["green"]))
def hoverEnterEvent(self, event: QGraphicsSceneHoverEvent):
self.update()
self.setCursor(Qt.PointingHandCursor)
@ -72,3 +112,7 @@ class QMapGroundObject(QGraphicsRectItem):
def hoverLeaveEvent(self, event: QGraphicsSceneHoverEvent):
self.update()
def openEditionMenu(self):
self.editionMenu = QGroundObjectMenu(self.window(), self.model, self.buildings, self.cp, self.game)
self.editionMenu.show()

View File

@ -1,16 +1,22 @@
from PySide2.QtWidgets import QGridLayout, QLabel, QGroupBox
from PySide2.QtWidgets import QGridLayout, QLabel, QGroupBox, QPushButton
from qt_ui.uiconstants import VEHICLES_ICONS
from qt_ui.windows.groundobject.QGroundObjectMenu import QGroundObjectMenu
from theater import ControlPoint, TheaterGroundObject
class QBaseDefenseGroupInfo(QGroupBox):
def __init__(self, cp:ControlPoint, ground_object: TheaterGroundObject):
def __init__(self, cp:ControlPoint, ground_object: TheaterGroundObject, game):
super(QBaseDefenseGroupInfo, self).__init__("Group : " + ground_object.obj_name)
self.ground_object = ground_object
self.cp = cp
self.game = game
self.buildings = game.theater.find_ground_objects_by_obj_name(self.ground_object.obj_name)
self.init_ui()
def init_ui(self):
unit_dict = {}
layout = QGridLayout()
@ -29,8 +35,18 @@ class QBaseDefenseGroupInfo(QGroupBox):
# icon.setText("<b>" + k[:6] + "</b>")
#icon.setProperty("style", "icon-plane")
#layout.addWidget(icon, i, 0)
layout.addWidget(QLabel(str(v) + " x " + "<strong>" + k + "</strong>"), i, 1)
layout.addWidget(QLabel(str(v) + " x " + "<strong>" + k + "</strong>"), i, 0)
i = i + 1
manage_button = QPushButton("Manage")
manage_button.setProperty("style", "btn-success")
manage_button.setMaximumWidth(180)
manage_button.clicked.connect(self.onManage)
layout.addWidget(manage_button, i+1, 0)
self.setLayout(layout)
def onManage(self):
self.editionMenu = QGroundObjectMenu(self.window(), self.ground_object, self.buildings, self.cp, self.game)
self.editionMenu.show()

View File

@ -15,6 +15,6 @@ class QBaseDefensesHQ(QFrame):
def init_ui(self):
airport = self.game.theater.terrain.airport_by_id(self.cp.id)
layout = QGridLayout()
layout.addWidget(QBaseInformation(self.cp, airport))
layout.addWidget(QBaseInformation(self.cp, airport, self.game))
self.setLayout(layout)

View File

@ -1,4 +1,5 @@
from PySide2.QtWidgets import QGridLayout, QLabel, QGroupBox, QVBoxLayout, QFrame
from PySide2.QtGui import Qt
from PySide2.QtWidgets import QGridLayout, QLabel, QGroupBox, QVBoxLayout, QFrame, QWidget, QScrollArea
from game import db
from qt_ui.uiconstants import AIRCRAFT_ICONS, VEHICLES_ICONS
@ -8,17 +9,34 @@ from theater import ControlPoint, Airport
class QBaseInformation(QFrame):
def __init__(self, cp:ControlPoint, airport:Airport):
def __init__(self, cp:ControlPoint, airport:Airport, game):
super(QBaseInformation, self).__init__()
self.cp = cp
self.airport = airport
self.game = game
self.setMinimumWidth(500)
self.init_ui()
def init_ui(self):
self.layout = QVBoxLayout()
self.mainLayout = QVBoxLayout()
scroll_content = QWidget()
task_box_layout = QGridLayout()
scroll_content.setLayout(task_box_layout)
row = 0
for g in self.cp.ground_objects:
if g.airbase_group:
group_info = QBaseDefenseGroupInfo(self.cp, g)
self.layout.addWidget(group_info)
self.setLayout(self.layout)
group_info = QBaseDefenseGroupInfo(self.cp, g, self.game)
task_box_layout.addWidget(group_info)
scroll_content.setLayout(task_box_layout)
scroll = QScrollArea()
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setWidgetResizable(True)
scroll.setWidget(scroll_content)
self.mainLayout.addWidget(scroll)
self.setLayout(self.mainLayout)

View File

@ -0,0 +1,33 @@
import os
from PySide2.QtGui import QPixmap
from PySide2.QtWidgets import QGroupBox, QHBoxLayout, QVBoxLayout, QLabel
class QBuildingInfo(QGroupBox):
def __init__(self, building, ground_object):
super(QBuildingInfo, self).__init__()
self.building = building
self.ground_object = ground_object
self.init_ui()
def init_ui(self):
self.header = QLabel()
path = os.path.join("./resources/ui/units/buildings/" + self.building.dcs_identifier + ".png")
if self.building.is_dead:
pixmap = QPixmap("./resources/ui/units/buildings/dead.png")
elif os.path.isfile(path):
pixmap = QPixmap(path)
else:
pixmap = QPixmap("./resources/ui/units/buildings/missing.png")
self.header.setPixmap(pixmap)
name = "<b>{}</b> {}".format(self.building.dcs_identifier[0:18], "[DEAD]" if self.building.is_dead else "")
self.name = QLabel(name)
self.name.setProperty("style", "small")
layout = QVBoxLayout()
layout.addWidget(self.header)
layout.addWidget(self.name)
footer = QHBoxLayout()
self.setLayout(layout)

View File

@ -0,0 +1,117 @@
import logging
from PySide2.QtGui import QCloseEvent
from PySide2.QtWidgets import QHBoxLayout, QWidget, QDialog, QGridLayout, QLabel, QGroupBox, QVBoxLayout, QPushButton
from dcs import Point
from game import Game
from game.data.building_data import FORTIFICATION_BUILDINGS
from game.db import PRICES, unit_type_of
from qt_ui.uiconstants import EVENT_ICONS
from qt_ui.widgets.QBudgetBox import QBudgetBox
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
from qt_ui.windows.groundobject.QBuildingInfo import QBuildingInfo
from theater import ControlPoint, TheaterGroundObject
class QGroundObjectMenu(QDialog):
def __init__(self, parent, ground_object: TheaterGroundObject, buildings:[], cp: ControlPoint, game: Game):
super(QGroundObjectMenu, self).__init__(parent)
self.setMinimumWidth(350)
self.ground_object = ground_object
self.buildings = buildings
self.cp = cp
self.game = game
self.setWindowTitle("Location " + self.ground_object.obj_name)
self.setWindowIcon(EVENT_ICONS["capture"])
self.intelBox = QGroupBox("Units :")
self.buildingBox = QGroupBox("Buildings :")
self.intelLayout = QGridLayout()
self.buildingsLayout = QGridLayout()
self.init_ui()
def init_ui(self):
self.mainLayout = QVBoxLayout()
self.budget = QBudgetBox(self.game)
self.budget.setGame(self.game)
self.doLayout()
if len(self.ground_object.groups) > 0:
self.mainLayout.addWidget(self.intelBox)
else:
self.mainLayout.addWidget(self.buildingBox)
self.setLayout(self.mainLayout)
def doLayout(self):
self.intelBox = QGroupBox("Units :")
self.intelLayout = QGridLayout()
i = 0
for g in self.ground_object.groups:
if not hasattr(g, "units_losts"):
g.units_losts = []
for u in g.units:
self.intelLayout.addWidget(QLabel("<b>Unit #" + str(u.id) + " - " + str(u.type) + "</b>"), i, 0)
i = i + 1
for u in g.units_losts:
utype = unit_type_of(u)
if utype in PRICES:
price = PRICES[utype]
else:
price = 6
self.intelLayout.addWidget(QLabel("<b>Unit #" + str(u.id) + " - " + str(u.type) + "</b> [DEAD]"), i, 0)
if self.cp.captured:
repair = QPushButton("Repair [" + str(price) + "M]")
repair.setProperty("style", "btn-success")
repair.clicked.connect(lambda u=u, g=g, p=price: self.repair_unit(g, u, p))
self.intelLayout.addWidget(repair, i, 1)
i = i + 1
self.buildingBox = QGroupBox("Buildings :")
self.buildingsLayout = QGridLayout()
j = 0
for i, building in enumerate(self.buildings):
if building.dcs_identifier not in FORTIFICATION_BUILDINGS:
self.buildingsLayout.addWidget(QBuildingInfo(building, self.ground_object), j/3, j%3)
j = j + 1
self.buildingBox.setLayout(self.buildingsLayout)
self.intelBox.setLayout(self.intelLayout)
def do_refresh_layout(self):
try:
for i in range(self.mainLayout.count()):
self.mainLayout.removeItem(self.mainLayout.itemAt(i))
self.doLayout()
if len(self.ground_object.groups) > 0:
self.mainLayout.addWidget(self.intelBox)
else:
self.mainLayout.addWidget(self.buildingBox)
except Exception as e:
print(e)
def repair_unit(self, group, unit, price):
if self.game.budget > price:
self.game.budget -= price
group.units_losts = [u for u in group.units_losts if u.id != unit.id]
group.units.append(unit)
GameUpdateSignal.get_instance().updateGame(self.game)
# Remove destroyed units in the vicinity
destroyed_units = self.game.get_destroyed_units()
for d in destroyed_units:
p = Point(d["x"], d["z"])
if p.distance_to_point(unit.position) < 15:
destroyed_units.remove(d)
logging.info("Removed destroyed units " + str(d))
logging.info("Repaired unit : " + str(unit.id) + " " + str(unit.type))
self.do_refresh_layout()
def closeEvent(self, closeEvent: QCloseEvent):
GameUpdateSignal.get_instance().updateGame(self.game)

View File

@ -24,7 +24,11 @@ class QLoadoutEditor(QGroupBox):
label = QLabel("<b>{}</b>".format(pylon.__name__[len("Pylon"):]))
label.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
layout.addWidget(label, i, 0)
layout.addWidget(QPylonEditor(flight, pylon, i+1), i, 1)
try:
pylon_number = int(pylon.__name__.split("Pylon")[1])
except:
pylon_number = i+1
layout.addWidget(QPylonEditor(flight, pylon, pylon_number), i, 1)
hboxLayout.addLayout(layout)
hboxLayout.addStretch()

View File

@ -1,3 +1,5 @@
import logging
from PySide2.QtCore import QSize, Qt, QItemSelectionModel, QPoint
from PySide2.QtGui import QStandardItemModel, QStandardItem
from PySide2.QtWidgets import QLabel, QDialog, QGridLayout, QListView, QStackedLayout, QComboBox, QWidget, \
@ -269,32 +271,28 @@ class QSettingsWindow(QDialog):
self.moneyCheatBoxLayout = QGridLayout()
self.moneyCheatBox.setLayout(self.moneyCheatBoxLayout)
self.cheat25M = QPushButton("Cheat +25M")
self.cheat50M = QPushButton("Cheat +50M")
self.cheat100M = QPushButton("Cheat +100M")
self.cheat200M = QPushButton("Cheat +200M")
self.cheat500M = QPushButton("Cheat +500M")
self.cheat1000M = QPushButton("Cheat +1000M")
self.cheat25M.clicked.connect(lambda: self.cheatMoney(25))
self.cheat50M.clicked.connect(lambda: self.cheatMoney(50))
self.cheat100M.clicked.connect(lambda: self.cheatMoney(100))
self.cheat200M.clicked.connect(lambda: self.cheatMoney(200))
self.cheat500M.clicked.connect(lambda: self.cheatMoney(500))
self.cheat1000M.clicked.connect(lambda: self.cheatMoney(1000))
self.moneyCheatBoxLayout.addWidget(self.cheat25M, 0, 0)
self.moneyCheatBoxLayout.addWidget(self.cheat50M, 0, 1)
self.moneyCheatBoxLayout.addWidget(self.cheat100M, 1, 0)
self.moneyCheatBoxLayout.addWidget(self.cheat200M, 1, 1)
self.moneyCheatBoxLayout.addWidget(self.cheat500M, 2, 0)
self.moneyCheatBoxLayout.addWidget(self.cheat1000M, 2, 1)
cheats_amounts = [25, 50, 100, 200, 500, 1000, -25, -50, -100, -200]
for i, amount in enumerate(cheats_amounts):
if amount > 0:
btn = QPushButton("Cheat +" + str(amount) + "M")
btn.setProperty("style", "btn-success")
else:
btn = QPushButton("Cheat " + str(amount) + "M")
btn.setProperty("style", "btn-danger")
btn.clicked.connect(self.cheatLambda(amount))
self.moneyCheatBoxLayout.addWidget(btn, i/2, i%2)
self.cheatLayout.addWidget(self.moneyCheatBox, 0, 0)
def cheatLambda(self, amount):
return lambda: self.cheatMoney(amount)
def cheatMoney(self, amount):
logging.info("CHEATING FOR AMOUNT : " + str(amount) + "M")
self.game.budget += amount
self.game.informations.append(Information("CHEATER", "You are a cheater and you should feel bad", self.game.turn))
if amount > 0:
self.game.informations.append(Information("CHEATER", "You are a cheater and you should feel bad", self.game.turn))
else:
self.game.informations.append(Information("CHEATER", "You are still a cheater !", self.game.turn))
GameUpdateSignal.get_instance().updateGame(self.game)
def applySettings(self):

View File

@ -1,4 +1,4 @@
pydcs>=0.9.10
#pydcs>=0.9.10
Pyside2>=5.13.0
pyinstaller==3.6
pyproj==2.6.1.post1

View File

@ -0,0 +1,118 @@
local unitPayloads = {
["name"] = "AH-64A",
["payloads"] = {
[1] = {
["name"] = "CAS",
["pylons"] = {
[1] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 4,
},
[2] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{FD90A1DC-9147-49FA-BF56-CB83EF0BD32B}",
["num"] = 3,
},
[4] = {
["CLSID"] = "{FD90A1DC-9147-49FA-BF56-CB83EF0BD32B}",
["num"] = 2,
},
},
["tasks"] = {
[1] = 18,
[2] = 31,
[3] = 32,
[4] = 30,
},
},
[2] = {
["name"] = "STRIKE",
["pylons"] = {
[1] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 4,
},
[2] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 1,
},
},
["tasks"] = {
[1] = 18,
[2] = 31,
[3] = 32,
[4] = 30,
},
},
[3] = {
["name"] = "CAP",
["pylons"] = {
[1] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 4,
},
[2] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 1,
},
},
["tasks"] = {
[1] = 18,
[2] = 31,
[3] = 32,
[4] = 30,
},
},
[4] = {
["name"] = "ANTISHIP",
["pylons"] = {
[1] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 4,
},
[2] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 3,
},
[3] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 2,
},
[4] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 1,
},
},
["tasks"] = {
[1] = 18,
[2] = 31,
[3] = 32,
[4] = 30,
},
},
[5] = {
["name"] = "SEAD",
["pylons"] = {
[1] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 4,
},
[2] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 1,
},
},
["tasks"] = {
[1] = 18,
[2] = 31,
[3] = 32,
[4] = 30,
},
},
},
["unitType"] = "AH-64A",
}
return unitPayloads

View File

@ -0,0 +1,110 @@
local unitPayloads = {
["name"] = "AH-64D",
["payloads"] = {
[1] = {
["name"] = "CAS",
["pylons"] = {
[1] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 4,
},
[2] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 1,
},
},
["tasks"] = {
[1] = 18,
[2] = 31,
[3] = 32,
[4] = 30,
},
},
[2] = {
["name"] = "CAP",
["pylons"] = {
[1] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 4,
},
[2] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 1,
},
},
["tasks"] = {
[1] = 18,
[2] = 31,
[3] = 32,
[4] = 30,
},
},
[3] = {
["name"] = "ANTISHIP",
["pylons"] = {
[1] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 4,
},
[2] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 3,
},
[4] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 2,
},
},
["tasks"] = {
[1] = 18,
[2] = 31,
[3] = 32,
[4] = 30,
},
},
[4] = {
["name"] = "SEAD",
["pylons"] = {
[1] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 4,
},
[2] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 1,
},
},
["tasks"] = {
[1] = 18,
[2] = 31,
[3] = 32,
[4] = 30,
},
},
[5] = {
["name"] = "STRIKE",
["pylons"] = {
[1] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 4,
},
[2] = {
["CLSID"] = "{88D18A5E-99C8-4B04-B40B-1C02F2018B6E}",
["num"] = 1,
},
},
["tasks"] = {
[1] = 18,
[2] = 31,
[3] = 32,
[4] = 30,
},
},
},
["unitType"] = "AH-64D",
}
return unitPayloads

View File

@ -2,53 +2,6 @@ local unitPayloads = {
["name"] = "F-16C_50",
["payloads"] = {
[1] = {
["name"] = "CAS",
["pylons"] = {
[1] = {
["CLSID"] = "{8A0BE8AE-58D4-4572-9263-3144C0D06364}",
["num"] = 5,
},
[2] = {
["CLSID"] = "{DB769D48-67D7-42ED-A2BE-108D566C8B1E}",
["num"] = 7,
},
[3] = {
["CLSID"] = "{DB769D48-67D7-42ED-A2BE-108D566C8B1E}",
["num"] = 3,
},
[4] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 2,
},
[5] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 1,
},
[6] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 8,
},
[7] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 9,
},
[8] = {
["CLSID"] = "{5335D97A-35A5-4643-9D9B-026C75961E52}",
["num"] = 4,
},
[9] = {
["CLSID"] = "{5335D97A-35A5-4643-9D9B-026C75961E52}",
["num"] = 6,
},
[10] = {
["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 11,
},
},
["tasks"] = {
},
},
[2] = {
["name"] = "ANTISHIP",
["pylons"] = {
[1] = {
@ -91,7 +44,7 @@ local unitPayloads = {
["tasks"] = {
},
},
[3] = {
[2] = {
["name"] = "CAP",
["pylons"] = {
[1] = {
@ -134,6 +87,53 @@ local unitPayloads = {
["tasks"] = {
},
},
[3] = {
["name"] = "CAS",
["pylons"] = {
[1] = {
["CLSID"] = "{8A0BE8AE-58D4-4572-9263-3144C0D06364}",
["num"] = 5,
},
[2] = {
["CLSID"] = "{DB769D48-67D7-42ED-A2BE-108D566C8B1E}",
["num"] = 7,
},
[3] = {
["CLSID"] = "{DB769D48-67D7-42ED-A2BE-108D566C8B1E}",
["num"] = 3,
},
[4] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 2,
},
[5] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 1,
},
[6] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 8,
},
[7] = {
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
["num"] = 9,
},
[8] = {
["CLSID"] = "{5335D97A-35A5-4643-9D9B-026C75961E52}",
["num"] = 4,
},
[9] = {
["CLSID"] = "{5335D97A-35A5-4643-9D9B-026C75961E52}",
["num"] = 6,
},
[11] = {
["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 11,
},
},
["tasks"] = {
},
},
[4] = {
["name"] = "STRIKE",
["pylons"] = {
@ -173,6 +173,10 @@ local unitPayloads = {
["CLSID"] = "{8A0BE8AE-58D4-4572-9263-3144C0D06364}",
["num"] = 5,
},
[11] = {
["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 11,
},
},
["tasks"] = {
},

View File

@ -486,3 +486,7 @@ QWidget[style="baseMenuHeader"]{
font-weight: bold;
color:white;
}*/
QLabel[style="small"]{
font-size: 8px;
}

View File

@ -178,4 +178,8 @@ QLabel[style="SEAD"]{
QWidget[style="baseMenuHeader"]{
font-size: 24px;
font-weight: bold;
}*/
}*/
QLabel[style="small"]{
font-size: 8px;
}

View File

@ -1,6 +1,6 @@
import os
import sys
import dcs
from pydcs import dcs
from game import db
from gen.aircraft import AircraftConflictGenerator

View File

@ -45,7 +45,7 @@ def _mk_archieve():
shutil.rmtree("./dist")
except FileNotFoundError:
pass
os.system("pyinstaller.exe pyinstaller.spec")
os.system("pyinstaller.exe --clean pyinstaller.spec")
#archieve = ZipFile(path, "w")
#archieve.writestr("dcs_liberation.bat", "cd dist\\dcs_liberation\r\nliberation_main \"%UserProfile%\\Saved Games\" \"{}\"".format(VERSION))
#_zip_dir(archieve, "./dist/dcs_liberation")

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1,6 +1,6 @@
import typing
import dcs
from pydcs import dcs
from dcs.mapping import Point
from .controlpoint import ControlPoint

View File

@ -110,7 +110,7 @@ class SyrianCivilWar(SyriaTheater):
self.palmyra = ControlPoint.from_airport(syria.Palmyra, LAND, SIZE_REGULAR, IMPORTANCE_LOW)
self.carrier = ControlPoint.carrier("Carrier", Point(18537, -52000), 1001)
self.lha = ControlPoint.lha("LHA", Point(116000, 30000), 1002)
self.lha = ControlPoint.lha("LHA", Point(116000, -30000), 1002)
self.add_controlpoint(self.basselAlAssad, connected_to=[self.hama])
self.add_controlpoint(self.marjruhayyil, connected_to=[self.aldumayr])
@ -140,6 +140,7 @@ class InherentResolve(SyriaTheater):
super(InherentResolve, self).__init__()
self.kinghussein = ControlPoint.from_airport(syria.King_Hussein_Air_College, LAND, SIZE_REGULAR, IMPORTANCE_HIGH)
self.incirlik = ControlPoint.from_airport(syria.Incirlik, LAND, SIZE_REGULAR, IMPORTANCE_HIGH)
self.khalkhala = ControlPoint.from_airport(syria.Khalkhalah, LAND, SIZE_REGULAR, IMPORTANCE_MEDIUM)
self.palmyra = ControlPoint.from_airport(syria.Palmyra, LAND, SIZE_REGULAR, IMPORTANCE_LOW)
self.jirah = ControlPoint.from_airport(syria.Jirah, LAND, SIZE_REGULAR, IMPORTANCE_LOW)
@ -149,6 +150,7 @@ class InherentResolve(SyriaTheater):
self.lha = ControlPoint.lha("LHA", Point(-131000, -161000), 1002)
self.add_controlpoint(self.kinghussein, connected_to=[self.khalkhala])
self.add_controlpoint(self.incirlik, connected_to=[self.incirlik])
self.add_controlpoint(self.khalkhala, connected_to=[self.kinghussein, self.palmyra])
self.add_controlpoint(self.palmyra, connected_to=[self.khalkhala, self.tabqa])
self.add_controlpoint(self.tabqa, connected_to=[self.palmyra, self.jirah])
@ -158,10 +160,12 @@ class InherentResolve(SyriaTheater):
self.add_controlpoint(self.lha)
self.kinghussein.captured = True
self.incirlik.captured = True
self.carrier.captured = True
self.lha.captured = True
self.jirah.captured_invert = True
self.incirlik.captured_invert = True
self.carrier.captured_invert = True
self.lha.captured_invert = True
@ -214,7 +218,7 @@ class SyriaFullMap(SyriaTheater):
self.carrier.captured = True
self.lha.captured = True
self.hatay.captured_invert = True
self.incirlik.captured_invert = True
self.carrier.captured_invert = True
self.lha.captured_invert = True

View File

@ -2,7 +2,7 @@ import json
import os
from shutil import copyfile
import dcs
from pydcs import dcs
from userdata import persistency