strafe-project/lib/common/src/gameplay_style.rs

612 lines
17 KiB
Rust
Raw Normal View History

2024-02-01 08:04:07 +00:00
const VALVE_SCALE:Planar64=Planar64::raw(1<<28);// 1/16
2024-08-27 20:33:50 +00:00
use crate::integer::{int,vec3::int as int3,Time,Ratio64,Planar64,Planar64Vec3};
2024-03-02 12:58:00 +00:00
use crate::controls_bitflag::Controls;
2024-01-30 06:38:43 +00:00
2024-03-02 12:58:00 +00:00
#[derive(Clone,Debug)]
2024-01-30 06:38:43 +00:00
pub struct StyleModifiers{
2024-03-02 12:58:00 +00:00
//controls which are allowed to pass into gameplay (usually all)
pub controls_mask:Controls,
//controls which are masked from control state (e.g. !jump in scroll style)
pub controls_mask_state:Controls,
//strafing
2024-02-01 08:04:07 +00:00
pub strafe:Option<StrafeSettings>,
2024-03-02 12:58:00 +00:00
//player gets a controllable rocket force
pub rocket:Option<PropulsionSettings>,
//flying
//pub move_type:MoveType::Fly(FlySettings)
2024-07-24 02:04:53 +00:00
//MoveType::Physics(PhysicsSettings) -> PhysicsSettings (strafe,rocket,jump,walk,ladder,swim,gravity)
2024-03-02 12:58:00 +00:00
//jumping is allowed
pub jump:Option<JumpSettings>,
//standing & walking is allowed
pub walk:Option<WalkSettings>,
//laddering is allowed
pub ladder:Option<LadderSettings>,
//water propulsion
pub swim:Option<PropulsionSettings>,
//maximum slope before sloped surfaces become frictionless
2024-02-01 08:04:07 +00:00
pub gravity:Planar64Vec3,
2024-03-02 12:58:00 +00:00
//hitbox
2024-02-01 08:04:07 +00:00
pub hitbox:Hitbox,
2024-03-02 12:58:00 +00:00
//camera location relative to the center (0,0,0) of the hitbox
2024-02-01 08:04:07 +00:00
pub camera_offset:Planar64Vec3,
2024-03-02 12:58:00 +00:00
//unused
pub mass:Planar64,
2024-01-30 06:38:43 +00:00
}
impl std::default::Default for StyleModifiers{
fn default()->Self{
Self::roblox_bhop()
}
}
2024-03-02 12:58:00 +00:00
#[derive(Clone,Debug)]
pub enum JumpCalculation{
2024-08-07 21:44:24 +00:00
Max,//Roblox: jumped_speed=max(velocity.boost(),velocity.jump())
BoostThenJump,//jumped_speed=velocity.boost().jump()
JumpThenBoost,//jumped_speed=velocity.jump().boost()
2024-03-02 12:58:00 +00:00
}
2024-01-30 06:38:43 +00:00
2024-03-02 12:58:00 +00:00
#[derive(Clone,Debug)]
pub enum JumpImpulse{
2024-08-07 21:44:24 +00:00
Time(Time),//jump time is invariant across mass and gravity changes
Height(Planar64),//jump height is invariant across mass and gravity changes
Linear(Planar64),//jump velocity is invariant across mass and gravity changes
Energy(Planar64),// :)
2024-03-02 12:58:00 +00:00
}
//Jumping acts on dot(walks_state.normal,body.velocity)
//Energy means it adds energy
//Linear means it linearly adds on
impl JumpImpulse{
2024-08-07 21:44:24 +00:00
pub fn jump(
&self,
velocity:Planar64Vec3,
jump_dir:Planar64Vec3,
gravity:&Planar64Vec3,
mass:Planar64,
)->Planar64Vec3{
match self{
2024-08-27 20:33:50 +00:00
&JumpImpulse::Time(time)=>velocity-(*gravity*time).map(|t|t.divide().fix_1()),
2024-08-07 21:44:24 +00:00
&JumpImpulse::Height(height)=>{
//height==-v.y*v.y/(2*g.y);
//use energy to determine max height
2024-08-27 20:33:50 +00:00
let gg=gravity.length_squared();
let g=gg.sqrt().fix_1();
let v_g=gravity.dot(velocity);
2024-08-07 21:44:24 +00:00
//do it backwards
2024-08-27 20:33:50 +00:00
let radicand=v_g*v_g+(g*height*2).fix_4();
velocity-(*gravity*(radicand.sqrt().fix_2()+v_g)/gg).divide().fix_1()
2024-08-07 21:44:24 +00:00
},
2024-08-27 20:33:50 +00:00
&JumpImpulse::Linear(jump_speed)=>velocity+(jump_dir*jump_speed/jump_dir.length()).divide().fix_1(),
2024-08-07 21:44:24 +00:00
&JumpImpulse::Energy(energy)=>{
//calculate energy
2024-08-27 20:33:50 +00:00
//let e=gravity.dot(velocity);
2024-08-07 21:44:24 +00:00
//add
//you get the idea
todo!()
},
}
}
//TODO: remove this and implement JumpCalculation properly
2024-03-02 12:58:00 +00:00
pub fn get_jump_deltav(&self,gravity:&Planar64Vec3,mass:Planar64)->Planar64{
//gravity.length() is actually the proper calculation because the jump is always opposite the gravity direction
match self{
2024-08-27 20:33:50 +00:00
&JumpImpulse::Time(time)=>(gravity.length().fix_1()*time/2).divide().fix_1(),
&JumpImpulse::Height(height)=>(gravity.length()*height*2).sqrt().fix_1(),
2024-08-07 21:44:24 +00:00
&JumpImpulse::Linear(deltav)=>deltav,
2024-08-27 20:33:50 +00:00
&JumpImpulse::Energy(energy)=>(energy.sqrt()*2/mass.sqrt()).divide().fix_1(),
2024-08-07 21:44:24 +00:00
}
}
}
#[derive(Clone,Debug)]
pub struct JumpSettings{
//information used to calculate jump power
pub impulse:JumpImpulse,
//information used to calculate jump behaviour
pub calculation:JumpCalculation,
//limit the minimum jump power when combined with downwards momentum
//This is true in both roblox and source
pub limit_minimum:bool,
}
impl JumpSettings{
pub fn jumped_velocity(
&self,
style:&StyleModifiers,
jump_dir:Planar64Vec3,
rel_velocity:Planar64Vec3,
booster:Option<&crate::gameplay_attributes::Booster>,
)->Planar64Vec3{
let jump_speed=self.impulse.get_jump_deltav(&style.gravity,style.mass);
match (self.limit_minimum,&self.calculation){
(true,JumpCalculation::Max)=>{
//the roblox calculation
let boost_vel=match booster{
Some(booster)=>booster.boost(rel_velocity),
None=>rel_velocity,
};
let j=boost_vel.dot(jump_dir);
2024-08-27 20:33:50 +00:00
let js=jump_speed.fix_2();
if j<js{
2024-08-07 21:44:24 +00:00
//weak booster: just do a regular jump
2024-08-27 20:33:50 +00:00
boost_vel+jump_dir.with_length(js-j).divide().fix_1()
2024-08-07 21:44:24 +00:00
}else{
//activate booster normally, jump does nothing
boost_vel
}
},
(true,_)=>{
//the source calculation (?)
let boost_vel=match booster{
Some(booster)=>booster.boost(rel_velocity),
None=>rel_velocity,
};
let j=boost_vel.dot(jump_dir);
2024-08-27 20:33:50 +00:00
let js=jump_speed.fix_2();
if j<js{
2024-08-07 21:44:24 +00:00
//speed in direction of jump cannot be lower than amount
2024-08-27 20:33:50 +00:00
boost_vel+jump_dir.with_length(js-j).divide().fix_1()
2024-08-07 21:44:24 +00:00
}else{
//boost and jump add together
2024-08-27 20:33:50 +00:00
boost_vel+jump_dir.with_length(js).divide().fix_1()
2024-08-07 21:44:24 +00:00
}
}
(false,JumpCalculation::Max)=>{
//??? calculation
//max(boost_vel,jump_vel)
let boost_vel=match booster{
Some(booster)=>booster.boost(rel_velocity),
None=>rel_velocity,
};
let boost_dot=boost_vel.dot(jump_dir);
2024-08-27 20:33:50 +00:00
let js=jump_speed.fix_2();
if boost_dot<js{
2024-08-07 21:44:24 +00:00
//weak boost is extended to jump speed
2024-08-27 20:33:50 +00:00
boost_vel+jump_dir.with_length(js-boost_dot).divide().fix_1()
2024-08-07 21:44:24 +00:00
}else{
//activate booster normally, jump does nothing
boost_vel
}
},
//the strafe client calculation
(false,_)=>{
let boost_vel=match booster{
Some(booster)=>booster.boost(rel_velocity),
None=>rel_velocity,
};
2024-08-27 20:33:50 +00:00
boost_vel+jump_dir.with_length(jump_speed).divide().fix_1()
2024-08-07 21:44:24 +00:00
},
2024-01-30 06:38:43 +00:00
}
}
2024-03-02 12:58:00 +00:00
}
2024-01-30 06:38:43 +00:00
2024-03-02 12:58:00 +00:00
#[derive(Clone,Debug)]
pub struct ControlsActivation{
//allowed keys
2024-08-07 21:43:34 +00:00
pub controls_mask:Controls,
2024-03-02 12:58:00 +00:00
//allow strafing only if any of the masked controls are held, eg W|S for shsw
2024-08-07 21:43:34 +00:00
pub controls_intersects:Controls,
2024-03-02 12:58:00 +00:00
//allow strafing only if all of the masked controls are held, eg W for hsw, w-only
2024-08-07 21:43:34 +00:00
pub controls_contains:Controls,
2024-03-02 12:58:00 +00:00
//Function(Box<dyn Fn(u32)->bool>),
}
impl ControlsActivation{
pub const fn mask(&self,controls:Controls)->Controls{
controls.intersection(self.controls_mask)
}
pub const fn activates(&self,controls:Controls)->bool{
(self.controls_intersects.is_empty()||controls.intersects(self.controls_intersects))
&&controls.contains(self.controls_contains)
}
pub const fn full_3d()->Self{
2024-01-30 06:38:43 +00:00
Self{
2024-03-02 12:58:00 +00:00
controls_mask:Controls::wasdqe(),
controls_intersects:Controls::wasdqe(),
controls_contains:Controls::empty(),
2024-01-30 06:38:43 +00:00
}
}
2024-03-02 12:58:00 +00:00
//classical styles
//Normal
pub const fn full_2d()->Self{
2024-01-30 06:38:43 +00:00
Self{
2024-03-02 12:58:00 +00:00
controls_mask:Controls::wasd(),
controls_intersects:Controls::wasd(),
controls_contains:Controls::empty(),
2024-01-30 06:38:43 +00:00
}
}
2024-03-02 12:58:00 +00:00
//Sideways
pub const fn sideways()->Self{
2024-01-30 06:38:43 +00:00
Self{
2024-03-02 12:58:00 +00:00
controls_mask:Controls::MoveForward.union(Controls::MoveBackward),
controls_intersects:Controls::MoveForward.union(Controls::MoveBackward),
controls_contains:Controls::empty(),
2024-01-30 06:38:43 +00:00
}
}
2024-03-02 12:58:00 +00:00
//Half-Sideways
pub const fn half_sideways()->Self{
2024-01-30 06:38:43 +00:00
Self{
2024-03-02 12:58:00 +00:00
controls_mask:Controls::MoveForward.union(Controls::MoveLeft).union(Controls::MoveRight),
controls_intersects:Controls::MoveLeft.union(Controls::MoveRight),
controls_contains:Controls::MoveForward,
2024-01-30 06:38:43 +00:00
}
}
2024-03-02 12:58:00 +00:00
//Surf Half-Sideways
pub const fn surf_half_sideways()->Self{
Self{
controls_mask:Controls::MoveForward.union(Controls::MoveBackward).union(Controls::MoveLeft).union(Controls::MoveRight),
controls_intersects:Controls::MoveForward.union(Controls::MoveBackward),
controls_contains:Controls::empty(),
}
}
//W-Only
pub const fn w_only()->Self{
Self{
controls_mask:Controls::MoveForward,
controls_intersects:Controls::empty(),
controls_contains:Controls::MoveForward,
}
}
//A-Only
pub const fn a_only()->Self{
Self{
controls_mask:Controls::MoveLeft,
controls_intersects:Controls::empty(),
controls_contains:Controls::MoveLeft,
}
}
//Backwards
2024-01-30 06:38:43 +00:00
}
2024-03-02 12:58:00 +00:00
#[derive(Clone,Debug)]
2024-02-01 08:04:07 +00:00
pub struct StrafeSettings{
2024-08-07 21:43:34 +00:00
pub enable:ControlsActivation,
pub mv:Planar64,
pub air_accel_limit:Option<Planar64>,
pub tick_rate:Ratio64,
2024-01-30 06:38:43 +00:00
}
2024-02-01 08:04:07 +00:00
impl StrafeSettings{
2024-03-02 12:58:00 +00:00
pub fn tick_velocity(&self,velocity:Planar64Vec3,control_dir:Planar64Vec3)->Option<Planar64Vec3>{
let d=velocity.dot(control_dir);
2024-08-27 20:33:50 +00:00
let mv=self.mv.fix_2();
match d<mv{
true=>Some(velocity+(control_dir*self.air_accel_limit.map_or(mv-d,|limit|limit.fix_2().min(mv-d))).fix_1()),
2024-03-02 12:58:00 +00:00
false=>None,
}
}
2024-02-01 08:04:07 +00:00
pub fn next_tick(&self,time:Time)->Time{
Time::from_nanos(self.tick_rate.rhs_div_int(self.tick_rate.mul_int(time.nanos())+1))
}
2024-03-02 12:58:00 +00:00
pub const fn activates(&self,controls:Controls)->bool{
self.enable.activates(controls)
}
pub const fn mask(&self,controls:Controls)->Controls{
self.enable.mask(controls)
}
}
#[derive(Clone,Debug)]
pub struct PropulsionSettings{
2024-08-07 21:43:34 +00:00
pub magnitude:Planar64,
2024-03-02 12:58:00 +00:00
}
impl PropulsionSettings{
pub fn acceleration(&self,control_dir:Planar64Vec3)->Planar64Vec3{
2024-08-27 20:33:50 +00:00
(control_dir*self.magnitude).fix_1()
2024-03-02 12:58:00 +00:00
}
}
#[derive(Clone,Debug)]
pub struct AccelerateSettings{
2024-08-07 21:43:34 +00:00
pub accel:Planar64,
pub topspeed:Planar64,
2024-07-24 02:04:53 +00:00
}
2024-03-02 12:58:00 +00:00
#[derive(Clone,Debug)]
pub struct WalkSettings{
2024-08-07 21:43:34 +00:00
pub accelerate:AccelerateSettings,
pub static_friction:Planar64,
pub kinetic_friction:Planar64,
2024-03-02 12:58:00 +00:00
//if a surf slope angle does not exist, then everything is slippery and walking is impossible
2024-08-07 21:43:34 +00:00
pub surf_dot:Planar64,//surf_dot<n.dot(up)/n.length()
2024-03-02 12:58:00 +00:00
}
impl WalkSettings{
pub fn accel(&self,target_diff:Planar64Vec3,gravity:Planar64Vec3)->Planar64{
//TODO: fallible walk accel
2024-08-27 20:33:50 +00:00
let diff_len=target_diff.length().fix_1();
2024-03-02 12:58:00 +00:00
let friction=if diff_len<self.accelerate.topspeed{
self.static_friction
}else{
self.kinetic_friction
};
2024-08-27 20:33:50 +00:00
self.accelerate.accel.min((-gravity.y*friction).fix_1())
2024-03-02 12:58:00 +00:00
}
pub fn get_walk_target_velocity(&self,control_dir:Planar64Vec3,normal:Planar64Vec3)->Planar64Vec3{
2024-08-27 20:33:50 +00:00
if control_dir==crate::integer::vec3::ZERO{
2024-03-02 12:58:00 +00:00
return control_dir;
}
2024-08-27 20:33:50 +00:00
let nn=normal.length_squared();
let mm=control_dir.length_squared();
let nnmm=nn*mm;
let d=normal.dot(control_dir);
let dd=d*d;
if dd<nnmm{
2024-03-02 12:58:00 +00:00
let cr=normal.cross(control_dir);
2024-08-27 20:33:50 +00:00
if cr==crate::integer::vec3::ZERO_2{
crate::integer::vec3::ZERO
2024-03-02 12:58:00 +00:00
}else{
2024-08-27 20:33:50 +00:00
(cr.cross(normal)*self.accelerate.topspeed/((nn*(nnmm-dd)).sqrt())).divide().fix_1()
2024-03-02 12:58:00 +00:00
}
}else{
2024-08-27 20:33:50 +00:00
crate::integer::vec3::ZERO
2024-03-02 12:58:00 +00:00
}
}
pub fn is_slope_walkable(&self,normal:Planar64Vec3,up:Planar64Vec3)->bool{
//normal is not guaranteed to be unit length
let ny=normal.dot(up);
2024-08-27 20:33:50 +00:00
let h=normal.length().fix_1();
2024-03-02 12:58:00 +00:00
//remember this is a normal vector
2024-08-27 20:33:50 +00:00
ny.is_positive()&&h*self.surf_dot<ny
2024-03-02 12:58:00 +00:00
}
}
#[derive(Clone,Debug)]
pub struct LadderSettings{
2024-08-07 21:43:34 +00:00
pub accelerate:AccelerateSettings,
2024-03-02 12:58:00 +00:00
//how close to pushing directly into/out of the ladder normal
//does your input need to be to redirect straight up/down the ladder
2024-08-07 21:43:34 +00:00
pub dot:Planar64,
2024-03-02 12:58:00 +00:00
}
impl LadderSettings{
2024-07-25 19:13:32 +00:00
pub const fn accel(&self,target_diff:Planar64Vec3,gravity:Planar64Vec3)->Planar64{
2024-03-02 12:58:00 +00:00
//TODO: fallible ladder accel
self.accelerate.accel
}
pub fn get_ladder_target_velocity(&self,mut control_dir:Planar64Vec3,normal:Planar64Vec3)->Planar64Vec3{
2024-08-27 20:33:50 +00:00
if control_dir==crate::integer::vec3::ZERO{
2024-03-02 12:58:00 +00:00
return control_dir;
}
2024-08-27 20:33:50 +00:00
let nn=normal.length_squared();
let mm=control_dir.length_squared();
let nnmm=nn*mm;
let d=normal.dot(control_dir);
let mut dd=d*d;
if (self.dot*self.dot*nnmm).fix_4()<dd{
if d.is_negative(){
control_dir=Planar64Vec3::new([Planar64::ZERO,mm.fix_1(),Planar64::ZERO]);
}else{
control_dir=Planar64Vec3::new([Planar64::ZERO,-mm.fix_1(),Planar64::ZERO]);
}
dd=(normal.y*normal.y).fix_4();
2024-03-02 12:58:00 +00:00
}
//n=d if you are standing on top of a ladder and press E.
//two fixes:
//- ladder movement is not allowed on walkable surfaces
//- fix the underlying issue
2024-08-27 20:33:50 +00:00
if dd<nnmm{
2024-03-02 12:58:00 +00:00
let cr=normal.cross(control_dir);
2024-08-27 20:33:50 +00:00
if cr==crate::integer::vec3::ZERO_2{
crate::integer::vec3::ZERO
2024-03-02 12:58:00 +00:00
}else{
2024-08-27 20:33:50 +00:00
(cr.cross(normal)*self.accelerate.topspeed/((nn*(nnmm-dd)).sqrt())).divide().fix_1()
2024-03-02 12:58:00 +00:00
}
}else{
2024-08-27 20:33:50 +00:00
crate::integer::vec3::ZERO
2024-02-01 08:04:07 +00:00
}
}
}
2024-01-30 06:38:43 +00:00
2024-03-02 12:58:00 +00:00
#[derive(Clone,Debug)]
2024-02-01 08:04:07 +00:00
pub enum HitboxMesh{
2024-01-31 03:30:11 +00:00
Box,//source
Cylinder,//roblox
//Sphere,//roblox old physics
//Point,
//Line,
//DualCone,
}
2024-03-02 12:58:00 +00:00
#[derive(Clone,Debug)]
2024-02-01 08:04:07 +00:00
pub struct Hitbox{
pub halfsize:Planar64Vec3,
pub mesh:HitboxMesh,
2024-01-30 06:38:43 +00:00
}
impl Hitbox{
2024-03-02 12:58:00 +00:00
pub fn roblox()->Self{
2024-01-30 06:38:43 +00:00
Self{
2024-08-27 20:33:50 +00:00
halfsize:int3(2,5,2)>>1,
2024-01-31 03:30:11 +00:00
mesh:HitboxMesh::Cylinder,
2024-01-30 06:38:43 +00:00
}
}
2024-03-02 12:58:00 +00:00
pub fn source()->Self{
2024-01-30 06:38:43 +00:00
Self{
2024-08-27 20:33:50 +00:00
halfsize:((int3(33,73,33)>>1)*VALVE_SCALE).fix_1(),
2024-01-31 03:30:11 +00:00
mesh:HitboxMesh::Box,
2024-01-30 06:38:43 +00:00
}
}
}
2024-03-02 12:58:00 +00:00
impl StyleModifiers{
2024-08-27 20:33:50 +00:00
pub const RIGHT_DIR:Planar64Vec3=crate::integer::vec3::X;
pub const UP_DIR:Planar64Vec3=crate::integer::vec3::Y;
pub const FORWARD_DIR:Planar64Vec3=crate::integer::vec3::NEG_Z;
2024-03-02 12:58:00 +00:00
pub fn neo()->Self{
Self{
controls_mask:Controls::all(),
controls_mask_state:Controls::all(),
strafe:Some(StrafeSettings{
enable:ControlsActivation::full_2d(),
air_accel_limit:None,
2024-08-27 20:33:50 +00:00
mv:int(3),
2024-03-02 12:58:00 +00:00
tick_rate:Ratio64::new(64,Time::ONE_SECOND.nanos() as u64).unwrap(),
}),
jump:Some(JumpSettings{
2024-08-27 20:33:50 +00:00
impulse:JumpImpulse::Energy(int(512)),
2024-08-07 21:44:24 +00:00
calculation:JumpCalculation::JumpThenBoost,
limit_minimum:false,
2024-03-02 12:58:00 +00:00
}),
2024-08-27 20:33:50 +00:00
gravity:int3(0,-80,0),
mass:int(1),
2024-03-02 12:58:00 +00:00
rocket:None,
walk:Some(WalkSettings{
accelerate:AccelerateSettings{
2024-08-27 20:33:50 +00:00
topspeed:int(16),
accel:int(80),
2024-03-02 12:58:00 +00:00
},
2024-08-27 20:33:50 +00:00
static_friction:int(2),
kinetic_friction:int(3),//unrealistic: kinetic friction is typically lower than static
surf_dot:int(3)/4,
2024-03-02 12:58:00 +00:00
}),
ladder:Some(LadderSettings{
accelerate:AccelerateSettings{
2024-08-27 20:33:50 +00:00
topspeed:int(16),
accel:int(160),
2024-03-02 12:58:00 +00:00
},
2024-08-27 20:33:50 +00:00
dot:(int(1)/2).sqrt(),
2024-03-02 12:58:00 +00:00
}),
swim:Some(PropulsionSettings{
2024-08-27 20:33:50 +00:00
magnitude:int(12),
2024-03-02 12:58:00 +00:00
}),
hitbox:Hitbox::roblox(),
2024-08-27 20:33:50 +00:00
camera_offset:int3(0,2,0),//4.5-2.5=2
2024-03-02 12:58:00 +00:00
}
}
pub fn roblox_bhop()->Self{
Self{
controls_mask:Controls::all(),
controls_mask_state:Controls::all(),
strafe:Some(StrafeSettings{
enable:ControlsActivation::full_2d(),
air_accel_limit:None,
2024-08-27 20:33:50 +00:00
mv:int(27)/10,
2024-03-02 12:58:00 +00:00
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
}),
jump:Some(JumpSettings{
2024-08-07 21:44:24 +00:00
impulse:JumpImpulse::Time(Time::from_micros(715_588)),
calculation:JumpCalculation::Max,
limit_minimum:true,
2024-03-02 12:58:00 +00:00
}),
2024-08-27 20:33:50 +00:00
gravity:int3(0,-100,0),
mass:int(1),
2024-03-02 12:58:00 +00:00
rocket:None,
walk:Some(WalkSettings{
accelerate:AccelerateSettings{
2024-08-27 20:33:50 +00:00
topspeed:int(18),
accel:int(90),
2024-03-02 12:58:00 +00:00
},
2024-08-27 20:33:50 +00:00
static_friction:int(2),
kinetic_friction:int(3),//unrealistic: kinetic friction is typically lower than static
surf_dot:int(3)/4,// normal.y=0.75
2024-03-02 12:58:00 +00:00
}),
ladder:Some(LadderSettings{
accelerate:AccelerateSettings{
2024-08-27 20:33:50 +00:00
topspeed:int(18),
accel:int(180),
2024-03-02 12:58:00 +00:00
},
2024-08-27 20:33:50 +00:00
dot:(int(1)/2).sqrt(),
2024-03-02 12:58:00 +00:00
}),
swim:Some(PropulsionSettings{
2024-08-27 20:33:50 +00:00
magnitude:int(12),
2024-03-02 12:58:00 +00:00
}),
hitbox:Hitbox::roblox(),
2024-08-27 20:33:50 +00:00
camera_offset:int3(0,2,0),//4.5-2.5=2
2024-03-02 12:58:00 +00:00
}
}
pub fn roblox_surf()->Self{
Self{
2024-08-27 20:33:50 +00:00
gravity:int3(0,-50,0),
2024-03-02 12:58:00 +00:00
..Self::roblox_bhop()
}
}
pub fn roblox_rocket()->Self{
Self{
strafe:None,
rocket:Some(PropulsionSettings{
2024-08-27 20:33:50 +00:00
magnitude:int(200),
2024-03-02 12:58:00 +00:00
}),
..Self::roblox_bhop()
}
}
pub fn source_bhop()->Self{
Self{
controls_mask:Controls::all()-Controls::MoveUp-Controls::MoveDown,
controls_mask_state:Controls::all(),
strafe:Some(StrafeSettings{
enable:ControlsActivation::full_2d(),
air_accel_limit:Some(Planar64::raw(150<<28)*100),
2024-08-27 20:33:50 +00:00
mv:(Planar64::raw(30)*VALVE_SCALE).fix_1(),
2024-03-02 12:58:00 +00:00
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
}),
jump:Some(JumpSettings{
2024-08-27 20:33:50 +00:00
impulse:JumpImpulse::Height((int(52)*VALVE_SCALE).fix_1()),
2024-08-07 21:44:24 +00:00
calculation:JumpCalculation::JumpThenBoost,
limit_minimum:true,
2024-03-02 12:58:00 +00:00
}),
2024-08-27 20:33:50 +00:00
gravity:(int3(0,-800,0)*VALVE_SCALE).fix_1(),
mass:int(1),
2024-03-02 12:58:00 +00:00
rocket:None,
walk:Some(WalkSettings{
accelerate:AccelerateSettings{
2024-08-27 20:33:50 +00:00
topspeed:int(18),//?
accel:int(90),//?
2024-03-02 12:58:00 +00:00
},
2024-08-27 20:33:50 +00:00
static_friction:int(2),//?
kinetic_friction:int(3),//?
surf_dot:int(3)/4,// normal.y=0.75
2024-03-02 12:58:00 +00:00
}),
ladder:Some(LadderSettings{
accelerate:AccelerateSettings{
2024-08-27 20:33:50 +00:00
topspeed:int(18),//?
accel:int(180),//?
2024-03-02 12:58:00 +00:00
},
2024-08-27 20:33:50 +00:00
dot:(int(1)/2).sqrt(),//?
2024-03-02 12:58:00 +00:00
}),
swim:Some(PropulsionSettings{
2024-08-27 20:33:50 +00:00
magnitude:int(12),//?
2024-03-02 12:58:00 +00:00
}),
hitbox:Hitbox::source(),
2024-08-27 20:33:50 +00:00
camera_offset:((int3(0,64,0)-(int3(0,73,0)>>1))*VALVE_SCALE).fix_1(),
2024-03-02 12:58:00 +00:00
}
}
pub fn source_surf()->Self{
Self{
controls_mask:Controls::all()-Controls::MoveUp-Controls::MoveDown,
controls_mask_state:Controls::all(),
strafe:Some(StrafeSettings{
enable:ControlsActivation::full_2d(),
2024-08-27 20:33:50 +00:00
air_accel_limit:Some((int(150)*66*VALVE_SCALE).fix_1()),
mv:(int(30)*VALVE_SCALE).fix_1(),
2024-03-02 12:58:00 +00:00
tick_rate:Ratio64::new(66,Time::ONE_SECOND.nanos() as u64).unwrap(),
}),
jump:Some(JumpSettings{
2024-08-27 20:33:50 +00:00
impulse:JumpImpulse::Height((int(52)*VALVE_SCALE).fix_1()),
2024-08-07 21:44:24 +00:00
calculation:JumpCalculation::JumpThenBoost,
limit_minimum:true,
2024-03-02 12:58:00 +00:00
}),
2024-08-27 20:33:50 +00:00
gravity:(int3(0,-800,0)*VALVE_SCALE).fix_1(),
mass:int(1),
2024-03-02 12:58:00 +00:00
rocket:None,
walk:Some(WalkSettings{
accelerate:AccelerateSettings{
2024-08-27 20:33:50 +00:00
topspeed:int(18),//?
accel:int(90),//?
2024-03-02 12:58:00 +00:00
},
2024-08-27 20:33:50 +00:00
static_friction:int(2),//?
kinetic_friction:int(3),//?
surf_dot:int(3)/4,// normal.y=0.75
2024-03-02 12:58:00 +00:00
}),
ladder:Some(LadderSettings{
accelerate:AccelerateSettings{
2024-08-27 20:33:50 +00:00
topspeed:int(18),//?
accel:int(180),//?
2024-03-02 12:58:00 +00:00
},
2024-08-27 20:33:50 +00:00
dot:(int(1)/2).sqrt(),//?
2024-03-02 12:58:00 +00:00
}),
swim:Some(PropulsionSettings{
2024-08-27 20:33:50 +00:00
magnitude:int(12),//?
2024-03-02 12:58:00 +00:00
}),
hitbox:Hitbox::source(),
2024-08-27 20:33:50 +00:00
camera_offset:((int3(0,64,0)-(int3(0,73,0)>>1))*VALVE_SCALE).fix_1(),
2024-03-02 12:58:00 +00:00
}
}
}