|
|
|
|
@@ -501,6 +501,27 @@ impl StyleHelper for StyleModifiers{
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#[derive(Clone,Debug)]
|
|
|
|
|
struct StrafeTickState{
|
|
|
|
|
tick_number:u64,
|
|
|
|
|
}
|
|
|
|
|
impl StrafeTickState{
|
|
|
|
|
fn new(time:Time,settings:&gameplay_style::StrafeSettings)->Self{
|
|
|
|
|
// let time=n*seconds/ticks;
|
|
|
|
|
let time=time.nanos() as i128;
|
|
|
|
|
let ticks=settings.tick_rate.num() as i128;
|
|
|
|
|
let seconds=settings.tick_rate.den() as i128;
|
|
|
|
|
let tick_number=(time*ticks/seconds) as u64;
|
|
|
|
|
StrafeTickState{tick_number}
|
|
|
|
|
}
|
|
|
|
|
fn next_tick(&self,settings:&gameplay_style::StrafeSettings)->Time{
|
|
|
|
|
let n=self.tick_number as i128;
|
|
|
|
|
let ticks=settings.tick_rate.num() as i128;
|
|
|
|
|
let seconds=settings.tick_rate.den() as i128;
|
|
|
|
|
let time=n*seconds/ticks;
|
|
|
|
|
Time::from_nanos(time as i64)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#[derive(Clone,Debug)]
|
|
|
|
|
enum MoveState{
|
|
|
|
|
Air,
|
|
|
|
|
Walk(ContactMoveState),
|
|
|
|
|
@@ -578,7 +599,7 @@ impl MoveState{
|
|
|
|
|
=>None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fn next_move_instruction(&self,strafe:&Option<gameplay_style::StrafeSettings>,time:Time)->Option<TimedInstruction<InternalInstruction,Time>>{
|
|
|
|
|
fn next_move_instruction(&self)->Option<TimedInstruction<InternalInstruction,Time>>{
|
|
|
|
|
//check if you have a valid walk state and create an instruction
|
|
|
|
|
match self{
|
|
|
|
|
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>match &walk_state.target{
|
|
|
|
|
@@ -590,13 +611,7 @@ impl MoveState{
|
|
|
|
|
|TransientAcceleration::Reached
|
|
|
|
|
=>None,
|
|
|
|
|
}
|
|
|
|
|
MoveState::Air=>strafe.as_ref().map(|strafe|{
|
|
|
|
|
TimedInstruction{
|
|
|
|
|
time:strafe.next_tick(time),
|
|
|
|
|
//only poll the physics if there is a before and after mouse event
|
|
|
|
|
instruction:InternalInstruction::StrafeTick
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
MoveState::Air=>None,
|
|
|
|
|
MoveState::Water=>None,//TODO
|
|
|
|
|
MoveState::Fly=>None,
|
|
|
|
|
}
|
|
|
|
|
@@ -605,25 +620,26 @@ impl MoveState{
|
|
|
|
|
*self=move_state;
|
|
|
|
|
//this function call reads the above state that was just set
|
|
|
|
|
self.update_walk_target(body,touching,models,hitbox_mesh,style,camera,input_state);
|
|
|
|
|
// Never used? make body immutable
|
|
|
|
|
self.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state);
|
|
|
|
|
}
|
|
|
|
|
fn cull_velocity(&mut self,velocity:Planar64Vec3,body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){
|
|
|
|
|
//TODO: be more precise about contacts
|
|
|
|
|
if set_velocity_cull(body,touching,models,hitbox_mesh,velocity){
|
|
|
|
|
// TODO do better
|
|
|
|
|
// TODO: unduplicate this code
|
|
|
|
|
match self.get_walk_state(){
|
|
|
|
|
// did you stop touching the thing you were walking on?
|
|
|
|
|
Some(walk_state)=>if !touching.contains_contact(&walk_state.contact.convex_mesh_id){
|
|
|
|
|
self.set_move_state(MoveState::Air,body,touching,models,hitbox_mesh,style,camera,input_state);
|
|
|
|
|
}else{
|
|
|
|
|
// stopped touching something else while walking
|
|
|
|
|
self.update_walk_target(body,touching,models,hitbox_mesh,style,camera,input_state);
|
|
|
|
|
self.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state);
|
|
|
|
|
},
|
|
|
|
|
// not walking, but stopped touching something
|
|
|
|
|
None=>self.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state),
|
|
|
|
|
}
|
|
|
|
|
self.update_move_state(body,touching,models,hitbox_mesh,style,camera,input_state,|contact|!touching.contains_contact(&contact.convex_mesh_id));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fn update_move_state(&mut self,body:&mut Body,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState,is_contact_removed:impl Fn(&ContactCollision)->bool){
|
|
|
|
|
match self.get_walk_state(){
|
|
|
|
|
// did you stop touching the thing you were walking on?
|
|
|
|
|
Some(walk_state)=>if is_contact_removed(&walk_state.contact){
|
|
|
|
|
self.set_move_state(MoveState::Air,body,touching,models,hitbox_mesh,style,camera,input_state);
|
|
|
|
|
}else{
|
|
|
|
|
// stopped touching something else while walking
|
|
|
|
|
self.update_walk_target(body,touching,models,hitbox_mesh,style,camera,input_state);
|
|
|
|
|
self.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state);
|
|
|
|
|
},
|
|
|
|
|
// not walking, but stopped touching something
|
|
|
|
|
None=>self.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -877,6 +893,7 @@ pub struct PhysicsState{
|
|
|
|
|
//gameplay_state
|
|
|
|
|
mode_state:ModeState,
|
|
|
|
|
move_state:MoveState,
|
|
|
|
|
strafe_tick_state:StrafeTickState,
|
|
|
|
|
//run is non optional: when you spawn in a run is created
|
|
|
|
|
//the run cannot be finished unless you start it by visiting
|
|
|
|
|
//a start zone. If you change mode, a new run is created.
|
|
|
|
|
@@ -895,6 +912,7 @@ impl Default for PhysicsState{
|
|
|
|
|
input_state:InputState::default(),
|
|
|
|
|
_world:WorldState{},
|
|
|
|
|
mode_state:ModeState::default(),
|
|
|
|
|
strafe_tick_state:StrafeTickState::new(Time::ZERO,&StyleModifiers::default().strafe.unwrap()),
|
|
|
|
|
run:run::Run::new(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -941,10 +959,7 @@ impl PhysicsState{
|
|
|
|
|
*self=Self::default();
|
|
|
|
|
}
|
|
|
|
|
fn next_move_instruction(&self)->Option<TimedInstruction<InternalInstruction,Time>>{
|
|
|
|
|
self.move_state.next_move_instruction(&self.style.strafe,self.time)
|
|
|
|
|
}
|
|
|
|
|
fn cull_velocity(&mut self,data:&PhysicsData,velocity:Planar64Vec3){
|
|
|
|
|
self.move_state.cull_velocity(velocity,&mut self.body,&mut self.touching,&data.models,&data.hitbox_mesh,&self.style,&self.camera,&self.input_state);
|
|
|
|
|
self.move_state.next_move_instruction()
|
|
|
|
|
}
|
|
|
|
|
fn set_move_state(&mut self,data:&PhysicsData,move_state:MoveState){
|
|
|
|
|
self.move_state.set_move_state(move_state,&mut self.body,&self.touching,&data.models,&data.hitbox_mesh,&self.style,&self.camera,&self.input_state);
|
|
|
|
|
@@ -1202,8 +1217,18 @@ fn next_instruction_internal(state:&PhysicsState,data:&PhysicsData,time_limit:Ti
|
|
|
|
|
//JUST POLLING!!! NO MUTATION
|
|
|
|
|
let mut collector=instruction::InstructionCollector::new(time_limit);
|
|
|
|
|
|
|
|
|
|
// walking
|
|
|
|
|
collector.collect(state.next_move_instruction());
|
|
|
|
|
|
|
|
|
|
// strafe tick
|
|
|
|
|
collector.collect(state.style.strafe.as_ref().map(|strafe|{
|
|
|
|
|
TimedInstruction{
|
|
|
|
|
time:state.strafe_tick_state.next_tick(strafe),
|
|
|
|
|
//only poll the physics if there is a before and after mouse event
|
|
|
|
|
instruction:InternalInstruction::StrafeTick
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
let trajectory=state.body.with_acceleration(state.acceleration(data));
|
|
|
|
|
//check for collision ends
|
|
|
|
|
state.touching.predict_collision_end(&mut collector,&data.models,&data.hitbox_mesh,&trajectory,state.time);
|
|
|
|
|
@@ -1701,22 +1726,7 @@ fn collision_end_contact(
|
|
|
|
|
){
|
|
|
|
|
touching.remove_contact(convex_mesh_id);//remove contact before calling contact_constrain_acceleration
|
|
|
|
|
//check ground
|
|
|
|
|
//TODO do better
|
|
|
|
|
//this is inner code from move_state.cull_velocity
|
|
|
|
|
match move_state.get_walk_state(){
|
|
|
|
|
// did you stop touching the thing you were walking on?
|
|
|
|
|
// This does not check the face! Is that a bad thing? It should be
|
|
|
|
|
// impossible to stop touching a different face than you started touching...
|
|
|
|
|
Some(walk_state)=>if &walk_state.contact.convex_mesh_id==convex_mesh_id{
|
|
|
|
|
move_state.set_move_state(MoveState::Air,body,touching,models,hitbox_mesh,style,camera,input_state);
|
|
|
|
|
}else{
|
|
|
|
|
// stopped touching something else while walking
|
|
|
|
|
move_state.update_walk_target(body,touching,models,hitbox_mesh,style,camera,input_state);
|
|
|
|
|
move_state.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state);
|
|
|
|
|
},
|
|
|
|
|
// not walking, but stopped touching something
|
|
|
|
|
None=>move_state.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state),
|
|
|
|
|
}
|
|
|
|
|
move_state.update_move_state(body,touching,models,hitbox_mesh,style,camera,input_state,|contact|contact.convex_mesh_id==*convex_mesh_id);
|
|
|
|
|
}
|
|
|
|
|
fn collision_end_intersect(
|
|
|
|
|
move_state:&mut MoveState,
|
|
|
|
|
@@ -1799,6 +1809,7 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
InternalInstruction::StrafeTick=>{
|
|
|
|
|
state.strafe_tick_state.tick_number+=1;
|
|
|
|
|
//TODO make this less huge
|
|
|
|
|
if let Some(strafe_settings)=&state.style.strafe{
|
|
|
|
|
let controls=state.input_state.controls;
|
|
|
|
|
@@ -1813,7 +1824,7 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim
|
|
|
|
|
state.body=extrapolated_body;
|
|
|
|
|
//this is wrong but will work ig
|
|
|
|
|
//need to note which push planes activate in push solve and keep those
|
|
|
|
|
state.cull_velocity(data,ticked_velocity);
|
|
|
|
|
state.move_state.cull_velocity(ticked_velocity,&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -1897,7 +1908,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
|
|
|
|
|
let jump_dir=walk_state.jump_direction.direction(&data.models,&data.hitbox_mesh,&walk_state.contact);
|
|
|
|
|
let booster_option=data.models.contact_attr(walk_state.contact.convex_mesh_id.model_id).general.booster.as_ref();
|
|
|
|
|
let jumped_velocity=jump_settings.jumped_velocity(&state.style,jump_dir,state.body.velocity,booster_option);
|
|
|
|
|
state.cull_velocity(data,jumped_velocity);
|
|
|
|
|
state.move_state.cull_velocity(jumped_velocity,&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b_refresh_walk_target=false;
|
|
|
|
|
@@ -1970,7 +1981,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
|
|
|
|
|
if b_refresh_walk_target{
|
|
|
|
|
state.move_state.update_walk_target(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state);
|
|
|
|
|
state.move_state.update_fly_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state);
|
|
|
|
|
state.cull_velocity(data,state.body.velocity);
|
|
|
|
|
state.move_state.cull_velocity(state.body.velocity,&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state);
|
|
|
|
|
//also check if accelerating away from surface
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|