Нуклип: Ctrl замедляет (как в GMod), а не опускает
Some checks are pending
CI / checks (push) Waiting to run
Some checks are pending
CI / checks (push) Waiting to run
Пользователь: в оригинале Ctrl в ноуклипе замедляет движение. Убрано `move_up -= 1` по Ctrl; скорость: Shift ×3, Ctrl ×0.35, иначе обычная. Плюс тесты-сканы карты: поверхности с «зеркальными» материалами (0 в зале) и сущности рядом с залом — подтверждают, что func_reflective_glass один (model *6, точка -2064 -2076 -286).
This commit is contained in:
parent
300a6c6d98
commit
209412ea3d
2 changed files with 94 additions and 3 deletions
|
|
@ -879,9 +879,6 @@ pub fn map(assets: Option<PathBuf>, args: MapArgs) -> anyhow::Result<()> {
|
|||
if pressed.contains(&Keycode::A) {
|
||||
move_right -= 1.0;
|
||||
}
|
||||
if pressed.contains(&Keycode::LCtrl) {
|
||||
move_up -= 1.0;
|
||||
}
|
||||
// Сенсорный стик складывается с клавиатурой: на Android клавиш нет,
|
||||
// а на десктопе `--touch` удобно проверять рядом с WASD.
|
||||
let (touch_forward, touch_right) = touch.movement();
|
||||
|
|
@ -892,8 +889,11 @@ pub fn map(assets: Option<PathBuf>, args: MapArgs) -> anyhow::Result<()> {
|
|||
}
|
||||
let touch_jump = touch.take_jump();
|
||||
if player.noclip {
|
||||
// Как в GMod: Shift ускоряет, Ctrl замедляет (а не опускает).
|
||||
let speed = if pressed.contains(&Keycode::LShift) {
|
||||
args.speed * 3.0
|
||||
} else if pressed.contains(&Keycode::LCtrl) {
|
||||
args.speed * 0.35
|
||||
} else {
|
||||
args.speed
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1472,3 +1472,94 @@ fn real_map_visual_entities() {
|
|||
}
|
||||
assert!(!classes.is_empty(), "сущностей нет");
|
||||
}
|
||||
|
||||
/// Где на карте поверхности с «зеркальными» материалами.
|
||||
#[test]
|
||||
fn real_map_mirror_materials() {
|
||||
let Some(root) = assets_root() else {
|
||||
eprintln!("пропуск: ассеты не найдены");
|
||||
return;
|
||||
};
|
||||
let map = root.join("garrysmod/maps/gm_construct.bsp");
|
||||
if !map.is_file() {
|
||||
eprintln!("пропуск: нет {}", map.display());
|
||||
return;
|
||||
}
|
||||
let bsp = formats::bsp::Bsp::from_path(&map).expect("разбор карты");
|
||||
let geometry = bsp.geometry().expect("геометрия");
|
||||
let texdata = bsp.texdata().expect("texdata");
|
||||
let names = bsp.texture_names().expect("имена текстур");
|
||||
let mut found = 0usize;
|
||||
for (index, face) in geometry.faces.iter().enumerate() {
|
||||
if face.num_edges < 3 {
|
||||
continue;
|
||||
}
|
||||
let Some(texinfo) = geometry.texinfos.get(face.texinfo.max(0) as usize) else {
|
||||
continue;
|
||||
};
|
||||
let name = texdata
|
||||
.get(texinfo.texdata.max(0) as usize)
|
||||
.map(|data| data.name_id.max(0) as usize)
|
||||
.and_then(|id| names.get(id))
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
let lower = name.to_ascii_lowercase();
|
||||
if !(lower.contains("mirror") || lower.contains("reflect") || lower.contains("glass")) {
|
||||
continue;
|
||||
}
|
||||
let Ok(indices) = geometry.face_vertex_indices(index) else {
|
||||
continue;
|
||||
};
|
||||
let mut center = math::Vec3::ZERO;
|
||||
let mut count = 0.0f32;
|
||||
for &v in &indices {
|
||||
if let Some(vertex) = geometry.vertices.get(v as usize) {
|
||||
center += math::Vec3::new(vertex.pos[0], vertex.pos[1], vertex.pos[2]);
|
||||
count += 1.0;
|
||||
}
|
||||
}
|
||||
if count == 0.0 {
|
||||
continue;
|
||||
}
|
||||
let center = center / count;
|
||||
// Интересуют только вертикальные поверхности в зале (z около -300..-500).
|
||||
if (-600.0..=-200.0).contains(¢er.z) {
|
||||
eprintln!("грань {index}: {name} в {center:?}");
|
||||
found += 1;
|
||||
}
|
||||
if found > 20 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
eprintln!("найдено зеркальных граней в зале: {found}");
|
||||
}
|
||||
|
||||
/// Сущности рядом с залом, где пользователь ждёт зеркало.
|
||||
#[test]
|
||||
fn real_map_entities_near_hall() {
|
||||
let Some(root) = assets_root() else {
|
||||
eprintln!("пропуск: ассеты не найдены");
|
||||
return;
|
||||
};
|
||||
let map = root.join("garrysmod/maps/gm_construct.bsp");
|
||||
if !map.is_file() {
|
||||
eprintln!("пропуск: нет {}", map.display());
|
||||
return;
|
||||
}
|
||||
let vfs = mount_game(&root);
|
||||
let bsp = formats::bsp::Bsp::from_path(&map).expect("разбор карты");
|
||||
let world = engine::build_world(&bsp, &vfs).expect("сборка мира");
|
||||
let hall = math::Vec3::new(-1717.0, -1693.0, -400.0);
|
||||
for entity in world.entities.iter() {
|
||||
let distance = (entity.origin - hall).length();
|
||||
if distance < 700.0 {
|
||||
eprintln!(
|
||||
"{:.0}: {} @ {:?} model={:?}",
|
||||
distance,
|
||||
entity.classname,
|
||||
entity.origin,
|
||||
entity.key("model")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue