mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Ground objects have 'Objective' name for easier search. Predefined Waypoint generator entirely reworked.
Added finances menu, and info panel.
This commit is contained in:
parent
6dec5ea8f8
commit
fc64e57495
@ -739,6 +739,14 @@ TIME_PERIODS = {
|
|||||||
"Syrian War [2011]": datetime(2011, 8, 7),
|
"Syrian War [2011]": datetime(2011, 8, 7),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
REWARDS = {
|
||||||
|
"power": 4, "warehouse": 2, "fuel": 2, "ammo": 2,
|
||||||
|
"farp": 1, "fob": 1, "factory": 10, "comms": 10, "oil": 10
|
||||||
|
}
|
||||||
|
|
||||||
|
# Base post-turn bonus value
|
||||||
|
PLAYER_BUDGET_BASE = 20
|
||||||
|
|
||||||
CARRIER_CAPABLE = [
|
CARRIER_CAPABLE = [
|
||||||
FA_18C_hornet,
|
FA_18C_hornet,
|
||||||
F_14B,
|
F_14B,
|
||||||
|
|||||||
@ -8,6 +8,7 @@ from dcs.vehicles import AirDefence
|
|||||||
from dcs.unittype import UnitType
|
from dcs.unittype import UnitType
|
||||||
|
|
||||||
from game import *
|
from game import *
|
||||||
|
from game.infos.information import Information
|
||||||
from theater import *
|
from theater import *
|
||||||
from gen.environmentgen import EnvironmentSettings
|
from gen.environmentgen import EnvironmentSettings
|
||||||
from gen.conflictgen import Conflict
|
from gen.conflictgen import Conflict
|
||||||
@ -220,6 +221,10 @@ class Event:
|
|||||||
cp.base.aa = {}
|
cp.base.aa = {}
|
||||||
for g in cp.ground_objects:
|
for g in cp.ground_objects:
|
||||||
g.groups = []
|
g.groups = []
|
||||||
|
info = Information(cp.name + " lost !",
|
||||||
|
"The ennemy took control of " + cp.name + "\nShame on us !",
|
||||||
|
self.game.turn)
|
||||||
|
self.game.informations.append(info)
|
||||||
elif not(cp.captured) and new_owner_coalition == coalition:
|
elif not(cp.captured) and new_owner_coalition == coalition:
|
||||||
cp.captured = True
|
cp.captured = True
|
||||||
cp.base.aircraft = {}
|
cp.base.aircraft = {}
|
||||||
@ -227,6 +232,10 @@ class Event:
|
|||||||
cp.base.aa = {}
|
cp.base.aa = {}
|
||||||
for g in cp.ground_objects:
|
for g in cp.ground_objects:
|
||||||
g.groups = []
|
g.groups = []
|
||||||
|
info = Information(cp.name + " captured !",
|
||||||
|
"The ennemy took control of " + cp.name + "\nShame on us !",
|
||||||
|
self.game.turn)
|
||||||
|
self.game.informations.append(info)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
@ -281,17 +290,25 @@ class Event:
|
|||||||
|
|
||||||
# No progress with defensive strategies
|
# No progress with defensive strategies
|
||||||
if player_won and cp.stances[enemy_cp.id] in [CombatStance.DEFENSIVE, CombatStance.AMBUSH]:
|
if player_won and cp.stances[enemy_cp.id] in [CombatStance.DEFENSIVE, CombatStance.AMBUSH]:
|
||||||
print("Defensive stance, no progress")
|
print("Defensive stance, progress is limited")
|
||||||
delta = 0
|
delta = MINOR_DEFEAT_INFLUENCE
|
||||||
|
|
||||||
if player_won:
|
if player_won:
|
||||||
print(cp.name + " won ! factor > " + str(delta))
|
print(cp.name + " won ! factor > " + str(delta))
|
||||||
cp.base.affect_strength(delta)
|
cp.base.affect_strength(delta)
|
||||||
enemy_cp.base.affect_strength(-delta)
|
enemy_cp.base.affect_strength(-delta)
|
||||||
|
info = Information("Frontline Report",
|
||||||
|
"Our ground forces from " + cp.name + " are making progress toward " + enemy_cp.name,
|
||||||
|
self.game.turn)
|
||||||
|
self.game.informations.append(info)
|
||||||
else:
|
else:
|
||||||
print(enemy_cp.name + " won ! factor > " + str(delta))
|
print(cp.name + " lost ! factor > " + str(delta))
|
||||||
enemy_cp.base.affect_strength(delta)
|
enemy_cp.base.affect_strength(delta)
|
||||||
cp.base.affect_strength(-delta)
|
cp.base.affect_strength(-delta)
|
||||||
|
info = Information("Frontline Report",
|
||||||
|
"Our ground forces from " + cp.name + " are losing ground against the enemy forces from" + enemy_cp.name,
|
||||||
|
self.game.turn)
|
||||||
|
self.game.informations.append(info)
|
||||||
|
|
||||||
def skip(self):
|
def skip(self):
|
||||||
pass
|
pass
|
||||||
@ -319,4 +336,9 @@ class UnitsDeliveryEvent(Event):
|
|||||||
self.units[k] = self.units.get(k, 0) + v
|
self.units[k] = self.units.get(k, 0) + v
|
||||||
|
|
||||||
def skip(self):
|
def skip(self):
|
||||||
|
|
||||||
|
for k, v in self.units.items():
|
||||||
|
info = Information("Ally Reinforcement", str(k.id) + " x " + str(v) + " at " + self.to_cp.name, self.game.turn)
|
||||||
|
self.game.informations.append(info)
|
||||||
|
|
||||||
self.to_cp.base.commision_units(self.units)
|
self.to_cp.base.commision_units(self.units)
|
||||||
|
|||||||
@ -4,7 +4,7 @@ from dcs.planes import *
|
|||||||
from dcs.helicopters import *
|
from dcs.helicopters import *
|
||||||
|
|
||||||
Lybia_2011 = {
|
Lybia_2011 = {
|
||||||
"country": "Libya",
|
"country": "Russia",
|
||||||
"side": "red",
|
"side": "red",
|
||||||
"units": [
|
"units": [
|
||||||
|
|
||||||
|
|||||||
79
game/game.py
79
game/game.py
@ -6,6 +6,7 @@ import math
|
|||||||
from dcs.task import *
|
from dcs.task import *
|
||||||
from dcs.vehicles import *
|
from dcs.vehicles import *
|
||||||
|
|
||||||
|
from game.db import REWARDS, PLAYER_BUDGET_BASE
|
||||||
from game.game_stats import GameStats
|
from game.game_stats import GameStats
|
||||||
from game.infos.information import Information
|
from game.infos.information import Information
|
||||||
from gen.conflictgen import Conflict
|
from gen.conflictgen import Conflict
|
||||||
@ -50,10 +51,7 @@ ENEMY_BASE_STRENGTH_RECOVERY = 0.05
|
|||||||
AWACS_BUDGET_COST = 4
|
AWACS_BUDGET_COST = 4
|
||||||
|
|
||||||
# Initial budget value
|
# Initial budget value
|
||||||
PLAYER_BUDGET_INITIAL = 450
|
PLAYER_BUDGET_INITIAL = 650
|
||||||
|
|
||||||
# Base post-turn bonus value
|
|
||||||
PLAYER_BUDGET_BASE = 20
|
|
||||||
|
|
||||||
# Bonus multiplier logarithm base
|
# Bonus multiplier logarithm base
|
||||||
PLAYER_BUDGET_IMPORTANCE_LOG = 2
|
PLAYER_BUDGET_IMPORTANCE_LOG = 2
|
||||||
@ -86,6 +84,7 @@ class Game:
|
|||||||
self.planners = {}
|
self.planners = {}
|
||||||
self.ground_planners = {}
|
self.ground_planners = {}
|
||||||
self.informations = []
|
self.informations = []
|
||||||
|
self.informations.append(Information("Game Start", "-" * 40, 0))
|
||||||
|
|
||||||
def _roll(self, prob, mult):
|
def _roll(self, prob, mult):
|
||||||
if self.settings.version == "dev":
|
if self.settings.version == "dev":
|
||||||
@ -111,10 +110,12 @@ class Game:
|
|||||||
|
|
||||||
def _commision_units(self, cp: ControlPoint):
|
def _commision_units(self, cp: ControlPoint):
|
||||||
for for_task in [CAS, CAP, AirDefence]:
|
for for_task in [CAS, CAP, AirDefence]:
|
||||||
limit = COMMISION_LIMITS_FACTORS[for_task] * math.pow(cp.importance, COMMISION_LIMITS_SCALE) * self.settings.multiplier
|
limit = COMMISION_LIMITS_FACTORS[for_task] * math.pow(cp.importance,
|
||||||
|
COMMISION_LIMITS_SCALE) * self.settings.multiplier
|
||||||
missing_units = limit - cp.base.total_units(for_task)
|
missing_units = limit - cp.base.total_units(for_task)
|
||||||
if missing_units > 0:
|
if missing_units > 0:
|
||||||
awarded_points = COMMISION_AMOUNTS_FACTORS[for_task] * math.pow(cp.importance, COMMISION_AMOUNTS_SCALE) * self.settings.multiplier
|
awarded_points = COMMISION_AMOUNTS_FACTORS[for_task] * math.pow(cp.importance,
|
||||||
|
COMMISION_AMOUNTS_SCALE) * self.settings.multiplier
|
||||||
points_to_spend = cp.base.append_commision_points(for_task, awarded_points)
|
points_to_spend = cp.base.append_commision_points(for_task, awarded_points)
|
||||||
if points_to_spend > 0:
|
if points_to_spend > 0:
|
||||||
unittypes = self.commision_unit_types(cp, for_task)
|
unittypes = self.commision_unit_types(cp, for_task)
|
||||||
@ -130,25 +131,8 @@ class Game:
|
|||||||
reward = PLAYER_BUDGET_BASE * len(self.theater.player_points())
|
reward = PLAYER_BUDGET_BASE * len(self.theater.player_points())
|
||||||
for cp in self.theater.player_points():
|
for cp in self.theater.player_points():
|
||||||
for g in cp.ground_objects:
|
for g in cp.ground_objects:
|
||||||
# (Reward is per building)
|
if g.category in REWARDS.keys():
|
||||||
if g.category == "power":
|
reward = reward + REWARDS[g.category]
|
||||||
reward = reward + 4
|
|
||||||
elif g.category == "warehouse":
|
|
||||||
reward = reward + 2
|
|
||||||
elif g.category == "fuel":
|
|
||||||
reward = reward + 2
|
|
||||||
elif g.category == "ammo":
|
|
||||||
reward = reward + 2
|
|
||||||
elif g.category == "farp":
|
|
||||||
reward = reward + 1
|
|
||||||
elif g.category == "fob":
|
|
||||||
reward = reward + 1
|
|
||||||
elif g.category == "factory":
|
|
||||||
reward = reward + 10
|
|
||||||
elif g.category == "comms":
|
|
||||||
reward = reward + 10
|
|
||||||
elif g.category == "oil":
|
|
||||||
reward = reward + 10
|
|
||||||
return reward
|
return reward
|
||||||
else:
|
else:
|
||||||
return reward
|
return reward
|
||||||
@ -197,9 +181,9 @@ class Game:
|
|||||||
else:
|
else:
|
||||||
return event.name == self.player_name
|
return event.name == self.player_name
|
||||||
|
|
||||||
def pass_turn(self, no_action=False, ignored_cps: typing.Collection[ControlPoint]=None):
|
def pass_turn(self, no_action=False, ignored_cps: typing.Collection[ControlPoint] = None):
|
||||||
logging.info("Pass turn")
|
logging.info("Pass turn")
|
||||||
|
self.informations.append(Information("End of turn #" + str(self.turn), "-" * 40, 0))
|
||||||
self.turn = self.turn + 1
|
self.turn = self.turn + 1
|
||||||
|
|
||||||
for event in self.events:
|
for event in self.events:
|
||||||
@ -210,7 +194,6 @@ class Game:
|
|||||||
else:
|
else:
|
||||||
event.skip()
|
event.skip()
|
||||||
|
|
||||||
|
|
||||||
self._enemy_reinforcement()
|
self._enemy_reinforcement()
|
||||||
self._budget_player()
|
self._budget_player()
|
||||||
|
|
||||||
@ -246,34 +229,17 @@ class Game:
|
|||||||
gplanner.plan_groundwar()
|
gplanner.plan_groundwar()
|
||||||
self.ground_planners[cp.id] = gplanner
|
self.ground_planners[cp.id] = gplanner
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _enemy_reinforcement(self):
|
def _enemy_reinforcement(self):
|
||||||
MAX_ARMOR = 50 * self.settings.multiplier
|
MAX_ARMOR = 30 * self.settings.multiplier
|
||||||
MAX_AIRCRAFT = 50 * self.settings.multiplier
|
MAX_AIRCRAFT = 25 * self.settings.multiplier
|
||||||
|
|
||||||
production = 0
|
production = 0.0
|
||||||
for enemy_point in self.theater.enemy_points():
|
for enemy_point in self.theater.enemy_points():
|
||||||
for g in enemy_point.ground_objects:
|
for g in enemy_point.ground_objects:
|
||||||
if g.category == "power":
|
if g.category in REWARDS.keys():
|
||||||
production = production + 4
|
production = production + REWARDS[g.category]
|
||||||
elif g.category == "warehouse":
|
|
||||||
production = production + 2
|
|
||||||
elif g.category == "fuel":
|
|
||||||
production = production + 2
|
|
||||||
elif g.category == "ammo":
|
|
||||||
production = production + 2
|
|
||||||
elif g.category == "farp":
|
|
||||||
production = production + 1
|
|
||||||
elif g.category == "fob":
|
|
||||||
production = production + 1
|
|
||||||
elif g.category == "factory":
|
|
||||||
production = production + 10
|
|
||||||
elif g.category == "comms":
|
|
||||||
production = production + 8
|
|
||||||
elif g.category == "oil":
|
|
||||||
production = production + 8
|
|
||||||
|
|
||||||
|
production = production * 0.75
|
||||||
budget_for_armored_units = production / 2
|
budget_for_armored_units = production / 2
|
||||||
budget_for_aircraft = production / 2
|
budget_for_aircraft = production / 2
|
||||||
|
|
||||||
@ -302,7 +268,7 @@ class Game:
|
|||||||
if target_cp.base.total_armor >= MAX_ARMOR:
|
if target_cp.base.total_armor >= MAX_ARMOR:
|
||||||
continue
|
continue
|
||||||
unit = random.choice(potential_units)
|
unit = random.choice(potential_units)
|
||||||
price = db.PRICES[unit]*2
|
price = db.PRICES[unit] * 2
|
||||||
budget_for_armored_units -= price * 2
|
budget_for_armored_units -= price * 2
|
||||||
target_cp.base.armor[unit] = target_cp.base.armor.get(unit, 0) + 2
|
target_cp.base.armor[unit] = target_cp.base.armor.get(unit, 0) + 2
|
||||||
info = Information("Enemy Reinforcement", unit.id + " x 2 at " + target_cp.name, self.turn)
|
info = Information("Enemy Reinforcement", unit.id + " x 2 at " + target_cp.name, self.turn)
|
||||||
@ -312,7 +278,8 @@ class Game:
|
|||||||
if budget_for_armored_units > 0:
|
if budget_for_armored_units > 0:
|
||||||
budget_for_aircraft += budget_for_armored_units
|
budget_for_aircraft += budget_for_armored_units
|
||||||
|
|
||||||
potential_units = [u for u in db.FACTIONS[self.enemy_name]["units"] if u in db.UNIT_BY_TASK[CAS] or u in db.UNIT_BY_TASK[CAP]]
|
potential_units = [u for u in db.FACTIONS[self.enemy_name]["units"] if
|
||||||
|
u in db.UNIT_BY_TASK[CAS] or u in db.UNIT_BY_TASK[CAP]]
|
||||||
if len(potential_units) > 0 and len(potential_cp_armor) > 0:
|
if len(potential_units) > 0 and len(potential_cp_armor) > 0:
|
||||||
while budget_for_aircraft > 0:
|
while budget_for_aircraft > 0:
|
||||||
i = i + 1
|
i = i + 1
|
||||||
@ -322,22 +289,20 @@ class Game:
|
|||||||
if target_cp.base.total_planes >= MAX_AIRCRAFT:
|
if target_cp.base.total_planes >= MAX_AIRCRAFT:
|
||||||
continue
|
continue
|
||||||
unit = random.choice(potential_units)
|
unit = random.choice(potential_units)
|
||||||
price = db.PRICES[unit]*2
|
price = db.PRICES[unit] * 2
|
||||||
budget_for_aircraft -= price * 2
|
budget_for_aircraft -= price * 2
|
||||||
target_cp.base.aircraft[unit] = target_cp.base.aircraft.get(unit, 0) + 2
|
target_cp.base.aircraft[unit] = target_cp.base.aircraft.get(unit, 0) + 2
|
||||||
info = Information("Enemy Reinforcement", unit.id + " x 2 at " + target_cp.name, self.turn)
|
info = Information("Enemy Reinforcement", unit.id + " x 2 at " + target_cp.name, self.turn)
|
||||||
print(str(info))
|
print(str(info))
|
||||||
self.informations.append(info)
|
self.informations.append(info)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_turn_daytime(self):
|
def current_turn_daytime(self):
|
||||||
return ["dawn", "day", "dusk", "night"][self.turn % 4]
|
return ["dawn", "day", "dusk", "night"][self.turn % 4]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_day(self):
|
def current_day(self):
|
||||||
return self.date + timedelta(days=self.turn//4)
|
return self.date + timedelta(days=self.turn // 4)
|
||||||
|
|
||||||
def next_unit_id(self):
|
def next_unit_id(self):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -39,6 +39,8 @@ class FlightWaypoint():
|
|||||||
self.name = ""
|
self.name = ""
|
||||||
self.description = ""
|
self.description = ""
|
||||||
self.targets = []
|
self.targets = []
|
||||||
|
self.obj_name = ""
|
||||||
|
self.pretty_name = ""
|
||||||
|
|
||||||
|
|
||||||
class Flight:
|
class Flight:
|
||||||
|
|||||||
@ -1,9 +1,48 @@
|
|||||||
from game import db
|
from game import db
|
||||||
|
import random
|
||||||
|
|
||||||
|
ALPHA_MILITARY = ["Alpha","Bravo","Charlie","Delta","Echo","Foxtrot",
|
||||||
|
"Golf","Hotel","India","Juliet","Kilo","Lima","Mike",
|
||||||
|
"November","Oscar","Papa","Quebec","Romeo","Sierra",
|
||||||
|
"Tango","Uniform","Victor","Whisky","XRay","Yankee",
|
||||||
|
"Zulu","Zero"]
|
||||||
|
|
||||||
class NameGenerator:
|
class NameGenerator:
|
||||||
number = 0
|
number = 0
|
||||||
|
|
||||||
|
ANIMALS = [
|
||||||
|
"SHARK", "TORTOISE", "BAT", "PANGOLIN", "AARDWOLF",
|
||||||
|
"MONKEY", "BUFFALO", "DOG", "BOBCAT", "LYNX", "PANTHER", "TIGER",
|
||||||
|
"LION", "OWL", "BUTTERFLY", "BISON", "DUCK", "COBRA", "MAMBA",
|
||||||
|
"DOLPHIN", "PHEASANT", "ARMADILLLO", "RACOON", "ZEBRA", "COW", "COYOTE", "FOX",
|
||||||
|
"LIGHTFOOT", "COTTONMOUTH", "TAURUS", "VIPER", "CASTOR", "GIRAFFE", "SNAKE",
|
||||||
|
"MONSTER", "ALBATROSS", "HAWK", "DOVE", "MOCKINGBIRD", "GECKO", "ORYX", "GORILLA",
|
||||||
|
"HARAMBE", "GOOSE", "MAVERICK", "HARE", "JACKAL", "LEOPARD", "CAT", "MUSK", "ORCA",
|
||||||
|
"OCELOT", "BEAR", "PANDA", "GULL", "PENGUIN", "PYTHON", "RAVEN", "DEER", "MOOSE",
|
||||||
|
"REINDEER", "SHEEP", "GAZELLE", "INSECT", "VULTURE", "WALLABY", "KANGAROO", "KOALA",
|
||||||
|
"KIWI", "WHALE", "FISH", "RHINO", "HIPPO", "RAT", "WOODPECKER", "WORM", "BABOON",
|
||||||
|
"YAK", "SCORPIO", "HORSE", "POODLE", "CENTIPEDE", "CHICKEN", "CHEETAH", "CHAMELEON",
|
||||||
|
"CATFISH", "CATERPILLAR", "CARACAL", "CAMEL", "CAIMAN", "BARRACUDA", "BANDICOOT",
|
||||||
|
"ALLIGATOR", "BONGO", "CORAL", "ELEPHANT", "ANTELOPE", "CRAB", "DACHSHUND", "DODO",
|
||||||
|
"FLAMINGO", "FERRET", "FALCON", "BULLDOG", "DONKEY", "IGUANA", "TAMARIN", "HARRIER",
|
||||||
|
"GRIZZLY", "GREYHOUND", "GRASSHOPPER", "JAGUAR", "LADYBUG", "KOMODO", "DRAGON", "LIZARD",
|
||||||
|
"LLAMA", "LOBSTER", "OCTOPUS", "MANATEE", "MAGPIE", "MACAW", "OSTRICH", "OYSTER",
|
||||||
|
"MOLE", "MULE", "MOTH", "MONGOOSE", "MOLLY", "MEERKAT", "MOUSE", "PEACOCK", "PIKE", "ROBIN",
|
||||||
|
"RAGDOLL", "PLATYPUS", "PELICAN", "PARROT", "PORCUPINE", "PIRANHA", "PUMA", "PUG", "TAPIR",
|
||||||
|
"TERMITE", "URCHIN", "SHRIMP", "TURKEY", "TOUCAN", "TETRA", "HUSKY", "STARFISH", "SWAN",
|
||||||
|
"FROG", "SQUIRREL", "WALRUS", "WARTHOG", "CORGI", "WEASEL", "WOMBAT", "WOLVERINE", "MAMMOTH",
|
||||||
|
"TOAD", "WOLF", "ZEBU", "SEAL", "SKATE", "JELLYFISH", "MOSQUITO", "LOCUST", "SLUG", "SNAIL",
|
||||||
|
"HEDGEHOG", "PIGLET", "FENNEC", "BADGER", "ALPACA"
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.number = 0
|
||||||
|
self.ANIMALS = NameGenerator.ANIMALS.copy()
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.number = 0
|
||||||
|
self.ANIMALS = NameGenerator.ANIMALS.copy()
|
||||||
|
|
||||||
def next_unit_name(self, country, parent_base_id, unit_type):
|
def next_unit_name(self, country, parent_base_id, unit_type):
|
||||||
self.number += 1
|
self.number += 1
|
||||||
return "unit|{}|{}|{}|{}|".format(country.id, self.number, parent_base_id, db.unit_type_name(unit_type))
|
return "unit|{}|{}|{}|{}|".format(country.id, self.number, parent_base_id, db.unit_type_name(unit_type))
|
||||||
@ -27,6 +66,16 @@ class NameGenerator:
|
|||||||
self.number += 1
|
self.number += 1
|
||||||
return "carrier|{}|{}|0|".format(country.id, self.number)
|
return "carrier|{}|{}|0|".format(country.id, self.number)
|
||||||
|
|
||||||
|
def random_objective_name(self):
|
||||||
|
if len(self.ANIMALS) == 0:
|
||||||
|
random.choice(ALPHA_MILITARY).upper() + " #" + str(random.randint(0, 100))
|
||||||
|
else:
|
||||||
|
animal = random.choice(self.ANIMALS)
|
||||||
|
self.ANIMALS.remove(animal)
|
||||||
|
return animal
|
||||||
|
|
||||||
|
|
||||||
namegen = NameGenerator()
|
namegen = NameGenerator()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -88,12 +88,10 @@ EVENT_ICONS: Dict[str, QPixmap] = {}
|
|||||||
|
|
||||||
|
|
||||||
def load_event_icons():
|
def load_event_icons():
|
||||||
for category, image in {
|
for image in os.listdir("./resources/ui/events/"):
|
||||||
"strike": "strike",
|
print(image)
|
||||||
FrontlineAttackEvent: "attack",
|
if image.endswith(".PNG"):
|
||||||
UnitsDeliveryEvent: "delivery"}.items():
|
EVENT_ICONS[image[:-4]] = QPixmap(os.path.join("./resources/ui/events/", image))
|
||||||
EVENT_ICONS[category] = QPixmap("./resources/ui/events/" + image + ".png")
|
|
||||||
|
|
||||||
|
|
||||||
def load_aircraft_icons():
|
def load_aircraft_icons():
|
||||||
for aircraft in os.listdir("./resources/ui/units/aircrafts/"):
|
for aircraft in os.listdir("./resources/ui/units/aircrafts/"):
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
from PySide2.QtWidgets import QLabel, QHBoxLayout, QGroupBox
|
from PySide2.QtWidgets import QLabel, QHBoxLayout, QGroupBox, QPushButton
|
||||||
|
|
||||||
import qt_ui.uiconstants as CONST
|
import qt_ui.uiconstants as CONST
|
||||||
|
from qt_ui.windows.finances.QFinancesMenu import QFinancesMenu
|
||||||
|
|
||||||
|
|
||||||
class QBudgetBox(QGroupBox):
|
class QBudgetBox(QGroupBox):
|
||||||
@ -8,16 +9,22 @@ class QBudgetBox(QGroupBox):
|
|||||||
UI Component to display current budget and player's money
|
UI Component to display current budget and player's money
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, game):
|
||||||
super(QBudgetBox, self).__init__("Budget")
|
super(QBudgetBox, self).__init__("Budget")
|
||||||
|
|
||||||
|
self.game = game
|
||||||
self.money_icon = QLabel()
|
self.money_icon = QLabel()
|
||||||
self.money_icon.setPixmap(CONST.ICONS["Money"])
|
self.money_icon.setPixmap(CONST.ICONS["Money"])
|
||||||
self.money_amount = QLabel()
|
self.money_amount = QLabel()
|
||||||
|
|
||||||
|
self.finances = QPushButton("Details")
|
||||||
|
self.finances.setProperty("style", "btn-primary")
|
||||||
|
self.finances.clicked.connect(self.openFinances)
|
||||||
|
|
||||||
self.layout = QHBoxLayout()
|
self.layout = QHBoxLayout()
|
||||||
self.layout.addWidget(self.money_icon)
|
self.layout.addWidget(self.money_icon)
|
||||||
self.layout.addWidget(self.money_amount)
|
self.layout.addWidget(self.money_amount)
|
||||||
|
self.layout.addWidget(self.finances)
|
||||||
self.setLayout(self.layout)
|
self.setLayout(self.layout)
|
||||||
|
|
||||||
def setBudget(self, budget, reward):
|
def setBudget(self, budget, reward):
|
||||||
@ -26,4 +33,12 @@ class QBudgetBox(QGroupBox):
|
|||||||
:param budget: Current money available
|
:param budget: Current money available
|
||||||
:param reward: Planned reward for next turn
|
:param reward: Planned reward for next turn
|
||||||
"""
|
"""
|
||||||
self.money_amount.setText(str(budget) + "M (+" + str(reward) + "M)")
|
self.money_amount.setText(str(budget) + "M (+" + str(reward) + "M)")
|
||||||
|
|
||||||
|
def setGame(self, game):
|
||||||
|
self.game = game
|
||||||
|
self.setBudget(self.game.budget, self.game.budget_reward_amount)
|
||||||
|
|
||||||
|
def openFinances(self):
|
||||||
|
self.subwindow = QFinancesMenu(self.game)
|
||||||
|
self.subwindow.show()
|
||||||
@ -15,6 +15,7 @@ class QFactionsInfos(QGroupBox):
|
|||||||
self.setGame(game)
|
self.setGame(game)
|
||||||
|
|
||||||
self.layout = QGridLayout()
|
self.layout = QGridLayout()
|
||||||
|
self.layout.setSpacing(0)
|
||||||
self.layout.addWidget(QLabel("<b>Player : </b>"),0,0)
|
self.layout.addWidget(QLabel("<b>Player : </b>"),0,0)
|
||||||
self.layout.addWidget(self.player_name,0,1)
|
self.layout.addWidget(self.player_name,0,1)
|
||||||
self.layout.addWidget(QLabel("<b>Enemy : </b>"),1,0)
|
self.layout.addWidget(QLabel("<b>Enemy : </b>"),1,0)
|
||||||
|
|||||||
146
qt_ui/widgets/QPredefinedWaypointSelectionComboBox.py
Normal file
146
qt_ui/widgets/QPredefinedWaypointSelectionComboBox.py
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
from PySide2.QtCore import QSortFilterProxyModel, Qt, QModelIndex
|
||||||
|
from PySide2.QtGui import QStandardItem, QStandardItemModel
|
||||||
|
from PySide2.QtWidgets import QComboBox, QCompleter
|
||||||
|
from game import Game
|
||||||
|
from gen.flights.flight import FlightWaypoint
|
||||||
|
from theater import ControlPointType
|
||||||
|
|
||||||
|
|
||||||
|
class QPredefinedWaypointSelectionComboBox(QComboBox):
|
||||||
|
|
||||||
|
def __init__(self, game: Game, parent=None):
|
||||||
|
super(QPredefinedWaypointSelectionComboBox, self).__init__(parent)
|
||||||
|
|
||||||
|
self.game = game
|
||||||
|
self.setFocusPolicy(Qt.StrongFocus)
|
||||||
|
self.setEditable(True)
|
||||||
|
self.completer = QCompleter(self)
|
||||||
|
|
||||||
|
# always show all completions
|
||||||
|
self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
|
||||||
|
self.pFilterModel = QSortFilterProxyModel(self)
|
||||||
|
self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
|
||||||
|
|
||||||
|
self.completer.setPopup(self.view())
|
||||||
|
|
||||||
|
self.setCompleter(self.completer)
|
||||||
|
|
||||||
|
self.lineEdit().textEdited.connect(self.pFilterModel.setFilterFixedString)
|
||||||
|
self.completer.activated.connect(self.setTextIfCompleterIsClicked)
|
||||||
|
|
||||||
|
self.find_possible_waypoints()
|
||||||
|
|
||||||
|
def setModel(self, model):
|
||||||
|
super(QPredefinedWaypointSelectionComboBox, self).setModel(model)
|
||||||
|
self.pFilterModel.setSourceModel(model)
|
||||||
|
self.completer.setModel(self.pFilterModel)
|
||||||
|
|
||||||
|
def setModelColumn(self, column):
|
||||||
|
self.completer.setCompletionColumn(column)
|
||||||
|
self.pFilterModel.setFilterKeyColumn(column)
|
||||||
|
super(QPredefinedWaypointSelectionComboBox, self).setModelColumn(column)
|
||||||
|
|
||||||
|
def view(self):
|
||||||
|
return self.completer.popup()
|
||||||
|
|
||||||
|
def index(self):
|
||||||
|
return self.currentIndex()
|
||||||
|
|
||||||
|
def setTextIfCompleterIsClicked(self, text):
|
||||||
|
if text:
|
||||||
|
index = self.findText(text)
|
||||||
|
self.setCurrentIndex(index)
|
||||||
|
|
||||||
|
def get_selected_waypoints(self, include_all_from_same_location=False):
|
||||||
|
n = self.currentText()
|
||||||
|
|
||||||
|
first_waypoint = None
|
||||||
|
for w in self.wpts:
|
||||||
|
if w.pretty_name == n:
|
||||||
|
first_waypoint = w
|
||||||
|
break
|
||||||
|
|
||||||
|
if first_waypoint is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
waypoints = [first_waypoint]
|
||||||
|
if include_all_from_same_location:
|
||||||
|
for w in self.wpts:
|
||||||
|
if w is not first_waypoint and w.obj_name and w.obj_name == first_waypoint.obj_name:
|
||||||
|
waypoints.append(w)
|
||||||
|
|
||||||
|
return waypoints
|
||||||
|
|
||||||
|
def find_possible_waypoints(self):
|
||||||
|
|
||||||
|
self.wpts = []
|
||||||
|
model = QStandardItemModel()
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
def add_model_item(i, model, name, wpt):
|
||||||
|
print(name)
|
||||||
|
item = QStandardItem(name)
|
||||||
|
model.setItem(i, 0, item)
|
||||||
|
self.wpts.append(wpt)
|
||||||
|
return i + 1
|
||||||
|
|
||||||
|
for cp in self.game.theater.controlpoints:
|
||||||
|
print(cp)
|
||||||
|
if cp.captured:
|
||||||
|
enemy_cp = [ecp for ecp in cp.connected_points if ecp.captured != cp.captured]
|
||||||
|
for ecp in enemy_cp:
|
||||||
|
wpt = FlightWaypoint((cp.position.x + ecp.position.x)/2, (cp.position.y + ecp.position.y)/2, 800)
|
||||||
|
wpt.name = "Frontline " + cp.name + "/" + ecp.name + " [CAS]"
|
||||||
|
wpt.pretty_name = wpt.name
|
||||||
|
wpt.description = "Frontline"
|
||||||
|
i = add_model_item(i, model, wpt.pretty_name, wpt)
|
||||||
|
|
||||||
|
|
||||||
|
for cp in self.game.theater.controlpoints:
|
||||||
|
for ground_object in cp.ground_objects:
|
||||||
|
if not ground_object.is_dead and not ground_object.dcs_identifier == "AA":
|
||||||
|
wpt = FlightWaypoint(ground_object.position.x,ground_object.position.y, 0)
|
||||||
|
wpt.name = wpt.name = "[" + str(ground_object.obj_name) + "] : " + ground_object.category + " #" + str(ground_object.object_id)
|
||||||
|
wpt.pretty_name = wpt.name
|
||||||
|
wpt.obj_name = ground_object.obj_name
|
||||||
|
if cp.captured:
|
||||||
|
wpt.description = "Friendly Building"
|
||||||
|
else:
|
||||||
|
wpt.description = "Enemy Building"
|
||||||
|
i = add_model_item(i, model, wpt.pretty_name, wpt)
|
||||||
|
|
||||||
|
for cp in self.game.theater.controlpoints:
|
||||||
|
|
||||||
|
for ground_object in cp.ground_objects:
|
||||||
|
if not ground_object.is_dead and ground_object.dcs_identifier == "AA":
|
||||||
|
for g in ground_object.groups:
|
||||||
|
for j, u in enumerate(g.units):
|
||||||
|
wpt = FlightWaypoint(u.position.x, u.position.y, 0)
|
||||||
|
wpt.name = wpt.name = "[" + str(ground_object.obj_name) + "] : " + u.type + " #" + str(j)
|
||||||
|
wpt.pretty_name = wpt.name
|
||||||
|
wpt.obj_name = ground_object.obj_name
|
||||||
|
if cp.captured:
|
||||||
|
wpt.description = "Friendly unit : " + u.type
|
||||||
|
else:
|
||||||
|
wpt.description = "Enemy unit : " + u.type
|
||||||
|
i = add_model_item(i, model, wpt.pretty_name, wpt)
|
||||||
|
|
||||||
|
for cp in self.game.theater.controlpoints:
|
||||||
|
|
||||||
|
wpt = FlightWaypoint(cp.position.x, cp.position.y, 0)
|
||||||
|
wpt.name = cp.name
|
||||||
|
if cp.captured:
|
||||||
|
wpt.description = "Position of " + cp.name + " [Friendly Airbase]"
|
||||||
|
else:
|
||||||
|
wpt.description = "Position of " + cp.name + " [Enemy Airbase]"
|
||||||
|
|
||||||
|
if cp.cptype == ControlPointType.AIRCRAFT_CARRIER_GROUP:
|
||||||
|
wpt.pretty_name = cp.name + " (Aircraft Carrier Group)"
|
||||||
|
elif cp.cptype == ControlPointType.LHA_GROUP:
|
||||||
|
wpt.pretty_name = cp.name + " (LHA Group)"
|
||||||
|
else:
|
||||||
|
wpt.pretty_name = cp.name + " (Airbase)"
|
||||||
|
|
||||||
|
i = add_model_item(i, model, wpt.pretty_name, wpt)
|
||||||
|
|
||||||
|
self.setModel(model)
|
||||||
@ -1,8 +1,9 @@
|
|||||||
from PySide2.QtWidgets import QFrame, QHBoxLayout, QPushButton, QVBoxLayout
|
from PySide2.QtWidgets import QFrame, QHBoxLayout, QPushButton, QVBoxLayout, QGroupBox
|
||||||
|
|
||||||
from game import Game
|
from game import Game
|
||||||
from qt_ui.widgets.QBudgetBox import QBudgetBox
|
from qt_ui.widgets.QBudgetBox import QBudgetBox
|
||||||
from qt_ui.widgets.QFactionsInfos import QFactionsInfos
|
from qt_ui.widgets.QFactionsInfos import QFactionsInfos
|
||||||
|
from qt_ui.windows.finances.QFinancesMenu import QFinancesMenu
|
||||||
from qt_ui.windows.stats.QStatsWindow import QStatsWindow
|
from qt_ui.windows.stats.QStatsWindow import QStatsWindow
|
||||||
from qt_ui.widgets.QTurnCounter import QTurnCounter
|
from qt_ui.widgets.QTurnCounter import QTurnCounter
|
||||||
|
|
||||||
@ -17,13 +18,14 @@ class QTopPanel(QFrame):
|
|||||||
def __init__(self, game: Game):
|
def __init__(self, game: Game):
|
||||||
super(QTopPanel, self).__init__()
|
super(QTopPanel, self).__init__()
|
||||||
self.game = game
|
self.game = game
|
||||||
|
self.setMaximumHeight(70)
|
||||||
self.init_ui()
|
self.init_ui()
|
||||||
GameUpdateSignal.get_instance().gameupdated.connect(self.setGame)
|
GameUpdateSignal.get_instance().gameupdated.connect(self.setGame)
|
||||||
|
|
||||||
def init_ui(self):
|
def init_ui(self):
|
||||||
|
|
||||||
self.turnCounter = QTurnCounter()
|
self.turnCounter = QTurnCounter()
|
||||||
self.budgetBox = QBudgetBox()
|
self.budgetBox = QBudgetBox(self.game)
|
||||||
|
|
||||||
self.passTurnButton = QPushButton("Pass Turn")
|
self.passTurnButton = QPushButton("Pass Turn")
|
||||||
self.passTurnButton.setIcon(CONST.ICONS["PassTurn"])
|
self.passTurnButton.setIcon(CONST.ICONS["PassTurn"])
|
||||||
@ -36,14 +38,9 @@ class QTopPanel(QFrame):
|
|||||||
self.proceedButton.clicked.connect(self.proceed)
|
self.proceedButton.clicked.connect(self.proceed)
|
||||||
if self.game and self.game.turn == 0:
|
if self.game and self.game.turn == 0:
|
||||||
self.proceedButton.setEnabled(False)
|
self.proceedButton.setEnabled(False)
|
||||||
elif not len(self.game.planners.keys()) == self.game.theater.controlpoints:
|
|
||||||
self.proceedButton.setEnabled(False)
|
|
||||||
else:
|
|
||||||
self.proceedButton.setEnabled(True)
|
|
||||||
|
|
||||||
self.factionsInfos = QFactionsInfos(self.game)
|
self.factionsInfos = QFactionsInfos(self.game)
|
||||||
|
|
||||||
self.submenus = QVBoxLayout()
|
|
||||||
self.settings = QPushButton("Settings")
|
self.settings = QPushButton("Settings")
|
||||||
self.settings.setIcon(CONST.ICONS["Settings"])
|
self.settings.setIcon(CONST.ICONS["Settings"])
|
||||||
self.settings.setProperty("style", "btn-primary")
|
self.settings.setProperty("style", "btn-primary")
|
||||||
@ -54,28 +51,40 @@ class QTopPanel(QFrame):
|
|||||||
self.statistics.setProperty("style", "btn-primary")
|
self.statistics.setProperty("style", "btn-primary")
|
||||||
self.statistics.clicked.connect(self.openStatisticsWindow)
|
self.statistics.clicked.connect(self.openStatisticsWindow)
|
||||||
|
|
||||||
self.submenus.addWidget(self.settings)
|
self.buttonBox = QGroupBox("Misc")
|
||||||
self.submenus.addWidget(self.statistics)
|
self.buttonBoxLayout = QHBoxLayout()
|
||||||
|
self.buttonBoxLayout.addWidget(self.settings)
|
||||||
|
self.buttonBoxLayout.addWidget(self.statistics)
|
||||||
|
self.buttonBox.setLayout(self.buttonBoxLayout)
|
||||||
|
|
||||||
|
self.proceedBox = QGroupBox("Proceed")
|
||||||
|
self.proceedBoxLayout = QHBoxLayout()
|
||||||
|
self.proceedBoxLayout.addWidget(self.passTurnButton)
|
||||||
|
self.proceedBoxLayout.addWidget(self.proceedButton)
|
||||||
|
self.proceedBox.setLayout(self.proceedBoxLayout)
|
||||||
|
|
||||||
self.layout = QHBoxLayout()
|
self.layout = QHBoxLayout()
|
||||||
self.layout.addWidget(self.factionsInfos)
|
self.layout.addWidget(self.factionsInfos)
|
||||||
self.layout.addWidget(self.turnCounter)
|
self.layout.addWidget(self.turnCounter)
|
||||||
self.layout.addWidget(self.budgetBox)
|
self.layout.addWidget(self.budgetBox)
|
||||||
self.layout.addLayout(self.submenus)
|
self.layout.addWidget(self.buttonBox)
|
||||||
self.layout.addStretch(1)
|
self.layout.addStretch(1)
|
||||||
self.layout.addWidget(self.passTurnButton)
|
self.layout.addWidget(self.proceedBox)
|
||||||
self.layout.addWidget(self.proceedButton)
|
|
||||||
|
self.layout.setContentsMargins(0,0,0,0)
|
||||||
self.setLayout(self.layout)
|
self.setLayout(self.layout)
|
||||||
|
|
||||||
def setGame(self, game:Game):
|
def setGame(self, game:Game):
|
||||||
self.game = game
|
self.game = game
|
||||||
if game is not None:
|
if game is not None:
|
||||||
self.turnCounter.setCurrentTurn(self.game.turn, self.game.current_day)
|
self.turnCounter.setCurrentTurn(self.game.turn, self.game.current_day)
|
||||||
self.budgetBox.setBudget(self.game.budget, self.game.budget_reward_amount)
|
self.budgetBox.setGame(self.game)
|
||||||
self.factionsInfos.setGame(self.game)
|
self.factionsInfos.setGame(self.game)
|
||||||
|
|
||||||
if not len(self.game.planners.keys()) == self.game.theater.controlpoints:
|
if not len(self.game.planners.keys()) == len(self.game.theater.controlpoints):
|
||||||
self.proceedButton.setEnabled(False)
|
self.proceedButton.setEnabled(False)
|
||||||
|
else:
|
||||||
|
self.proceedButton.setEnabled(True)
|
||||||
|
|
||||||
def openSettings(self):
|
def openSettings(self):
|
||||||
self.subwindow = QSettingsWindow(self.game)
|
self.subwindow = QSettingsWindow(self.game)
|
||||||
|
|||||||
@ -76,13 +76,6 @@ class QLiberationMap(QGraphicsView):
|
|||||||
scene.addItem(QMapControlPoint(self, pos[0] - CONST.CP_SIZE / 2, pos[1] - CONST.CP_SIZE / 2, CONST.CP_SIZE,
|
scene.addItem(QMapControlPoint(self, pos[0] - CONST.CP_SIZE / 2, pos[1] - CONST.CP_SIZE / 2, CONST.CP_SIZE,
|
||||||
CONST.CP_SIZE, cp, self.game))
|
CONST.CP_SIZE, cp, self.game))
|
||||||
|
|
||||||
text = scene.addText(cp.name, font=QFont("Trebuchet MS", 10, weight=5, italic=False))
|
|
||||||
text.setPos(pos[0] + CONST.CP_SIZE, pos[1] - CONST.CP_SIZE / 2)
|
|
||||||
|
|
||||||
text = scene.addText(cp.name, font=QFont("Trebuchet MS", 10, weight=5, italic=False))
|
|
||||||
text.setDefaultTextColor(Qt.white)
|
|
||||||
text.setPos(pos[0] + CONST.CP_SIZE + 1, pos[1] - CONST.CP_SIZE / 2 + 1)
|
|
||||||
|
|
||||||
|
|
||||||
if cp.captured:
|
if cp.captured:
|
||||||
pen = QPen(brush=CONST.COLORS["blue"])
|
pen = QPen(brush=CONST.COLORS["blue"])
|
||||||
@ -105,7 +98,7 @@ class QLiberationMap(QGraphicsView):
|
|||||||
|
|
||||||
go_pos = self._transform_point(ground_object.position)
|
go_pos = self._transform_point(ground_object.position)
|
||||||
if not ground_object.airbase_group:
|
if not ground_object.airbase_group:
|
||||||
scene.addItem(QMapGroundObject(self, go_pos[0], go_pos[1], 16, 16, cp, ground_object))
|
scene.addItem(QMapGroundObject(self, go_pos[0], go_pos[1], 12, 12, cp, ground_object))
|
||||||
|
|
||||||
if ground_object.category == "aa" and self.get_display_rule("sam"):
|
if ground_object.category == "aa" and self.get_display_rule("sam"):
|
||||||
max_range = 0
|
max_range = 0
|
||||||
@ -126,6 +119,7 @@ class QLiberationMap(QGraphicsView):
|
|||||||
self.scene_create_lines_for_cp(cp)
|
self.scene_create_lines_for_cp(cp)
|
||||||
|
|
||||||
for cp in self.game.theater.controlpoints:
|
for cp in self.game.theater.controlpoints:
|
||||||
|
pos = self._transform_point(cp.position)
|
||||||
if self.get_display_rule("flight_paths"):
|
if self.get_display_rule("flight_paths"):
|
||||||
if cp.id in self.game.planners.keys():
|
if cp.id in self.game.planners.keys():
|
||||||
planner = self.game.planners[cp.id]
|
planner = self.game.planners[cp.id]
|
||||||
@ -139,6 +133,14 @@ class QLiberationMap(QGraphicsView):
|
|||||||
prev_pos = list(new_pos)
|
prev_pos = list(new_pos)
|
||||||
scene.addLine(prev_pos[0] + 2, prev_pos[1] + 2, pos[0] + 2, pos[1] + 2, flight_path_pen)
|
scene.addLine(prev_pos[0] + 2, prev_pos[1] + 2, pos[0] + 2, pos[1] + 2, flight_path_pen)
|
||||||
|
|
||||||
|
for cp in self.game.theater.controlpoints:
|
||||||
|
pos = self._transform_point(cp.position)
|
||||||
|
text = scene.addText(cp.name, font=QFont("Trebuchet MS", 10, weight=5, italic=False))
|
||||||
|
text.setPos(pos[0] + CONST.CP_SIZE, pos[1] - CONST.CP_SIZE / 2)
|
||||||
|
text = scene.addText(cp.name, font=QFont("Trebuchet MS", 10, weight=5, italic=False))
|
||||||
|
text.setDefaultTextColor(Qt.white)
|
||||||
|
text.setPos(pos[0] + CONST.CP_SIZE + 1, pos[1] - CONST.CP_SIZE / 2 + 1)
|
||||||
|
|
||||||
def scene_create_lines_for_cp(self, cp: ControlPoint):
|
def scene_create_lines_for_cp(self, cp: ControlPoint):
|
||||||
scene = self.scene()
|
scene = self.scene()
|
||||||
pos = self._transform_point(cp.position)
|
pos = self._transform_point(cp.position)
|
||||||
|
|||||||
@ -27,12 +27,12 @@ class QMapGroundObject(QGraphicsRectItem):
|
|||||||
units[u.type] = units[u.type]+1
|
units[u.type] = units[u.type]+1
|
||||||
else:
|
else:
|
||||||
units[u.type] = 1
|
units[u.type] = 1
|
||||||
tooltip = ""
|
tooltip = "[" + self.model.obj_name + "]" + "\n"
|
||||||
for unit in units.keys():
|
for unit in units.keys():
|
||||||
tooltip = tooltip + str(unit) + "x" + str(units[unit]) + "\n"
|
tooltip = tooltip + str(unit) + "x" + str(units[unit]) + "\n"
|
||||||
self.setToolTip(tooltip[:-1])
|
self.setToolTip(tooltip[:-1])
|
||||||
else:
|
else:
|
||||||
self.setToolTip(cp.name + "'s " + self.model.category)
|
self.setToolTip("[" + self.model.obj_name + "] : " + self.model.category)
|
||||||
|
|
||||||
|
|
||||||
def paint(self, painter, option, widget=None):
|
def paint(self, painter, option, widget=None):
|
||||||
|
|||||||
@ -4,7 +4,8 @@ import webbrowser
|
|||||||
from PySide2 import QtGui
|
from PySide2 import QtGui
|
||||||
from PySide2.QtCore import Qt
|
from PySide2.QtCore import Qt
|
||||||
from PySide2.QtGui import QIcon
|
from PySide2.QtGui import QIcon
|
||||||
from PySide2.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QMainWindow, QAction, QMessageBox, QDesktopWidget
|
from PySide2.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QMainWindow, QAction, QMessageBox, QDesktopWidget, \
|
||||||
|
QSplitter
|
||||||
|
|
||||||
import qt_ui.uiconstants as CONST
|
import qt_ui.uiconstants as CONST
|
||||||
from game import Game
|
from game import Game
|
||||||
@ -14,6 +15,7 @@ from qt_ui.widgets.map.QLiberationMap import QLiberationMap
|
|||||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal, DebriefingSignal
|
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal, DebriefingSignal
|
||||||
from qt_ui.windows.QDebriefingWindow import QDebriefingWindow
|
from qt_ui.windows.QDebriefingWindow import QDebriefingWindow
|
||||||
from qt_ui.windows.QNewGameWizard import NewGameWizard
|
from qt_ui.windows.QNewGameWizard import NewGameWizard
|
||||||
|
from qt_ui.windows.infos.QInfoPanel import QInfoPanel
|
||||||
from userdata import persistency
|
from userdata import persistency
|
||||||
|
|
||||||
|
|
||||||
@ -22,6 +24,7 @@ class QLiberationWindow(QMainWindow):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(QLiberationWindow, self).__init__()
|
super(QLiberationWindow, self).__init__()
|
||||||
|
|
||||||
|
self.info_panel = None
|
||||||
self.setGame(persistency.restore_game())
|
self.setGame(persistency.restore_game())
|
||||||
|
|
||||||
self.setGeometry(300, 100, 270, 100)
|
self.setGeometry(300, 100, 270, 100)
|
||||||
@ -44,11 +47,16 @@ class QLiberationWindow(QMainWindow):
|
|||||||
def initUi(self):
|
def initUi(self):
|
||||||
|
|
||||||
self.liberation_map = QLiberationMap(self.game)
|
self.liberation_map = QLiberationMap(self.game)
|
||||||
|
self.info_panel = QInfoPanel(self.game)
|
||||||
|
|
||||||
|
hbox = QSplitter(Qt.Horizontal)
|
||||||
|
hbox.addWidget(self.info_panel)
|
||||||
|
hbox.addWidget(self.liberation_map)
|
||||||
|
|
||||||
vbox = QVBoxLayout()
|
vbox = QVBoxLayout()
|
||||||
vbox.setMargin(0)
|
vbox.setMargin(0)
|
||||||
vbox.addWidget(QTopPanel(self.game))
|
vbox.addWidget(QTopPanel(self.game))
|
||||||
vbox.addWidget(self.liberation_map)
|
vbox.addWidget(hbox)
|
||||||
|
|
||||||
central_widget = QWidget()
|
central_widget = QWidget()
|
||||||
central_widget.setLayout(vbox)
|
central_widget.setLayout(vbox)
|
||||||
@ -164,6 +172,8 @@ class QLiberationWindow(QMainWindow):
|
|||||||
|
|
||||||
def setGame(self, game: Game):
|
def setGame(self, game: Game):
|
||||||
self.game = game
|
self.game = game
|
||||||
|
if self.info_panel:
|
||||||
|
self.info_panel.setGame(game)
|
||||||
|
|
||||||
def showAboutDialog(self):
|
def showAboutDialog(self):
|
||||||
text = "<h3>DCS Liberation</h3>" + \
|
text = "<h3>DCS Liberation</h3>" + \
|
||||||
|
|||||||
@ -1,20 +1,13 @@
|
|||||||
import traceback
|
|
||||||
|
|
||||||
from PySide2.QtCore import Qt
|
from PySide2.QtCore import Qt
|
||||||
from PySide2.QtGui import QCloseEvent
|
from PySide2.QtGui import QCloseEvent
|
||||||
from PySide2.QtWidgets import QHBoxLayout, QLabel, QWidget, QDialog, QVBoxLayout, QGridLayout, QPushButton, \
|
from PySide2.QtWidgets import QHBoxLayout, QLabel, QWidget, QDialog, QGridLayout
|
||||||
QGroupBox, QSizePolicy, QSpacerItem
|
|
||||||
from dcs.unittype import UnitType
|
|
||||||
|
|
||||||
from game.event import UnitsDeliveryEvent, ControlPointType
|
|
||||||
from qt_ui.widgets.QBudgetBox import QBudgetBox
|
|
||||||
from qt_ui.widgets.base.QAirportInformation import QAirportInformation
|
|
||||||
from qt_ui.widgets.base.QBaseInformation import QBaseInformation
|
|
||||||
from qt_ui.windows.basemenu.QBaseMenuTabs import QBaseMenuTabs
|
|
||||||
from qt_ui.windows.mission.QPlannedFlightsView import QPlannedFlightsView
|
|
||||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
|
||||||
from theater import ControlPoint, CAP, Embarking, CAS, PinpointStrike, db
|
|
||||||
from game import Game
|
from game import Game
|
||||||
|
from game.event import ControlPointType
|
||||||
|
from qt_ui.uiconstants import EVENT_ICONS
|
||||||
|
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||||
|
from qt_ui.windows.basemenu.QBaseMenuTabs import QBaseMenuTabs
|
||||||
|
from theater import ControlPoint
|
||||||
|
|
||||||
|
|
||||||
class QBaseMenu2(QDialog):
|
class QBaseMenu2(QDialog):
|
||||||
@ -38,6 +31,8 @@ class QBaseMenu2(QDialog):
|
|||||||
if self.cp.captured:
|
if self.cp.captured:
|
||||||
self.deliveryEvent = None
|
self.deliveryEvent = None
|
||||||
|
|
||||||
|
self.setWindowIcon(EVENT_ICONS["capture"])
|
||||||
|
|
||||||
self.setWindowFlags(Qt.WindowStaysOnTopHint)
|
self.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||||
self.setMinimumSize(300, 200)
|
self.setMinimumSize(300, 200)
|
||||||
self.setModal(True)
|
self.setModal(True)
|
||||||
|
|||||||
70
qt_ui/windows/finances/QFinancesMenu.py
Normal file
70
qt_ui/windows/finances/QFinancesMenu.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
from PySide2.QtWidgets import QDialog, QGridLayout, QLabel, QFrame, QSizePolicy
|
||||||
|
|
||||||
|
import qt_ui.uiconstants as CONST
|
||||||
|
from game.db import REWARDS, PLAYER_BUDGET_BASE
|
||||||
|
from game.game import Game
|
||||||
|
|
||||||
|
|
||||||
|
class QHorizontalSeparationLine(QFrame):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.setMinimumWidth(1)
|
||||||
|
self.setFixedHeight(20)
|
||||||
|
self.setFrameShape(QFrame.HLine)
|
||||||
|
self.setFrameShadow(QFrame.Sunken)
|
||||||
|
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum)
|
||||||
|
|
||||||
|
class QFinancesMenu(QDialog):
|
||||||
|
|
||||||
|
def __init__(self, game: Game):
|
||||||
|
super(QFinancesMenu, self).__init__()
|
||||||
|
|
||||||
|
self.game = game
|
||||||
|
self.setModal(True)
|
||||||
|
self.setWindowTitle("Finances")
|
||||||
|
self.setWindowIcon(CONST.ICONS["Money"])
|
||||||
|
self.setMinimumSize(450, 200)
|
||||||
|
|
||||||
|
reward = PLAYER_BUDGET_BASE * len(self.game.theater.player_points())
|
||||||
|
layout = QGridLayout()
|
||||||
|
layout.addWidget(QLabel("<b>Control Points</b>"), 0, 0)
|
||||||
|
layout.addWidget(QLabel(str(len(self.game.theater.player_points())) + " bases x " + str(PLAYER_BUDGET_BASE) + "M"), 0, 1)
|
||||||
|
layout.addWidget(QLabel(str(reward) + "M"), 0, 2)
|
||||||
|
|
||||||
|
layout.addWidget(QHorizontalSeparationLine(), 1, 0, 1, 3)
|
||||||
|
|
||||||
|
i = 2
|
||||||
|
for cp in self.game.theater.player_points():
|
||||||
|
obj_names = []
|
||||||
|
[obj_names.append(ground_object.obj_name) for ground_object in cp.ground_objects if ground_object.obj_name not in obj_names]
|
||||||
|
for obj_name in obj_names:
|
||||||
|
reward = 0
|
||||||
|
g = None
|
||||||
|
cat = None
|
||||||
|
number = 0
|
||||||
|
for ground_object in cp.ground_objects:
|
||||||
|
if ground_object.obj_name != obj_name or ground_object.is_dead:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if g is None:
|
||||||
|
g = ground_object
|
||||||
|
cat = g.category
|
||||||
|
if cat in REWARDS.keys():
|
||||||
|
number = number + 1
|
||||||
|
reward += REWARDS[cat]
|
||||||
|
|
||||||
|
if g is not None and cat in REWARDS.keys():
|
||||||
|
layout.addWidget(QLabel("<b>" + g.category.upper() + " [" + obj_name + "]</b>"), i, 0)
|
||||||
|
layout.addWidget(QLabel(str(number) + " buildings x " + str(REWARDS[cat]) + "M"), i, 1)
|
||||||
|
rlabel = QLabel(str(reward) + "M")
|
||||||
|
rlabel.setProperty("style", "green")
|
||||||
|
layout.addWidget(rlabel, i, 2)
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
layout.addWidget(QHorizontalSeparationLine(), i+1, 0, 1, 3)
|
||||||
|
|
||||||
|
layout.addWidget(QLabel("<b>" + str(self.game.budget_reward_amount) + "M </b>"), i+2, 2)
|
||||||
|
|
||||||
12
qt_ui/windows/infos/QInfoItem.py
Normal file
12
qt_ui/windows/infos/QInfoItem.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from PySide2.QtGui import QStandardItem
|
||||||
|
|
||||||
|
from game.infos.information import Information
|
||||||
|
|
||||||
|
|
||||||
|
class QInfoItem(QStandardItem):
|
||||||
|
|
||||||
|
def __init__(self, info: Information):
|
||||||
|
super(QInfoItem, self).__init__()
|
||||||
|
self.info = info
|
||||||
|
self.setText("[%02d]" % self.info.turn + " " + self.info.title + ' : {:<16}'.format(info.text))
|
||||||
|
self.setEditable(False)
|
||||||
33
qt_ui/windows/infos/QInfoList.py
Normal file
33
qt_ui/windows/infos/QInfoList.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
from PySide2.QtCore import QItemSelectionModel, QPoint
|
||||||
|
from PySide2.QtGui import QStandardItemModel
|
||||||
|
from PySide2.QtWidgets import QListView
|
||||||
|
|
||||||
|
from game import Game, game
|
||||||
|
from qt_ui.windows.infos.QInfoItem import QInfoItem
|
||||||
|
|
||||||
|
|
||||||
|
class QInfoList(QListView):
|
||||||
|
|
||||||
|
def __init__(self, game:Game):
|
||||||
|
super(QInfoList, self).__init__()
|
||||||
|
self.model = QStandardItemModel(self)
|
||||||
|
self.setModel(self.model)
|
||||||
|
self.game = game
|
||||||
|
self.update_list()
|
||||||
|
|
||||||
|
self.selectionModel().setCurrentIndex(self.indexAt(QPoint(1, 1)), QItemSelectionModel.Select)
|
||||||
|
self.selectionModel().selectionChanged.connect(self.on_selected_info_changed)
|
||||||
|
|
||||||
|
def on_selected_info_changed(self):
|
||||||
|
index = self.selectionModel().currentIndex().row()
|
||||||
|
|
||||||
|
def update_list(self):
|
||||||
|
self.model.clear()
|
||||||
|
if self.game is not None:
|
||||||
|
for i, info in enumerate(reversed(self.game.informations)):
|
||||||
|
self.model.appendRow(QInfoItem(info))
|
||||||
|
self.selectionModel().setCurrentIndex(self.indexAt(QPoint(1, 1)), QItemSelectionModel.Select)
|
||||||
|
|
||||||
|
def setGame(self, game):
|
||||||
|
self.game = game
|
||||||
|
self.update_list()
|
||||||
28
qt_ui/windows/infos/QInfoPanel.py
Normal file
28
qt_ui/windows/infos/QInfoPanel.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
from PySide2.QtWidgets import QFrame, QVBoxLayout, QLabel, QGroupBox
|
||||||
|
|
||||||
|
from game import Game
|
||||||
|
from qt_ui.windows.infos.QInfoList import QInfoList
|
||||||
|
|
||||||
|
|
||||||
|
class QInfoPanel(QGroupBox):
|
||||||
|
|
||||||
|
def __init__(self, game: Game):
|
||||||
|
super(QInfoPanel, self).__init__("Info Panel")
|
||||||
|
self.informations_list = QInfoList(game)
|
||||||
|
self.init_ui()
|
||||||
|
|
||||||
|
def setGame(self, game):
|
||||||
|
self.game = game
|
||||||
|
self.informations_list.setGame(game)
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
self.informations_list.update_list()
|
||||||
|
|
||||||
|
def init_ui(self):
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
layout.addWidget(self.informations_list)
|
||||||
|
layout.setSpacing(0)
|
||||||
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
|
||||||
21
qt_ui/windows/infos/QInfoWidget.py
Normal file
21
qt_ui/windows/infos/QInfoWidget.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from PySide2.QtWidgets import QFrame, QLabel, QGridLayout
|
||||||
|
|
||||||
|
from game.infos.information import Information
|
||||||
|
|
||||||
|
|
||||||
|
class QInfoWidget(QFrame):
|
||||||
|
|
||||||
|
def __init__(self, info: Information):
|
||||||
|
super(QInfoWidget, self).__init__()
|
||||||
|
self.info = info
|
||||||
|
self.titleLabel = QLabel("<b>" + info.title + "</b>")
|
||||||
|
self.textLabel = QLabel(info.text)
|
||||||
|
self.init_ui()
|
||||||
|
|
||||||
|
def init_ui(self):
|
||||||
|
layout = QGridLayout()
|
||||||
|
layout.addWidget(self.titleLabel,0,0)
|
||||||
|
layout.addWidget(self.textLabel,1,0)
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ class QMissionPlanning(QDialog):
|
|||||||
super(QMissionPlanning, self).__init__()
|
super(QMissionPlanning, self).__init__()
|
||||||
self.game = game
|
self.game = game
|
||||||
self.setWindowFlags(Qt.WindowStaysOnTopHint)
|
self.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||||
self.setMinimumSize(750, 420)
|
self.setMinimumSize(800, 420)
|
||||||
self.setModal(True)
|
self.setModal(True)
|
||||||
self.setWindowTitle("Mission Preparation")
|
self.setWindowTitle("Mission Preparation")
|
||||||
self.setWindowIcon(EVENT_ICONS["strike"])
|
self.setWindowIcon(EVENT_ICONS["strike"])
|
||||||
@ -133,8 +133,3 @@ class QMissionPlanning(QDialog):
|
|||||||
waiting = QWaitingForMissionResultWindow(self.gameEvent, self.game)
|
waiting = QWaitingForMissionResultWindow(self.gameEvent, self.game)
|
||||||
waiting.show()
|
waiting.show()
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from gen.flights.flight import FlightWaypoint
|
|||||||
|
|
||||||
class QFlightWaypointInfoBox(QGroupBox):
|
class QFlightWaypointInfoBox(QGroupBox):
|
||||||
|
|
||||||
def __init__(self, flight_wpt:FlightWaypoint):
|
def __init__(self, flight_wpt:FlightWaypoint = None):
|
||||||
super(QFlightWaypointInfoBox, self).__init__("Waypoint")
|
super(QFlightWaypointInfoBox, self).__init__("Waypoint")
|
||||||
self.flight_wpt = flight_wpt
|
self.flight_wpt = flight_wpt
|
||||||
if flight_wpt is None:
|
if flight_wpt is None:
|
||||||
@ -22,31 +22,31 @@ class QFlightWaypointInfoBox(QGroupBox):
|
|||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
x_pos_layout = QHBoxLayout()
|
x_pos_layout = QHBoxLayout()
|
||||||
x_pos_layout.addWidget(QLabel("X : "))
|
x_pos_layout.addWidget(QLabel("<b>X : </b>"))
|
||||||
x_pos_layout.addWidget(self.x_position_label)
|
x_pos_layout.addWidget(self.x_position_label)
|
||||||
x_pos_layout.addStretch()
|
x_pos_layout.addStretch()
|
||||||
|
|
||||||
y_pos_layout = QHBoxLayout()
|
y_pos_layout = QHBoxLayout()
|
||||||
y_pos_layout.addWidget(QLabel("Y : "))
|
y_pos_layout.addWidget(QLabel("<b>Y : </b>"))
|
||||||
y_pos_layout.addWidget(self.y_position_label)
|
y_pos_layout.addWidget(self.y_position_label)
|
||||||
y_pos_layout.addStretch()
|
y_pos_layout.addStretch()
|
||||||
|
|
||||||
alt_layout = QHBoxLayout()
|
alt_layout = QHBoxLayout()
|
||||||
alt_layout.addWidget(QLabel("Alt : "))
|
alt_layout.addWidget(QLabel("<b>Alt : </b>"))
|
||||||
alt_layout.addWidget(self.alt_label)
|
alt_layout.addWidget(self.alt_label)
|
||||||
alt_layout.addStretch()
|
alt_layout.addStretch()
|
||||||
|
|
||||||
name_layout = QHBoxLayout()
|
name_layout = QHBoxLayout()
|
||||||
name_layout.addWidget(QLabel("Name : "))
|
name_layout.addWidget(QLabel("<b>Name : </b>"))
|
||||||
name_layout.addWidget(self.name_label)
|
name_layout.addWidget(self.name_label)
|
||||||
name_layout.addStretch()
|
name_layout.addStretch()
|
||||||
|
|
||||||
desc_layout = QHBoxLayout()
|
desc_layout = QHBoxLayout()
|
||||||
desc_layout.addWidget(QLabel("Description : "))
|
desc_layout.addWidget(QLabel("<b>Description : </b>"))
|
||||||
desc_layout.addWidget(self.desc_label)
|
desc_layout.addWidget(self.desc_label)
|
||||||
desc_layout.addStretch()
|
desc_layout.addStretch()
|
||||||
|
|
||||||
layout.addLayout(name_layout)
|
#layout.addLayout(name_layout)
|
||||||
layout.addLayout(x_pos_layout)
|
layout.addLayout(x_pos_layout)
|
||||||
layout.addLayout(y_pos_layout)
|
layout.addLayout(y_pos_layout)
|
||||||
layout.addLayout(alt_layout)
|
layout.addLayout(alt_layout)
|
||||||
|
|||||||
@ -7,7 +7,9 @@ from gen.flights.flight import FlightWaypoint
|
|||||||
|
|
||||||
class QWaypointItem(QStandardItem):
|
class QWaypointItem(QStandardItem):
|
||||||
|
|
||||||
def __init__(self, point: FlightWaypoint):
|
def __init__(self, point: FlightWaypoint, number):
|
||||||
super(QWaypointItem, self).__init__()
|
super(QWaypointItem, self).__init__()
|
||||||
self.setText('{0: <16}'.format(point.description) + " -- [X: " + str(int(point.x)) + "; Y: " + str(int(point.y)) + "; Alt: " + str(int(point.alt)) + "m]")
|
self.number = number
|
||||||
|
self.setText("%02d" % self.number + ' | ' + '{:<16}'.format(point.pretty_name))
|
||||||
|
self.setEditable(False)
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,8 @@ class QFlightWaypointList(QListView):
|
|||||||
self.model.clear()
|
self.model.clear()
|
||||||
takeoff = FlightWaypoint(self.flight.from_cp.position.x, self.flight.from_cp.position.y, 0)
|
takeoff = FlightWaypoint(self.flight.from_cp.position.x, self.flight.from_cp.position.y, 0)
|
||||||
takeoff.description = "Take Off"
|
takeoff.description = "Take Off"
|
||||||
self.model.appendRow(QWaypointItem(takeoff))
|
takeoff.name = takeoff.pretty_name = "Take Off from " + self.flight.from_cp.name
|
||||||
|
self.model.appendRow(QWaypointItem(takeoff, 0))
|
||||||
for i, point in enumerate(self.flight.points):
|
for i, point in enumerate(self.flight.points):
|
||||||
self.model.appendRow(QWaypointItem(point))
|
self.model.appendRow(QWaypointItem(point, i + 1))
|
||||||
self.selectionModel().setCurrentIndex(self.indexAt(QPoint(1, 1)), QItemSelectionModel.Select)
|
self.selectionModel().setCurrentIndex(self.indexAt(QPoint(1, 1)), QItemSelectionModel.Select)
|
||||||
@ -1,11 +1,13 @@
|
|||||||
from PySide2.QtCore import Qt
|
from PySide2.QtCore import Qt
|
||||||
from PySide2.QtWidgets import QDialog, QGridLayout, QLabel, QComboBox, QHBoxLayout, QVBoxLayout, QPushButton
|
from PySide2.QtWidgets import QDialog, QGridLayout, QLabel, QComboBox, QHBoxLayout, QVBoxLayout, QPushButton, QCheckBox
|
||||||
from dcs import Point
|
from dcs import Point
|
||||||
|
|
||||||
from game import Game
|
from game import Game
|
||||||
from gen.flights.flight import Flight, FlightWaypoint
|
from gen.flights.flight import Flight, FlightWaypoint
|
||||||
from qt_ui.uiconstants import EVENT_ICONS
|
from qt_ui.uiconstants import EVENT_ICONS
|
||||||
|
from qt_ui.widgets.QPredefinedWaypointSelectionComboBox import QPredefinedWaypointSelectionComboBox
|
||||||
from qt_ui.windows.mission.flight.waypoints.QFlightWaypointInfoBox import QFlightWaypointInfoBox
|
from qt_ui.windows.mission.flight.waypoints.QFlightWaypointInfoBox import QFlightWaypointInfoBox
|
||||||
|
from theater import ControlPointType
|
||||||
|
|
||||||
PREDEFINED_WAYPOINT_CATEGORIES = [
|
PREDEFINED_WAYPOINT_CATEGORIES = [
|
||||||
"Frontline (CAS AREA)",
|
"Frontline (CAS AREA)",
|
||||||
@ -23,135 +25,64 @@ class QPredefinedWaypointSelectionWindow(QDialog):
|
|||||||
self.game = game
|
self.game = game
|
||||||
self.flight = flight
|
self.flight = flight
|
||||||
self.setWindowFlags(Qt.WindowStaysOnTopHint)
|
self.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||||
self.setMinimumSize(450, 350)
|
self.setMinimumSize(400, 250)
|
||||||
self.setModal(True)
|
self.setModal(True)
|
||||||
self.setWindowTitle("Add Predefined Waypoint")
|
self.setWindowTitle("Add Predefined Waypoint")
|
||||||
self.setWindowIcon(EVENT_ICONS["strike"])
|
self.setWindowIcon(EVENT_ICONS["strike"])
|
||||||
self.flight_waypoint_list = flight_waypoint_list
|
self.flight_waypoint_list = flight_waypoint_list
|
||||||
|
|
||||||
self.selected_cp = self.game.theater.controlpoints[0]
|
self.wpt_selection_box = QPredefinedWaypointSelectionComboBox(self.game)
|
||||||
self.cp_selection_box = QComboBox()
|
|
||||||
for cp in self.game.theater.controlpoints:
|
|
||||||
self.cp_selection_box.addItem(cp.name)
|
|
||||||
|
|
||||||
self.wpt_type_selection_box = QComboBox()
|
|
||||||
for cat in PREDEFINED_WAYPOINT_CATEGORIES:
|
|
||||||
self.wpt_type_selection_box.addItem(cat)
|
|
||||||
|
|
||||||
self.cp_selection_box.currentTextChanged.connect(self.on_parameters_changed)
|
|
||||||
self.wpt_type_selection_box.currentTextChanged.connect(self.on_parameters_changed)
|
|
||||||
|
|
||||||
self.wpt_selection_box = QComboBox()
|
|
||||||
self.wpt_selection_box.setMinimumWidth(200)
|
self.wpt_selection_box.setMinimumWidth(200)
|
||||||
self.wpt_selection_box.currentTextChanged.connect(self.on_select_wpt_changed)
|
self.wpt_selection_box.currentTextChanged.connect(self.on_select_wpt_changed)
|
||||||
|
self.selected_waypoints = []
|
||||||
self.selected_waypoint = None
|
self.wpt_info = QFlightWaypointInfoBox()
|
||||||
self.wpt_info = QFlightWaypointInfoBox(self.selected_waypoint)
|
|
||||||
|
|
||||||
self.add_button = QPushButton("Add")
|
self.add_button = QPushButton("Add")
|
||||||
self.add_button.clicked.connect(self.add_waypoint)
|
self.add_button.clicked.connect(self.add_waypoint)
|
||||||
|
|
||||||
|
self.include_all = QCheckBox()
|
||||||
|
self.include_all.stateChanged.connect(self.on_select_wpt_changed)
|
||||||
|
self.include_all.setChecked(True)
|
||||||
|
|
||||||
self.init_ui()
|
self.init_ui()
|
||||||
self.on_parameters_changed()
|
self.on_select_wpt_changed()
|
||||||
print("DONE")
|
print("DONE")
|
||||||
|
|
||||||
|
|
||||||
def init_ui(self):
|
def init_ui(self):
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
near_layout = QHBoxLayout()
|
|
||||||
near_layout.addWidget(QLabel("Near : "))
|
|
||||||
near_layout.addWidget(self.cp_selection_box)
|
|
||||||
near_layout.addStretch()
|
|
||||||
|
|
||||||
type_layout = QHBoxLayout()
|
|
||||||
type_layout.addWidget(QLabel("Type : "))
|
|
||||||
type_layout.addWidget(self.wpt_type_selection_box)
|
|
||||||
type_layout.addStretch()
|
|
||||||
|
|
||||||
wpt_layout = QHBoxLayout()
|
wpt_layout = QHBoxLayout()
|
||||||
wpt_layout.addWidget(QLabel("Waypoint : "))
|
wpt_layout.addWidget(QLabel("Waypoint : "))
|
||||||
wpt_layout.addWidget(self.wpt_selection_box)
|
wpt_layout.addWidget(self.wpt_selection_box)
|
||||||
wpt_layout.addStretch()
|
wpt_layout.addStretch()
|
||||||
|
|
||||||
layout.addLayout(near_layout)
|
include_all = QHBoxLayout()
|
||||||
layout.addLayout(type_layout)
|
include_all.addWidget(QLabel("Include all objects from the same location : "))
|
||||||
|
include_all.addWidget(self.include_all)
|
||||||
|
include_all.addStretch()
|
||||||
|
|
||||||
layout.addLayout(wpt_layout)
|
layout.addLayout(wpt_layout)
|
||||||
layout.addWidget(self.wpt_info)
|
layout.addWidget(self.wpt_info)
|
||||||
|
layout.addLayout(include_all)
|
||||||
layout.addStretch()
|
layout.addStretch()
|
||||||
layout.addWidget(self.add_button)
|
layout.addWidget(self.add_button)
|
||||||
|
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
def on_select_wpt_changed(self):
|
def on_select_wpt_changed(self):
|
||||||
self.selected_waypoint = self.wpt_selection_box.currentData()
|
self.selected_waypoints = self.wpt_selection_box.get_selected_waypoints(self.include_all.isChecked())
|
||||||
self.wpt_info.set_flight_waypoint(self.selected_waypoint)
|
if self.selected_waypoints is None or len(self.selected_waypoints) <= 0:
|
||||||
if self.selected_waypoint is None:
|
|
||||||
self.add_button.setDisabled(True)
|
self.add_button.setDisabled(True)
|
||||||
else:
|
else:
|
||||||
|
self.wpt_info.set_flight_waypoint(self.selected_waypoints[0])
|
||||||
self.add_button.setDisabled(False)
|
self.add_button.setDisabled(False)
|
||||||
|
|
||||||
def on_parameters_changed(self):
|
|
||||||
self.wpt_selection_box.clear()
|
|
||||||
|
|
||||||
select_cp_text = self.cp_selection_box.currentText()
|
|
||||||
select_cp = None
|
|
||||||
for cp in self.game.theater.controlpoints:
|
|
||||||
if cp.name == select_cp_text:
|
|
||||||
select_cp = cp
|
|
||||||
break
|
|
||||||
if select_cp is not None:
|
|
||||||
selected_wpt_type = self.wpt_type_selection_box.currentText()
|
|
||||||
|
|
||||||
if selected_wpt_type == PREDEFINED_WAYPOINT_CATEGORIES[0]: # CAS
|
|
||||||
enemy_cp = [cp for cp in select_cp.connected_points if cp.captured != select_cp.captured]
|
|
||||||
for ecp in enemy_cp:
|
|
||||||
wpt = FlightWaypoint((select_cp.position.x + ecp.position.x)/2, (select_cp.position.y + ecp.position.y)/2, 800)
|
|
||||||
wpt.name = "Frontline with " + ecp.name + " [CAS]"
|
|
||||||
wpt.description = "Frontline"
|
|
||||||
self.wpt_selection_box.addItem(wpt.name, userData=wpt)
|
|
||||||
if len(enemy_cp) == 0:
|
|
||||||
self.wpt_selection_box.addItem("None", userData=None)
|
|
||||||
elif selected_wpt_type == PREDEFINED_WAYPOINT_CATEGORIES[1]: # Building
|
|
||||||
for ground_object in select_cp.ground_objects:
|
|
||||||
if not ground_object.is_dead and not ground_object.dcs_identifier == "AA":
|
|
||||||
wpt = FlightWaypoint(ground_object.position.x,ground_object.position.y, 0)
|
|
||||||
wpt.name = ground_object.category + " #" + str(ground_object.object_id) + " @ site #" + str(ground_object.group_id)
|
|
||||||
if select_cp.captured:
|
|
||||||
wpt.description = "Friendly Building"
|
|
||||||
else:
|
|
||||||
wpt.description = "Enemy Building"
|
|
||||||
self.wpt_selection_box.addItem(wpt.name, userData=wpt)
|
|
||||||
elif selected_wpt_type == PREDEFINED_WAYPOINT_CATEGORIES[2]: # Known units position
|
|
||||||
for ground_object in select_cp.ground_objects:
|
|
||||||
if not ground_object.is_dead and ground_object.dcs_identifier == "AA":
|
|
||||||
for g in ground_object.groups:
|
|
||||||
for u in g.units:
|
|
||||||
wpt = FlightWaypoint(ground_object.position.x, ground_object.position.y, 0)
|
|
||||||
wpt.name = u.type + " @ site #" + str(ground_object.group_id)
|
|
||||||
if select_cp.captured:
|
|
||||||
wpt.description = "Friendly unit :" + u.type
|
|
||||||
else:
|
|
||||||
wpt.description = "Enemy unit :" + u.type
|
|
||||||
self.wpt_selection_box.addItem(wpt.name, userData=wpt)
|
|
||||||
elif selected_wpt_type == PREDEFINED_WAYPOINT_CATEGORIES[3]: # CAS
|
|
||||||
wpt = FlightWaypoint(select_cp.position.x, select_cp.position.y, 0)
|
|
||||||
wpt.name = select_cp.name
|
|
||||||
if select_cp.captured:
|
|
||||||
wpt.description = "Position of " + select_cp.name + " [Friendly Airbase]"
|
|
||||||
else:
|
|
||||||
wpt.description = "Position of " + select_cp.name + " [Enemy Airbase]"
|
|
||||||
self.wpt_selection_box.addItem("Airbase", userData=wpt)
|
|
||||||
else:
|
|
||||||
self.wpt_selection_box.addItem("None", userData=None)
|
|
||||||
else:
|
|
||||||
self.wpt_selection_box.addItem("None", userData=None)
|
|
||||||
|
|
||||||
self.wpt_selection_box.setCurrentIndex(0)
|
|
||||||
|
|
||||||
def add_waypoint(self):
|
def add_waypoint(self):
|
||||||
if not self.selected_waypoint is None:
|
|
||||||
self.flight.points.append(self.selected_waypoint)
|
for wpt in self.selected_waypoints:
|
||||||
|
self.flight.points.append(wpt)
|
||||||
|
|
||||||
self.flight_waypoint_list.update_list()
|
self.flight_waypoint_list.update_list()
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
|||||||
BIN
resources/ui/ground_assets/destroyed.png
Normal file
BIN
resources/ui/ground_assets/destroyed.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 318 B |
@ -166,16 +166,13 @@ class Emirates(ConflictTheater):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Emirates, self).__init__()
|
super(Emirates, self).__init__()
|
||||||
|
|
||||||
self.al_dhafra = ControlPoint.from_airport(persiangulf.Al_Dhafra_AB, LAND, SIZE_BIG, IMPORTANCE_LOW)
|
self.al_dhafra = ControlPoint.from_airport(persiangulf.Al_Dhafra_AB, LAND, SIZE_BIG, IMPORTANCE_MEDIUM)
|
||||||
self.al_maktoum = ControlPoint.from_airport(persiangulf.Al_Maktoum_Intl, LAND, SIZE_BIG, IMPORTANCE_LOW)
|
self.al_maktoum = ControlPoint.from_airport(persiangulf.Al_Maktoum_Intl, LAND, SIZE_BIG, IMPORTANCE_LOW)
|
||||||
self.al_minhad = ControlPoint.from_airport(persiangulf.Al_Minhad_AB, LAND, SIZE_REGULAR, 1.1)
|
self.al_minhad = ControlPoint.from_airport(persiangulf.Al_Minhad_AB, LAND, SIZE_REGULAR, IMPORTANCE_LOW)
|
||||||
self.sir_abu_nuayr = ControlPoint.from_airport(persiangulf.Sir_Abu_Nuayr, [0, 330], SIZE_SMALL, 1.1, has_frontline=False)
|
self.sharjah = ControlPoint.from_airport(persiangulf.Sharjah_Intl, LAND, SIZE_BIG, IMPORTANCE_LOW)
|
||||||
self.dubai = ControlPoint.from_airport(persiangulf.Dubai_Intl, COAST_DL_E, SIZE_LARGE, IMPORTANCE_MEDIUM)
|
self.fujairah = ControlPoint.from_airport(persiangulf.Fujairah_Intl, COAST_V_W, SIZE_REGULAR, IMPORTANCE_LOW)
|
||||||
self.sharjah = ControlPoint.from_airport(persiangulf.Sharjah_Intl, LAND, SIZE_BIG, 1.0)
|
self.ras_al_khaimah = ControlPoint.from_airport(persiangulf.Ras_Al_Khaimah, LAND, SIZE_REGULAR,IMPORTANCE_LOW)
|
||||||
self.fujairah = ControlPoint.from_airport(persiangulf.Fujairah_Intl, COAST_V_W, SIZE_REGULAR, 1.0)
|
self.al_ain = ControlPoint.from_airport(persiangulf.Al_Ain_International_Airport, LAND, SIZE_BIG,IMPORTANCE_LOW)
|
||||||
self.ras_al_khaimah = ControlPoint.from_airport(persiangulf.Ras_Al_Khaimah, LAND, SIZE_REGULAR,IMPORTANCE_MEDIUM)
|
|
||||||
self.al_ain = ControlPoint.from_airport(persiangulf.Al_Ain_International_Airport, LAND, SIZE_BIG,
|
|
||||||
IMPORTANCE_HIGH)
|
|
||||||
|
|
||||||
self.east_carrier = ControlPoint.carrier("Carrier", Point(-61770, 69039), 1001)
|
self.east_carrier = ControlPoint.carrier("Carrier", Point(-61770, 69039), 1001)
|
||||||
self.tarawa_carrier = ControlPoint.lha("LHA Carrier", Point(-79770, 49430), 1002)
|
self.tarawa_carrier = ControlPoint.lha("LHA Carrier", Point(-79770, 49430), 1002)
|
||||||
@ -183,12 +180,10 @@ class Emirates(ConflictTheater):
|
|||||||
self.add_controlpoint(self.al_dhafra, connected_to=[self.al_ain, self.al_maktoum])
|
self.add_controlpoint(self.al_dhafra, connected_to=[self.al_ain, self.al_maktoum])
|
||||||
self.add_controlpoint(self.al_ain, connected_to=[self.fujairah, self.al_maktoum, self.al_dhafra])
|
self.add_controlpoint(self.al_ain, connected_to=[self.fujairah, self.al_maktoum, self.al_dhafra])
|
||||||
self.add_controlpoint(self.al_maktoum, connected_to=[self.al_dhafra, self.al_minhad, self.al_ain])
|
self.add_controlpoint(self.al_maktoum, connected_to=[self.al_dhafra, self.al_minhad, self.al_ain])
|
||||||
self.add_controlpoint(self.al_minhad, connected_to=[self.al_maktoum, self.dubai])
|
self.add_controlpoint(self.al_minhad, connected_to=[self.al_maktoum, self.sharjah])
|
||||||
self.add_controlpoint(self.dubai, connected_to=[self.al_minhad, self.sharjah])
|
self.add_controlpoint(self.sharjah, connected_to=[self.al_minhad, self.ras_al_khaimah, self.fujairah])
|
||||||
self.add_controlpoint(self.sharjah, connected_to=[self.dubai, self.ras_al_khaimah, self.fujairah])
|
|
||||||
self.add_controlpoint(self.ras_al_khaimah, connected_to=[self.sharjah])
|
self.add_controlpoint(self.ras_al_khaimah, connected_to=[self.sharjah])
|
||||||
self.add_controlpoint(self.fujairah, connected_to=[self.sharjah, self.al_ain])
|
self.add_controlpoint(self.fujairah, connected_to=[self.sharjah, self.al_ain])
|
||||||
self.add_controlpoint(self.sir_abu_nuayr, connected_to=[])
|
|
||||||
|
|
||||||
self.add_controlpoint(self.tarawa_carrier)
|
self.add_controlpoint(self.tarawa_carrier)
|
||||||
self.add_controlpoint(self.east_carrier)
|
self.add_controlpoint(self.east_carrier)
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import random
|
|||||||
import typing
|
import typing
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from gen import namegen
|
||||||
from gen.defenses.armor_group_generator import generate_armor_group
|
from gen.defenses.armor_group_generator import generate_armor_group
|
||||||
from gen.fleet.ship_group_generator import generate_carrier_group, generate_lha_group
|
from gen.fleet.ship_group_generator import generate_carrier_group, generate_lha_group
|
||||||
from gen.sam.sam_group_generator import generate_anti_air_group, generate_shorad_group
|
from gen.sam.sam_group_generator import generate_anti_air_group, generate_shorad_group
|
||||||
@ -79,6 +80,7 @@ def generate_groundobjects(theater: ConflictTheater, game):
|
|||||||
g.cp_id = cp.id
|
g.cp_id = cp.id
|
||||||
g.airbase_group = True
|
g.airbase_group = True
|
||||||
g.dcs_identifier = "CARRIER"
|
g.dcs_identifier = "CARRIER"
|
||||||
|
g.obj_name = namegen.random_objective_name()
|
||||||
g.heading = 0
|
g.heading = 0
|
||||||
g.position = Point(cp.position.x, cp.position.y)
|
g.position = Point(cp.position.x, cp.position.y)
|
||||||
group = generate_carrier_group(faction, game, g)
|
group = generate_carrier_group(faction, game, g)
|
||||||
@ -98,6 +100,7 @@ def generate_groundobjects(theater: ConflictTheater, game):
|
|||||||
g.cp_id = cp.id
|
g.cp_id = cp.id
|
||||||
g.airbase_group = True
|
g.airbase_group = True
|
||||||
g.dcs_identifier = "LHA"
|
g.dcs_identifier = "LHA"
|
||||||
|
g.obj_name = namegen.random_objective_name()
|
||||||
g.heading = 0
|
g.heading = 0
|
||||||
g.position = Point(cp.position.x, cp.position.y)
|
g.position = Point(cp.position.x, cp.position.y)
|
||||||
group = generate_lha_group(faction, game, g)
|
group = generate_lha_group(faction, game, g)
|
||||||
@ -124,6 +127,7 @@ def generate_groundobjects(theater: ConflictTheater, game):
|
|||||||
g.cp_id = cp.id
|
g.cp_id = cp.id
|
||||||
g.airbase_group = True
|
g.airbase_group = True
|
||||||
g.dcs_identifier = "AA"
|
g.dcs_identifier = "AA"
|
||||||
|
g.obj_name = namegen.random_objective_name()
|
||||||
g.heading = 0
|
g.heading = 0
|
||||||
g.position = Point(point.x, point.y)
|
g.position = Point(point.x, point.y)
|
||||||
|
|
||||||
@ -160,6 +164,8 @@ def find_location(on_ground, near, theater, min, max, others) -> typing.Optional
|
|||||||
"""
|
"""
|
||||||
point = None
|
point = None
|
||||||
for _ in range(1000):
|
for _ in range(1000):
|
||||||
|
|
||||||
|
# Check if on land or sea
|
||||||
p = near.random_point_within(max, min)
|
p = near.random_point_within(max, min)
|
||||||
if on_ground and theater.is_on_land(p):
|
if on_ground and theater.is_on_land(p):
|
||||||
point = p
|
point = p
|
||||||
@ -180,6 +186,20 @@ def find_location(on_ground, near, theater, min, max, others) -> typing.Optional
|
|||||||
if other.position.distance_to_point(point) < 10000:
|
if other.position.distance_to_point(point) < 10000:
|
||||||
point = None
|
point = None
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if point:
|
||||||
|
for other in theater.controlpoints:
|
||||||
|
if other.position != near:
|
||||||
|
if point is None:
|
||||||
|
break
|
||||||
|
if other.position.distance_to_point(point) < 30000:
|
||||||
|
point = None
|
||||||
|
break
|
||||||
|
for ground_obj in other.ground_objects:
|
||||||
|
if ground_obj.position.distance_to_point(point) < 10000:
|
||||||
|
point = None
|
||||||
|
break
|
||||||
|
|
||||||
if point:
|
if point:
|
||||||
return point
|
return point
|
||||||
return None
|
return None
|
||||||
@ -201,13 +221,16 @@ def generate_cp_ground_points(cp: ControlPoint, theater, game, group_id, templat
|
|||||||
if cp.is_global:
|
if cp.is_global:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
amount = random.randrange(1, 7)
|
amount = random.randrange(3, 8)
|
||||||
for i in range(0, amount):
|
for i in range(0, amount):
|
||||||
|
|
||||||
available_categories = list(templates)
|
available_categories = list(templates)
|
||||||
|
obj_name = namegen.random_objective_name()
|
||||||
|
|
||||||
if i >= amount - 1:
|
if i >= amount - 1:
|
||||||
tpl_category = "aa"
|
tpl_category = "aa"
|
||||||
else:
|
else:
|
||||||
if random.randint(0, 2) == 0:
|
if random.randint(0, 3) == 0:
|
||||||
tpl_category = "aa"
|
tpl_category = "aa"
|
||||||
else:
|
else:
|
||||||
tpl_category = random.choice(available_categories)
|
tpl_category = random.choice(available_categories)
|
||||||
@ -223,6 +246,7 @@ def generate_cp_ground_points(cp: ControlPoint, theater, game, group_id, templat
|
|||||||
group_id = group_id + 1
|
group_id = group_id + 1
|
||||||
|
|
||||||
logging.info("generated {} for {}".format(tpl_category, cp))
|
logging.info("generated {} for {}".format(tpl_category, cp))
|
||||||
|
|
||||||
for object in tpl:
|
for object in tpl:
|
||||||
object_id += 1
|
object_id += 1
|
||||||
|
|
||||||
@ -231,12 +255,12 @@ def generate_cp_ground_points(cp: ControlPoint, theater, game, group_id, templat
|
|||||||
g.object_id = object_id
|
g.object_id = object_id
|
||||||
g.cp_id = cp.id
|
g.cp_id = cp.id
|
||||||
g.airbase_gorup = False
|
g.airbase_gorup = False
|
||||||
|
g.obj_name = obj_name
|
||||||
|
|
||||||
g.dcs_identifier = object["type"]
|
g.dcs_identifier = object["type"]
|
||||||
g.heading = object["heading"]
|
g.heading = object["heading"]
|
||||||
g.position = Point(point.x + object["offset"].x, point.y + object["offset"].y)
|
g.position = Point(point.x + object["offset"].x, point.y + object["offset"].y)
|
||||||
|
|
||||||
|
|
||||||
if g.dcs_identifier == "AA":
|
if g.dcs_identifier == "AA":
|
||||||
if cp.captured:
|
if cp.captured:
|
||||||
faction = game.player_name
|
faction = game.player_name
|
||||||
|
|||||||
@ -49,15 +49,13 @@ class TheaterGroundObject:
|
|||||||
cp_id = 0
|
cp_id = 0
|
||||||
group_id = 0
|
group_id = 0
|
||||||
object_id = 0
|
object_id = 0
|
||||||
|
|
||||||
dcs_identifier = None # type: str
|
dcs_identifier = None # type: str
|
||||||
is_dead = False
|
is_dead = False
|
||||||
airbase_group = False
|
airbase_group = False
|
||||||
|
|
||||||
heading = 0
|
heading = 0
|
||||||
position = None # type: Point
|
position = None # type: Point
|
||||||
|
|
||||||
groups = []
|
groups = []
|
||||||
|
obj_name = ""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def category(self) -> str:
|
def category(self) -> str:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user