factor out immutable checkpoint_check logic
This commit is contained in:
parent
4f21985290
commit
1dc2556d85
@ -1441,7 +1441,7 @@ enum TeleportToSpawnError{
|
||||
NoModel,
|
||||
}
|
||||
fn teleport_to_spawn(
|
||||
stage:&gameplay_modes::Stage,
|
||||
spawn_model_id:ModelId,
|
||||
move_state:&mut MoveState,
|
||||
body:&mut Body,
|
||||
touching:&mut TouchingState,
|
||||
@ -1457,13 +1457,71 @@ fn teleport_to_spawn(
|
||||
time:Time,
|
||||
)->Result<(),TeleportToSpawnError>{
|
||||
const EPSILON:Planar64=Planar64::raw((1<<32)/16);
|
||||
let transform=models.get_model_transform(stage.spawn()).ok_or(TeleportToSpawnError::NoModel)?;
|
||||
let transform=models.get_model_transform(spawn_model_id).ok_or(TeleportToSpawnError::NoModel)?;
|
||||
//TODO: transform.vertex.matrix3.col(1)+transform.vertex.translation
|
||||
let point=transform.vertex.transform_point3(vec3::Y).fix_1()+Planar64Vec3::new([Planar64::ZERO,style.hitbox.halfsize.y+EPSILON,Planar64::ZERO]);
|
||||
teleport(point,move_state,body,touching,run,mode_state,Some(mode),models,hitbox_mesh,bvh,style,camera,input_state,time);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct CheckpointCheckOutcome{
|
||||
set_stage:Option<StageId>,
|
||||
teleport_to_model:Option<ModelId>,
|
||||
}
|
||||
|
||||
fn checkpoint_check(
|
||||
mode_state:&ModeState,
|
||||
stage_element:&gameplay_modes::StageElement,
|
||||
mode:&gameplay_modes::Mode,
|
||||
)->CheckpointCheckOutcome{
|
||||
if mode_state.get_stage_id()<stage_element.stage_id(){
|
||||
//checkpoint check
|
||||
//check if current stage is complete
|
||||
if let Some(current_stage)=mode.get_stage(mode_state.get_stage_id()){
|
||||
if !current_stage.is_complete(mode_state.ordered_checkpoint_count(),mode_state.unordered_checkpoint_count()){
|
||||
//do the stage checkpoints have to be reset?
|
||||
return CheckpointCheckOutcome{
|
||||
set_stage:None,
|
||||
teleport_to_model:Some(current_stage.spawn()),
|
||||
};
|
||||
}
|
||||
}
|
||||
//check if all between stages have no checkpoints required to pass them
|
||||
for stage_id in mode_state.get_stage_id().get()+1..stage_element.stage_id().get(){
|
||||
let stage_id=StageId::new(stage_id);
|
||||
//check if none of the between stages has checkpoints, if they do teleport back to that stage
|
||||
match mode.get_stage(stage_id){
|
||||
Some(stage)=>if !stage.is_empty(){
|
||||
return CheckpointCheckOutcome{
|
||||
set_stage:Some(stage_id),
|
||||
teleport_to_model:Some(stage.spawn()),
|
||||
};
|
||||
},
|
||||
//no such stage! set to last existing stage
|
||||
None=>return CheckpointCheckOutcome{
|
||||
set_stage:Some(StageId::new(stage_id.get()-1)),
|
||||
teleport_to_model:None,
|
||||
},
|
||||
}
|
||||
};
|
||||
//notably you do not get teleported for touching ordered checkpoints in the wrong order within the same stage.
|
||||
return CheckpointCheckOutcome{
|
||||
set_stage:Some(stage_element.stage_id()),
|
||||
teleport_to_model:None,
|
||||
};
|
||||
}else if stage_element.force(){
|
||||
//forced stage_element will set the stage_id even if the stage has already been passed
|
||||
return CheckpointCheckOutcome{
|
||||
set_stage:Some(stage_element.stage_id()),
|
||||
teleport_to_model:None,
|
||||
};
|
||||
}
|
||||
CheckpointCheckOutcome{
|
||||
set_stage:None,
|
||||
teleport_to_model:None,
|
||||
}
|
||||
}
|
||||
|
||||
fn run_teleport_behaviour(
|
||||
model_id:ModelId,
|
||||
wormhole:Option<&gameplay_attributes::Wormhole>,
|
||||
@ -1485,66 +1543,37 @@ fn run_teleport_behaviour(
|
||||
//Map makers are expected to use tools to prevent
|
||||
//multi-boosting on JumpLimit boosters such as spawning into a SetVelocity
|
||||
if let Some(mode)=mode{
|
||||
if let Some(stage_element)=mode.get_element(model_id){
|
||||
if let Some(stage)=mode.get_stage(stage_element.stage_id()){
|
||||
if mode_state.get_stage_id()<stage_element.stage_id(){
|
||||
//checkpoint check
|
||||
//check if current stage is complete
|
||||
if let Some(current_stage)=mode.get_stage(mode_state.get_stage_id()){
|
||||
if !current_stage.is_complete(mode_state.ordered_checkpoint_count(),mode_state.unordered_checkpoint_count()){
|
||||
//do the stage checkpoints have to be reset?
|
||||
let _=teleport_to_spawn(current_stage,move_state,body,touching,run,mode_state,mode,models,hitbox_mesh,bvh,style,camera,input_state,time);
|
||||
return;
|
||||
}
|
||||
if let Some(stage_element)=mode.get_element(model_id){
|
||||
if let Some(stage)=mode.get_stage(stage_element.stage_id()){
|
||||
let CheckpointCheckOutcome{set_stage,teleport_to_model}=checkpoint_check(mode_state,stage_element,mode);
|
||||
if let Some(stage_id)=set_stage{
|
||||
mode_state.set_stage_id(stage_id);
|
||||
}
|
||||
//check if all between stages have no checkpoints required to pass them
|
||||
let mut loop_unbroken=true;
|
||||
for stage_id in mode_state.get_stage_id().get()+1..stage_element.stage_id().get(){
|
||||
let stage_id=StageId::new(stage_id);
|
||||
//check if none of the between stages has checkpoints, if they do teleport back to that stage
|
||||
match mode.get_stage(stage_id){
|
||||
Some(stage)=>if !stage.is_empty(){
|
||||
mode_state.set_stage_id(stage_id);
|
||||
let _=teleport_to_spawn(stage,move_state,body,touching,run,mode_state,mode,models,hitbox_mesh,bvh,style,camera,input_state,time);
|
||||
return;
|
||||
},
|
||||
None=>{
|
||||
//no such stage! set to last existing stage and break loop
|
||||
mode_state.set_stage_id(StageId::new(stage_id.get()-1));
|
||||
loop_unbroken=false;
|
||||
break;
|
||||
},
|
||||
}
|
||||
};
|
||||
//notably you do not get teleported for touching ordered checkpoints in the wrong order within the same stage.
|
||||
if loop_unbroken{
|
||||
mode_state.set_stage_id(stage_element.stage_id());
|
||||
}
|
||||
}else if stage_element.force(){
|
||||
//forced stage_element will set the stage_id even if the stage has already been passed
|
||||
mode_state.set_stage_id(stage_element.stage_id());
|
||||
}
|
||||
match stage_element.behaviour(){
|
||||
gameplay_modes::StageElementBehaviour::SpawnAt=>(),
|
||||
gameplay_modes::StageElementBehaviour::Trigger
|
||||
|gameplay_modes::StageElementBehaviour::Teleport=>if let Some(mode_state_stage)=mode.get_stage(mode_state.get_stage_id()){
|
||||
//I guess this is correct behaviour when trying to teleport to a non-existent spawn but it's still weird
|
||||
let _=teleport_to_spawn(mode_state_stage,move_state,body,touching,run,mode_state,mode,models,hitbox_mesh,bvh,style,camera,input_state,time);
|
||||
if let Some(model_id)=teleport_to_model{
|
||||
let _=teleport_to_spawn(model_id,move_state,body,touching,run,mode_state,mode,models,hitbox_mesh,bvh,style,camera,input_state,time);
|
||||
return;
|
||||
},
|
||||
gameplay_modes::StageElementBehaviour::Platform=>(),
|
||||
gameplay_modes::StageElementBehaviour::Check=>(),//this is to run the checkpoint check behaviour without any other side effects
|
||||
gameplay_modes::StageElementBehaviour::Checkpoint=>{
|
||||
//each of these checks if the model is actually a valid respective checkpoint object
|
||||
//accumulate sequential ordered checkpoints
|
||||
mode_state.accumulate_ordered_checkpoint(&stage,model_id);
|
||||
//insert model id in accumulated unordered checkpoints
|
||||
mode_state.accumulate_unordered_checkpoint(&stage,model_id);
|
||||
},
|
||||
}
|
||||
match stage_element.behaviour(){
|
||||
gameplay_modes::StageElementBehaviour::SpawnAt=>(),
|
||||
gameplay_modes::StageElementBehaviour::Trigger
|
||||
|gameplay_modes::StageElementBehaviour::Teleport=>if let Some(mode_state_stage)=mode.get_stage(mode_state.get_stage_id()){
|
||||
//I guess this is correct behaviour when trying to teleport to a non-existent spawn but it's still weird
|
||||
let _=teleport_to_spawn(mode_state_stage.spawn(),move_state,body,touching,run,mode_state,mode,models,hitbox_mesh,bvh,style,camera,input_state,time);
|
||||
return;
|
||||
},
|
||||
gameplay_modes::StageElementBehaviour::Platform=>(),
|
||||
gameplay_modes::StageElementBehaviour::Check=>(),//this is to run the checkpoint check behaviour without any other side effects
|
||||
gameplay_modes::StageElementBehaviour::Checkpoint=>{
|
||||
//each of these checks if the model is actually a valid respective checkpoint object
|
||||
//accumulate sequential ordered checkpoints
|
||||
mode_state.accumulate_ordered_checkpoint(&stage,model_id);
|
||||
//insert model id in accumulated unordered checkpoints
|
||||
mode_state.accumulate_unordered_checkpoint(&stage,model_id);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(&gameplay_attributes::Wormhole{destination_model})=wormhole{
|
||||
if let (Some(origin),Some(destination))=(models.get_model_transform(model_id),models.get_model_transform(destination_model)){
|
||||
let point=body.position-origin.vertex.translation+destination.vertex.translation;
|
||||
@ -1914,7 +1943,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
|
||||
if let Some(mode)=data.modes.get_mode(mode_id){
|
||||
if let Some(stage)=mode.get_stage(stage_id){
|
||||
let _=teleport_to_spawn(
|
||||
stage,
|
||||
stage.spawn(),
|
||||
&mut state.move_state,&mut state.body,&mut state.touching,&mut state.run,&mut state.mode_state,
|
||||
mode,
|
||||
&data.models,&data.hitbox_mesh,&data.bvh,&state.style,&state.camera,&state.input_state,state.time
|
||||
|
Loading…
Reference in New Issue
Block a user