make a distinction between restart and spawning

This commit is contained in:
Quaternions 2024-08-01 12:57:58 -07:00
parent 76a9b33fb2
commit 3a806f10f3
3 changed files with 44 additions and 11 deletions

View File

@ -42,7 +42,8 @@ pub enum PhysicsInputInstruction{
SetMoveForward(bool),
SetJump(bool),
SetZoom(bool),
Reset,
Restart,
Spawn(gameplay_modes::ModeId,StageId),
Idle,
//Idle: there were no input events, but the simulation is safe to advance to this timestep
//for interpolation / networking / playback reasons, most playback heads will always want
@ -963,6 +964,11 @@ impl PhysicsState{
fn clear(&mut self){
self.touching.clear();
}
fn reset_to_default(&mut self){
let mut new_state=Self::default();
new_state.camera.sensitivity=self.camera.sensitivity;
*self=new_state;
}
fn next_move_instruction(&self)->Option<TimedInstruction<PhysicsInternalInstruction>>{
self.move_state.next_move_instruction(&self.style.strafe,self.time)
}
@ -1059,10 +1065,16 @@ impl PhysicsContext{
instruction:PhysicsInputInstruction::SetSensitivity(user_settings.calculate_sensitivity()),
});
}
pub fn restart(&mut self){
self.run_input_instruction(TimedInstruction{
time:self.state.time,
instruction:PhysicsInputInstruction::Restart,
});
}
pub fn spawn(&mut self){
self.run_input_instruction(TimedInstruction{
time:self.state.time,
instruction:PhysicsInputInstruction::Reset,
instruction:PhysicsInputInstruction::Spawn(gameplay_modes::ModeId::MAIN,StageId::FIRST),
});
}
pub const fn output(&self)->PhysicsOutputState{
@ -1530,7 +1542,8 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
//the body may as well be a quantum wave function
//as far as these instruction are concerned (they don't care where it is)
PhysicsInputInstruction::SetSensitivity(..)
|PhysicsInputInstruction::Reset
|PhysicsInputInstruction::Restart
|PhysicsInputInstruction::Spawn(..)
|PhysicsInputInstruction::SetZoom(..)
|PhysicsInputInstruction::Idle=>false,
//these controls only update the body if you are on the ground
@ -1593,18 +1606,26 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
state.input_state.set_control(Controls::Zoom,s);
b_refresh_walk_target=false;
},
PhysicsInputInstruction::Reset=>{
//it matters which of these runs first, but I have not thought it through yet as it doesn't matter yet
state.mode_state.clear();
state.mode_state.set_stage_id(gameplay_modes::StageId::FIRST);
PhysicsInputInstruction::Restart=>{
//totally reset physics state
state.reset_to_default();
//spawn at start zone
let spawn_point=data.modes.get_mode(state.mode_state.get_mode_id()).map(|mode|
//TODO: spawn at the bottom of the start zone plus the hitbox size
//TODO: set camera andles to face the same way as the start zone
data.models.model(mode.get_start().into()).transform.vertex.translation
).unwrap_or(Planar64Vec3::ZERO);
set_position(&mut state.body,&mut state.touching,spawn_point);
set_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,Planar64Vec3::ZERO);
state.set_move_state(data,MoveState::Air);
b_refresh_walk_target=false;
}
PhysicsInputInstruction::Spawn(mode_id,stage_id)=>{
//spawn at a particular stage
if let Some(mode)=data.modes.get_mode(mode_id){
teleport_to_spawn(&mut state.body,&mut state.touching,&state.style,&data.hitbox_mesh,mode,&data.models,stage_id);
}
b_refresh_walk_target=false;
},
PhysicsInputInstruction::PracticeFly=>{
match &state.move_state{

View File

@ -12,7 +12,8 @@ pub enum InputInstruction{
MoveForward(bool),
Jump(bool),
Zoom(bool),
Reset,
Restart,
Spawn(strafesnet_common::gameplay_modes::ModeId,strafesnet_common::gameplay_modes::StageId),
PracticeFly,
}
pub enum Instruction{
@ -68,7 +69,8 @@ impl MouseInterpolator{
&InputInstruction::MoveDown(s)=>Some(PhysicsInputInstruction::SetMoveDown(s)),
&InputInstruction::Jump(s)=>Some(PhysicsInputInstruction::SetJump(s)),
&InputInstruction::Zoom(s)=>Some(PhysicsInputInstruction::SetZoom(s)),
InputInstruction::Reset=>Some(PhysicsInputInstruction::Reset),
&InputInstruction::Spawn(mode_id,stage_id)=>Some(PhysicsInputInstruction::Spawn(mode_id,stage_id)),
InputInstruction::Restart=>Some(PhysicsInputInstruction::Restart),
InputInstruction::PracticeFly=>Some(PhysicsInputInstruction::PracticeFly),
},
Instruction::GenerateModels(_)=>Some(PhysicsInputInstruction::Idle),
@ -150,6 +152,12 @@ pub fn new(mut physics:crate::physics::PhysicsContext,mut graphics_worker:crate:
},
Instruction::GenerateModels(map)=>{
physics.generate_models(&map);
//important!
//bots will not work properly without this exact restart + spawn setup
//reset the physics state to start a new run on the new map
physics.restart();
//generate a spawn event so bots work properly on the first run
//no run started so does not invalidate the run
physics.spawn();
graphics_worker.send(crate::graphics_worker::Instruction::GenerateModels(map)).unwrap();
},

View File

@ -107,7 +107,11 @@ impl WindowContext<'_>{
"e"=>Some(InputInstruction::MoveUp(s)),
"q"=>Some(InputInstruction::MoveDown(s)),
"z"=>Some(InputInstruction::Zoom(s)),
"r"=>if s{Some(InputInstruction::Reset)}else{None},
"r"=>if s{
//mouse needs to be reset since the position is absolute
self.mouse=crate::physics::MouseState::default();
Some(InputInstruction::Restart)
}else{None},
"f"=>if s{Some(InputInstruction::PracticeFly)}else{None},
_=>None,
},
@ -233,4 +237,4 @@ impl<'a> WindowContextSetup<'a>{
}
})
}
}
}