mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
planes db updates: fixed loadouts & tasks
This commit is contained in:
parent
45dbb37d50
commit
002ee75a26
17
game/db.py
17
game/db.py
@ -24,7 +24,6 @@ PRICES = {
|
|||||||
|
|
||||||
M_2000C: 18,
|
M_2000C: 18,
|
||||||
FA_18C_hornet: 22,
|
FA_18C_hornet: 22,
|
||||||
AV8BNA: 18,
|
|
||||||
F_15C: 28,
|
F_15C: 28,
|
||||||
|
|
||||||
# bomber
|
# bomber
|
||||||
@ -75,7 +74,7 @@ PRICES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UNIT_BY_TASK = {
|
UNIT_BY_TASK = {
|
||||||
FighterSweep: [
|
CAP: [
|
||||||
C_101CC,
|
C_101CC,
|
||||||
AJS37,
|
AJS37,
|
||||||
F_5E,
|
F_5E,
|
||||||
@ -84,21 +83,20 @@ UNIT_BY_TASK = {
|
|||||||
MiG_31,
|
MiG_31,
|
||||||
Su_27,
|
Su_27,
|
||||||
Su_33,
|
Su_33,
|
||||||
MiG_15bis,
|
|
||||||
MiG_21Bis,
|
MiG_21Bis,
|
||||||
MiG_29A,
|
MiG_29A,
|
||||||
FA_18C_hornet,
|
FA_18C_hornet,
|
||||||
AV8BNA,
|
|
||||||
F_15C,
|
F_15C,
|
||||||
M_2000C,
|
M_2000C,
|
||||||
],
|
],
|
||||||
CAS: [
|
CAS: [
|
||||||
|
MiG_15bis,
|
||||||
|
L_39ZA,
|
||||||
A_10A,
|
A_10A,
|
||||||
A_10C,
|
A_10C,
|
||||||
Su_25T,
|
Su_25T,
|
||||||
Su_24M,
|
Su_24M,
|
||||||
Su_17M4,
|
Su_17M4,
|
||||||
L_39ZA,
|
|
||||||
MiG_29G,
|
MiG_29G,
|
||||||
Su_34,
|
Su_34,
|
||||||
],
|
],
|
||||||
@ -114,7 +112,7 @@ UNIT_BY_TASK = {
|
|||||||
],
|
],
|
||||||
AWACS: [E_3A, A_50, ],
|
AWACS: [E_3A, A_50, ],
|
||||||
|
|
||||||
CAP: [Armor.MBT_T_90, Armor.MBT_T_80U, Armor.MBT_T_55, Armor.MBT_M1A2_Abrams, Armor.MBT_M60A3_Patton, Armor.ATGM_M1134_Stryker, Armor.APC_BTR_80, ],
|
PinpointStrike: [Armor.MBT_T_90, Armor.MBT_T_80U, Armor.MBT_T_55, Armor.MBT_M1A2_Abrams, Armor.MBT_M60A3_Patton, Armor.ATGM_M1134_Stryker, Armor.APC_BTR_80, ],
|
||||||
AirDefence: [
|
AirDefence: [
|
||||||
AirDefence.AAA_Vulcan_M163,
|
AirDefence.AAA_Vulcan_M163,
|
||||||
AirDefence.AAA_Vulcan_M163,
|
AirDefence.AAA_Vulcan_M163,
|
||||||
@ -192,7 +190,6 @@ UNIT_BY_COUNTRY = {
|
|||||||
"USA": [
|
"USA": [
|
||||||
F_15C,
|
F_15C,
|
||||||
FA_18C_hornet,
|
FA_18C_hornet,
|
||||||
AV8BNA,
|
|
||||||
AJS37,
|
AJS37,
|
||||||
F_5E,
|
F_5E,
|
||||||
M_2000C,
|
M_2000C,
|
||||||
@ -223,6 +220,12 @@ PLANE_PAYLOAD_OVERRIDES = {
|
|||||||
"*": "AIM-9M*6, AIM-7M*2, FUEL*3",
|
"*": "AIM-9M*6, AIM-7M*2, FUEL*3",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Su_33: FighterSweep,
|
||||||
|
|
||||||
|
M_2000C: {
|
||||||
|
"*": "Combat Air Patrol",
|
||||||
|
},
|
||||||
|
|
||||||
MiG_21Bis: {
|
MiG_21Bis: {
|
||||||
"*": "Patrol, medium range",
|
"*": "Patrol, medium range",
|
||||||
}
|
}
|
||||||
|
|||||||
@ -104,7 +104,7 @@ class GroundInterceptEvent(Event):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def player_attacking(self, strikegroup: db.PlaneDict, clients: db.PlaneDict):
|
def player_attacking(self, strikegroup: db.PlaneDict, clients: db.PlaneDict):
|
||||||
suitable_unittypes = db.find_unittype(CAP, self.defender_name)
|
suitable_unittypes = db.find_unittype(PinpointStrike, self.defender_name)
|
||||||
random.shuffle(suitable_unittypes)
|
random.shuffle(suitable_unittypes)
|
||||||
unittypes = suitable_unittypes[:self.TARGET_VARIETY]
|
unittypes = suitable_unittypes[:self.TARGET_VARIETY]
|
||||||
typecount = max(math.floor(self.difficulty * self.TARGET_AMOUNT_FACTOR), 1)
|
typecount = max(math.floor(self.difficulty * self.TARGET_AMOUNT_FACTOR), 1)
|
||||||
|
|||||||
14
game/game.py
14
game/game.py
@ -2,18 +2,18 @@ from game.event import *
|
|||||||
|
|
||||||
COMMISION_LIMITS_SCALE = 2
|
COMMISION_LIMITS_SCALE = 2
|
||||||
COMMISION_LIMITS_FACTORS = {
|
COMMISION_LIMITS_FACTORS = {
|
||||||
CAP: 2,
|
PinpointStrike: 2,
|
||||||
CAS: 1,
|
CAS: 1,
|
||||||
FighterSweep: 3,
|
CAP: 3,
|
||||||
AirDefence: 1,
|
AirDefence: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMISION_AMOUNTS_SCALE = 2
|
COMMISION_AMOUNTS_SCALE = 2
|
||||||
COMMISION_UNIT_VARIETY = 4
|
COMMISION_UNIT_VARIETY = 4
|
||||||
COMMISION_AMOUNTS_FACTORS = {
|
COMMISION_AMOUNTS_FACTORS = {
|
||||||
CAP: 0.6,
|
PinpointStrike: 0.6,
|
||||||
CAS: 0.3,
|
CAS: 0.3,
|
||||||
FighterSweep: 0.5,
|
CAP: 0.5,
|
||||||
AirDefence: 0.3,
|
AirDefence: 0.3,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ class Game:
|
|||||||
def _generate_interceptions(self):
|
def _generate_interceptions(self):
|
||||||
enemy_interception = False
|
enemy_interception = False
|
||||||
for from_cp, to_cp in self.theater.conflicts(False):
|
for from_cp, to_cp in self.theater.conflicts(False):
|
||||||
if from_cp.base.total_units(FighterSweep) == 0:
|
if from_cp.base.total_units(CAP) == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if self._roll(ENEMY_INTERCEPT_PROBABILITY_BASE, from_cp.base.strength):
|
if self._roll(ENEMY_INTERCEPT_PROBABILITY_BASE, from_cp.base.strength):
|
||||||
@ -93,7 +93,7 @@ class Game:
|
|||||||
|
|
||||||
if self._roll(ENEMY_INTERCEPT_GLOBAL_PROBABILITY_BASE, 1):
|
if self._roll(ENEMY_INTERCEPT_GLOBAL_PROBABILITY_BASE, 1):
|
||||||
for from_cp, _ in self.theater.conflicts(False):
|
for from_cp, _ in self.theater.conflicts(False):
|
||||||
if from_cp.base.total_units(FighterSweep) > 0:
|
if from_cp.base.total_units(CAP) > 0:
|
||||||
self.events.append(InterceptEvent(attacker_name=self.enemy,
|
self.events.append(InterceptEvent(attacker_name=self.enemy,
|
||||||
defender_name=self.player,
|
defender_name=self.player,
|
||||||
from_cp=from_cp,
|
from_cp=from_cp,
|
||||||
@ -136,7 +136,7 @@ class Game:
|
|||||||
break
|
break
|
||||||
|
|
||||||
def _commision_units(self, cp: ControlPoint):
|
def _commision_units(self, cp: ControlPoint):
|
||||||
for for_task in [CAP, CAS, FighterSweep, AirDefence]:
|
for for_task in [PinpointStrike, CAS, CAP, AirDefence]:
|
||||||
limit = COMMISION_LIMITS_FACTORS[for_task] * math.pow(cp.importance, COMMISION_LIMITS_SCALE)
|
limit = COMMISION_LIMITS_FACTORS[for_task] * math.pow(cp.importance, COMMISION_LIMITS_SCALE)
|
||||||
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:
|
||||||
|
|||||||
@ -58,11 +58,16 @@ class AircraftConflictGenerator:
|
|||||||
did_load_loadout = False
|
did_load_loadout = False
|
||||||
unit_type = group.units[0].unit_type
|
unit_type = group.units[0].unit_type
|
||||||
if unit_type in db.PLANE_PAYLOAD_OVERRIDES:
|
if unit_type in db.PLANE_PAYLOAD_OVERRIDES:
|
||||||
if for_task in db.PLANE_PAYLOAD_OVERRIDES[unit_type]:
|
override_loadout = db.PLANE_PAYLOAD_OVERRIDES[unit_type]
|
||||||
group.load_loadout(db.PLANE_PAYLOAD_OVERRIDES[unit_type][for_task])
|
if type(override_loadout) == dict:
|
||||||
did_load_loadout = True
|
if for_task in db.PLANE_PAYLOAD_OVERRIDES[unit_type]:
|
||||||
elif "*" in db.PLANE_PAYLOAD_OVERRIDES[unit_type]:
|
group.load_loadout(db.PLANE_PAYLOAD_OVERRIDES[unit_type][for_task])
|
||||||
group.load_loadout(db.PLANE_PAYLOAD_OVERRIDES[unit_type]["*"])
|
did_load_loadout = True
|
||||||
|
elif "*" in db.PLANE_PAYLOAD_OVERRIDES[unit_type]:
|
||||||
|
group.load_loadout(db.PLANE_PAYLOAD_OVERRIDES[unit_type]["*"])
|
||||||
|
did_load_loadout = True
|
||||||
|
elif issubclass(override_loadout, MainTask):
|
||||||
|
group.load_task_default_loadout(override_loadout)
|
||||||
did_load_loadout = True
|
did_load_loadout = True
|
||||||
|
|
||||||
if not did_load_loadout:
|
if not did_load_loadout:
|
||||||
@ -162,7 +167,7 @@ class AircraftConflictGenerator:
|
|||||||
position = group.position # type: Point
|
position = group.position # type: Point
|
||||||
wayp = group.add_waypoint(position.point_from_heading(heading, WORKAROUND_WAYP_DIST), CAS_ALTITUDE, WARM_START_AIRSPEED)
|
wayp = group.add_waypoint(position.point_from_heading(heading, WORKAROUND_WAYP_DIST), CAS_ALTITUDE, WARM_START_AIRSPEED)
|
||||||
|
|
||||||
self._setup_group(group, FighterSweep)
|
self._setup_group(group, CAP)
|
||||||
|
|
||||||
for group in self.escort_targets:
|
for group in self.escort_targets:
|
||||||
wayp.tasks.append(EscortTaskAction(group.id, engagement_max_dist=ESCORT_MAX_DIST))
|
wayp.tasks.append(EscortTaskAction(group.id, engagement_max_dist=ESCORT_MAX_DIST))
|
||||||
@ -208,11 +213,11 @@ class AircraftConflictGenerator:
|
|||||||
client_count=client_count,
|
client_count=client_count,
|
||||||
at=at and at or self._group_point(self.conflict.air_defenders_location))
|
at=at and at or self._group_point(self.conflict.air_defenders_location))
|
||||||
|
|
||||||
group.task = FighterSweep.name
|
group.task = CAP.name
|
||||||
wayp = group.add_waypoint(self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED)
|
wayp = group.add_waypoint(self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED)
|
||||||
wayp.tasks.append(dcs.task.EngageTargets(max_distance=self.conflict.size * INTERCEPT_MAX_DISTANCE_FACTOR))
|
wayp.tasks.append(dcs.task.EngageTargets(max_distance=self.conflict.size * INTERCEPT_MAX_DISTANCE_FACTOR))
|
||||||
wayp.tasks.append(dcs.task.OrbitAction())
|
wayp.tasks.append(dcs.task.OrbitAction())
|
||||||
self._setup_group(group, FighterSweep)
|
self._setup_group(group, CAP)
|
||||||
|
|
||||||
def generate_transport(self, transport: db.PlaneDict, destination: Airport):
|
def generate_transport(self, transport: db.PlaneDict, destination: Airport):
|
||||||
assert len(self.escort_targets) == 0
|
assert len(self.escort_targets) == 0
|
||||||
@ -242,7 +247,7 @@ class AircraftConflictGenerator:
|
|||||||
client_count=client_count,
|
client_count=client_count,
|
||||||
at=at and at or self._group_point(self.conflict.air_attackers_location))
|
at=at and at or self._group_point(self.conflict.air_attackers_location))
|
||||||
|
|
||||||
group.task = FighterSweep.name
|
group.task = CAP.name
|
||||||
|
|
||||||
heading = group.position.heading_between_point(self.conflict.position)
|
heading = group.position.heading_between_point(self.conflict.position)
|
||||||
initial_wayp = group.add_waypoint(group.position.point_from_heading(heading, WORKAROUND_WAYP_DIST), INTERCEPTION_ALT, INTERCEPTION_AIRSPEED)
|
initial_wayp = group.add_waypoint(group.position.point_from_heading(heading, WORKAROUND_WAYP_DIST), INTERCEPTION_ALT, INTERCEPTION_AIRSPEED)
|
||||||
@ -250,4 +255,4 @@ class AircraftConflictGenerator:
|
|||||||
|
|
||||||
wayp = group.add_waypoint(self.conflict.position, 0)
|
wayp = group.add_waypoint(self.conflict.position, 0)
|
||||||
wayp.tasks.append(EngageTargets())
|
wayp.tasks.append(EngageTargets())
|
||||||
self._setup_group(group, FighterSweep)
|
self._setup_group(group, CAP)
|
||||||
|
|||||||
30
resources/tools/generate_loadout_check.py
Normal file
30
resources/tools/generate_loadout_check.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import dcs
|
||||||
|
|
||||||
|
from gen.aircraft import AircraftConflictGenerator
|
||||||
|
from game import db
|
||||||
|
mis = dcs.Mission(dcs.terrain.PersianGulf())
|
||||||
|
pos = dcs.terrain.PersianGulf().khasab().position
|
||||||
|
airgen = AircraftConflictGenerator(mis, None)
|
||||||
|
|
||||||
|
for t, uts in db.UNIT_BY_TASK.items():
|
||||||
|
if t != dcs.task.CAP and t != dcs.task.CAS:
|
||||||
|
continue
|
||||||
|
|
||||||
|
pos.y = dcs.terrain.PersianGulf().khasab().position.x
|
||||||
|
for t in t == dcs.task.CAP and [dcs.task.CAP, dcs.task.Escort] or [t]:
|
||||||
|
pos.x += 10000
|
||||||
|
for ut in uts:
|
||||||
|
pos.y += 5000
|
||||||
|
ctr = mis.country([k for k, v in db.UNIT_BY_COUNTRY.items() if ut in v][0])
|
||||||
|
|
||||||
|
g = mis.flight_group_inflight(
|
||||||
|
country=ctr,
|
||||||
|
name="{} - {}".format(t.name, ut),
|
||||||
|
aircraft_type=ut,
|
||||||
|
position=pos,
|
||||||
|
altitude=10000
|
||||||
|
)
|
||||||
|
g.task = t.name
|
||||||
|
airgen._setup_group(g, t)
|
||||||
|
|
||||||
|
mis.save("loadout_test.miz")
|
||||||
@ -116,9 +116,9 @@ class Base:
|
|||||||
for_task = db.unit_task(unit_type)
|
for_task = db.unit_task(unit_type)
|
||||||
|
|
||||||
target_dict = None
|
target_dict = None
|
||||||
if for_task == CAS or for_task == FighterSweep:
|
if for_task == CAS or for_task == CAP:
|
||||||
target_dict = self.aircraft
|
target_dict = self.aircraft
|
||||||
elif for_task == CAP:
|
elif for_task == PinpointStrike:
|
||||||
target_dict = self.armor
|
target_dict = self.armor
|
||||||
elif for_task == AirDefence:
|
elif for_task == AirDefence:
|
||||||
target_dict = self.aa
|
target_dict = self.aa
|
||||||
@ -160,19 +160,19 @@ class Base:
|
|||||||
return int(self.total_aa * (self.strength > 0.2 and self.strength or 0))
|
return int(self.total_aa * (self.strength > 0.2 and self.strength or 0))
|
||||||
|
|
||||||
def scramble_sweep(self) -> typing.Dict[PlaneType, int]:
|
def scramble_sweep(self) -> typing.Dict[PlaneType, int]:
|
||||||
return self._find_best_planes(FighterSweep, self.scramble_count())
|
return self._find_best_planes(CAP, self.scramble_count())
|
||||||
|
|
||||||
def scramble_cas(self) -> typing.Dict[PlaneType, int]:
|
def scramble_cas(self) -> typing.Dict[PlaneType, int]:
|
||||||
return self._find_best_planes(CAS, self.scramble_count())
|
return self._find_best_planes(CAS, self.scramble_count())
|
||||||
|
|
||||||
def scramble_interceptors(self) -> typing.Dict[PlaneType, int]:
|
def scramble_interceptors(self) -> typing.Dict[PlaneType, int]:
|
||||||
return self._find_best_planes(FighterSweep, self.scramble_count())
|
return self._find_best_planes(CAP, self.scramble_count())
|
||||||
|
|
||||||
def assemble_cap(self) -> typing.Dict[Armor, int]:
|
def assemble_cap(self) -> typing.Dict[Armor, int]:
|
||||||
return self._find_best_armor(CAP, self.assemble_count())
|
return self._find_best_armor(PinpointStrike, self.assemble_count())
|
||||||
|
|
||||||
def assemble_defense(self) -> typing.Dict[Armor, int]:
|
def assemble_defense(self) -> typing.Dict[Armor, int]:
|
||||||
return self._find_best_armor(CAP, self.assemble_count())
|
return self._find_best_armor(PinpointStrike, self.assemble_count())
|
||||||
|
|
||||||
def assemble_aa(self) -> typing.Dict[AirDefence, int]:
|
def assemble_aa(self) -> typing.Dict[AirDefence, int]:
|
||||||
return self._find_best_unit(self.aa, AirDefence, self.assemble_aa_count())
|
return self._find_best_unit(self.aa, AirDefence, self.assemble_aa_count())
|
||||||
|
|||||||
@ -7,8 +7,8 @@ UNIT_VARIETY = 3
|
|||||||
UNIT_AMOUNT_FACTOR = 16
|
UNIT_AMOUNT_FACTOR = 16
|
||||||
|
|
||||||
COUNT_BY_TASK = {
|
COUNT_BY_TASK = {
|
||||||
CAP: 12,
|
PinpointStrike: 12,
|
||||||
FighterSweep: 16,
|
CAP: 16,
|
||||||
CAS: 8,
|
CAS: 8,
|
||||||
AirDefence: 0.5,
|
AirDefence: 0.5,
|
||||||
}
|
}
|
||||||
@ -19,7 +19,7 @@ def generate_initial(theater: ConflictTheater, enemy: str, sams: bool):
|
|||||||
if cp.captured:
|
if cp.captured:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for task in [CAP, FighterSweep, CAS, AirDefence]:
|
for task in [PinpointStrike, CAP, CAS, AirDefence]:
|
||||||
assert cp.importance <= IMPORTANCE_HIGH, "invalid importance {}".format(cp.importance)
|
assert cp.importance <= IMPORTANCE_HIGH, "invalid importance {}".format(cp.importance)
|
||||||
assert cp.importance >= IMPORTANCE_LOW, "invalid importance {}".format(cp.importance)
|
assert cp.importance >= IMPORTANCE_LOW, "invalid importance {}".format(cp.importance)
|
||||||
|
|
||||||
|
|||||||
@ -30,9 +30,9 @@ class BaseMenu(Menu):
|
|||||||
row += 1
|
row += 1
|
||||||
|
|
||||||
units = {
|
units = {
|
||||||
CAP: db.find_unittype(CAP, self.game.player),
|
PinpointStrike: db.find_unittype(PinpointStrike, self.game.player),
|
||||||
CAS: db.find_unittype(CAS, self.game.player),
|
CAS: db.find_unittype(CAS, self.game.player),
|
||||||
FighterSweep: db.find_unittype(FighterSweep, self.game.player),
|
CAP: db.find_unittype(CAP, self.game.player),
|
||||||
AirDefence: db.find_unittype(AirDefence, self.game.player),
|
AirDefence: db.find_unittype(AirDefence, self.game.player),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -111,7 +111,7 @@ class EventMenu(Menu):
|
|||||||
scrambled_aircraft[unit_type] = amount
|
scrambled_aircraft[unit_type] = amount
|
||||||
if task == CAS:
|
if task == CAS:
|
||||||
scrambled_cas[unit_type] = amount
|
scrambled_cas[unit_type] = amount
|
||||||
elif task == FighterSweep:
|
elif task == CAP:
|
||||||
scrambled_sweep[unit_type] = amount
|
scrambled_sweep[unit_type] = amount
|
||||||
|
|
||||||
scrambled_clients = {}
|
scrambled_clients = {}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user