mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Add runway bombing missions.
This allows planning the missions and the missions are functional, but they will have no effect on future turns yet.
This commit is contained in:
parent
63bdbebcaa
commit
9394ed663a
@ -401,7 +401,7 @@ class Airfield(ControlPoint):
|
||||
return True
|
||||
|
||||
def mission_types(self, for_player: bool) -> Iterator[FlightType]:
|
||||
yield from super().mission_types(for_player)
|
||||
from gen.flights.flight import FlightType
|
||||
if self.is_friendly(for_player):
|
||||
yield from [
|
||||
# TODO: FlightType.INTERCEPTION
|
||||
@ -409,8 +409,10 @@ class Airfield(ControlPoint):
|
||||
]
|
||||
else:
|
||||
yield from [
|
||||
# TODO: FlightType.STRIKE
|
||||
FlightType.RUNWAY_ATTACK,
|
||||
# TODO: FlightType.OCA_STRIKE
|
||||
]
|
||||
yield from super().mission_types(for_player)
|
||||
|
||||
@property
|
||||
def total_aircraft_parking(self) -> int:
|
||||
|
||||
@ -41,6 +41,7 @@ from dcs.task import (
|
||||
AntishipStrike,
|
||||
AttackGroup,
|
||||
Bombing,
|
||||
BombingRunway,
|
||||
CAP,
|
||||
CAS,
|
||||
ControlledTask,
|
||||
@ -55,6 +56,7 @@ from dcs.task import (
|
||||
OptReactOnThreat,
|
||||
OptRestrictJettison,
|
||||
OrbitAction,
|
||||
RunwayAttack,
|
||||
SEAD,
|
||||
StartCommand,
|
||||
Targets,
|
||||
@ -1169,6 +1171,18 @@ class AircraftConflictGenerator:
|
||||
roe=OptROE.Values.OpenFire,
|
||||
restrict_jettison=True)
|
||||
|
||||
def configure_runway_attack(
|
||||
self, group: FlyingGroup, package: Package, flight: Flight,
|
||||
dynamic_runways: Dict[str, RunwayData]) -> None:
|
||||
group.task = RunwayAttack.name
|
||||
self._setup_group(group, RunwayAttack, package, flight,
|
||||
dynamic_runways)
|
||||
self.configure_behavior(
|
||||
group,
|
||||
react_on_threat=OptReactOnThreat.Values.EvadeFire,
|
||||
roe=OptROE.Values.OpenFire,
|
||||
restrict_jettison=True)
|
||||
|
||||
def configure_escort(self, group: FlyingGroup, package: Package,
|
||||
flight: Flight,
|
||||
dynamic_runways: Dict[str, RunwayData]) -> None:
|
||||
@ -1206,6 +1220,9 @@ class AircraftConflictGenerator:
|
||||
self.configure_anti_ship(group, package, flight, dynamic_runways)
|
||||
elif flight_type == FlightType.ESCORT:
|
||||
self.configure_escort(group, package, flight, dynamic_runways)
|
||||
elif flight_type == FlightType.RUNWAY_ATTACK:
|
||||
self.configure_runway_attack(group, package, flight,
|
||||
dynamic_runways)
|
||||
else:
|
||||
self.configure_unknown_task(group, flight)
|
||||
|
||||
@ -1345,6 +1362,7 @@ class PydcsWaypointBuilder:
|
||||
FlightWaypointType.INGRESS_BAI: BaiIngressBuilder,
|
||||
FlightWaypointType.INGRESS_CAS: CasIngressBuilder,
|
||||
FlightWaypointType.INGRESS_DEAD: DeadIngressBuilder,
|
||||
FlightWaypointType.INGRESS_RUNWAY_BOMBING: RunwayBombingIngressBuilder,
|
||||
FlightWaypointType.INGRESS_SEAD: SeadIngressBuilder,
|
||||
FlightWaypointType.INGRESS_STRIKE: StrikeIngressBuilder,
|
||||
FlightWaypointType.JOIN: JoinPointBuilder,
|
||||
@ -1480,6 +1498,22 @@ class DeadIngressBuilder(PydcsWaypointBuilder):
|
||||
return waypoint
|
||||
|
||||
|
||||
class RunwayBombingIngressBuilder(PydcsWaypointBuilder):
|
||||
def build(self) -> MovingPoint:
|
||||
waypoint = super().build()
|
||||
|
||||
target = self.package.target
|
||||
if not isinstance(target, Airfield):
|
||||
logging.error(
|
||||
"Unexpected target type for runway bombing mission: %s",
|
||||
target.__class__.__name__)
|
||||
return waypoint
|
||||
|
||||
waypoint.tasks.append(
|
||||
BombingRunway(airport_id=target.airport.id, group_attack=True))
|
||||
return waypoint
|
||||
|
||||
|
||||
class SeadIngressBuilder(PydcsWaypointBuilder):
|
||||
def build(self) -> MovingPoint:
|
||||
waypoint = super().build()
|
||||
|
||||
@ -44,6 +44,8 @@ from gen.flights.ai_flight_planner_db import (
|
||||
CAP_PREFERRED,
|
||||
CAS_CAPABLE,
|
||||
CAS_PREFERRED,
|
||||
RUNWAY_ATTACK_CAPABLE,
|
||||
RUNWAY_ATTACK_PREFERRED,
|
||||
SEAD_CAPABLE,
|
||||
SEAD_PREFERRED,
|
||||
STRIKE_CAPABLE,
|
||||
@ -160,6 +162,8 @@ class AircraftAllocator:
|
||||
return CAS_PREFERRED
|
||||
elif task in (FlightType.DEAD, FlightType.SEAD):
|
||||
return SEAD_PREFERRED
|
||||
elif task == FlightType.RUNWAY_ATTACK:
|
||||
return RUNWAY_ATTACK_PREFERRED
|
||||
elif task == FlightType.STRIKE:
|
||||
return STRIKE_PREFERRED
|
||||
elif task == FlightType.ESCORT:
|
||||
@ -180,6 +184,8 @@ class AircraftAllocator:
|
||||
return CAS_CAPABLE
|
||||
elif task in (FlightType.DEAD, FlightType.SEAD):
|
||||
return SEAD_CAPABLE
|
||||
elif task == FlightType.RUNWAY_ATTACK:
|
||||
return RUNWAY_ATTACK_CAPABLE
|
||||
elif task == FlightType.STRIKE:
|
||||
return STRIKE_CAPABLE
|
||||
elif task == FlightType.ESCORT:
|
||||
|
||||
@ -484,6 +484,13 @@ ANTISHIP_PREFERRED = [
|
||||
Su_24M,
|
||||
]
|
||||
|
||||
RUNWAY_ATTACK_PREFERRED = [
|
||||
JF_17,
|
||||
M_2000C,
|
||||
]
|
||||
|
||||
RUNWAY_ATTACK_CAPABLE = STRIKE_CAPABLE
|
||||
|
||||
DRONES = [
|
||||
MQ_9_Reaper,
|
||||
RQ_1A_Predator,
|
||||
|
||||
@ -39,6 +39,7 @@ class FlightType(Enum):
|
||||
EWAR = 16
|
||||
|
||||
SWEEP = 17
|
||||
RUNWAY_ATTACK = 18
|
||||
|
||||
|
||||
class FlightWaypointType(Enum):
|
||||
@ -66,6 +67,7 @@ class FlightWaypointType(Enum):
|
||||
INGRESS_SWEEP = 21
|
||||
INGRESS_BAI = 22
|
||||
DIVERT = 23
|
||||
INGRESS_RUNWAY_BOMBING = 24
|
||||
|
||||
|
||||
class FlightWaypoint:
|
||||
|
||||
@ -20,6 +20,7 @@ from dcs.unit import Unit
|
||||
|
||||
from game.data.doctrine import Doctrine
|
||||
from game.theater import (
|
||||
Airfield,
|
||||
ControlPoint,
|
||||
FrontLine,
|
||||
MissionTarget,
|
||||
@ -650,6 +651,8 @@ class FlightPlanBuilder:
|
||||
return self.generate_dead(flight, custom_targets)
|
||||
elif task == FlightType.ESCORT:
|
||||
return self.generate_escort(flight)
|
||||
elif task == FlightType.RUNWAY_ATTACK:
|
||||
return self.generate_runway_attack(flight)
|
||||
elif task == FlightType.SEAD:
|
||||
return self.generate_sead(flight, custom_targets)
|
||||
elif task == FlightType.STRIKE:
|
||||
@ -713,7 +716,9 @@ class FlightPlanBuilder:
|
||||
|
||||
targets.append(StrikeTarget(building.category, building))
|
||||
|
||||
return self.strike_flightplan(flight, location, targets)
|
||||
return self.strike_flightplan(flight, location,
|
||||
FlightWaypointType.INGRESS_STRIKE,
|
||||
targets)
|
||||
|
||||
def generate_bai(self, flight: Flight) -> StrikeFlightPlan:
|
||||
"""Generates a BAI flight plan.
|
||||
@ -731,7 +736,8 @@ class FlightPlanBuilder:
|
||||
targets.append(
|
||||
StrikeTarget(f"{group.name} at {location.name}", group))
|
||||
|
||||
return self.strike_flightplan(flight, location, targets)
|
||||
return self.strike_flightplan(flight, location,
|
||||
FlightWaypointType.INGRESS_BAI, targets)
|
||||
|
||||
def generate_anti_ship(self, flight: Flight) -> StrikeFlightPlan:
|
||||
"""Generates an anti-ship flight plan.
|
||||
@ -756,7 +762,8 @@ class FlightPlanBuilder:
|
||||
targets.append(
|
||||
StrikeTarget(f"{group.name} at {location.name}", group))
|
||||
|
||||
return self.strike_flightplan(flight, location, targets)
|
||||
return self.strike_flightplan(flight, location,
|
||||
FlightWaypointType.INGRESS_BAI, targets)
|
||||
|
||||
def generate_barcap(self, flight: Flight) -> BarCapFlightPlan:
|
||||
"""Generate a BARCAP flight at a given location.
|
||||
@ -942,7 +949,25 @@ class FlightPlanBuilder:
|
||||
for target in custom_targets:
|
||||
targets.append(StrikeTarget(location.name, target))
|
||||
|
||||
return self.strike_flightplan(flight, location, targets)
|
||||
return self.strike_flightplan(flight, location,
|
||||
FlightWaypointType.INGRESS_DEAD, targets)
|
||||
|
||||
def generate_runway_attack(self, flight: Flight) -> StrikeFlightPlan:
|
||||
"""Generate a runway attack flight plan at a given location.
|
||||
|
||||
Args:
|
||||
flight: The flight to generate the flight plan for.
|
||||
"""
|
||||
location = self.package.target
|
||||
|
||||
if not isinstance(location, Airfield):
|
||||
logging.exception(
|
||||
f"Invalid Objective Location for runway bombing flight "
|
||||
f"{flight=} at {location=}.")
|
||||
raise InvalidObjectiveLocation(flight.flight_type, location)
|
||||
|
||||
return self.strike_flightplan(flight, location,
|
||||
FlightWaypointType.INGRESS_RUNWAY_BOMBING)
|
||||
|
||||
def generate_sead(self, flight: Flight,
|
||||
custom_targets: Optional[List[Unit]]) -> StrikeFlightPlan:
|
||||
@ -963,7 +988,8 @@ class FlightPlanBuilder:
|
||||
for target in custom_targets:
|
||||
targets.append(StrikeTarget(location.name, target))
|
||||
|
||||
return self.strike_flightplan(flight, location, targets)
|
||||
return self.strike_flightplan(flight, location,
|
||||
FlightWaypointType.INGRESS_SEAD, targets)
|
||||
|
||||
def generate_escort(self, flight: Flight) -> StrikeFlightPlan:
|
||||
assert self.package.waypoints is not None
|
||||
@ -1012,7 +1038,8 @@ class FlightPlanBuilder:
|
||||
flight=flight,
|
||||
patrol_duration=self.doctrine.cas_duration,
|
||||
takeoff=builder.takeoff(flight.departure),
|
||||
patrol_start=builder.ingress_cas(ingress, location),
|
||||
patrol_start=builder.ingress(FlightWaypointType.INGRESS_CAS,
|
||||
ingress, location),
|
||||
target=builder.cas(center),
|
||||
patrol_end=builder.egress(egress, location),
|
||||
land=builder.land(flight.arrival),
|
||||
@ -1101,23 +1128,11 @@ class FlightPlanBuilder:
|
||||
|
||||
def strike_flightplan(
|
||||
self, flight: Flight, location: MissionTarget,
|
||||
ingress_type: FlightWaypointType,
|
||||
targets: Optional[List[StrikeTarget]] = None) -> StrikeFlightPlan:
|
||||
assert self.package.waypoints is not None
|
||||
builder = WaypointBuilder(self.game.conditions, flight, self.doctrine,
|
||||
targets)
|
||||
if flight.flight_type is FlightType.SEAD:
|
||||
ingress = builder.ingress_sead(self.package.waypoints.ingress,
|
||||
location)
|
||||
|
||||
elif flight.flight_type is FlightType.DEAD:
|
||||
ingress = builder.ingress_dead(self.package.waypoints.ingress,
|
||||
location)
|
||||
elif flight.flight_type in {FlightType.ANTISHIP, FlightType.BAI}:
|
||||
ingress = builder.ingress_bai(self.package.waypoints.ingress,
|
||||
location)
|
||||
else:
|
||||
ingress = builder.ingress_strike(self.package.waypoints.ingress,
|
||||
location)
|
||||
|
||||
target_waypoints: List[FlightWaypoint] = []
|
||||
if targets is not None:
|
||||
@ -1134,7 +1149,8 @@ class FlightPlanBuilder:
|
||||
takeoff=builder.takeoff(flight.departure),
|
||||
hold=builder.hold(self._hold_point(flight)),
|
||||
join=builder.join(self.package.waypoints.join),
|
||||
ingress=ingress,
|
||||
ingress=builder.ingress(ingress_type,
|
||||
self.package.waypoints.ingress, location),
|
||||
targets=target_waypoints,
|
||||
egress=builder.egress(self.package.waypoints.egress, location),
|
||||
split=builder.split(self.package.waypoints.split),
|
||||
|
||||
@ -173,37 +173,7 @@ class WaypointBuilder:
|
||||
waypoint.name = "SPLIT"
|
||||
return waypoint
|
||||
|
||||
def ingress_cas(self, position: Point,
|
||||
objective: MissionTarget) -> FlightWaypoint:
|
||||
return self._ingress(FlightWaypointType.INGRESS_CAS, position,
|
||||
objective)
|
||||
|
||||
def ingress_escort(self, position: Point,
|
||||
objective: MissionTarget) -> FlightWaypoint:
|
||||
return self._ingress(FlightWaypointType.INGRESS_ESCORT, position,
|
||||
objective)
|
||||
|
||||
def ingress_bai(self, position: Point,
|
||||
objective: MissionTarget) -> FlightWaypoint:
|
||||
return self._ingress(FlightWaypointType.INGRESS_BAI, position,
|
||||
objective)
|
||||
|
||||
def ingress_dead(self, position:Point,
|
||||
objective: MissionTarget) -> FlightWaypoint:
|
||||
return self._ingress(FlightWaypointType.INGRESS_DEAD, position,
|
||||
objective)
|
||||
|
||||
def ingress_sead(self, position: Point,
|
||||
objective: MissionTarget) -> FlightWaypoint:
|
||||
return self._ingress(FlightWaypointType.INGRESS_SEAD, position,
|
||||
objective)
|
||||
|
||||
def ingress_strike(self, position: Point,
|
||||
objective: MissionTarget) -> FlightWaypoint:
|
||||
return self._ingress(FlightWaypointType.INGRESS_STRIKE, position,
|
||||
objective)
|
||||
|
||||
def _ingress(self, ingress_type: FlightWaypointType, position: Point,
|
||||
def ingress(self, ingress_type: FlightWaypointType, position: Point,
|
||||
objective: MissionTarget) -> FlightWaypoint:
|
||||
waypoint = FlightWaypoint(
|
||||
ingress_type,
|
||||
@ -415,7 +385,7 @@ class WaypointBuilder:
|
||||
# description in gen.aircraft.JoinPointBuilder), so instead we give
|
||||
# the escort flights a flight plan including the ingress point, target
|
||||
# area, and egress point.
|
||||
ingress = self._ingress(FlightWaypointType.INGRESS_ESCORT, ingress,
|
||||
ingress = self.ingress(FlightWaypointType.INGRESS_ESCORT, ingress,
|
||||
target)
|
||||
|
||||
waypoint = FlightWaypoint(
|
||||
|
||||
@ -1,8 +1,17 @@
|
||||
from PySide2.QtCore import Qt
|
||||
from PySide2.QtGui import QCloseEvent, QPixmap
|
||||
from PySide2.QtWidgets import QDialog, QGridLayout, QHBoxLayout, QLabel, QWidget
|
||||
from PySide2.QtWidgets import (
|
||||
QDialog,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QPushButton,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from game.theater import ControlPoint, ControlPointType
|
||||
from gen.flights.flight import FlightType
|
||||
from qt_ui.dialogs import Dialog
|
||||
from qt_ui.models import GameModel
|
||||
from qt_ui.uiconstants import EVENT_ICONS
|
||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||
@ -20,9 +29,6 @@ class QBaseMenu2(QDialog):
|
||||
self.game_model = game_model
|
||||
self.objectName = "menuDialogue"
|
||||
|
||||
# Widgets
|
||||
self.qbase_menu_tab = QBaseMenuTabs(cp, self.game_model)
|
||||
|
||||
try:
|
||||
game = self.game_model.game
|
||||
self.airport = game.theater.terrain.airport_by_id(self.cp.id)
|
||||
@ -39,15 +45,11 @@ class QBaseMenu2(QDialog):
|
||||
self.setMinimumWidth(800)
|
||||
self.setMaximumWidth(800)
|
||||
self.setModal(True)
|
||||
self.initUi()
|
||||
|
||||
def initUi(self):
|
||||
self.setWindowTitle(self.cp.name)
|
||||
self.topLayoutWidget = QWidget()
|
||||
self.topLayout = QHBoxLayout()
|
||||
|
||||
self.topLayoutWidget = QWidget()
|
||||
self.topLayout = QHBoxLayout()
|
||||
base_menu_header = QWidget()
|
||||
top_layout = QHBoxLayout()
|
||||
|
||||
header = QLabel(self)
|
||||
header.setGeometry(0, 0, 655, 106)
|
||||
@ -57,26 +59,42 @@ class QBaseMenu2(QDialog):
|
||||
title = QLabel("<b>" + self.cp.name + "</b>")
|
||||
title.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
||||
title.setProperty("style", "base-title")
|
||||
unitsPower = QLabel("{} / {} / Runway : {}".format(self.cp.base.total_aircraft, self.cp.base.total_armor,
|
||||
"Available" if self.cp.has_runway() else "Unavailable"))
|
||||
self.topLayout.addWidget(title)
|
||||
self.topLayout.addWidget(unitsPower)
|
||||
self.topLayout.setAlignment(Qt.AlignTop)
|
||||
self.topLayoutWidget.setProperty("style", "baseMenuHeader")
|
||||
self.topLayoutWidget.setLayout(self.topLayout)
|
||||
aircraft = self.cp.base.total_aircraft
|
||||
armor = self.cp.base.total_armor
|
||||
runway_status = "operational" if self.cp.has_runway() else "inoperative"
|
||||
intel_summary = QLabel("\n".join([
|
||||
f"{aircraft} aircraft",
|
||||
f"{armor} ground units",
|
||||
f"Runway {runway_status}"
|
||||
]))
|
||||
top_layout.addWidget(title)
|
||||
top_layout.addWidget(intel_summary)
|
||||
top_layout.setAlignment(Qt.AlignTop)
|
||||
base_menu_header.setProperty("style", "baseMenuHeader")
|
||||
base_menu_header.setLayout(top_layout)
|
||||
|
||||
self.mainLayout = QGridLayout()
|
||||
self.mainLayout.addWidget(header, 0, 0)
|
||||
self.mainLayout.addWidget(self.topLayoutWidget, 1, 0)
|
||||
self.mainLayout.addWidget(self.qbase_menu_tab, 2, 0)
|
||||
totalBudget = QLabel(
|
||||
main_layout = QVBoxLayout()
|
||||
main_layout.addWidget(header)
|
||||
main_layout.addWidget(base_menu_header)
|
||||
main_layout.addWidget(QBaseMenuTabs(cp, self.game_model))
|
||||
bottom_row = QHBoxLayout()
|
||||
main_layout.addLayout(bottom_row)
|
||||
|
||||
if FlightType.RUNWAY_ATTACK in self.cp.mission_types(for_player=True):
|
||||
runway_attack_button = QPushButton("Attack airfield")
|
||||
bottom_row.addWidget(runway_attack_button)
|
||||
|
||||
runway_attack_button.setProperty("style", "btn-danger")
|
||||
runway_attack_button.clicked.connect(self.new_package)
|
||||
|
||||
budget_display = QLabel(
|
||||
QRecruitBehaviour.BUDGET_FORMAT.format(self.game_model.game.budget)
|
||||
)
|
||||
totalBudget.setObjectName("budgetField")
|
||||
totalBudget.setAlignment(Qt.AlignRight | Qt.AlignBottom)
|
||||
totalBudget.setProperty("style", "budget-label")
|
||||
self.mainLayout.addWidget(totalBudget)
|
||||
self.setLayout(self.mainLayout)
|
||||
budget_display.setObjectName("budgetField")
|
||||
budget_display.setAlignment(Qt.AlignRight | Qt.AlignBottom)
|
||||
budget_display.setProperty("style", "budget-label")
|
||||
bottom_row.addWidget(budget_display)
|
||||
self.setLayout(main_layout)
|
||||
|
||||
def closeEvent(self, closeEvent:QCloseEvent):
|
||||
GameUpdateSignal.get_instance().updateGame(self.game_model.game)
|
||||
@ -88,3 +106,6 @@ class QBaseMenu2(QDialog):
|
||||
return "./resources/ui/lha.png"
|
||||
else:
|
||||
return "./resources/ui/airbase.png"
|
||||
|
||||
def new_package(self) -> None:
|
||||
Dialog.open_new_package_dialog(self.cp, parent=self.window())
|
||||
|
||||
@ -265,6 +265,50 @@ local unitPayloads = {
|
||||
[1] = 11,
|
||||
},
|
||||
},
|
||||
[7] = {
|
||||
["name"] = "RUNWAY_ATTACK",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "{5CE2FF2A-645A-4197-B48D-8720AC69394F}",
|
||||
["num"] = 9,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "{5CE2FF2A-645A-4197-B48D-8720AC69394F}",
|
||||
["num"] = 1,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "{BRU33_2X_MK-82}",
|
||||
["num"] = 5,
|
||||
},
|
||||
[4] = {
|
||||
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
|
||||
["num"] = 6,
|
||||
},
|
||||
[5] = {
|
||||
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
|
||||
["num"] = 4,
|
||||
},
|
||||
[6] = {
|
||||
["CLSID"] = "{FPU_8A_FUEL_TANK}",
|
||||
["num"] = 7,
|
||||
},
|
||||
[7] = {
|
||||
["CLSID"] = "{FPU_8A_FUEL_TANK}",
|
||||
["num"] = 3,
|
||||
},
|
||||
[8] = {
|
||||
["CLSID"] = "{BRU33_2X_MK-82}",
|
||||
["num"] = 2,
|
||||
},
|
||||
[9] = {
|
||||
["CLSID"] = "{BRU33_2X_MK-82}",
|
||||
["num"] = 8,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 34,
|
||||
},
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
},
|
||||
|
||||
@ -189,6 +189,54 @@ local unitPayloads = {
|
||||
[1] = 11,
|
||||
},
|
||||
},
|
||||
[6] = {
|
||||
["name"] = "RUNWAY_ATTACK",
|
||||
["pylons"] = {
|
||||
[1] = {
|
||||
["CLSID"] = "{Eclair}",
|
||||
["num"] = 10,
|
||||
},
|
||||
[2] = {
|
||||
["CLSID"] = "{MMagicII}",
|
||||
["num"] = 9,
|
||||
},
|
||||
[3] = {
|
||||
["CLSID"] = "{MMagicII}",
|
||||
["num"] = 1,
|
||||
},
|
||||
[4] = {
|
||||
["CLSID"] = "{BLG66_BELOUGA_AC}",
|
||||
["num"] = 8,
|
||||
},
|
||||
[5] = {
|
||||
["CLSID"] = "{BLG66_BELOUGA_AC}",
|
||||
["num"] = 2,
|
||||
},
|
||||
[6] = {
|
||||
["CLSID"] = "{BLG66_BELOUGA_AC}",
|
||||
["num"] = 7,
|
||||
},
|
||||
[7] = {
|
||||
["CLSID"] = "{BLG66_BELOUGA_AC}",
|
||||
["num"] = 3,
|
||||
},
|
||||
[8] = {
|
||||
["CLSID"] = "{BLG66_BELOUGA_AC}",
|
||||
["num"] = 4,
|
||||
},
|
||||
[9] = {
|
||||
["CLSID"] = "{BLG66_BELOUGA_AC}",
|
||||
["num"] = 6,
|
||||
},
|
||||
[10] = {
|
||||
["CLSID"] = "{BLG66_BELOUGA_AC}",
|
||||
["num"] = 5,
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
[1] = 34,
|
||||
},
|
||||
},
|
||||
},
|
||||
["tasks"] = {
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user