minor fixes; F-14B
6
.gitignore
vendored
@ -1,10 +1,14 @@
|
||||
*.pyc
|
||||
__pycache__
|
||||
build/*
|
||||
build/**
|
||||
resources/payloads/*.lua
|
||||
venv
|
||||
logs.txt
|
||||
.DS_Store
|
||||
dist/**
|
||||
a.py
|
||||
resources/tools/a.miz
|
||||
tests/**
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
|
||||
1
.idea/modules.xml
generated
@ -3,7 +3,6 @@
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/dcs_pmcliberation.iml" filepath="$PROJECT_DIR$/.idea/dcs_pmcliberation.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/dcs_pmcliberation.iml" filepath="$PROJECT_DIR$/.idea/dcs_pmcliberation.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@ -52,9 +52,7 @@ w = ui.window.Window()
|
||||
try:
|
||||
game = persistency.restore_game()
|
||||
if not game or not is_version_compatible(game.settings.version):
|
||||
new_game_menu = None # type: NewGameMenu
|
||||
new_game_menu = ui.newgamemenu.NewGameMenu(w, w.start_new_game)
|
||||
new_game_menu.display()
|
||||
ui.newgamemenu.NewGameMenu(w, w.start_new_game).display()
|
||||
else:
|
||||
game.settings.version = VERSION_STRING
|
||||
proceed_to_main_menu(game)
|
||||
|
||||
38
a.py
Normal file
@ -0,0 +1,38 @@
|
||||
from theater.caucasus import *
|
||||
from gen.conflictgen import Conflict
|
||||
|
||||
from matplotlib import pyplot
|
||||
from matplotlib import lines
|
||||
from shapely import geometry
|
||||
from shapely.geometry import Polygon
|
||||
from descartes.patch import PolygonPatch
|
||||
|
||||
def put_lines(ls, ax):
|
||||
for g in ls.geoms:
|
||||
ax.plot([g.xy[0][0], g.xy[0][1]], [g.xy[1][0], g.xy[1][1]])
|
||||
|
||||
cau = CaucasusTheater()
|
||||
#left, heading, dist = Conflict.frontline_vector(cau.soganlug, cau.kutaisi, cau)
|
||||
#right = left.point_from_heading(heading, dist)
|
||||
|
||||
left, heading = Conflict.frontline_position(cau, cau.soganlug, cau.kutaisi)
|
||||
right = left.point_from_heading(heading+90, 80000)
|
||||
left = left.point_from_heading(heading-90, 80000)
|
||||
|
||||
line = geometry.LineString([(left.x, left.y), (right.x, right.y)])
|
||||
line = line.intersection(cau.land_poly)
|
||||
|
||||
fig = pyplot.figure(1, figsize=(20, 20), dpi=90)
|
||||
ax = fig.add_subplot(121)
|
||||
ax.set_ylim([0, 1500000])
|
||||
ax.set_xlim([-600000, 400000])
|
||||
|
||||
patch = PolygonPatch(cau.land_poly, facecolor=(0, 0, 0), edgecolor=(0, 0, 0), alpha=0.5, zorder=2)
|
||||
ax.add_patch(patch)
|
||||
ax.plot([left.x, right.x], [left.y, right.y], 'k-', lw=2)
|
||||
|
||||
ax.plot([cau.soganlug.position.x, cau.soganlug.position.x+1000], [cau.soganlug.position.y, cau.soganlug.position.y+1000], lw=5)
|
||||
ax.plot([cau.kutaisi.position.x, cau.kutaisi.position.x+1000], [cau.kutaisi.position.y, cau.kutaisi.position.y+1000], lw=5)
|
||||
put_lines(line, ax)
|
||||
pyplot.show()
|
||||
|
||||
21
game/db.py
@ -39,11 +39,11 @@ and prioritization for the enemy (i.e. less important bases will receive units w
|
||||
"""
|
||||
PRICES = {
|
||||
# fighter
|
||||
MiG_23MLD: 18,
|
||||
Su_27: 20,
|
||||
MiG_23MLD: 13,
|
||||
Su_27: 18,
|
||||
Su_33: 22,
|
||||
MiG_29A: 23,
|
||||
MiG_29S: 25,
|
||||
MiG_29A: 18,
|
||||
MiG_29S: 20,
|
||||
|
||||
F_5E_3: 6,
|
||||
MiG_15bis: 5,
|
||||
@ -54,6 +54,7 @@ PRICES = {
|
||||
M_2000C: 13,
|
||||
FA_18C_hornet: 18,
|
||||
F_15C: 20,
|
||||
F_14B: 14,
|
||||
|
||||
# bomber
|
||||
Su_25: 15,
|
||||
@ -145,6 +146,7 @@ UNIT_BY_TASK = {
|
||||
MiG_29S,
|
||||
FA_18C_hornet,
|
||||
F_15C,
|
||||
F_14B,
|
||||
M_2000C,
|
||||
],
|
||||
CAS: [
|
||||
@ -304,6 +306,7 @@ UNIT_BY_COUNTRY = {
|
||||
"USA": [
|
||||
F_5E_3,
|
||||
F_15C,
|
||||
F_14B,
|
||||
FA_18C_hornet,
|
||||
AJS37,
|
||||
M_2000C,
|
||||
@ -367,16 +370,25 @@ Payload will be used for operation of following type, "*" category will be used
|
||||
PLANE_PAYLOAD_OVERRIDES = {
|
||||
FA_18C_hornet: {
|
||||
CAP: "AIM-120*4,AIM-9*2,AIM-7*2,Fuel",
|
||||
Escort: "AIM-120*4,AIM-9*2,AIM-7*2,Fuel",
|
||||
PinpointStrike: "MK-82*8,AIM-9*2,AIM-7,FLIR Pod,Fuel",
|
||||
AntishipStrike: "MK-82*8,AIM-9*2,AIM-7,FLIR Pod,Fuel",
|
||||
},
|
||||
|
||||
F_14B: {
|
||||
CAP: "AIM-54A-MK47*4, AIM-7M*2, AIM-9M*2, XT*2",
|
||||
Escort: "AIM-54A-MK47*4, AIM-7M*2, AIM-9M*2, XT*2",
|
||||
CAS: "AIM-54A-MK60*1, AIM-7M*1, AIM-9M*2, XT*2, Mk-82*2, LANTIRN",
|
||||
GroundAttack: "AIM-54A-MK60*1, AIM-7M*1, AIM-9M*2, XT*2, Mk-82*2, LANTIRN",
|
||||
},
|
||||
|
||||
Su_25T: {
|
||||
CAS: "APU-8 Vikhr-M*2,Kh-25ML,R-73*2,SPPU-22*2,Mercury LLTV Pod,MPS-410",
|
||||
},
|
||||
|
||||
Su_33: {
|
||||
CAP: "R-73*4,R-27R*2,R-27ER*6",
|
||||
Escort: "R-73*4,R-27R*2,R-27ER*6",
|
||||
},
|
||||
|
||||
AJS37: {
|
||||
@ -399,6 +411,7 @@ PLANE_PAYLOAD_OVERRIDES = {
|
||||
|
||||
M_2000C: {
|
||||
CAP: "Combat Air Patrol",
|
||||
Escort: "Combat Air Patrol",
|
||||
GroundAttack: "MK-82S Heavy Strike",
|
||||
},
|
||||
|
||||
|
||||
14
game/game.py
@ -111,7 +111,7 @@ class Game:
|
||||
# skip naval events for non-coastal CPs
|
||||
return
|
||||
|
||||
if event_class == BaseAttackEvent and enemy_cp.base.strength > PLAYER_BASEATTACK_THRESHOLD:
|
||||
if event_class == BaseAttackEvent and enemy_cp.base.strength > PLAYER_BASEATTACK_THRESHOLD and self.settings.version != "dev":
|
||||
# skip base attack events for CPs yet too strong
|
||||
return
|
||||
|
||||
@ -163,6 +163,7 @@ class Game:
|
||||
|
||||
def _generate_events(self):
|
||||
strikes_generated_for = set()
|
||||
base_attack_generated_for = set()
|
||||
|
||||
for player_cp, enemy_cp in self.theater.conflicts(True):
|
||||
for event_class, (player_probability, enemy_probability) in EVENT_PROBABILITIES.items():
|
||||
@ -171,15 +172,20 @@ class Game:
|
||||
if not Conflict.has_frontline_between(player_cp, enemy_cp):
|
||||
continue
|
||||
|
||||
if event_class in [StrikeEvent]:
|
||||
# don't generate multiple 100% strike events from each attack direction
|
||||
# don't generate multiple 100% events from each attack direction
|
||||
if event_class is StrikeEvent:
|
||||
if enemy_cp in strikes_generated_for:
|
||||
continue
|
||||
if event_class is BaseAttackEvent:
|
||||
if enemy_cp in base_attack_generated_for:
|
||||
continue
|
||||
|
||||
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 event_class in [StrikeEvent]:
|
||||
if event_class is StrikeEvent:
|
||||
strikes_generated_for.add(enemy_cp)
|
||||
if event_class is BaseAttackEvent:
|
||||
base_attack_generated_for.add(enemy_cp)
|
||||
|
||||
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)
|
||||
|
||||
@ -162,6 +162,8 @@ class Conflict:
|
||||
|
||||
strength_delta = (from_cp.base.strength - to_cp.base.strength) / 1.0
|
||||
position = middle_point.point_from_heading(attack_heading, strength_delta * attack_distance / 2 - FRONTLINE_MIN_CP_DISTANCE)
|
||||
return position, _opposite_heading(attack_heading)
|
||||
|
||||
ground_position = cls._find_ground_position(position, attack_distance / 2 - FRONTLINE_MIN_CP_DISTANCE, attack_heading, theater)
|
||||
if ground_position:
|
||||
return ground_position, _opposite_heading(attack_heading)
|
||||
@ -172,6 +174,23 @@ class Conflict:
|
||||
|
||||
@classmethod
|
||||
def frontline_vector(cls, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater) -> typing.Optional[typing.Tuple[Point, int, int]]:
|
||||
initial, heading = cls.frontline_position(theater, from_cp, to_cp)
|
||||
|
||||
"""
|
||||
probe_end_point = initial.point_from_heading(heading, FRONTLINE_LENGTH)
|
||||
probe = geometry.LineString([(initial.x, initial.y), (probe_end_point.x, probe_end_point.y) ])
|
||||
intersection = probe.intersection(theater.land_poly)
|
||||
|
||||
if isinstance(intersection, geometry.LineString):
|
||||
intersection = intersection
|
||||
elif isinstance(intersection, geometry.MultiLineString):
|
||||
intersection = intersection.geoms[0]
|
||||
else:
|
||||
print(intersection)
|
||||
return None
|
||||
|
||||
return Point(*intersection.xy[0]), _heading_sum(heading, 90), intersection.length
|
||||
"""
|
||||
frontline = cls.frontline_position(theater, from_cp, to_cp)
|
||||
if not frontline:
|
||||
return None
|
||||
@ -207,9 +226,21 @@ class Conflict:
|
||||
pos = new_pos
|
||||
else:
|
||||
return pos
|
||||
|
||||
return pos
|
||||
|
||||
"""
|
||||
probe_end_point = initial.point_from_heading(heading, max_distance)
|
||||
probe = geometry.LineString([(initial.x, initial.y), (probe_end_point.x, probe_end_point.y)])
|
||||
|
||||
intersection = probe.intersection(theater.land_poly)
|
||||
if intersection is geometry.LineString:
|
||||
return Point(*intersection.xy[1])
|
||||
elif intersection is geometry.MultiLineString:
|
||||
return Point(*intersection.geoms[0].xy[1])
|
||||
|
||||
return None
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def _find_ground_position(cls, initial: Point, max_distance: int, heading: int, theater: ConflictTheater) -> typing.Optional[Point]:
|
||||
pos = initial
|
||||
@ -218,8 +249,18 @@ class Conflict:
|
||||
return pos
|
||||
|
||||
pos = pos.point_from_heading(heading, 500)
|
||||
"""
|
||||
probe_end_point = initial.point_from_heading(heading, max_distance)
|
||||
probe = geometry.LineString([(initial.x, initial.y), (probe_end_point.x, probe_end_point.y) ])
|
||||
|
||||
logging.error("Didn't find ground position!")
|
||||
intersection = probe.intersection(theater.land_poly)
|
||||
if isinstance(intersection, geometry.LineString):
|
||||
return Point(*intersection.xy[1])
|
||||
elif isinstance(intersection, geometry.MultiLineString):
|
||||
return Point(*intersection.geoms[0].xy[1])
|
||||
"""
|
||||
|
||||
logging.error("Didn't find ground position ({})!".format(initial))
|
||||
return initial
|
||||
|
||||
@classmethod
|
||||
@ -305,7 +346,7 @@ class Conflict:
|
||||
initial_location = to_cp.position.random_point_within(*GROUND_ATTACK_DISTANCE)
|
||||
position = Conflict._find_ground_position(initial_location, GROUND_INTERCEPT_SPREAD, _heading_sum(heading, 180), theater)
|
||||
if not position:
|
||||
heading = to_cp.find_radial(to_cp.positioN.heading_between_point(from_cp.position))
|
||||
heading = to_cp.find_radial(to_cp.position.heading_between_point(from_cp.position))
|
||||
position = to_cp.position.point_from_heading(heading, to_cp.size * GROUND_DISTANCE_FACTOR)
|
||||
|
||||
return cls(
|
||||
|
||||
40
pyinstaller.spec
Normal file
@ -0,0 +1,40 @@
|
||||
# -*- mode: python -*-
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['__init__.py'],
|
||||
pathex=['C:\\Users\\shdwp\\PycharmProjects\\dcs_liberation'],
|
||||
binaries=[],
|
||||
datas=[
|
||||
('resources', 'resources'),
|
||||
('submodules/dcs/dcs/terrain/caucasus.p', 'dcs/terrain/'),
|
||||
('submodules/dcs/dcs/terrain/nevada.p', 'dcs/terrain/'),
|
||||
],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False)
|
||||
pyz = PYZ(a.pure, a.zipped_data,
|
||||
cipher=block_cipher)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
icon="resources/icon.ico",
|
||||
exclude_binaries=True,
|
||||
name='liberation_main',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=True )
|
||||
coll = COLLECT(exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
name='dcs_liberation')
|
||||
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
@ -1,4 +1,5 @@
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from zipfile import *
|
||||
|
||||
@ -42,11 +43,13 @@ def _mk_archieve():
|
||||
print("version already exists")
|
||||
return
|
||||
|
||||
shutil.rmtree("./dist")
|
||||
|
||||
os.system("pyinstaller.exe pyinstaller.spec")
|
||||
|
||||
archieve = ZipFile(path, "w")
|
||||
archieve.writestr("start.bat", "py.exe __init__.py \"%UserProfile%\\Saved Games\" \"{}\"".format(VERSION))
|
||||
_zip_dir(archieve, ".")
|
||||
os.chdir("submodules\\dcs")
|
||||
_zip_dir(archieve, "dcs")
|
||||
archieve.writestr("dcs_liberation.bat", "cd dist\\dcs_liberation;\nliberation_main \"%UserProfile%\\Saved Games\" \"{}\"".format(VERSION))
|
||||
_zip_dir(archieve, "./dist/dcs_liberation")
|
||||
|
||||
|
||||
_mk_archieve()
|
||||
BIN
resources/ui/ground_assets/aa.png
Normal file
|
After Width: | Height: | Size: 229 B |
BIN
resources/ui/ground_assets/ammo.png
Normal file
|
After Width: | Height: | Size: 197 B |
BIN
resources/ui/ground_assets/cleared.png
Normal file
|
After Width: | Height: | Size: 315 B |
BIN
resources/ui/ground_assets/comms.png
Normal file
|
After Width: | Height: | Size: 196 B |
BIN
resources/ui/ground_assets/factory.png
Normal file
|
After Width: | Height: | Size: 220 B |
BIN
resources/ui/ground_assets/farp.png
Normal file
|
After Width: | Height: | Size: 253 B |
BIN
resources/ui/ground_assets/fob.png
Normal file
|
After Width: | Height: | Size: 213 B |
BIN
resources/ui/ground_assets/fuel.png
Normal file
|
After Width: | Height: | Size: 224 B |
BIN
resources/ui/ground_assets/oil.png
Normal file
|
After Width: | Height: | Size: 227 B |
BIN
resources/ui/ground_assets/power.png
Normal file
|
After Width: | Height: | Size: 235 B |
BIN
resources/ui/ground_assets/target.png
Normal file
|
After Width: | Height: | Size: 230 B |
BIN
resources/ui/ground_assets/warehouse.png
Normal file
|
After Width: | Height: | Size: 232 B |
@ -1 +1 @@
|
||||
Subproject commit fae126689132d643d317252adfb03184042a0ded
|
||||
Subproject commit 4fbb7ad3e0e2eecedc4e1dd14f2eb18025fef9f5
|
||||
@ -53,10 +53,18 @@ class ConflictTheater:
|
||||
reference_points = None # type: typing.Dict
|
||||
overview_image = None # type: str
|
||||
landmap = None # type: landmap.Landmap
|
||||
"""
|
||||
land_poly = None # type: Polygon
|
||||
"""
|
||||
daytime_map = None # type: typing.Dict[str, typing.Tuple[int, int]]
|
||||
|
||||
def __init__(self):
|
||||
self.controlpoints = []
|
||||
"""
|
||||
self.land_poly = geometry.Polygon(self.landmap[0][0])
|
||||
for x in self.landmap[1]:
|
||||
self.land_poly = self.land_poly.difference(geometry.Polygon(x))
|
||||
"""
|
||||
|
||||
def add_controlpoint(self, point: ControlPoint, connected_to: typing.Collection[ControlPoint] = []):
|
||||
for connected_point in connected_to:
|
||||
|
||||
@ -19,7 +19,6 @@ class NevadaTheater(ConflictTheater):
|
||||
"night": (0, 5),
|
||||
}
|
||||
|
||||
mina = ControlPoint.from_airport(nevada.Mina_Airport_3Q0, LAND, SIZE_SMALL, IMPORTANCE_LOW)
|
||||
tonopah = ControlPoint.from_airport(nevada.Tonopah_Airport, LAND, SIZE_SMALL, IMPORTANCE_LOW)
|
||||
tonopah_test_range = ControlPoint.from_airport(nevada.Tonopah_Test_Range_Airfield, LAND, SIZE_SMALL, IMPORTANCE_LOW)
|
||||
lincoln_conty = ControlPoint.from_airport(nevada.Lincoln_County, LAND, SIZE_SMALL, 1.2)
|
||||
@ -37,8 +36,7 @@ class NevadaTheater(ConflictTheater):
|
||||
def __init__(self):
|
||||
super(NevadaTheater, self).__init__()
|
||||
|
||||
self.add_controlpoint(self.mina, connected_to=[self.tonopah])
|
||||
self.add_controlpoint(self.tonopah, connected_to=[self.mina, self.tonopah_test_range, self.lincoln_conty])
|
||||
self.add_controlpoint(self.tonopah, connected_to=[self.tonopah_test_range, self.lincoln_conty])
|
||||
self.add_controlpoint(self.tonopah_test_range, connected_to=[self.tonopah, self.lincoln_conty, self.groom_lake, self.pahute_mesa])
|
||||
self.add_controlpoint(self.lincoln_conty, connected_to=[self.tonopah_test_range, self.mesquite])
|
||||
|
||||
@ -52,5 +50,5 @@ class NevadaTheater(ConflictTheater):
|
||||
self.add_controlpoint(self.jean, connected_to=[self.laughlin, self.las_vegas])
|
||||
self.add_controlpoint(self.laughlin, connected_to=[self.jean, self.las_vegas])
|
||||
|
||||
self.mina.captured = True
|
||||
self.tonopah.captured = True
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ BLACK = (0, 0, 0)
|
||||
BACKGROUND = pygame.Color(0, 64, 64)
|
||||
ANTIALIASING = True
|
||||
|
||||
WIDTH = 1066
|
||||
WIDTH = 800
|
||||
HEIGHT = 600
|
||||
MAP_PADDING = 100
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ class Window:
|
||||
def __init__(self):
|
||||
self.tk = Tk()
|
||||
self.tk.title("DCS Liberation")
|
||||
self.tk.iconbitmap("icon.ico")
|
||||
self.tk.iconbitmap("resources/icon.ico")
|
||||
self.tk.resizable(False, False)
|
||||
self.tk.grid_columnconfigure(0, weight=1)
|
||||
self.tk.grid_rowconfigure(0, weight=1)
|
||||
@ -44,7 +44,7 @@ class Window:
|
||||
helpmenu.add_separator()
|
||||
helpmenu.add_command(label="Contribute", command=lambda: webbrowser.open_new_tab("https://github.com/shdwp/dcs_liberation"))
|
||||
helpmenu.add_command(label="Forum Thread", command=lambda: webbrowser.open_new_tab("https://forums.eagle.ru/showthread.php?t=214834"))
|
||||
helpmenu.add_command(label="Report an issue", command=lambda: webbrowser.open_new_tab("https://github.com/shdwp/dcs_liberation/issues"))
|
||||
helpmenu.add_command(label="Report an issue", command=self.report_issue)
|
||||
menubar.add_cascade(label="Help", menu=helpmenu)
|
||||
|
||||
self.tk.config(menu=menubar)
|
||||
@ -133,6 +133,9 @@ class Window:
|
||||
else:
|
||||
pass
|
||||
|
||||
def report_issue(self):
|
||||
raise logging_module.ShowLogsException()
|
||||
|
||||
def exit(self):
|
||||
self.tk.destroy()
|
||||
sys.exit(0)
|
||||
|
||||