This commit is contained in:
Robin Appelman 2022-04-03 16:47:40 +02:00
commit cb395c87a4
4 changed files with 40 additions and 7 deletions

View file

@ -29,7 +29,7 @@ pub fn map_coords<C: Into<[f32; 3]>>(vec: C) -> [f32; 3] {
} }
// 1 hammer unit is ~1.905cm // 1 hammer unit is ~1.905cm
const UNIT_SCALE: f32 = 1.0 / (1.905 * 100.0); pub const UNIT_SCALE: f32 = 1.0 / (1.905 * 100.0);
fn model_to_mesh(model: Handle<vbsp::data::Model>) -> CPUMesh { fn model_to_mesh(model: Handle<vbsp::data::Model>) -> CPUMesh {
let positions: Vec<f32> = model let positions: Vec<f32> = model

View file

@ -150,7 +150,6 @@ impl Control for DemoCamera {
if text == "p" { if text == "p" {
change = true; change = true;
self.playing = !self.playing; self.playing = !self.playing;
dbg!(self.playing);
if self.playing { if self.playing {
self.playback_start_time = accumulated_time; self.playback_start_time = accumulated_time;
} else { } else {

View file

@ -1,10 +1,12 @@
use crate::bsp::map_coords; use crate::bsp::{map_coords, UNIT_SCALE};
use crate::Error; use crate::Error;
use std::fs; use std::fs;
use std::path::Path; use std::path::Path;
use tf_demo_parser::demo::data::UserInfo; use tf_demo_parser::demo::data::UserInfo;
use tf_demo_parser::demo::header::Header;
use tf_demo_parser::demo::message::packetentities::EntityId; use tf_demo_parser::demo::message::packetentities::EntityId;
use tf_demo_parser::demo::message::Message; use tf_demo_parser::demo::message::Message;
use tf_demo_parser::demo::packet::message::MessagePacketMeta;
use tf_demo_parser::demo::packet::stringtable::StringTableEntry; use tf_demo_parser::demo::packet::stringtable::StringTableEntry;
use tf_demo_parser::demo::parser::MessageHandler; use tf_demo_parser::demo::parser::MessageHandler;
use tf_demo_parser::demo::sendprop::SendPropIdentifier; use tf_demo_parser::demo::sendprop::SendPropIdentifier;
@ -39,11 +41,14 @@ impl DemoInfo {
struct PovAnalyzer { struct PovAnalyzer {
last_position: Vector, last_position: Vector,
last_angles: [f32; 2], last_angles: [f32; 2],
view_offset: f32,
positions: Vec<(Vec3, [f32; 2])>, positions: Vec<(Vec3, [f32; 2])>,
name: String, name: String,
player: Option<EntityId>, player: Option<EntityId>,
start_tick: u32, start_tick: u32,
last_tick: u32, last_tick: u32,
pov_name: String,
is_pov: bool,
} }
impl MessageHandler for PovAnalyzer { impl MessageHandler for PovAnalyzer {
@ -53,6 +58,23 @@ impl MessageHandler for PovAnalyzer {
matches!(message_type, MessageType::PacketEntities) matches!(message_type, MessageType::PacketEntities)
} }
fn handle_header(&mut self, header: &Header) {
self.pov_name = header.nick.clone();
if self.name.is_empty() {
self.name = self.pov_name.clone();
}
}
fn handle_packet_meta(&mut self, meta: &MessagePacketMeta) {
if self.is_pov {
self.last_angles = [
meta.view_angles.local_angles.1.x,
meta.view_angles.local_angles.1.y,
];
self.last_position = meta.view_angles.origin.1
}
}
fn handle_message(&mut self, message: &Message, tick: u32) { fn handle_message(&mut self, message: &Message, tick: u32) {
const LOCAL_ORIGIN: SendPropIdentifier = const LOCAL_ORIGIN: SendPropIdentifier =
SendPropIdentifier::new("DT_TFLocalPlayerExclusive", "m_vecOrigin"); SendPropIdentifier::new("DT_TFLocalPlayerExclusive", "m_vecOrigin");
@ -70,6 +92,8 @@ impl MessageHandler for PovAnalyzer {
SendPropIdentifier::new("DT_TFLocalPlayerExclusive", "m_angEyeAngles[0]"); SendPropIdentifier::new("DT_TFLocalPlayerExclusive", "m_angEyeAngles[0]");
const NON_LOCAL_PITCH_ANGLES: SendPropIdentifier = const NON_LOCAL_PITCH_ANGLES: SendPropIdentifier =
SendPropIdentifier::new("DT_TFNonLocalPlayerExclusive", "m_angEyeAngles[0]"); SendPropIdentifier::new("DT_TFNonLocalPlayerExclusive", "m_angEyeAngles[0]");
const VIEW_OFFSET: SendPropIdentifier =
SendPropIdentifier::new("DT_LocalPlayerExclusive", "m_vecViewOffset[2]");
if let (Message::PacketEntities(message), Some(player_id)) = (message, self.player) { if let (Message::PacketEntities(message), Some(player_id)) = (message, self.player) {
if self.start_tick == 0 { if self.start_tick == 0 {
@ -94,6 +118,10 @@ impl MessageHandler for PovAnalyzer {
LOCAL_PITCH_ANGLES | NON_LOCAL_PITCH_ANGLES => { LOCAL_PITCH_ANGLES | NON_LOCAL_PITCH_ANGLES => {
self.last_angles[0] = f32::try_from(&prop.value).unwrap_or_default() self.last_angles[0] = f32::try_from(&prop.value).unwrap_or_default()
} }
VIEW_OFFSET => {
self.view_offset =
f32::try_from(&prop.value).unwrap_or_default() * UNIT_SCALE;
}
_ => {} _ => {}
} }
} }
@ -104,8 +132,10 @@ impl MessageHandler for PovAnalyzer {
if tick > self.last_tick { if tick > self.last_tick {
self.last_tick = tick; self.last_tick = tick;
let pos = map_coords(self.last_position); let pos = map_coords(self.last_position);
self.positions self.positions.push((
.push((vec3(pos[0], pos[1], pos[2]), self.last_angles)); vec3(pos[0], pos[1] + self.view_offset, pos[2]),
self.last_angles,
));
} }
} }
@ -132,11 +162,14 @@ impl PovAnalyzer {
PovAnalyzer { PovAnalyzer {
last_position: Vector::default(), last_position: Vector::default(),
last_angles: [0.0, 0.0], last_angles: [0.0, 0.0],
view_offset: 0.0,
positions: vec![], positions: vec![],
name, name,
player: None, player: None,
start_tick: 0, start_tick: 0,
last_tick: 0, last_tick: 0,
pov_name: String::new(),
is_pov: false,
} }
} }
@ -148,6 +181,7 @@ impl PovAnalyzer {
.to_ascii_lowercase() .to_ascii_lowercase()
.contains(&self.name) .contains(&self.name)
{ {
self.is_pov = user_info.player_info.name == self.pov_name;
self.player = Some(user_info.entity_id); self.player = Some(user_info.entity_id);
} }
} }

View file

@ -27,7 +27,7 @@ struct Args {
/// Path of the demo or map file /// Path of the demo or map file
path: String, path: String,
/// Name of the player to follow /// Name of the player to follow
player: String, player: Option<String>,
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]
@ -79,7 +79,7 @@ fn main() -> Result<(), Error> {
})?; })?;
if args.path.ends_with(".dem") { if args.path.ends_with(".dem") {
let demo = DemoInfo::new(args.path, &args.player)?; let demo = DemoInfo::new(args.path, &args.player.unwrap_or_default())?;
let mut loader = Loader::new()?; let mut loader = Loader::new()?;
let map = loader.load(&format!("maps/{}.bsp", demo.map))?; let map = loader.load(&format!("maps/{}.bsp", demo.map))?;