diff --git a/src/interpolation/Interpolation.py b/src/interpolation/Interpolation.py new file mode 100644 index 00000000..2dae5223 --- /dev/null +++ b/src/interpolation/Interpolation.py @@ -0,0 +1,61 @@ +from renderer.data import ReplayData, Events +from interpolation.interpolator.liner import LinerInterpolationer +import math +import copy +import logging +import collections +from tqdm import tqdm + +class Interpolator(): + def interpolate(self, + replay_info: ReplayData, + fpsTarget=60, + speedScale=6.0, + method="liner" + ): + logging.info("started interpolating") + evtList=list(replay_info.events.values()) + # add more frames in replays to support higher fps + # by default, one frame in game represents 1 second + origTotLen=len(evtList) + # number of events in one sec + framePerEvt=fpsTarget/speedScale + + + # total events + afterLen=int((origTotLen - 1)/framePerEvt) + 1 + newRepInfo=[] + for i in tqdm(range(origTotLen)): + currentLenTarget=framePerEvt*(i+1) + # in case speed scale is faster than 60 events per sec + if currentLenTarget <= len(newRepInfo): + continue + + originEvt=evtList[i] + newRepInfo.append(originEvt) + if originEvt.last_frame or i+1 >= origTotLen: + break + nextEvt=evtList[i+1] + + eventsToAdd=math.floor(currentLenTarget - len(newRepInfo)) + + match method: + case "liner": + # liner implementation + for item in (LinerInterpolationer().doLinerInterpolation(originEvt, nextEvt, eventsToAdd)): + newRepInfo.append(item) + case "bezier": + # todo + raise NotImplementedError("not implemented") + logging.info("interpolation complete") + tmp = replay_info._asdict() + tmp['events']=dict(zip(range(len(newRepInfo)), newRepInfo)) + return toNamedTuple('ReplayData', tmp) + +def toNamedTuple(name: str, evt: dict): + keyList=evt.keys() + valueList=evt.values() + tmpTuple=collections.namedtuple(name, keyList) + return tmpTuple._make(valueList) + + \ No newline at end of file diff --git a/src/interpolation/interpolator/liner.py b/src/interpolation/interpolator/liner.py new file mode 100644 index 00000000..5631515f --- /dev/null +++ b/src/interpolation/interpolator/liner.py @@ -0,0 +1,291 @@ +from typing import NamedTuple, Optional +from renderer.data import ( + PlayerInfo, + Vehicle, + ReplayData, + Events, + Smoke, + Shot, + Torpedo, + Consumable, + Plane, + Ward, + ControlPoint, + Score, + Frag, + Message, + BattleResult, + BuildingInfo, + Building, + Units, + Skills, + AcousticTorpedo, +) +import math +import copy +import logging +import collections + +class VehicleDiff(NamedTuple): + x: float + y: float + yaw: float + regenerated_health: float + regen_crew_hp_limit: float + regeneration_health: float + +class PlaneDiff(NamedTuple): + x: float + y: float + +class ShotDiff(NamedTuple): + origX: float + origY: float + destX: float + destY: float + +class TorpedoDiff(NamedTuple): + x: float + y: float + yaw: float + +class AcousticTorpedoDiff(NamedTuple): + x: float + y: float + yaw: float + +# dict key is id of elements(vehicle_id, plane_id, etc.). +class LinerDiff(NamedTuple): + vehicleDiff: dict[int, VehicleDiff] + planeDiff: dict[int, PlaneDiff] + shotDiff: dict[int, ShotDiff] + torpedoDiff: dict[int, TorpedoDiff] + acousticTorpedoDiff: dict[int, AcousticTorpedoDiff] + +class LinerInterpolationer: + + def __init__(self) -> None: + pass + + def doLinerInterpolation(self, originEvt: Events, nextEvt: Events, eventsToAdd: int): + result = [] + if eventsToAdd <= 0 : + return result + diffData=self.calcDiff(originEvt, nextEvt, eventsToAdd) + currentEvt = self.initCurrentEvt(originEvt) + for i in range(eventsToAdd): + tmpEvt = currentEvt._asdict() + self.applyDiffData(diffData, tmpEvt) + currentEvt = toNamedTuple('Events', tmpEvt) + result.append(currentEvt) + return result + + def initCurrentEvt(self, originEvt: Events): + currentEvt = Events( + time_left=originEvt.time_left, + evt_vehicle=originEvt.evt_vehicle, + evt_plane=originEvt.evt_plane, + evt_shot=[], + evt_torpedo=originEvt.evt_torpedo, + evt_acoustic_torpedo=originEvt.evt_acoustic_torpedo, + evt_building = dict(), + evt_ward = originEvt.evt_ward, + evt_smoke = originEvt.evt_smoke, + evt_hits = [], + evt_consumable = dict(), + evt_control = originEvt.evt_control, + evt_score = originEvt.evt_score, + evt_damage_maps = originEvt.evt_damage_maps, + evt_frag = [], + evt_ribbon = originEvt.evt_ribbon, + evt_achievement = originEvt.evt_achievement, + evt_times_to_win = originEvt.evt_times_to_win, + evt_chat = [], + ) + return currentEvt + + def calcDiff(self, originEvt: Events, nextEvt: Events, eventsToAdd: int): + result=LinerDiff( + vehicleDiff=self.calcVehicle(originEvt, nextEvt, eventsToAdd), + planeDiff=self.calcPlaneDiff(originEvt, nextEvt, eventsToAdd), + shotDiff=self.calcShotDiff(originEvt, nextEvt, eventsToAdd), + torpedoDiff=self.calcTorpedoDiff(originEvt, nextEvt, eventsToAdd), + acousticTorpedoDiff=self.calcAcousticTorpedoDiff(originEvt, nextEvt, eventsToAdd) + ) + return result + + def calcVehicle(self, originEvt: Events, nextEvt: Events, eventsToAdd: int): + result=dict() + if eventsToAdd <= 0: + return result + for id, vehicle in originEvt.evt_vehicle.items(): + nextVehicle=nextEvt.evt_vehicle.get(id) + if nextVehicle is None: + continue + result[id]=VehicleDiff( + float(nextVehicle.x - vehicle.x)/ float(eventsToAdd), + float(nextVehicle.y - vehicle.y)/ float(eventsToAdd), + (nextVehicle.yaw - vehicle.yaw )/ eventsToAdd, + (nextVehicle.regenerated_health - vehicle.regenerated_health)/ eventsToAdd, + (nextVehicle.regen_crew_hp_limit - vehicle.regen_crew_hp_limit)/ eventsToAdd, + (nextVehicle.regeneration_health - vehicle.regeneration_health)/ eventsToAdd + ) + + return result + + def calcPlaneDiff(self, originEvt: Events, nextEvt: Events, eventsToAdd: int): + result=dict() + if eventsToAdd <= 0: + return result + for id, plane in originEvt.evt_plane.items(): + nextPlane=nextEvt.evt_plane.get(id) + if nextPlane is None: + continue + result[id]=PlaneDiff( + float(nextPlane.position[0] - plane.position[0])/ float(eventsToAdd), + float(nextPlane.position[1] - plane.position[1])/ float(eventsToAdd) + ) + + return result + + def calcShotDiff(self, originEvt: Events, nextEvt: Events, eventsToAdd: int): + result=dict() + if eventsToAdd <= 0: + return result + for shot in originEvt.evt_shot: + id=shot.shot_id + + nextShot=None + for tmp in nextEvt.evt_shot: + if tmp.shot_id==id: + nextShot=tmp + break + if nextShot is None: + continue + result[id]=ShotDiff( + float(nextShot.origin[0] - shot.origin[0])/ float(eventsToAdd), + float(nextShot.origin[1] - shot.origin[1])/ float(eventsToAdd), + float(nextShot.destination[0] - shot.destination[0])/ float(eventsToAdd), + float(nextShot.destination[1] - shot.destination[1])/ float(eventsToAdd), + ) + + return result + + def calcTorpedoDiff(self, originEvt: Events, nextEvt: Events, eventsToAdd: int): + result=dict() + if eventsToAdd <= 0: + return result + for id, torpedo in originEvt.evt_torpedo.items(): + nextTorpedo=nextEvt.evt_torpedo.get(id) + if nextTorpedo is None: + continue + result[id]=TorpedoDiff( + float(nextTorpedo.x - torpedo.x)/ float(eventsToAdd), + float(nextTorpedo.y - torpedo.y)/ float(eventsToAdd), + (nextTorpedo.yaw - torpedo.yaw )/ eventsToAdd, + ) + + return result + + def calcAcousticTorpedoDiff(self, originEvt: Events, nextEvt: Events, eventsToAdd: int): + result=dict() + if eventsToAdd <= 0: + return result + for id, acousticTorpedo in originEvt.evt_acoustic_torpedo.items(): + nextAcousticTorpedo=nextEvt.evt_acoustic_torpedo.get(id) + if nextAcousticTorpedo is None: + continue + result[id]=TorpedoDiff( + float(nextAcousticTorpedo.x - acousticTorpedo.x)/ float(eventsToAdd), + float(nextAcousticTorpedo.y - acousticTorpedo.y)/ float(eventsToAdd), + (nextAcousticTorpedo.yaw - acousticTorpedo.yaw )/ eventsToAdd, + ) + + return result + + + def applyDiffData(self, diffData: LinerDiff, currentEvt: dict): + tmp=[] + for id, vehicle in currentEvt['evt_vehicle'].items(): + vehicle: Vehicle + diffVehicle = diffData.vehicleDiff.get(id) + diffVehicle: VehicleDiff + + if diffVehicle is None: + logging.debug("diffVehicle: id %s is none.", vehicle.vehicle_id) + continue + dic = vehicle._asdict() + dic['x']=dic['x'] + diffVehicle.x + dic['y']=dic['y'] + diffVehicle.y + dic['yaw']=dic['yaw'] + diffVehicle.yaw + dic['regenerated_health']=dic['regenerated_health']+diffVehicle.regenerated_health + dic['regen_crew_hp_limit']=dic['regen_crew_hp_limit']+diffVehicle.regen_crew_hp_limit + dic['regeneration_health']=dic['regeneration_health']+diffVehicle.regeneration_health + + currentEvt['evt_vehicle'][id]=toNamedTuple('Vehicle', dic) + + for id, plane in currentEvt['evt_plane'].items(): + plane: Plane + diffPlane = diffData.planeDiff.get(id) + diffPlane: PlaneDiff + + if diffPlane is None: + logging.debug("diffPlane: id %s is none.", id) + continue + dic=plane._asdict() + dic['position']=tuple([ + dic['position'][0]+diffPlane.x, + dic['position'][1]+diffPlane.y] + ) + + currentEvt['evt_plane'][id]=toNamedTuple('Plane', dic) + for i in range(len(currentEvt['evt_shot'])): + shot = currentEvt['evt_shot'][i] + id = shot.shot_id + shot: Shot + diffShot = diffData.shotDiff.get(id) + diffShot: ShotDiff + + if diffShot is None: + logging.debug("diffShot: id %s is none.", id) + continue + dic=shot._asdict() + origOrigin=dic['origin'] + origDest=dic['destnation'] + dic['origin']=tuple([origOrigin[0]+diffShot.origX,origOrigin[1]+diffShot.origY]) + dic['destnation']=tuple([origDest[0]+diffShot.destX,origDest[1]+diffShot.destY]) + currentEvt['evt_shot'][i]=toNamedTuple('Shot', dic) + for id, torpedo in currentEvt['evt_torpedo'].items(): + torpedo: Torpedo + diffTorpedo = diffData.torpedoDiff.get(id) + diffTorpedo: TorpedoDiff + + if diffTorpedo is None: + logging.debug("diffTorpedo: id %s is none.", id) + continue + dic=torpedo._asdict() + origOrigin=dic['origin'] + dic['origin']=tuple(origOrigin[0]+diffTorpedo.x,origOrigin[1]+diffTorpedo.y) + dic['yaw']=dic['yaw']+diffTorpedo.yaw + currentEvt['evt_torpedo'][id]=toNamedTuple('Torpedo', dic) + + for id, acoustic_torpedo in currentEvt['evt_acoustic_torpedo'].items(): + acoustic_torpedo: Torpedo + diffAcousticTorpedo = diffData.acousticTorpedoDiff.get(id) + diffAcousticTorpedo: AcousticTorpedoDiff + + if diffAcousticTorpedo is None: + logging.debug("diffAcousticTorpedo: id %s is none.", id) + continue + dic=acoustic_torpedo._asdict() + dic['x']=dic['x']+diffAcousticTorpedo.x + dic['y']=dic['y']+diffAcousticTorpedo.y + dic['yaw']=dic['yaw']+diffAcousticTorpedo.yaw + currentEvt['evt_acoustic_torpedo'][id]=toNamedTuple('AcousticTorpedo', dic) + + +def toNamedTuple(name: str, evt: dict): + keyList=evt.keys() + valueList=evt.values() + tmpTuple=collections.namedtuple(name, keyList) + return tmpTuple._make(valueList) diff --git a/src/render.py b/src/render.py index 2ee163d4..bc15490b 100644 --- a/src/render.py +++ b/src/render.py @@ -2,28 +2,41 @@ from renderer.render import Renderer from replay_parser import ReplayParser from renderer.utils import LOGGER +from interpolation.Interpolation import Interpolator - -if __name__ == "__main__": - import argparse - - parser = argparse.ArgumentParser() - parser.add_argument("--replay", type=str, required=True) - namespace = parser.parse_args() - path = Path(namespace.replay) +def run(pathStr, fps: int = 60, speed_scale: float = 20.0): + path = Path(pathStr) video_path = path.parent.joinpath(f"{path.stem}.mp4") - with open(namespace.replay, "rb") as f: + with open(path, "rb") as f: LOGGER.info("Parsing the replay file...") replay_info = ReplayParser( f, strict=True, raw_data_output=False ).get_info() + LOGGER.info("before interpolation: replay_info length: %d", len(replay_info["hidden"]["replay_data"].events)) + replay_info["hidden"]["replay_data"]=Interpolator().interpolate( + replay_info["hidden"]["replay_data"], + fpsTarget=fps, + speedScale=speed_scale + ) + LOGGER.info("after interpolation: replay_info length: %d", len(replay_info["hidden"]["replay_data"].events)) LOGGER.info("Rendering the replay file...") renderer = Renderer( replay_info["hidden"]["replay_data"], logs=True, enable_chat=True, use_tqdm=True, + fps=fps, + speed_scale=speed_scale ) renderer.start(str(video_path)) LOGGER.info(f"The video file is at: {str(video_path)}") LOGGER.info("Done.") + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser() + parser.add_argument("--replay", type=str, required=True) + parser.add_argument("--fps", type=int, required=False, default=60) + parser.add_argument("--speed", type=float, required=False, default=20.0) + namespace = parser.parse_args() + run(namespace.replay, namespace.fps, namespace.speed) \ No newline at end of file diff --git a/src/renderer/data.py b/src/renderer/data.py index 79f514e7..836ea5be 100644 --- a/src/renderer/data.py +++ b/src/renderer/data.py @@ -62,8 +62,8 @@ class Vehicle(NamedTuple): vehicle_id: int health: int is_alive: bool - x: int - y: int + x: float + y: float yaw: float relation: int is_visible: bool @@ -125,6 +125,7 @@ class Shot(NamedTuple): destination: tuple[int, int] shot_id: int t_time: int + server_time_left: int class Torpedo(NamedTuple): diff --git a/src/renderer/layers/shot.py b/src/renderer/layers/shot.py index abc64db1..55a3d559 100644 --- a/src/renderer/layers/shot.py +++ b/src/renderer/layers/shot.py @@ -70,10 +70,15 @@ def draw(self, game_time: int, image: Image.Image): draw = ImageDraw.Draw(base) for shot in events[game_time].evt_shot: + # adapt for fps & speed configuration + server_time_left = shot.server_time_left + fps = self._renderer.fps + speed_scale = self._renderer.speed_scale + t_time = server_time_left / (speed_scale / fps) / 2.7 result = getEquidistantPoints( flip_y(shot.origin), flip_y(shot.destination), - shot.t_time, + round(t_time), ) p = self._projectiles.setdefault(shot.shot_id, []) prev_x, prev_y = self._renderer.get_scaled(shot.origin) diff --git a/src/renderer/layers/torpedo.py b/src/renderer/layers/torpedo.py index ed1cadaf..bef9f375 100644 --- a/src/renderer/layers/torpedo.py +++ b/src/renderer/layers/torpedo.py @@ -114,6 +114,14 @@ def draw(self, game_time: int, draw: ImageDraw.ImageDraw): angle = active_torpedo.yaw angle = angle - radians(90) m_s_bw = active_torpedo.speed_bw + + # adapt for fps & speed configuration + fps = self._renderer.fps + speed_scale = self._renderer.speed_scale + + + m_s_bw = m_s_bw / fps * speed_scale + (x2, y2) = ( x1 + m_s_bw * cos(angle), y1 + m_s_bw * sin(angle), diff --git a/src/renderer/render.py b/src/renderer/render.py index 099a3232..b96ff283 100644 --- a/src/renderer/render.py +++ b/src/renderer/render.py @@ -200,7 +200,6 @@ def __init__( def start( self, path: str, - fps: int = 20, quality: int = 7, progress_cb: Optional[Callable[[float], Any]] = None, ): @@ -246,7 +245,7 @@ def start( self, self.replay_r, "red" ) - video_writer = self.get_writer(path, fps, quality) + video_writer = self.get_writer(path, self.fps, quality) video_writer.send(None) if self.use_tqdm: @@ -313,6 +312,8 @@ def __init__( enable_chat: bool = True, team_tracers: bool = False, use_tqdm: bool = False, + fps: int = 60, + speed_scale: float = 6.0, ): """Orchestrates the rendering process. @@ -331,6 +332,8 @@ def __init__( self.bg_color: tuple[int, int, int] = (0, 0, 0) self.use_tqdm = use_tqdm self._builder = ShipBuilder(self.resman) + self.fps = fps + self.speed_scale = speed_scale if self.anon: for i, (pid, pi) in enumerate( @@ -367,7 +370,6 @@ def get_player_build(self) -> list[dict]: def start( self, path: str, - fps: int = 20, quality: int = 7, progress_cb: Optional[Callable[[float], Any]] = None, ): @@ -395,7 +397,7 @@ def start( layer_chat = self._load_layer("LayerChat")(self) layer_markers = self._load_layer("LayerMarkers")(self) - video_writer = self.get_writer(path, fps, quality) + video_writer = self.get_writer(path, self.fps, quality) video_writer.send(None) self._draw_header(self.minimap_bg) @@ -470,8 +472,8 @@ def start( offset_y = 6 px, py = mid_x - tw, mid_y - th - offset_y - for i in range(3 * fps): - per = min(1, i / (1.5 * fps)) + for i in range(3 * self.fps): + per = min(1, i / (1.5 * self.fps)) drw_win.text( (px, py), text=text, diff --git a/src/replay_unpack/clients/wows/versions/0_11_10/battle_controller.py b/src/replay_unpack/clients/wows/versions/0_11_10/battle_controller.py index 87c70b5b..e96aead5 100644 --- a/src/replay_unpack/clients/wows/versions/0_11_10/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/0_11_10/battle_controller.py @@ -613,6 +613,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/0_11_11/battle_controller.py b/src/replay_unpack/clients/wows/versions/0_11_11/battle_controller.py index 18db9f5e..f3af4b3f 100644 --- a/src/replay_unpack/clients/wows/versions/0_11_11/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/0_11_11/battle_controller.py @@ -624,6 +624,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/0_11_6/battle_controller.py b/src/replay_unpack/clients/wows/versions/0_11_6/battle_controller.py index 27f06025..ff5b5aec 100644 --- a/src/replay_unpack/clients/wows/versions/0_11_6/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/0_11_6/battle_controller.py @@ -593,6 +593,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/0_11_7/battle_controller.py b/src/replay_unpack/clients/wows/versions/0_11_7/battle_controller.py index 27f06025..ff5b5aec 100644 --- a/src/replay_unpack/clients/wows/versions/0_11_7/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/0_11_7/battle_controller.py @@ -593,6 +593,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/0_11_8/battle_controller.py b/src/replay_unpack/clients/wows/versions/0_11_8/battle_controller.py index 87c70b5b..e96aead5 100644 --- a/src/replay_unpack/clients/wows/versions/0_11_8/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/0_11_8/battle_controller.py @@ -613,6 +613,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/0_11_9/battle_controller.py b/src/replay_unpack/clients/wows/versions/0_11_9/battle_controller.py index 87c70b5b..e96aead5 100644 --- a/src/replay_unpack/clients/wows/versions/0_11_9/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/0_11_9/battle_controller.py @@ -613,6 +613,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/12_0_0/battle_controller.py b/src/replay_unpack/clients/wows/versions/12_0_0/battle_controller.py index 383b03b5..fba685e9 100644 --- a/src/replay_unpack/clients/wows/versions/12_0_0/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/12_0_0/battle_controller.py @@ -627,6 +627,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/12_1_0/battle_controller.py b/src/replay_unpack/clients/wows/versions/12_1_0/battle_controller.py index 383b03b5..fba685e9 100644 --- a/src/replay_unpack/clients/wows/versions/12_1_0/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/12_1_0/battle_controller.py @@ -627,6 +627,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/12_2_0/battle_controller.py b/src/replay_unpack/clients/wows/versions/12_2_0/battle_controller.py index 383b03b5..fba685e9 100644 --- a/src/replay_unpack/clients/wows/versions/12_2_0/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/12_2_0/battle_controller.py @@ -627,6 +627,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/12_3_1/battle_controller.py b/src/replay_unpack/clients/wows/versions/12_3_1/battle_controller.py index 383b03b5..fba685e9 100644 --- a/src/replay_unpack/clients/wows/versions/12_3_1/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/12_3_1/battle_controller.py @@ -627,6 +627,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/12_4_0/battle_controller.py b/src/replay_unpack/clients/wows/versions/12_4_0/battle_controller.py index 383b03b5..fba685e9 100644 --- a/src/replay_unpack/clients/wows/versions/12_4_0/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/12_4_0/battle_controller.py @@ -627,6 +627,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/12_5_0/battle_controller.py b/src/replay_unpack/clients/wows/versions/12_5_0/battle_controller.py index fe4853d2..0b9ac896 100644 --- a/src/replay_unpack/clients/wows/versions/12_5_0/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/12_5_0/battle_controller.py @@ -630,6 +630,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/12_6_0/battle_controller.py b/src/replay_unpack/clients/wows/versions/12_6_0/battle_controller.py index fe4853d2..0b9ac896 100644 --- a/src/replay_unpack/clients/wows/versions/12_6_0/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/12_6_0/battle_controller.py @@ -630,6 +630,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/12_7_0/battle_controller.py b/src/replay_unpack/clients/wows/versions/12_7_0/battle_controller.py index fe4853d2..0b9ac896 100644 --- a/src/replay_unpack/clients/wows/versions/12_7_0/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/12_7_0/battle_controller.py @@ -630,6 +630,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/12_8_0/battle_controller.py b/src/replay_unpack/clients/wows/versions/12_8_0/battle_controller.py index fe4853d2..0b9ac896 100644 --- a/src/replay_unpack/clients/wows/versions/12_8_0/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/12_8_0/battle_controller.py @@ -630,6 +630,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + server_time_left=projectile["serverTimeLeft"] ) ) diff --git a/src/replay_unpack/clients/wows/versions/12_9_0/battle_controller.py b/src/replay_unpack/clients/wows/versions/12_9_0/battle_controller.py index fe4853d2..8f059f51 100644 --- a/src/replay_unpack/clients/wows/versions/12_9_0/battle_controller.py +++ b/src/replay_unpack/clients/wows/versions/12_9_0/battle_controller.py @@ -630,6 +630,7 @@ def _r_shots(self, entity: Entity, shots: list): (x2, y2), int(f"{owner_id}{projectile['shotID']}"), t_time, + projectile["serverTimeLeft"], ) ) diff --git a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/component_defs/XmppComponent.def b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/component_defs/XmppComponent.def index abe4a5fa..e07a2105 100644 --- a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/component_defs/XmppComponent.def +++ b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/component_defs/XmppComponent.def @@ -1,4 +1,4 @@ - + MSGPACK_BLOB diff --git a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/alias.xml b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/alias.xml index de51cf5f..42d98e2f 100644 --- a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/alias.xml +++ b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/alias.xml @@ -1,4 +1,4 @@ - + UINT8 UINT32 INT32 diff --git a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AccountCMDs.def b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AccountCMDs.def index b2d214b8..82b8b63b 100644 --- a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AccountCMDs.def +++ b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AccountCMDs.def @@ -1,4 +1,4 @@ - + diff --git a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AccountPData.def b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AccountPData.def index de981b9f..d3157061 100644 --- a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AccountPData.def +++ b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AccountPData.def @@ -1,4 +1,4 @@ - + diff --git a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AirDefenceOwner.def b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AirDefenceOwner.def index 41e917f5..2e860599 100644 --- a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AirDefenceOwner.def +++ b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AirDefenceOwner.def @@ -1,4 +1,4 @@ - + BOOL diff --git a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AtbaOwner.def b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AtbaOwner.def index 4723f299..5672c02a 100644 --- a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AtbaOwner.def +++ b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AtbaOwner.def @@ -1,4 +1,4 @@ - + ATBA_TARGETS diff --git a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AviationOwner.def b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AviationOwner.def index 09420ce6..9507b7f7 100644 --- a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AviationOwner.def +++ b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/AviationOwner.def @@ -1,4 +1,4 @@ - + diff --git a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/BattleLogicEntityOwner.def b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/BattleLogicEntityOwner.def index d716467c..af6574f1 100644 --- a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/BattleLogicEntityOwner.def +++ b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/BattleLogicEntityOwner.def @@ -1,4 +1,4 @@ - + ENTITY_ID diff --git a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/BattleStarterClient.def b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/BattleStarterClient.def index f5f209e7..94f23790 100644 --- a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/BattleStarterClient.def +++ b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/entity_defs/interfaces/BattleStarterClient.def @@ -1,4 +1,4 @@ - + diff --git a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/user_data_object_defs/SoundedEffect.def b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/user_data_object_defs/SoundedEffect.def new file mode 100644 index 00000000..d56c21a4 --- /dev/null +++ b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/user_data_object_defs/SoundedEffect.def @@ -0,0 +1,31 @@ + + CLIENT + + + + STRING + true + + + + STRING + true + + + + STRING + true + + + + BOOL + true + + + + FLOAT32 + true + + + + diff --git a/src/replay_unpack/clients/wows/versions/12_9_0/scripts/user_data_object_defs/SoundedModel.def b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/user_data_object_defs/SoundedModel.def new file mode 100644 index 00000000..75aea60e --- /dev/null +++ b/src/replay_unpack/clients/wows/versions/12_9_0/scripts/user_data_object_defs/SoundedModel.def @@ -0,0 +1,42 @@ + + CLIENT + Enable + + + STRING + true + + + + STRING + True + + + + + STRING + True + + + + STRING + True + + + + FLOAT32 + 1.0 + True + + + + STRING + True + + + + BOOL + False + + +