mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
commit
2179e4af47
@ -65,6 +65,7 @@ try:
|
||||
else:
|
||||
proceed_to_main_menu(game)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
ui.corruptedsavemenu.CorruptedSaveMenu(w).display()
|
||||
|
||||
w.run()
|
||||
|
||||
BIN
resources/ui/terrain_caucasus.png
Normal file
BIN
resources/ui/terrain_caucasus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
BIN
resources/ui/terrain_nevada.png
Normal file
BIN
resources/ui/terrain_nevada.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
BIN
resources/ui/terrain_pg.png
Normal file
BIN
resources/ui/terrain_pg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
@ -1,6 +1,7 @@
|
||||
from ui.eventmenu import *
|
||||
|
||||
from game.game import *
|
||||
from .styles import STYLES
|
||||
|
||||
|
||||
class BaseMenu(Menu):
|
||||
@ -9,7 +10,6 @@ class BaseMenu(Menu):
|
||||
|
||||
def __init__(self, window: Window, parent, game: Game, cp: ControlPoint):
|
||||
super(BaseMenu, self).__init__(window, parent, game)
|
||||
|
||||
self.cp = cp
|
||||
self.base = cp.base
|
||||
self.frame = window.right_pane
|
||||
@ -26,15 +26,15 @@ class BaseMenu(Menu):
|
||||
existing_units = self.base.total_units_of_type(unit_type)
|
||||
scheduled_units = self.event.units.get(unit_type, 0)
|
||||
|
||||
Label(self.frame, text="{}".format(db.unit_type_name(unit_type))).grid(row=row, sticky=W)
|
||||
Label(self.frame, text="{}".format(db.unit_type_name(unit_type)), **STYLES["widget"]).grid(row=row, sticky=W)
|
||||
|
||||
label = Label(self.frame, text="({})".format(existing_units))
|
||||
label = Label(self.frame, text="({})".format(existing_units), **STYLES["widget"])
|
||||
label.grid(column=1, row=row)
|
||||
self.bought_amount_labels[unit_type] = label
|
||||
|
||||
Label(self.frame, text="{}m".format(unit_price)).grid(column=2, row=row)
|
||||
Button(self.frame, text="+", command=self.buy(unit_type)).grid(column=3, row=row)
|
||||
Button(self.frame, text="-", command=self.sell(unit_type)).grid(column=4, row=row)
|
||||
Label(self.frame, text="{}m".format(unit_price), **STYLES["widget"]).grid(column=2, row=row, sticky=E)
|
||||
Button(self.frame, text="+", command=self.buy(unit_type), **STYLES["btn-primary"]).grid(column=3, row=row, padx=(10,0))
|
||||
Button(self.frame, text="-", command=self.sell(unit_type), **STYLES["btn-warning"]).grid(column=4, row=row, padx=(10,5))
|
||||
row += 1
|
||||
|
||||
units = {
|
||||
@ -45,13 +45,21 @@ class BaseMenu(Menu):
|
||||
AirDefence: db.find_unittype(AirDefence, self.game.player),
|
||||
}
|
||||
|
||||
self.budget_label = Label(self.frame, text="Budget: {}m".format(self.game.budget))
|
||||
# Header
|
||||
head = Frame(self.frame, **STYLES["header"])
|
||||
head.grid(row=row, column=0, columnspan=5, sticky=NSEW, pady=5)
|
||||
Label(head, text=self.cp.name, **STYLES["title"]).grid(row=0, column=0, sticky=NW+S)
|
||||
units_title = "{}/{}/{}".format(self.cp.base.total_planes, self.cp.base.total_armor, self.cp.base.total_aa)
|
||||
Label(head, text=units_title, **STYLES["strong-grey"]).grid(row=0, column=1, sticky=NE+S)
|
||||
row += 1
|
||||
|
||||
self.budget_label = Label(self.frame, text="Budget: {}m".format(self.game.budget), **STYLES["widget"])
|
||||
self.budget_label.grid(row=row, sticky=W)
|
||||
Button(self.frame, text="Back", command=self.dismiss).grid(column=4, row=row)
|
||||
Button(self.frame, text="Back", command=self.dismiss, **STYLES["btn-primary"]).grid(column=4, row=row, padx=(0,15), pady=(0,5))
|
||||
row += 1
|
||||
|
||||
for task_type, units in units.items():
|
||||
Label(self.frame, text="{}".format(db.task_name(task_type))).grid(row=row, columnspan=5); row += 1
|
||||
Label(self.frame, text="{}".format(db.task_name(task_type)), **STYLES["strong"]).grid(row=row, columnspan=5, sticky=NSEW); row += 1
|
||||
|
||||
units = list(set(units))
|
||||
units.sort(key=lambda x: db.PRICES[x])
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
from tkinter import *
|
||||
from tkinter.ttk import *
|
||||
from .styles import STYLES
|
||||
|
||||
from ui.window import *
|
||||
|
||||
@ -34,22 +35,36 @@ class ConfigurationMenu(Menu):
|
||||
def display(self):
|
||||
self.window.clear_right_pane()
|
||||
|
||||
Label(self.frame, text="Player coalition skill").grid(row=0, column=0)
|
||||
Label(self.frame, text="Enemy coalition skill").grid(row=1, column=0)
|
||||
# Header
|
||||
head = Frame(self.frame, **STYLES["header"])
|
||||
head.grid(row=0, column=0, columnspan=2, sticky=NSEW)
|
||||
Label(head, text="Configuration", **STYLES["title"]).grid()
|
||||
|
||||
OptionMenu(self.frame, self.player_skill_var, "Average", "Good", "High", "Excellent").grid(row=0, column=1)
|
||||
OptionMenu(self.frame, self.enemy_skill_var, "Average", "Good", "High", "Excellent").grid(row=1, column=1)
|
||||
# Body
|
||||
body = Frame(self.frame, **STYLES["body"])
|
||||
body.grid(row=1, column=0, sticky=NSEW)
|
||||
|
||||
Label(self.frame, text="Aircraft cold start").grid(row=2, column=0)
|
||||
Label(self.frame, text="Takeoff only for player group").grid(row=3, column=0)
|
||||
Label(self.frame, text="Disable night missions").grid(row=4, column=0)
|
||||
Label(body, text="Player coalition skill", **STYLES["widget"]).grid(row=0, column=0, sticky=W)
|
||||
Label(body, text="Enemy coalition skill", **STYLES["widget"]).grid(row=1, column=0, sticky=W)
|
||||
|
||||
Checkbutton(self.frame, variable=self.cold_start_var).grid(row=2, column=1)
|
||||
Checkbutton(self.frame, variable=self.takeoff_var).grid(row=3, column=1)
|
||||
Checkbutton(self.frame, variable=self.night_var).grid(row=4, column=1)
|
||||
p_skill = OptionMenu(body, self.player_skill_var, "Average", "Good", "High", "Excellent")
|
||||
p_skill.grid(row=0, column=1, sticky=E, pady=5)
|
||||
p_skill.configure(**STYLES["btn-primary"])
|
||||
|
||||
Button(self.frame, text="Back", command=self.dismiss).grid(row=5, column=0, columnspan=1)
|
||||
Button(self.frame, text="Cheat +200m", command=self.cheat_money).grid(row=6, column=1)
|
||||
e_skill = OptionMenu(body, self.enemy_skill_var, "Average", "Good", "High", "Excellent")
|
||||
e_skill.grid(row=1, column=1, sticky=E)
|
||||
e_skill.configure(**STYLES["btn-primary"])
|
||||
|
||||
Label(body, text="Aircraft cold start", **STYLES["widget"]).grid(row=2, column=0, sticky=W)
|
||||
Label(body, text="Takeoff only for player group", **STYLES["widget"]).grid(row=3, column=0, sticky=W)
|
||||
Label(body, text="Disable night missions", **STYLES["widget"]).grid(row=4, column=0, sticky=W)
|
||||
|
||||
Checkbutton(body, variable=self.cold_start_var, **STYLES["radiobutton"]).grid(row=2, column=1, sticky=E)
|
||||
Checkbutton(body, variable=self.takeoff_var, **STYLES["radiobutton"]).grid(row=3, column=1, sticky=E)
|
||||
Checkbutton(body, variable=self.night_var, **STYLES["radiobutton"]).grid(row=4, column=1, sticky=E)
|
||||
|
||||
Button(body, text="Back", command=self.dismiss, **STYLES["btn-primary"]).grid(row=5, column=1, sticky=E, pady=30)
|
||||
Button(body, text="Cheat +200m", command=self.cheat_money, **STYLES["btn-danger"]).grid(row=6, column=1)
|
||||
|
||||
def cheat_money(self):
|
||||
self.game.budget += 200
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
from tkinter import *
|
||||
from tkinter.ttk import *
|
||||
from .styles import STYLES
|
||||
|
||||
from ui.window import *
|
||||
|
||||
@ -12,6 +13,6 @@ class CorruptedSaveMenu(Menu):
|
||||
def display(self):
|
||||
self.window.clear_right_pane()
|
||||
|
||||
Label(text="Your save game was corrupted!").grid(row=0, column=0)
|
||||
Label(text="Please restore it by replacing \"liberation_save\" file with \"liberation_save_tmp\" to restore last saved copy.").grid(row=1, column=0)
|
||||
Label(text="You can find those files under user DCS directory.").grid(row=2, column=0)
|
||||
Label(text="Your save game was corrupted!", **STYLES["widget"]).grid(row=0, column=0)
|
||||
Label(text="Please restore it by replacing \"liberation_save\" file with \"liberation_save_tmp\" to restore last saved copy.", **STYLES["widget"]).grid(row=1, column=0)
|
||||
Label(text="You can find those files under user DCS directory.", **STYLES["widget"]).grid(row=2, column=0)
|
||||
|
||||
@ -4,6 +4,7 @@ from ui.eventresultsmenu import *
|
||||
|
||||
from game import *
|
||||
from game.event import *
|
||||
from .styles import STYLES
|
||||
|
||||
|
||||
UNITTYPES_FOR_EVENTS = {
|
||||
@ -44,39 +45,46 @@ class EventMenu(Menu):
|
||||
self.window.clear_right_pane()
|
||||
row = 0
|
||||
|
||||
def header(text, style="strong"):
|
||||
nonlocal row
|
||||
head = Frame(self.frame, **STYLES["header"])
|
||||
head.grid(row=row, column=0, sticky=N+EW, columnspan=5)
|
||||
Label(head, text=text, **STYLES[style]).grid()
|
||||
row += 1
|
||||
|
||||
def label(text, _row=None, _column=None, sticky=None):
|
||||
nonlocal row
|
||||
Label(self.frame, text=text).grid(row=_row and _row or row, column=_column and _column or 0, sticky=sticky)
|
||||
Label(self.frame, text=text, **STYLES["widget"]).grid(row=_row and _row or row, column=_column and _column or 0, sticky=sticky)
|
||||
|
||||
if _row is None:
|
||||
row += 1
|
||||
|
||||
def scrable_row(unit_type, unit_count):
|
||||
nonlocal row
|
||||
Label(self.frame, text="{} ({})".format(db.unit_type_name(unit_type), unit_count)).grid(row=row, sticky=W)
|
||||
Label(self.frame, text="{} ({})".format(db.unit_type_name(unit_type), unit_count), **STYLES["widget"]).grid(row=row, sticky=W)
|
||||
|
||||
scramble_entry = Entry(self.frame, width=2)
|
||||
scramble_entry.grid(column=1, row=row, sticky=W)
|
||||
scramble_entry.grid(column=1, row=row, sticky=E, padx=5)
|
||||
scramble_entry.insert(0, "0")
|
||||
self.aircraft_scramble_entries[unit_type] = scramble_entry
|
||||
Button(self.frame, text="+", command=self.scramble_half(True, unit_type)).grid(column=2, row=row)
|
||||
Button(self.frame, text="+", command=self.scramble_half(True, unit_type), **STYLES["btn-primary"]).grid(column=2, row=row)
|
||||
|
||||
client_entry = Entry(self.frame, width=2)
|
||||
client_entry.grid(column=3, row=row, sticky=E)
|
||||
client_entry.grid(column=3, row=row, sticky=E, padx=5)
|
||||
client_entry.insert(0, "0")
|
||||
self.aircraft_client_entries[unit_type] = client_entry
|
||||
Button(self.frame, text="+", command=self.client_one(unit_type)).grid(column=4, row=row)
|
||||
Button(self.frame, text="+", command=self.client_one(unit_type), **STYLES["btn-primary"]).grid(column=4, row=row)
|
||||
|
||||
row += 1
|
||||
|
||||
def scramble_armor_row(unit_type, unit_count):
|
||||
nonlocal row
|
||||
Label(self.frame, text="{} ({})".format(db.unit_type_name(unit_type), unit_count)).grid(row=row, sticky=W)
|
||||
Label(self.frame, text="{} ({})".format(db.unit_type_name(unit_type), unit_count), **STYLES["widget"]).grid(row=row, sticky=W)
|
||||
scramble_entry = Entry(self.frame, width=2)
|
||||
scramble_entry.insert(0, "0")
|
||||
scramble_entry.grid(column=1, row=row)
|
||||
scramble_entry.grid(column=1, row=row, sticky=E, padx=5)
|
||||
self.armor_scramble_entries[unit_type] = scramble_entry
|
||||
Button(self.frame, text="+", command=self.scramble_half(False, unit_type)).grid(column=2, row=row)
|
||||
Button(self.frame, text="+", command=self.scramble_half(False, unit_type),**STYLES["btn-primary"]).grid(column=2, row=row)
|
||||
|
||||
row += 1
|
||||
|
||||
@ -84,21 +92,18 @@ class EventMenu(Menu):
|
||||
if threat_descr:
|
||||
threat_descr = "Approx. {}".format(threat_descr)
|
||||
|
||||
Label(self.frame, text="{}. {}".format(self.event, threat_descr)).grid(row=row, column=0, columnspan=5)
|
||||
# Header
|
||||
header("Mission Menu", "title")
|
||||
|
||||
# Mission Description
|
||||
Label(self.frame, text="{}. {}".format(self.event, threat_descr), **STYLES["mission-preview"]).grid(row=row, column=0, columnspan=5, sticky=S+EW, padx=5, pady=5)
|
||||
row += 1
|
||||
|
||||
Button(self.frame, text="Commit", command=self.start).grid(column=3, row=row, sticky=E)
|
||||
Button(self.frame, text="Back", command=self.dismiss).grid(column=4, row=row, sticky=E)
|
||||
|
||||
awacs_enabled = self.game.budget >= AWACS_BUDGET_COST and NORMAL or DISABLED
|
||||
Checkbutton(self.frame, text="AWACS ({}m)".format(AWACS_BUDGET_COST), var=self.awacs, state=awacs_enabled).grid(row=row, column=0, sticky=W)
|
||||
row += 1
|
||||
|
||||
label("Aircraft")
|
||||
header("Aircraft :")
|
||||
|
||||
if self.base.aircraft:
|
||||
Label(self.frame, text="Amount").grid(row=row, column=1, columnspan=2)
|
||||
Label(self.frame, text="Client slots").grid(row=row, column=3, columnspan=2)
|
||||
Label(self.frame, text="Amount", **STYLES["widget"]).grid(row=row, column=1, columnspan=2)
|
||||
Label(self.frame, text="Client slots", **STYLES["widget"]).grid(row=row, column=3, columnspan=2)
|
||||
row += 1
|
||||
|
||||
filter_to = UNITTYPES_FOR_EVENTS[self.event.__class__]
|
||||
@ -114,16 +119,29 @@ class EventMenu(Menu):
|
||||
if not self.base.total_planes:
|
||||
label("None", sticky=W)
|
||||
|
||||
label("Armor")
|
||||
header("Armor :")
|
||||
armor_counter = 0
|
||||
for unit_type, count in self.base.armor.items():
|
||||
if filter_to and db.unit_task(unit_type) not in filter_to:
|
||||
continue
|
||||
|
||||
scramble_armor_row(unit_type, count)
|
||||
armor_counter += 1
|
||||
|
||||
if not self.base.total_armor:
|
||||
if not self.base.total_armor or armor_counter == 0:
|
||||
label("None", sticky=W)
|
||||
|
||||
header("Support :")
|
||||
# Options
|
||||
awacs_enabled = self.game.budget >= AWACS_BUDGET_COST and NORMAL or DISABLED
|
||||
Checkbutton(self.frame, var=self.awacs, state=awacs_enabled, **STYLES["radiobutton"]).grid(row=row, column=0, sticky=E)
|
||||
Label(self.frame, text="AWACS ({}m)".format(AWACS_BUDGET_COST), **STYLES["widget"]).grid(row=row, column=3, sticky=W, padx=5, pady=5)
|
||||
row += 1
|
||||
|
||||
header("Ready ?")
|
||||
Button(self.frame, text="Commit", command=self.start, **STYLES["btn-primary"]).grid(column=0, row=row, sticky=E, padx=5, pady=(10,10))
|
||||
Button(self.frame, text="Back", command=self.dismiss, **STYLES["btn-warning"]).grid(column=3, row=row, sticky=E, padx=5, pady=(10,10))
|
||||
row += 1
|
||||
|
||||
def _scrambled_aircraft_count(self, unit_type: UnitType) -> int:
|
||||
value = self.aircraft_scramble_entries[unit_type].get()
|
||||
if value and int(value) > 0:
|
||||
|
||||
@ -3,6 +3,7 @@ from ui.window import *
|
||||
|
||||
from game.game import *
|
||||
from userdata.debriefing import *
|
||||
from .styles import STYLES
|
||||
|
||||
|
||||
class EventResultsMenu(Menu):
|
||||
@ -13,6 +14,7 @@ class EventResultsMenu(Menu):
|
||||
def __init__(self, window: Window, parent, game: Game, event: Event):
|
||||
super(EventResultsMenu, self).__init__(window, parent, game)
|
||||
self.frame = window.right_pane
|
||||
self.frame.grid_rowconfigure(0, weight=0)
|
||||
self.event = event
|
||||
self.finished = False
|
||||
|
||||
@ -21,46 +23,82 @@ class EventResultsMenu(Menu):
|
||||
def display(self):
|
||||
self.window.clear_right_pane()
|
||||
|
||||
row = 0
|
||||
|
||||
def header(text, style="strong"):
|
||||
nonlocal row
|
||||
head = Frame(self.frame, **STYLES["header"])
|
||||
head.grid(row=row, column=0, sticky=N + EW, columnspan=2, pady=(0, 10))
|
||||
Label(head, text=text, **STYLES[style]).grid()
|
||||
row += 1
|
||||
|
||||
def label(text, style="widget"):
|
||||
nonlocal row
|
||||
Label(self.frame, text=text, **STYLES[style]).grid(row=row, column=0, sticky=NW, columnspan=2)
|
||||
row += 1
|
||||
|
||||
if not self.finished:
|
||||
Label(self.frame, text="Play the mission and save debriefing to").grid(row=0, column=0)
|
||||
Label(self.frame, text=debriefing_directory_location()).grid(row=1, column=0)
|
||||
|
||||
"""
|
||||
For debugging purposes
|
||||
"""
|
||||
header("You are clear for takeoff !")
|
||||
|
||||
label("In DCS, open and play the mission :")
|
||||
label("liberation_nextturn", "italic")
|
||||
label("or")
|
||||
label("liberation_nextturn_quick", "italic")
|
||||
header("Then save the debriefing to the folder:")
|
||||
label(debriefing_directory_location(), "italic")
|
||||
header("Waiting for results...")
|
||||
|
||||
pg = Progressbar(self.frame, orient="horizontal", length=200, mode="determinate")
|
||||
pg.grid(row=row, column=0, columnspan=2, sticky=EW, pady=5, padx=5)
|
||||
pg.start(10)
|
||||
row += 1
|
||||
|
||||
Separator(self.frame, orient=HORIZONTAL).grid(row=row, sticky=EW);
|
||||
row += 1
|
||||
|
||||
Label(self.frame, text="Cheat operation results: ", **STYLES["strong"]).grid(column=0, row=row,
|
||||
columnspan=2, sticky=NSEW,
|
||||
pady=5);
|
||||
|
||||
row += 1
|
||||
Button(self.frame, text="full enemy losses", command=self.simulate_result(0, 1),
|
||||
**STYLES["btn-warning"]).grid(column=0, row=row, padx=5, pady=5)
|
||||
Button(self.frame, text="full player losses", command=self.simulate_result(1, 0),
|
||||
**STYLES["btn-warning"]).grid(column=1, row=row, padx=5, pady=5)
|
||||
row += 1
|
||||
Button(self.frame, text="some enemy losses", command=self.simulate_result(0, 0.8),
|
||||
**STYLES["btn-warning"]).grid(column=0, row=row, padx=5, pady=5)
|
||||
Button(self.frame, text="some player losses", command=self.simulate_result(0.8, 0),
|
||||
**STYLES["btn-warning"]).grid(column=1, row=row, padx=5, pady=5)
|
||||
row += 1
|
||||
|
||||
row = 3
|
||||
Separator(self.frame, orient=HORIZONTAL).grid(row=row, sticky=EW); row += 1
|
||||
Label(self.frame, text="Cheat operation results: ").grid(row=row); row += 1
|
||||
Button(self.frame, text="full enemy losses", command=self.simulate_result(0, 1)).grid(row=row); row += 1
|
||||
Button(self.frame, text="full player losses", command=self.simulate_result(1, 0)).grid(row=row); row += 1
|
||||
Button(self.frame, text="some enemy losses", command=self.simulate_result(0, 0.8)).grid(row=row); row += 1
|
||||
Button(self.frame, text="some player losses", command=self.simulate_result(0.8, 0)).grid(row=row); row += 1
|
||||
else:
|
||||
row = 0
|
||||
if self.event.is_successfull(self.debriefing):
|
||||
Label(self.frame, text="Operation success").grid(row=row, columnspan=1); row += 1
|
||||
header("Operation success", "title-green")
|
||||
else:
|
||||
Label(self.frame, text="Operation failed").grid(row=row, columnspan=1); row += 1
|
||||
header("Operation failed", "title-red")
|
||||
|
||||
header("Player losses")
|
||||
|
||||
Separator(self.frame, orient='horizontal').grid(row=row, columnspan=1, sticky=NE); row += 1
|
||||
Label(self.frame, text="Player losses").grid(row=row, columnspan=1); row += 1
|
||||
for unit_type, count in self.player_losses.items():
|
||||
Label(self.frame, text=db.unit_type_name(unit_type)).grid(row=row)
|
||||
Label(self.frame, text="{}".format(count)).grid(column=1, row=row)
|
||||
Label(self.frame, text=db.unit_type_name(unit_type), **STYLES["widget"]).grid(row=row)
|
||||
Label(self.frame, text="{}".format(count), **STYLES["widget"]).grid(column=1, row=row)
|
||||
row += 1
|
||||
|
||||
Separator(self.frame, orient='horizontal').grid(row=row, columnspan=1, sticky=NE); row += 1
|
||||
Label(self.frame, text="Enemy losses").grid(columnspan=1, row=row); row += 1
|
||||
header("Enemy losses")
|
||||
|
||||
for unit_type, count in self.enemy_losses.items():
|
||||
if count == 0:
|
||||
continue
|
||||
|
||||
Label(self.frame, text=db.unit_type_name(unit_type)).grid(row=row)
|
||||
Label(self.frame, text="{}".format(count)).grid(column=1, row=row)
|
||||
Label(self.frame, text=db.unit_type_name(unit_type), **STYLES["widget"]).grid(row=row)
|
||||
Label(self.frame, text="{}".format(count), **STYLES["widget"]).grid(column=1, row=row)
|
||||
row += 1
|
||||
|
||||
Button(self.frame, text="Okay", command=self.dismiss).grid(columnspan=1, row=row); row += 1
|
||||
Button(self.frame, text="Okay", command=self.dismiss, **STYLES["btn-primary"]).grid(columnspan=1, row=row);
|
||||
row += 1
|
||||
|
||||
def process_debriefing(self, debriefing: Debriefing):
|
||||
self.debriefing = debriefing
|
||||
@ -106,8 +144,10 @@ class EventResultsMenu(Menu):
|
||||
alive_player_units = count(player)
|
||||
alive_enemy_units = count(enemy)
|
||||
|
||||
destroyed_player_units = db.unitdict_restrict_count(alive_player_units, math.ceil(sum(alive_player_units.values()) * player_factor))
|
||||
destroyed_enemy_units = db.unitdict_restrict_count(alive_enemy_units, math.ceil(sum(alive_enemy_units.values()) * enemy_factor))
|
||||
destroyed_player_units = db.unitdict_restrict_count(alive_player_units, math.ceil(
|
||||
sum(alive_player_units.values()) * player_factor))
|
||||
destroyed_enemy_units = db.unitdict_restrict_count(alive_enemy_units, math.ceil(
|
||||
sum(alive_enemy_units.values()) * enemy_factor))
|
||||
|
||||
alive_player_units = {k: v - destroyed_player_units.get(k, 0) for k, v in alive_player_units.items()}
|
||||
alive_enemy_units = {k: v - destroyed_enemy_units.get(k, 0) for k, v in alive_enemy_units.items()}
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import pickle
|
||||
|
||||
from ui.basemenu import *
|
||||
from ui.overviewcanvas import *
|
||||
from ui.configurationmenu import *
|
||||
|
||||
from game.game import *
|
||||
from ui.basemenu import *
|
||||
from ui.configurationmenu import *
|
||||
from ui.overviewcanvas import *
|
||||
from userdata import persistency
|
||||
from .styles import STYLES
|
||||
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
|
||||
|
||||
class MainMenu(Menu):
|
||||
@ -18,45 +20,57 @@ class MainMenu(Menu):
|
||||
self.upd.update()
|
||||
|
||||
self.frame = self.window.right_pane
|
||||
self.frame.grid_columnconfigure(0, weight=1)
|
||||
self.frame.columnconfigure(0, weight=1)
|
||||
self.frame.rowconfigure(0, weight=1)
|
||||
|
||||
def display(self):
|
||||
persistency.save_game(self.game)
|
||||
|
||||
self.window.clear_right_pane()
|
||||
self.upd.update()
|
||||
row = 1
|
||||
row = 0
|
||||
|
||||
# Header :
|
||||
header = Frame(self.frame, **STYLES["header"])
|
||||
Button(header, text="Configuration", command=self.configuration_menu, **STYLES["btn-primary"]).grid(column=0, row=0, sticky=NE)
|
||||
Label(header, text="Budget: {}m (+{}m)".format(self.game.budget, self.game.budget_reward_amount), **STYLES["strong"]).grid(column=1, row=0, sticky=NSEW, padx=50)
|
||||
Button(header, text="Pass turn", command=self.pass_turn, **STYLES["btn-primary"]).grid(column=2, row=0, sticky=NW)
|
||||
header.grid(column=0, row=0, sticky=N+EW)
|
||||
|
||||
body = LabelFrame(self.frame, **STYLES["body"])
|
||||
body.grid(column=0, row=1, sticky=NSEW)
|
||||
|
||||
def label(text):
|
||||
nonlocal row
|
||||
Label(self.frame, text=text).grid(row=row, sticky=NW)
|
||||
nonlocal row, body
|
||||
frame = LabelFrame(body, **STYLES["label-frame"])
|
||||
frame.grid(row=row, sticky=NSEW, columnspan=2)
|
||||
Label(frame, text=text, **STYLES["widget"]).grid(row=row, sticky=NS)
|
||||
row += 1
|
||||
|
||||
def event_button(event):
|
||||
nonlocal row
|
||||
Message(self.frame, text="{}{} at {}".format(
|
||||
nonlocal row, body
|
||||
frame = LabelFrame(body, **STYLES["label-frame"])
|
||||
frame.grid(row=row, sticky=NSEW)
|
||||
Message(frame, text="{}{} at {}".format(
|
||||
event.defender_name == self.game.player and "Enemy attacking: " or "",
|
||||
event,
|
||||
event.to_cp,
|
||||
), aspect=1600).grid(column=0, row=row, sticky=NW)
|
||||
Button(self.frame, text=">", command=self.start_event(event)).grid(column=0, row=row, sticky=NE+S); row += 1
|
||||
), aspect=1600, **STYLES["widget"]).grid(column=0, row=0, sticky=NSEW)
|
||||
Button(body, text=">", command=self.start_event(event), **STYLES["btn-primary"]).grid(column=1, row=row, sticky=E)
|
||||
row += 1
|
||||
|
||||
def destination_header(text, separator=True):
|
||||
nonlocal row
|
||||
if separator:
|
||||
Separator(self.frame, orient=HORIZONTAL).grid(row=row, sticky=EW); row += 1
|
||||
Label(self.frame, text=text).grid(column=0, row=row, sticky=N); row += 1
|
||||
def destination_header(text, pady=0):
|
||||
nonlocal row, body
|
||||
Label(body, text=text, **STYLES["strong"]).grid(column=0, columnspan=2, row=row, sticky=N+EW, pady=(pady,0)); row += 1
|
||||
|
||||
Button(self.frame, text="Configuration", command=self.configuration_menu).grid(column=0, row=0, sticky=NE)
|
||||
Button(self.frame, text="Pass turn", command=self.pass_turn).grid(column=0, row=0, sticky=NW)
|
||||
Label(self.frame, text="Budget: {}m (+{}m)".format(self.game.budget, self.game.budget_reward_amount)).grid(column=0, row=0, sticky=N)
|
||||
Separator(self.frame, orient='horizontal').grid(row=row, sticky=EW); row += 1
|
||||
#Separator(self.frame, orient='horizontal').grid(row=row, sticky=EW); row += 1
|
||||
|
||||
events = self.game.events
|
||||
events.sort(key=lambda x: x.from_cp.name)
|
||||
events.sort(key=lambda x: x.informational and 2 or (self.game.is_player_attack(x) and 1 or 0))
|
||||
|
||||
destination = None
|
||||
deliveries = False
|
||||
for event in events:
|
||||
if not event.informational:
|
||||
if self.game.is_player_attack(event):
|
||||
@ -64,10 +78,13 @@ class MainMenu(Menu):
|
||||
else:
|
||||
new_destination = "Enemy attack"
|
||||
if destination != new_destination:
|
||||
destination_header(new_destination, destination is not None)
|
||||
destination_header(new_destination)
|
||||
destination = new_destination
|
||||
|
||||
if event.informational:
|
||||
if not deliveries:
|
||||
deliveries = True
|
||||
destination_header("Deliveries", 15)
|
||||
label(str(event))
|
||||
else:
|
||||
event_button(event)
|
||||
@ -92,3 +109,7 @@ class MainMenu(Menu):
|
||||
|
||||
self.basemenu = BaseMenu(self.window, self, self.game, cp)
|
||||
self.basemenu.display()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import os
|
||||
from tkinter import *
|
||||
from tkinter.ttk import *
|
||||
|
||||
from ui.window import *
|
||||
from .styles import STYLES
|
||||
|
||||
|
||||
class NewGameMenu(Menu):
|
||||
@ -14,6 +16,7 @@ class NewGameMenu(Menu):
|
||||
def __init__(self, window: Window, callback: typing.Callable):
|
||||
super(NewGameMenu, self).__init__(window, None, None)
|
||||
self.frame = window.right_pane
|
||||
window.left_pane.configure(background="black")
|
||||
self.callback = callback
|
||||
|
||||
self.selected_country = IntVar()
|
||||
@ -57,23 +60,69 @@ class NewGameMenu(Menu):
|
||||
def display(self):
|
||||
self.window.clear_right_pane()
|
||||
|
||||
Label(self.frame, text="Player country").grid(row=0, column=0)
|
||||
Radiobutton(self.frame, text="USA", variable=self.selected_country, value=0).grid(row=1, column=0)
|
||||
Radiobutton(self.frame, text="Russia", variable=self.selected_country, value=1).grid(row=2, column=0)
|
||||
# Header
|
||||
head = Frame(self.frame, **STYLES["header"])
|
||||
head.grid(row=0, column=0, sticky=NSEW)
|
||||
Label(head, text="Start a new game", **STYLES["title"]).grid()
|
||||
|
||||
Label(self.frame, text="Terrain").grid(row=0, column=1)
|
||||
Radiobutton(self.frame, text="Caucasus", variable=self.selected_terrain, value=0).grid(row=1, column=1)
|
||||
Radiobutton(self.frame, text="Nevada", variable=self.selected_terrain, value=1).grid(row=2, column=1)
|
||||
Radiobutton(self.frame, text="Persian Gulf", variable=self.selected_terrain, value=2).grid(row=3, column=1)
|
||||
# Body
|
||||
body = Frame(self.frame, **STYLES["body"])
|
||||
body.grid(row=1, column=0, sticky=NSEW)
|
||||
|
||||
Label(self.frame, text="Options").grid(row=1, column=2)
|
||||
Checkbutton(self.frame, text="SAMs", variable=self.sams).grid(row=1, column=2)
|
||||
Checkbutton(self.frame, text="Mid game", variable=self.midgame).grid(row=2, column=2)
|
||||
# Country Selection
|
||||
country = LabelFrame(body, text="Player Side", **STYLES["label-frame"])
|
||||
country.grid(row=0, column=0, sticky=NW, padx=5)
|
||||
Radiobutton(country, variable=self.selected_country, value=0, **STYLES["radiobutton"]).grid(row=0, column=0,
|
||||
sticky=W)
|
||||
Label(country, text="USA", **STYLES["widget"]).grid(row=0, column=1, sticky=W)
|
||||
Radiobutton(country, variable=self.selected_country, value=1, **STYLES["radiobutton"]).grid(row=1, column=0,
|
||||
sticky=W)
|
||||
Label(country, text="Russia", **STYLES["widget"]).grid(row=1, column=1, sticky=W)
|
||||
|
||||
Label(self.frame, text="Multiplier").grid(row=0, column=3)
|
||||
Entry(self.frame, textvariable=self.multiplier).grid(row=1, column=3)
|
||||
# Terrain Selection
|
||||
terrain = LabelFrame(body, text="Terrain", **STYLES["label-frame"])
|
||||
terrain.grid(row=0, column=1, sticky=N, padx=5)
|
||||
|
||||
Button(self.frame, text="Proceed", command=self.proceed).grid(row=5, column=0, columnspan=4)
|
||||
Radiobutton(terrain, variable=self.selected_terrain, value=0, **STYLES["radiobutton"]) \
|
||||
.grid(row=0, column=0, sticky=W)
|
||||
Label(terrain, text="Caucasus", **STYLES["widget"]).grid(row=0, column=1, sticky=W)
|
||||
self.create_label_image(terrain, "terrain_caucasus.png").grid(row=0, column=2, padx=5)
|
||||
|
||||
Radiobutton(terrain, variable=self.selected_terrain, value=1, **STYLES["radiobutton"]) \
|
||||
.grid(row=1, column=0, sticky=W)
|
||||
Label(terrain, text="Nevada", **STYLES["widget"]).grid(row=1, column=1, sticky=W)
|
||||
self.create_label_image(terrain, "terrain_nevada.png").grid(row=1, column=2, padx=5)
|
||||
|
||||
Radiobutton(terrain, variable=self.selected_terrain, value=2, **STYLES["radiobutton"]) \
|
||||
.grid(row=2, column=0, sticky=W)
|
||||
Label(terrain, text="Persian Gulf", **STYLES["widget"]).grid(row=2, column=1, sticky=W)
|
||||
self.create_label_image(terrain, "terrain_pg.png").grid(row=2, column=2, padx=5)
|
||||
|
||||
# Misc Options
|
||||
options = LabelFrame(body, text="Misc Options", **STYLES["label-frame"])
|
||||
options.grid(row=0, column=2, sticky=NE, padx=5)
|
||||
|
||||
Checkbutton(options, variable=self.sams, **STYLES["radiobutton"]).grid(row=0, column=0, sticky=W)
|
||||
Label(options, text="SAMs", **STYLES["widget"]).grid(row=0, column=1, sticky=W)
|
||||
|
||||
Checkbutton(options, variable=self.midgame, **STYLES["radiobutton"]).grid(row=1, column=0, sticky=W)
|
||||
Label(options, text="Mid Game", **STYLES["widget"]).grid(row=1, column=1, sticky=W)
|
||||
|
||||
Label(options, text="Multiplier", **STYLES["widget"]).grid(row=2, column=0, sticky=W)
|
||||
Entry(options, textvariable=self.multiplier).grid(row=2, column=1, sticky=W)
|
||||
|
||||
# Footer with Proceed Button
|
||||
footer = Frame(self.frame, **STYLES["header"])
|
||||
footer.grid(row=2, sticky=N + E + W)
|
||||
Button(footer, text="Proceed", command=self.proceed, **STYLES["btn-primary"]).grid(row=0, column=0, sticky=SE,
|
||||
padx=5, pady=5)
|
||||
|
||||
@staticmethod
|
||||
def create_label_image(parent, image):
|
||||
im = PhotoImage(file=os.path.join("resources", "ui", image))
|
||||
label = Label(parent, image=im)
|
||||
label.image = im
|
||||
return label
|
||||
|
||||
def proceed(self):
|
||||
self.callback(self.player_country_name,
|
||||
|
||||
@ -50,11 +50,12 @@ class OverviewCanvas:
|
||||
title = cp.name
|
||||
font = ("Helvetica", 10)
|
||||
|
||||
id = self.canvas.create_text(coords[0]+1, coords[1]+1, text=title, fill='white', font=font)
|
||||
self.canvas.tag_bind(id, "<Button-1>", self.display(cp))
|
||||
id = self.canvas.create_text(coords[0], coords[1], text=title, font=font)
|
||||
self.canvas.tag_bind(id, "<Button-1>", self.display(cp))
|
||||
|
||||
id = self.canvas.create_text(coords[0]+1, coords[1]+1, text=title, fill='white', font=font)
|
||||
self.canvas.tag_bind(id, "<Button-1>", self.display(cp))
|
||||
|
||||
def _player_color(self):
|
||||
return self.game.player == "USA" and "blue" or "red"
|
||||
|
||||
@ -116,7 +117,8 @@ class OverviewCanvas:
|
||||
self.create_cp_title((coords[0] + arc_size/4, coords[1] + arc_size/4), cp)
|
||||
|
||||
units_title = "{}/{}/{}".format(cp.base.total_planes, cp.base.total_armor, cp.base.total_aa)
|
||||
self.canvas.create_text(coords[0], coords[1] - arc_size / 1.5, text=units_title, font=("Helvetica", 10))
|
||||
self.canvas.create_text(coords[0]+1, coords[1] - arc_size / 1.5 +1, text=units_title, font=("Helvetica", 10), fill=color)
|
||||
self.canvas.create_text(coords[0], coords[1] - arc_size / 1.5, text=units_title, font=("Helvetica", 10), fill="white")
|
||||
|
||||
def display(self, cp: ControlPoint):
|
||||
def action(_):
|
||||
|
||||
45
ui/styles.py
Normal file
45
ui/styles.py
Normal file
@ -0,0 +1,45 @@
|
||||
# Style for UI
|
||||
|
||||
# Padding
|
||||
PADDING_X = 5
|
||||
PADDING_Y = 5
|
||||
|
||||
# Colors
|
||||
FG_COLOR = "white"
|
||||
FG_COLOR_LIGHT = "#dddddd"
|
||||
BG_COLOR = "#4E5760"
|
||||
GREEN = "#699245"
|
||||
YELLOW = "#BF9A46"
|
||||
RED = "#D0232E"
|
||||
BG_TITLE_COLOR = "#2D3E50"
|
||||
|
||||
# Fonts
|
||||
FONT_FAMILY = "Trebuchet MS"
|
||||
DEFAULT_FONT = (FONT_FAMILY, 8)
|
||||
ITALIC = (FONT_FAMILY, 8, "italic")
|
||||
BOLD_FONT = (FONT_FAMILY, 10, "bold italic")
|
||||
TITLE_FONT = (FONT_FAMILY, 16, "bold italic")
|
||||
|
||||
# List of styles
|
||||
STYLES = {}
|
||||
STYLES["label-frame"] = {"font": BOLD_FONT, "bg": BG_COLOR, "fg": FG_COLOR}
|
||||
STYLES["frame-wrapper"] = {"bg": BG_COLOR, "relief":"sunken"}
|
||||
|
||||
STYLES["body"] = {"bg": BG_COLOR, "padx": 25, "pady": 35}
|
||||
STYLES["strong"] = {"font": BOLD_FONT, "bg": BG_TITLE_COLOR, "fg": FG_COLOR}
|
||||
STYLES["strong-grey"] = {"font": BOLD_FONT, "bg": BG_TITLE_COLOR, "fg": FG_COLOR_LIGHT}
|
||||
|
||||
STYLES["mission-preview"] = {"font": BOLD_FONT, "bg": YELLOW, "fg": FG_COLOR}
|
||||
|
||||
STYLES["widget"] = {"bg": BG_COLOR, "fg": FG_COLOR, "padx": PADDING_X, "pady": PADDING_Y, "font": DEFAULT_FONT}
|
||||
STYLES["italic"] = {"bg": BG_COLOR, "fg": FG_COLOR, "padx": PADDING_X, "pady": PADDING_Y, "font": ITALIC}
|
||||
STYLES["radiobutton"] = {"bg": BG_COLOR, "fg": "black", "padx": PADDING_X, "pady": PADDING_Y, "font": DEFAULT_FONT,
|
||||
"activebackground": BG_COLOR, "highlightbackground": BG_COLOR, "selectcolor": "white"}
|
||||
STYLES["title"] = {"bg": BG_TITLE_COLOR, "fg": FG_COLOR, "padx": PADDING_X, "pady": PADDING_Y, "font": TITLE_FONT}
|
||||
STYLES["title-green"] = {"bg": GREEN, "fg": FG_COLOR, "padx": PADDING_X, "pady": PADDING_Y, "font": TITLE_FONT}
|
||||
STYLES["title-red"] = {"bg": RED, "fg": FG_COLOR, "padx": PADDING_X, "pady": PADDING_Y, "font": TITLE_FONT}
|
||||
STYLES["header"] = {"bg": BG_TITLE_COLOR}
|
||||
|
||||
STYLES["btn-primary"] = {"bg": GREEN, "fg": FG_COLOR, "padx": PADDING_X, "pady": 2, "font": DEFAULT_FONT}
|
||||
STYLES["btn-danger"] = {"bg": RED, "fg": FG_COLOR, "padx": PADDING_X, "pady": 2, "font": DEFAULT_FONT}
|
||||
STYLES["btn-warning"] = {"bg": YELLOW, "fg": FG_COLOR, "padx": PADDING_X, "pady": 2, "font": DEFAULT_FONT}
|
||||
15
ui/window.py
15
ui/window.py
@ -1,6 +1,6 @@
|
||||
from tkinter import *
|
||||
from game.game import *
|
||||
|
||||
from .styles import BG_COLOR,BG_TITLE_COLOR
|
||||
|
||||
class Window:
|
||||
image = None
|
||||
@ -9,21 +9,24 @@ class Window:
|
||||
|
||||
def __init__(self):
|
||||
self.tk = Tk()
|
||||
self.tk.title("DCS Liberation")
|
||||
self.tk.iconbitmap("icon.ico")
|
||||
self.tk.resizable(True, True)
|
||||
self.tk.grid_columnconfigure(0, weight=1)
|
||||
self.tk.grid_rowconfigure(0, weight=1)
|
||||
|
||||
self.frame = Frame(self.tk)
|
||||
self.frame = Frame(self.tk, bg=BG_COLOR)
|
||||
self.frame.grid(column=0, row=0, sticky=NSEW)
|
||||
self.frame.grid_columnconfigure(0, minsize=300)
|
||||
self.frame.grid_columnconfigure(1, minsize=400)
|
||||
self.frame.grid_columnconfigure(0)
|
||||
self.frame.grid_columnconfigure(1)
|
||||
|
||||
self.frame.grid_columnconfigure(0, weight=0)
|
||||
self.frame.grid_columnconfigure(1, weight=1)
|
||||
self.frame.grid_rowconfigure(0, weight=1)
|
||||
|
||||
self.left_pane = Frame(self.frame)
|
||||
self.left_pane = Frame(self.frame, bg=BG_TITLE_COLOR)
|
||||
self.left_pane.grid(row=0, column=0, sticky=NSEW)
|
||||
self.right_pane = Frame(self.frame)
|
||||
self.right_pane = Frame(self.frame, bg=BG_COLOR)
|
||||
self.right_pane.grid(row=0, column=1, sticky=NSEW)
|
||||
|
||||
self.tk.focus()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user