Skip to content

Commit

Permalink
Ground objects are always generated and destroyable, even when it's n…
Browse files Browse the repository at this point in the history
…ot the current mission objective.

Fix : SAM site destruction status is saved correctly.
Added most SAM site to generator.
  • Loading branch information
Khopa committed Oct 6, 2019
1 parent 17352bf commit 2167953
Show file tree
Hide file tree
Showing 40 changed files with 812 additions and 72 deletions.
3 changes: 1 addition & 2 deletions game/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -1018,8 +1018,7 @@ def unit_task(unit: UnitType) -> Task:
return unit_task(SAM_CONVERT[unit])

print(unit.name + " cause issue")
assert False

return None

def find_unittype(for_task: Task, country_name: str) -> typing.List[UnitType]:
return [x for x in UNIT_BY_TASK[for_task] if x in FACTIONS[country_name]["units"]]
Expand Down
19 changes: 19 additions & 0 deletions game/event/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from userdata.debriefing import Debriefing
from userdata import persistency

import game.db as db

DIFFICULTY_LOG_BASE = 1.1
EVENT_DEPARTURE_MAX_DISTANCE = 340000

Expand Down Expand Up @@ -127,6 +129,23 @@ def generate_quick(self):
self.operation.current_mission.save(persistency.mission_path_for("liberation_nextturn_quick.miz"))

def commit(self, debriefing: Debriefing):

for destroyed_unit_name in debriefing.dead_units_name:

for cp in self.game.theater.controlpoints:

for i, ground_object in enumerate(cp.ground_objects):
if ground_object.dcs_identifier == "AA":
for g in ground_object.groups:
for u in g.units:
if u.name == destroyed_unit_name:
g.units.remove(u)
ucount = sum([len(g.units) for g in ground_object.groups])
print(ucount)
if ucount == 0:
print("SET DEAD")
ground_object.is_dead = True

for country, losses in debriefing.destroyed_units.items():
if country == self.attacker_name:
cp = self.departure_cp
Expand Down
16 changes: 16 additions & 0 deletions game/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ class Game:
turn = 0
game_stats: GameStats = None

current_unit_id = 0
current_group_id = 0

def __init__(self, player_name: str, enemy_name: str, theater: ConflictTheater, start_date: datetime):
self.settings = Settings()
self.events = []
Expand Down Expand Up @@ -315,3 +318,16 @@ def current_turn_daytime(self):
def current_day(self):
return self.date + timedelta(days=self.turn//4)

def next_unit_id(self):
"""
Next unit id for pre-generated units
"""
self.current_unit_id += 1
return self.current_unit_id

def next_group_id(self):
"""
Next unit id for pre-generated units
"""
self.current_group_id += 1
return self.current_group_id
8 changes: 6 additions & 2 deletions game/operation/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ def prepare(self, terrain: Terrain, is_quick: bool):
options_dict = loads(f.read())["options"]

dcs.Mission.aaa_vehicle_group = aaa.aaa_vehicle_group

self.current_mission = dcs.Mission(terrain)

if is_quick:
self.quick_mission = self.current_mission
else:
Expand Down Expand Up @@ -117,6 +119,10 @@ def prepare_carriers(self, for_units: db.UnitsDict):
self.defenders_starting_position = ship

def generate(self):

# Generate ground object first
self.groundobjectgen.generate()

# air support
self.airsupportgen.generate(self.is_awacs_enabled)
for i, tanker_type in enumerate(self.airsupportgen.generated_tankers):
Expand All @@ -132,8 +138,6 @@ def generate(self):
else:
self.current_mission.groundControl.red_tactical_commander = self.ca_slots

# ground infrastructure
self.groundobjectgen.generate()
self.extra_aagen.generate()

# triggers
Expand Down
95 changes: 49 additions & 46 deletions gen/groundobjectsgen.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging

from game import db
from game.db import unit_type_from_name
from .conflictgen import *
from .naming import *

Expand Down Expand Up @@ -42,7 +43,6 @@ def generate_farps(self, number_of_units=1) -> typing.Collection[StaticGroup]:
)

def generate(self):
side = self.m.country(self.game.enemy_country)

cp = None # type: ControlPoint
if self.conflict.attackers_country.name == self.game.player_country:
Expand All @@ -52,54 +52,58 @@ def generate(self):

consumed_farps = set()

for ground_object in cp.ground_objects:
if ground_object.dcs_identifier == "AA":

if ground_object.is_dead:
continue
for cp in self.game.theater.controlpoints:

unit_type = random.choice(self.game.commision_unit_types(cp, AirDefence))
assert unit_type is not None, "Cannot find unit type for GroundObject defense ({})!".format(cp)

group = self.m.aaa_vehicle_group(
country=side,
name=ground_object.string_identifier,
_type=unit_type,
position=ground_object.position,
heading=ground_object.heading,
)

logging.info("generated defense object identifier {} with mission id {}".format(group.name, group.id))
if cp.captured:
country = self.game.player_country
else:
if ground_object.dcs_identifier in warehouse_map:
static_type = warehouse_map[ground_object.dcs_identifier]
country = self.game.enemy_country
side = self.m.country(country)

for ground_object in cp.ground_objects:
if ground_object.dcs_identifier == "AA":
for g in ground_object.groups:
if len(g.units) > 0:
vg = self.m.vehicle_group(side, g.name, unit_type_from_name(g.units[0].type), position=g.position)
vg.units[0].name = self.m.string(g.units[0].name)
for i,u in enumerate(g.units):
if i > 0:
vehicle = Vehicle(self.m.next_unit_id(), self.m.string(u.name), u.type)
vehicle.position.x = u.position.x
vehicle.position.y = u.position.y
vehicle.heading = u.heading
vg.add_unit(vehicle)
else:
static_type = fortification_map[ground_object.dcs_identifier]

if not static_type:
print("Didn't find {} in static _map(s)!".format(ground_object.dcs_identifier))
continue

if ground_object.group_id not in consumed_farps:
consumed_farps.add(ground_object.group_id)
if random.randint(0, 100) > 50:
farp_aa(
self.m,
side,
ground_object.string_identifier,
ground_object.position,
)

group = self.m.static_group(
country=side,
name=ground_object.string_identifier,
_type=static_type,
position=ground_object.position,
heading=ground_object.heading,
dead=ground_object.is_dead,
)

logging.info("generated {}object identifier {} with mission id {}".format("dead " if ground_object.is_dead else "", group.name, group.id))
if ground_object.dcs_identifier in warehouse_map:
static_type = warehouse_map[ground_object.dcs_identifier]
else:
static_type = fortification_map[ground_object.dcs_identifier]

if not static_type:
print("Didn't find {} in static _map(s)!".format(ground_object.dcs_identifier))
continue

if ground_object.group_id not in consumed_farps:
consumed_farps.add(ground_object.group_id)
if random.randint(0, 100) > 50:
farp_aa(
self.m,
side,
ground_object.string_identifier,
ground_object.position,
)

group = self.m.static_group(
country=side,
name=ground_object.string_identifier,
_type=static_type,
position=ground_object.position,
heading=ground_object.heading,
dead=ground_object.is_dead,
)

logging.info("generated {}object identifier {} with mission id {}".format("dead " if ground_object.is_dead else "", group.name, group.id))


def farp_aa(mission_obj, country, name, position: mapping.Point):
Expand All @@ -116,7 +120,6 @@ def farp_aa(mission_obj, country, name, position: mapping.Point):
units = [
AirDefence.SPAAA_ZSU_23_4_Shilka,
AirDefence.AAA_ZU_23_Closed,
Armor.MBT_T_55,
]

v = mission_obj.vehicle(name + "_AAA", random.choice(units))
Expand Down
73 changes: 73 additions & 0 deletions gen/sam/group_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import math
import random

from dcs import unitgroup
from dcs.point import PointAction
from dcs.unit import Vehicle


class AntiAirGroupGenerator():

def __init__(self, game, ground_object, group_object_group_id):
self.game = game
self.go = ground_object
self.position = ground_object.position
self.heading = random.randint(0, 359)
self.vg = unitgroup.VehicleGroup(self.game.next_group_id(), self.go.group_identifier)

wp = self.vg.add_waypoint(self.position, PointAction.OffRoad, 0)
wp.ETA_locked = True

def generate(self):
raise NotImplementedError

def get_generated_group(self):
return self.vg

def add_unit(self, unit_type, name, pos_x, pos_y, heading):

nn = "cgroup|" + str(self.go.cp_id) + '|' + str(self.go.group_id) + '|' + str(self.go.group_identifier) + "|" + name

unit = Vehicle(self.game.next_unit_id(),
nn, unit_type.id)
unit.position.x = pos_x
unit.position.y = pos_y
unit.heading = heading
self.vg.add_unit(unit)
return unit

def get_circular_position(self, num_units, launcher_distance, coverage=90):
"""
Given a position on the map, array a group of units in a circle a uniform distance from the unit
:param num_units:
number of units to play on the circle
:param launcher_distance:
distance the units should be from the center unit
:param coverage:
0-360
:return:
list of tuples representing each unit location
[(pos_x, pos_y, heading), ...]
"""
if coverage == 360:
# one of the positions is shared :'(
outer_offset = coverage / num_units
else:
outer_offset = coverage / (num_units - 1)

positions = []

if num_units % 2 == 0:
current_offset = self.heading - ((coverage / (num_units - 1)) / 2)
else:
current_offset = self.heading
current_offset -= outer_offset * (math.ceil(num_units / 2) - 1)
for x in range(1, num_units + 1):
positions.append((
self.position.x + launcher_distance * math.cos(math.radians(current_offset)),
self.position.y + launcher_distance * math.sin(math.radians(current_offset)),
current_offset,
))
current_offset += outer_offset
return positions

19 changes: 19 additions & 0 deletions gen/sam/sam_avenger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import random

from dcs.vehicles import AirDefence, Unarmed

from gen.sam.group_generator import AntiAirGroupGenerator


class AvengerGenerator(AntiAirGroupGenerator):
"""
This generate an Avenger group
"""

def generate(self):
num_launchers = random.randint(2, 3)

self.add_unit(Unarmed.Transport_M818, "TRUCK", self.position.x, self.position.y, self.heading)
positions = self.get_circular_position(num_launchers, launcher_distance=110, coverage=180)
for i, position in enumerate(positions):
self.add_unit(AirDefence.SAM_Avenger_M1097, "SPAA#" + str(i), position[0], position[1], position[2])
19 changes: 19 additions & 0 deletions gen/sam/sam_chaparral.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import random

from dcs.vehicles import AirDefence, Unarmed

from gen.sam.group_generator import AntiAirGroupGenerator


class ChaparralGenerator(AntiAirGroupGenerator):
"""
This generate a Chaparral group
"""

def generate(self):
num_launchers = random.randint(2, 4)

self.add_unit(Unarmed.Transport_M818, "TRUCK", self.position.x, self.position.y, self.heading)
positions = self.get_circular_position(num_launchers, launcher_distance=110, coverage=180)
for i, position in enumerate(positions):
self.add_unit(AirDefence.SAM_Chaparral_M48, "SPAA#" + str(i), position[0], position[1], position[2])
18 changes: 18 additions & 0 deletions gen/sam/sam_gepard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import random

from dcs.vehicles import AirDefence, Unarmed

from gen.sam.group_generator import AntiAirGroupGenerator


class GepardGenerator(AntiAirGroupGenerator):
"""
This generate a Gepard group
"""

def generate(self):
self.add_unit(AirDefence.SPAAA_Gepard, "SPAAA", self.position.x, self.position.y, self.heading)
if random.randint(0, 1) == 1:
self.add_unit(AirDefence.SPAAA_Gepard, "SPAAA2", self.position.x, self.position.y, self.heading)
self.add_unit(Unarmed.Transport_M818, "TRUCK", self.position.x + 80, self.position.y, self.heading)

Loading

0 comments on commit 2167953

Please sign in to comment.