Crashes and vehicle hits¶
Everything that hits a vehicle comes through
vehicleHit: crashes into other
vehicles, players and peds, objects and walls (and the ground, when a
landing did harm), and bullets, fire and explosions. Return false to undo
a hit, or a number for the health it costs instead.
A no-crash zone¶
Vehicles inside a zone (a showroom, a spawn area) can't be damaged by anything.
no-crash.ts
import type { Server, Vehicle } from "@sagl/server";
export function noCrashZone(server: Server) {
const showroom = server.createZone({ min: { x: 540, y: -1300, z: 10 }, max: { x: 570, y: -1270, z: 30 } });
const inside = new Set<Vehicle>();
server.on("zoneEnter", (player, zone) => { if (zone === showroom && player.vehicle) inside.add(player.vehicle); });
server.on("zoneLeave", (player, zone) => { if (zone === showroom && player.vehicle) inside.delete(player.vehicle); });
server.on("vehicleHit", (vehicle) => {
if (inside.has(vehicle)) return false; // health and dents put back
});
}
Demolition derby¶
Only ramming other cars counts: walls and the ground do nothing, and the rammer scores what they did.
derby.ts
import type { Server, Player } from "@sagl/server";
export function derby(server: Server) {
const score = new Map<Player, number>();
server.on("vehicleHit", (vehicle, hit) => {
if (hit.cause === "weapon") return false; // no guns in the arena
if (hit.with !== "vehicle") return false; // walls are free
if (hit.player && hit.player !== vehicle.driver) {
score.set(hit.player, (score.get(hit.player) ?? 0) + Math.round(hit.loss));
}
return hit.loss * 1.5; // and hurt more
});
server.on("vehicleDeath", (vehicle, killer) => {
const victim = vehicle.driver;
if (killer && victim) server.broadcast(`${killer.name} wrecked ${victim.name}!`);
});
setInterval(() => {
const top = [...score.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3);
if (top.length) server.broadcast(`Leaders: ${top.map(([p, s]) => `${p.name} ${s}`).join(", ")}`);
}, 30_000);
}
Hit-and-run reports¶
server.on("vehicleHit", (vehicle, hit) => {
const driver = vehicle.driver;
if (hit.cause === "collision" && hit.with === "ped" && hit.player && driver) {
hit.player.send(`You were hit by ${driver.name}'s car.`);
driver.wantedLevel = Math.max(driver.wantedLevel, 1);
}
});