Физган: колесо мыши крутит взятый проп
Some checks are pending
CI / checks (push) Waiting to run

Взятое тело хранит не только расстояние, но и углы: при захвате углы берутся у
тела, колесо мыши добавляет к рысканью по 15° на щелчок, удержание каждый кадр
телепортирует тело на луч взгляда с этими углами. Как в GMod: взял проп — крути
колесом, не отпуская.
This commit is contained in:
Niko Marmeladkov 2026-10-16 23:55:14 +03:00
parent 761238e58d
commit 82d9b3a32b

View file

@ -390,7 +390,8 @@ pub fn map(assets: Option<PathBuf>, args: MapArgs) -> anyhow::Result<()> {
}
// Физган: тело, которое держим, и расстояние удержания (A21/A23).
let mut grabbed: Option<(engine::physics::BodyId, f32)> = None;
// Тело, расстояние удержания и углы: колесо мыши крутит взятый проп.
let mut grabbed: Option<(engine::physics::BodyId, f32, math::Vec3)> = None;
// `SOURCE_RS_PHYSGUN=1` — держать ближайшее тело без мыши: нужно, чтобы
// проверять физган кадром и скриптом, а не руками.
let auto_grab = std::env::var_os("SOURCE_RS_PHYSGUN").is_some();
@ -431,7 +432,7 @@ pub fn map(assets: Option<PathBuf>, args: MapArgs) -> anyhow::Result<()> {
}
}
if let Some((along, id)) = best {
grabbed = Some((id, along));
grabbed = Some((id, along, math::Vec3::ZERO));
log.push_back(format!("физган: взял ({} юнитов)", along as i32));
while log.len() > 8 {
log.pop_front();
@ -526,6 +527,13 @@ pub fn map(assets: Option<PathBuf>, args: MapArgs) -> anyhow::Result<()> {
} => {
pressed.remove(&code);
}
Event::MouseWheel { y, .. } => {
// Колесо крутит взятый проп вокруг вертикальной оси.
if let Some((id, along, angles)) = grabbed {
let angles = math::Vec3::new(angles.x, angles.y + y * 15.0, angles.z);
grabbed = Some((id, along, angles));
}
}
Event::MouseMotion { xrel, yrel, .. } if relative_mouse => {
// Source: +Y — влево, поэтому движение мыши вправо уменьшает yaw.
camera.rotate(-xrel * 0.15, yrel * 0.15);
@ -573,17 +581,19 @@ pub fn map(assets: Option<PathBuf>, args: MapArgs) -> anyhow::Result<()> {
}
}
if let Some((along, id)) = best {
grabbed = Some((id, along));
grabbed = Some((id, along, math::Vec3::ZERO));
}
}
if let Some((id, along)) = grabbed {
if let Some((id, along, mut angles)) = grabbed {
// Углы при захвате берём у тела, дальше их крутит колесо.
if angles == math::Vec3::ZERO
&& let Some((_, current)) = w.physics.transform(id)
{
angles = current;
}
let target = player.eye_position() + camera.forward() * along;
let angles = w
.physics
.transform(id)
.map(|(_, angles)| angles)
.unwrap_or(math::Vec3::ZERO);
w.physics.teleport(id, target, angles);
grabbed = Some((id, along, angles));
}
// Модель игрока едет за игроком: позиция — ступни, поворот — курс.
if let Some(index) = player_model_instance {