diff --git a/korangar/src/main.rs b/korangar/src/main.rs index 908487bc..7979a5b6 100644 --- a/korangar/src/main.rs +++ b/korangar/src/main.rs @@ -964,7 +964,7 @@ impl Client { &mut self.path_finder, saved_login_data.account_id, character_information, - WorldPosition { x: 0, y: 0 }, + WorldPosition { x: 0, y: 0, direction: 0 }, client_tick, ); let player = Entity::Player(player); @@ -1589,6 +1589,7 @@ impl Client { let _ = self.networking_system.player_move(WorldPosition { x: destination.x, y: destination.y, + direction: 0, }); } } @@ -1604,6 +1605,7 @@ impl Client { WorldPosition { x: position.x, y: position.y, + direction: 0, } }), _ => Ok(()), diff --git a/korangar/src/world/animation/mod.rs b/korangar/src/world/animation/mod.rs index 3ac2055e..5362ccd6 100644 --- a/korangar/src/world/animation/mod.rs +++ b/korangar/src/world/animation/mod.rs @@ -82,9 +82,9 @@ impl Default for AnimationFramePart { } impl AnimationData { - pub fn get_frame(&self, animation_state: &AnimationState, camera: &dyn Camera, head_direction: usize) -> &AnimationFrame { + pub fn get_frame(&self, animation_state: &AnimationState, camera: &dyn Camera, direction: usize) -> &AnimationFrame { let camera_direction = camera.camera_direction(); - let direction = (camera_direction + head_direction) % 8; + let direction = (camera_direction + direction) % 8; let animation_action_index = animation_state.action as usize * 8 + direction; let delay_index = animation_action_index % self.delays.len(); @@ -143,9 +143,9 @@ impl AnimationData { entity_id: EntityId, entity_position: Point3, animation_state: &AnimationState, - head_direction: usize, + direction: usize, ) { - let frame = self.get_frame(animation_state, camera, head_direction); + let frame = self.get_frame(animation_state, camera, direction); let world_matrix = self.calculate_world_matrix(camera, frame, entity_position); for (index, frame_part) in frame.frame_parts.iter().enumerate() { @@ -187,11 +187,11 @@ impl AnimationData { camera: &dyn Camera, entity_position: Point3, animation_state: &AnimationState, - head_direction: usize, + direction: usize, color_external: Color, color_internal: Color, ) { - let frame = self.get_frame(animation_state, camera, head_direction); + let frame = self.get_frame(animation_state, camera, direction); let world_matrix = self.calculate_world_matrix(camera, frame, entity_position); instructions.push(DebugRectangleInstruction { world: world_matrix, diff --git a/korangar/src/world/entity/mod.rs b/korangar/src/world/entity/mod.rs index b9e37727..55f41aed 100644 --- a/korangar/src/world/entity/mod.rs +++ b/korangar/src/world/entity/mod.rs @@ -115,6 +115,7 @@ pub struct Common { pub health_points: usize, pub maximum_health_points: usize, pub movement_speed: usize, + pub direction: usize, pub head_direction: usize, pub sex: Sex, @@ -345,6 +346,7 @@ impl Common { let grid_position = Vector2::new(grid_position.x, grid_position.y); let position = map.get_world_position(grid_position); let head_direction = entity_data.head_direction; + let direction = entity_data.position.direction; let movement_speed = entity_data.movement_speed as usize; let health_points = entity_data.health_points as usize; @@ -375,6 +377,7 @@ impl Common { position, entity_id, job_id, + direction, head_direction, sex, active_movement, @@ -414,7 +417,7 @@ impl Common { self.update_movement(map, client_tick); self.animation_state.update(client_tick); - let frame = self.animation_data.get_frame(&self.animation_state, camera, self.head_direction); + let frame = self.animation_data.get_frame(&self.animation_state, camera, self.direction); match frame.event { Some(ActionEvent::Sound { key }) => { self.sound_state.update(audio_engine, self.position, key, client_tick); @@ -449,7 +452,7 @@ impl Common { let array = last_step_position - next_step_position; let array: &[isize; 2] = array.as_ref(); - self.head_direction = match array { + self.direction = match array { [0, 1] => 0, [1, 1] => 1, [1, 0] => 2, @@ -762,7 +765,7 @@ impl Common { self.entity_id, self.position, &self.animation_state, - self.head_direction, + self.direction, ); } @@ -773,7 +776,7 @@ impl Common { camera, self.position, &self.animation_state, - self.head_direction, + self.direction, Color::rgb_u8(255, 0, 0), Color::rgb_u8(0, 255, 0), ); diff --git a/ragnarok_packets/src/position.rs b/ragnarok_packets/src/position.rs index 93f696ab..815b5222 100644 --- a/ragnarok_packets/src/position.rs +++ b/ragnarok_packets/src/position.rs @@ -5,11 +5,12 @@ use ragnarok_bytes::{ByteReader, ConversionResult, FromBytes, ToBytes}; pub struct WorldPosition { pub x: usize, pub y: usize, + pub direction: usize, } impl WorldPosition { pub fn new(x: usize, y: usize) -> Self { - Self { x, y } + Self { x, y, direction: 0 } } } @@ -19,19 +20,23 @@ impl FromBytes for WorldPosition { let x = (coordinates[1] >> 6) | (coordinates[0] << 2); let y = (coordinates[2] >> 4) | ((coordinates[1] & 0b111111) << 4); - //let direction = ... + let mut direction = coordinates[2] & 0b1111; + // faster than direction = (8 - direction + 4) % 8 + direction = (8 - direction + 4) & 7; - Ok(Self { x, y }) + Ok(Self { x, y, direction }) } } impl ToBytes for WorldPosition { fn to_bytes(&self) -> ConversionResult> { let mut coordinates = vec![0, 0, 0]; + // faster than direction = (8 - direction + 4) % 8 + let direction = (8 - self.direction + 4) & 7; coordinates[0] = (self.x >> 2) as u8; coordinates[1] = ((self.x << 6) as u8) | (((self.y >> 4) & 0x3F) as u8); - coordinates[2] = (self.y << 4) as u8; + coordinates[2] = (self.y << 4) as u8 | (direction & 0xF) as u8; Ok(coordinates) } @@ -52,10 +57,18 @@ impl WorldPosition2 { } pub fn to_origin_destination(self) -> (WorldPosition, WorldPosition) { - (WorldPosition { x: self.x1, y: self.y1 }, WorldPosition { - x: self.x2, - y: self.y2, - }) + ( + WorldPosition { + x: self.x1, + y: self.y1, + direction: 0, + }, + WorldPosition { + x: self.x2, + y: self.y2, + direction: 0, + }, + ) } } @@ -95,10 +108,9 @@ mod conversion { #[test] fn world_position() { - // Since we don't save the orientation when deserializing, this is a lossy - // operation. So we construct some test cases that igonore the bits in - // question. - let cases = [[255, 0, 0], [0, 255, 0], [0, 0, 240]]; + // The direction must be between 0 and 7 inclusive. + let direction = [0, 3, 7]; + let cases = [[255, 0, 0 + direction[0]], [0, 255, 0 + direction[1]], [0, 0, 240 + direction[2]]]; for case in cases { let mut byte_reader = ragnarok_bytes::ByteReader::without_metadata(&case);