mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
fixes to frontline attack; frontline CAP WIP
This commit is contained in:
committed by
Vasyl Horbachenko
parent
820820eb92
commit
932bec2f84
15
game/db.py
15
game/db.py
@@ -73,6 +73,8 @@ PRICES = {
|
||||
An_30M: 13,
|
||||
Yak_40: 13,
|
||||
S_3B_Tanker: 13,
|
||||
IL_78M: 13,
|
||||
KC_135: 13,
|
||||
|
||||
A_50: 8,
|
||||
E_3A: 8,
|
||||
@@ -167,6 +169,11 @@ UNIT_BY_TASK = {
|
||||
C_130,
|
||||
],
|
||||
|
||||
Refueling: [
|
||||
IL_78M,
|
||||
KC_135,
|
||||
],
|
||||
|
||||
AWACS: [E_3A, A_50, ],
|
||||
|
||||
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, ],
|
||||
@@ -251,6 +258,7 @@ UNIT_BY_COUNTRY = {
|
||||
L_39ZA,
|
||||
|
||||
IL_76MD,
|
||||
IL_78M,
|
||||
An_26B,
|
||||
An_30M,
|
||||
Yak_40,
|
||||
@@ -290,6 +298,7 @@ UNIT_BY_COUNTRY = {
|
||||
A_10C,
|
||||
AV8BNA,
|
||||
|
||||
KC_135,
|
||||
S_3B_Tanker,
|
||||
C_130,
|
||||
E_3A,
|
||||
@@ -450,7 +459,11 @@ def unitdict_split(unit_dict: UnitsDict, count: int):
|
||||
|
||||
|
||||
def unitdict_restrict_count(unit_dict: UnitsDict, total_count: int) -> UnitsDict:
|
||||
return list(unitdict_split(unit_dict, total_count))[0]
|
||||
groups = list(unitdict_split(unit_dict, total_count))
|
||||
if len(groups) > 0:
|
||||
return groups[0]
|
||||
else:
|
||||
return {}
|
||||
|
||||
|
||||
def _validate_db():
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from .event import *
|
||||
from .frontlineattack import *
|
||||
from .frontlinepatrol import *
|
||||
from .intercept import *
|
||||
from .baseattack import *
|
||||
from .navalintercept import *
|
||||
|
||||
@@ -16,7 +16,7 @@ class BaseAttackEvent(Event):
|
||||
STRENGTH_RECOVERY = 0.55
|
||||
|
||||
def __str__(self):
|
||||
return "Attack from {} to {}".format(self.from_cp, self.to_cp)
|
||||
return "Base attack from {} to {}".format(self.from_cp, self.to_cp)
|
||||
|
||||
def is_successfull(self, debriefing: Debriefing):
|
||||
alive_attackers = sum([v for k, v in debriefing.alive_units[self.attacker_name].items() if db.unit_task(k) == PinpointStrike])
|
||||
|
||||
@@ -16,7 +16,7 @@ class FrontlineAttackEvent(Event):
|
||||
ATTACKER_AMOUNT_FACTOR = 0.4
|
||||
ATTACKER_DEFENDER_FACTOR = 0.7
|
||||
STRENGTH_INFLUENCE = 0.3
|
||||
SUCCESS_MIN_TARGETS = 3
|
||||
SUCCESS_TARGETS_HIT_PERCENTAGE = 0.25
|
||||
|
||||
defenders = None # type: db.ArmorDict
|
||||
|
||||
@@ -35,9 +35,9 @@ class FrontlineAttackEvent(Event):
|
||||
destroyed_targets += count
|
||||
|
||||
if self.from_cp.captured:
|
||||
return float(destroyed_targets) >= min(self.SUCCESS_MIN_TARGETS, total_targets)
|
||||
return float(destroyed_targets) / total_targets >= self.SUCCESS_TARGETS_HIT_PERCENTAGE
|
||||
else:
|
||||
return float(destroyed_targets) < min(self.SUCCESS_MIN_TARGETS, total_targets)
|
||||
return float(destroyed_targets) / total_targets < self.SUCCESS_TARGETS_HIT_PERCENTAGE
|
||||
|
||||
def commit(self, debriefing: Debriefing):
|
||||
super(FrontlineAttackEvent, self).commit(debriefing)
|
||||
|
||||
72
game/event/frontlinepatrol.py
Normal file
72
game/event/frontlinepatrol.py
Normal file
@@ -0,0 +1,72 @@
|
||||
import math
|
||||
import random
|
||||
|
||||
from dcs.task import *
|
||||
from dcs.vehicles import AirDefence
|
||||
|
||||
from game import *
|
||||
from game.event import *
|
||||
from game.operation.frontlinepatrol import FrontlinePatrolOperation
|
||||
from userdata.debriefing import Debriefing
|
||||
|
||||
|
||||
class FrontlinePatrolEvent(Event):
|
||||
ESCORT_FACTOR = 0.5
|
||||
STRENGTH_INFLUENCE = 0.3
|
||||
SUCCESS_TARGETS_HIT_PERCENTAGE = 0.6
|
||||
|
||||
cas = None # type: db.PlaneDict
|
||||
escort = None # type: db.PlaneDict
|
||||
|
||||
@property
|
||||
def threat_description(self):
|
||||
return "{} aircraft + ? CAS".format(self.to_cp.base.scramble_count(self.game.settings.multiplier * self.ESCORT_FACTOR, CAP))
|
||||
|
||||
def __str__(self):
|
||||
return "Frontline CAP from {} at {}".format(self.from_cp, self.to_cp)
|
||||
|
||||
def is_successfull(self, debriefing: Debriefing):
|
||||
total_targets = sum(self.cas.values())
|
||||
destroyed_targets = 0
|
||||
for unit, count in debriefing.destroyed_units[self.defender_name].items():
|
||||
if unit in self.cas:
|
||||
destroyed_targets += count
|
||||
|
||||
if self.from_cp.captured:
|
||||
return float(destroyed_targets) / total_targets >= self.SUCCESS_TARGETS_HIT_PERCENTAGE
|
||||
else:
|
||||
return float(destroyed_targets) / total_targets < self.SUCCESS_TARGETS_HIT_PERCENTAGE
|
||||
|
||||
def commit(self, debriefing: Debriefing):
|
||||
super(FrontlinePatrolEvent, self).commit(debriefing)
|
||||
|
||||
if self.from_cp.captured:
|
||||
if self.is_successfull(debriefing):
|
||||
self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
|
||||
else:
|
||||
self.to_cp.base.affect_strength(+self.STRENGTH_INFLUENCE)
|
||||
else:
|
||||
if self.is_successfull(debriefing):
|
||||
self.from_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
|
||||
else:
|
||||
self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
|
||||
|
||||
def skip(self):
|
||||
pass
|
||||
|
||||
def player_attacking(self, interceptors: db.PlaneDict, clients: db.PlaneDict):
|
||||
self.cas = self.to_cp.base.scramble_cas(self.game.settings.multiplier)
|
||||
self.escort = self.to_cp.base.scramble_sweep(self.game.settings.multiplier * self.ESCORT_FACTOR)
|
||||
|
||||
op = FrontlinePatrolOperation(game=self.game,
|
||||
attacker_name=self.attacker_name,
|
||||
defender_name=self.defender_name,
|
||||
attacker_clients={},
|
||||
defender_clients=clients,
|
||||
from_cp=self.from_cp,
|
||||
to_cp=self.to_cp)
|
||||
op.setup(cas=self.cas,
|
||||
escort=self.escort,
|
||||
interceptors=interceptors)
|
||||
|
||||
self.operation = op
|
||||
18
game/game.py
18
game/game.py
@@ -5,6 +5,7 @@ import math
|
||||
from dcs.task import *
|
||||
from dcs.vehicles import *
|
||||
|
||||
from gen.conflictgen import Conflict
|
||||
from userdata.debriefing import Debriefing
|
||||
from theater import *
|
||||
|
||||
@@ -23,7 +24,7 @@ COMMISION_LIMITS_FACTORS = {
|
||||
|
||||
COMMISION_AMOUNTS_SCALE = 1.5
|
||||
COMMISION_AMOUNTS_FACTORS = {
|
||||
PinpointStrike: 2,
|
||||
PinpointStrike: 6,
|
||||
CAS: 1,
|
||||
CAP: 2,
|
||||
AirDefence: 0.3,
|
||||
@@ -31,6 +32,7 @@ COMMISION_AMOUNTS_FACTORS = {
|
||||
|
||||
PLAYER_INTERCEPT_GLOBAL_PROBABILITY_BASE = 25
|
||||
PLAYER_INTERCEPT_GLOBAL_PROBABILITY_LOG = 2
|
||||
PLAYER_BASEATTACK_THRESHOLD = 0.2
|
||||
|
||||
"""
|
||||
Various events probabilities. First key is player probabilty, second is enemy probability.
|
||||
@@ -47,8 +49,9 @@ Events:
|
||||
"""
|
||||
EVENT_PROBABILITIES = {
|
||||
BaseAttackEvent: [100, 10],
|
||||
InterceptEvent: [25, 10],
|
||||
FrontlineAttackEvent: [100, 0],
|
||||
FrontlinePatrolEvent: [1000, 0],
|
||||
InterceptEvent: [25, 10],
|
||||
InsurgentAttackEvent: [0, 10],
|
||||
NavalInterceptEvent: [25, 10],
|
||||
AntiAAStrikeEvent: [25, 10],
|
||||
@@ -65,7 +68,7 @@ ENEMY_BASE_STRENGTH_RECOVERY = 0.05
|
||||
AWACS_BUDGET_COST = 4
|
||||
|
||||
# Initial budget value
|
||||
PLAYER_BUDGET_INITIAL = 120
|
||||
PLAYER_BUDGET_INITIAL = 170
|
||||
# Base post-turn bonus value
|
||||
PLAYER_BUDGET_BASE = 10
|
||||
# Bonus multiplier logarithm base
|
||||
@@ -112,11 +115,18 @@ class Game:
|
||||
continue
|
||||
|
||||
for event_class, (player_probability, enemy_probability) in EVENT_PROBABILITIES.items():
|
||||
if event_class == FrontlineAttackEvent or event_class == InfantryTransportEvent or event_class == FrontlinePatrolEvent:
|
||||
if not Conflict.has_frontline_between(player_cp, enemy_cp):
|
||||
continue
|
||||
|
||||
if self._roll(player_probability, player_cp.base.strength):
|
||||
if event_class == NavalInterceptEvent and enemy_cp.radials == LAND:
|
||||
pass
|
||||
else:
|
||||
self.events.append(event_class(self.player, self.enemy, player_cp, enemy_cp, self))
|
||||
if event_class == BaseAttackEvent and enemy_cp.base.strength > PLAYER_BASEATTACK_THRESHOLD:
|
||||
pass
|
||||
else:
|
||||
self.events.append(event_class(self.player, self.enemy, player_cp, enemy_cp, self))
|
||||
elif self._roll(enemy_probability, enemy_cp.base.strength):
|
||||
if event_class in enemy_generated_types:
|
||||
continue
|
||||
|
||||
@@ -6,7 +6,7 @@ from gen.aircraft import *
|
||||
from gen.aaa import *
|
||||
from gen.shipgen import *
|
||||
from gen.triggergen import *
|
||||
from gen.awacsgen import *
|
||||
from gen.airsupportgen import *
|
||||
from gen.visualgen import *
|
||||
from gen.conflictgen import Conflict
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from gen.aircraft import *
|
||||
from gen.aaa import *
|
||||
from gen.shipgen import *
|
||||
from gen.triggergen import *
|
||||
from gen.awacsgen import *
|
||||
from gen.airsupportgen import *
|
||||
from gen.visualgen import *
|
||||
|
||||
from .operation import Operation
|
||||
@@ -60,7 +60,7 @@ class BaseAttackOperation(Operation):
|
||||
self.airgen.generate_defense(self.intercept, clients=self.defender_clients, at=self.defenders_starting_position)
|
||||
|
||||
self.airgen.generate_cas_strikegroup(self.cas, clients=self.attacker_clients, at=self.attackers_starting_position)
|
||||
self.airgen.generate_strikegroup_escort(self.escort, clients=self.attacker_clients, at=self.attackers_starting_position)
|
||||
self.airgen.generate_attackers_escort(self.escort, clients=self.attacker_clients, at=self.attackers_starting_position)
|
||||
|
||||
self.visualgen.generate_target_smokes(self.to_cp)
|
||||
super(BaseAttackOperation, self).generate()
|
||||
|
||||
@@ -8,7 +8,7 @@ from gen.aircraft import *
|
||||
from gen.aaa import *
|
||||
from gen.shipgen import *
|
||||
from gen.triggergen import *
|
||||
from gen.awacsgen import *
|
||||
from gen.airsupportgen import *
|
||||
from gen.visualgen import *
|
||||
from gen.conflictgen import Conflict
|
||||
|
||||
|
||||
53
game/operation/frontlinepatrol.py
Normal file
53
game/operation/frontlinepatrol.py
Normal file
@@ -0,0 +1,53 @@
|
||||
from itertools import zip_longest
|
||||
|
||||
from dcs.terrain import Terrain
|
||||
|
||||
from game import db
|
||||
from gen.armor import *
|
||||
from gen.aircraft import *
|
||||
from gen.aaa import *
|
||||
from gen.shipgen import *
|
||||
from gen.triggergen import *
|
||||
from gen.airsupportgen import *
|
||||
from gen.visualgen import *
|
||||
from gen.conflictgen import Conflict
|
||||
|
||||
from .operation import Operation
|
||||
|
||||
|
||||
MAX_DISTANCE_BETWEEN_GROUPS = 12000
|
||||
|
||||
|
||||
class FrontlinePatrolOperation(Operation):
|
||||
cas = None # type: db.PlaneDict
|
||||
escort = None # type: db.PlaneDict
|
||||
interceptors = None # type: db.PlaneDict
|
||||
|
||||
def setup(self, cas: db.PlaneDict, escort: db.PlaneDict, interceptors: db.PlaneDict):
|
||||
self.cas = cas
|
||||
self.escort = escort
|
||||
self.interceptors = interceptors
|
||||
|
||||
def prepare(self, terrain: Terrain, is_quick: bool):
|
||||
super(FrontlinePatrolOperation, self).prepare(terrain, is_quick)
|
||||
self.defenders_starting_position = None
|
||||
|
||||
conflict = Conflict.frontline_cap_conflict(
|
||||
attacker=self.mission.country(self.attacker_name),
|
||||
defender=self.mission.country(self.defender_name),
|
||||
from_cp=self.from_cp,
|
||||
to_cp=self.to_cp,
|
||||
theater=self.game.theater
|
||||
)
|
||||
|
||||
self.initialize(mission=self.mission,
|
||||
conflict=conflict)
|
||||
|
||||
def generate(self):
|
||||
self.airgen.generate_defenders_cas(self.cas, {}, self.defenders_starting_position)
|
||||
self.airgen.generate_defenders_escort(self.escort, {}, self.defenders_starting_position)
|
||||
self.airgen.generate_patrol(self.interceptors, self.defender_clients, self.attackers_starting_position)
|
||||
|
||||
# todo: generate armor
|
||||
|
||||
super(FrontlinePatrolOperation, self).generate()
|
||||
@@ -6,7 +6,7 @@ from gen.aircraft import *
|
||||
from gen.aaa import *
|
||||
from gen.shipgen import *
|
||||
from gen.triggergen import *
|
||||
from gen.awacsgen import *
|
||||
from gen.airsupportgen import *
|
||||
from gen.visualgen import *
|
||||
from gen.conflictgen import Conflict
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from gen.aircraft import *
|
||||
from gen.aaa import *
|
||||
from gen.shipgen import *
|
||||
from gen.triggergen import *
|
||||
from gen.awacsgen import *
|
||||
from gen.airsupportgen import *
|
||||
from gen.visualgen import *
|
||||
from gen.conflictgen import Conflict
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class InterceptOperation(Operation):
|
||||
self.attackers_starting_position = ship
|
||||
|
||||
self.airgen.generate_transport(self.transport, self.to_cp.at)
|
||||
self.airgen.generate_transport_escort(self.escort, clients=self.defender_clients)
|
||||
self.airgen.generate_defenders_escort(self.escort, clients=self.defender_clients)
|
||||
|
||||
self.airgen.generate_interception(self.interceptors, clients=self.attacker_clients, at=self.attackers_starting_position)
|
||||
super(InterceptOperation, self).generate()
|
||||
|
||||
@@ -18,7 +18,7 @@ class Operation:
|
||||
extra_aagen = None # type: ExtraAAConflictGenerator
|
||||
shipgen = None # type: ShipGenerator
|
||||
triggersgen = None # type: TriggersGenerator
|
||||
awacsgen = None # type: AWACSConflictGenerator
|
||||
awacsgen = None # type: AirSupportConflictGenerator
|
||||
visualgen = None # type: VisualGenerator
|
||||
envgen = None # type: EnvironmentGenerator
|
||||
|
||||
@@ -52,7 +52,7 @@ class Operation:
|
||||
self.airgen = AircraftConflictGenerator(mission, conflict, self.game.settings)
|
||||
self.aagen = AAConflictGenerator(mission, conflict)
|
||||
self.shipgen = ShipGenerator(mission, conflict)
|
||||
self.awacsgen = AWACSConflictGenerator(mission, conflict, self.game)
|
||||
self.awacsgen = AirSupportConflictGenerator(mission, conflict, self.game)
|
||||
self.triggersgen = TriggersGenerator(mission, conflict, self.game)
|
||||
self.visualgen = VisualGenerator(mission, conflict, self.game)
|
||||
self.envgen = EnviromentGenerator(mission, conflict, self.game)
|
||||
@@ -78,9 +78,7 @@ class Operation:
|
||||
|
||||
def generate(self):
|
||||
self.visualgen.generate()
|
||||
|
||||
if self.is_awacs_enabled:
|
||||
self.awacsgen.generate()
|
||||
self.awacsgen.generate(self.is_awacs_enabled)
|
||||
|
||||
self.extra_aagen.generate()
|
||||
self.triggersgen.generate(self.is_quick, self.trigger_radius)
|
||||
|
||||
Reference in New Issue
Block a user