UNPKG

@overextended/ox_lib

Version:
127 lines (126 loc) 5.03 kB
console.warn(`The ox_lib zones module is experimental and may change in future versions.`); import { Grid } from '@overextended/core/grid'; import { Prism, Sphere } from '@overextended/core/geometry'; import { Vector3 } from '@overextended/core/vector'; import { cache } from '../cache'; export class Zone { static nextId = 1; static map = new Map(); static grid = new Grid(); static Prism(...args) { return new Zone(new Prism(...args)); } static Cuboid(...args) { return new Zone(Prism.createCuboid(...args)); } static Sphere(...args) { return new Zone(new Sphere(...args)); } static delete(id) { const zone = Zone.map.get(id); if (zone) { Zone.map.delete(id); Zone.grid.remove(zone); } } static getNearby(point) { return Zone.grid.getEntries(point.x, point.y); } static has(id) { return Zone.map.has(id); } shouldDraw = false; constructor(shape) { this.shape = shape; this.x = shape.centroid.x; this.y = shape.centroid.y; this.id = `zone:${Zone.nextId++}`; if (shape instanceof Prism) { const bounds = shape.bounds; this.width = Math.abs(bounds.maxX - bounds.minX); this.height = Math.abs(bounds.maxY - bounds.minY); } else { const diametre = ('circle' in shape ? shape.circle.radius : shape.radius) * 2; this.width = diametre; this.height = diametre; } Zone.grid.add(this); Zone.map.set(this.id, this); } draw(red = 255, green = 42, blue = 24, alpha = 100) { if (cache.game === 'fxserver') return; if (this.shape instanceof Sphere) { const { x, y, z } = this.shape.coords; const radius = this.shape.radius; return DrawMarker(28, x, y, z, 0, 0, 0, 0, 0, 0, radius, radius, radius, red, green, blue, alpha, false, false, 0, false, null, null, false); } if (this.shape instanceof Prism) { const polygon = this.shape.polygon; const half = this.shape.height / 2; const minZ = this.shape.z - half; const maxZ = this.shape.z + half; for (let i = 0; i < polygon.vertices.length; i++) { const curr = polygon.vertices[i]; const next = (polygon.vertices[i + 1] || polygon.vertices[0]); DrawLine(curr.x, curr.y, minZ, curr.x, curr.y, maxZ, red, green, blue, 225); DrawLine(curr.x, curr.y, maxZ, next.x, next.y, maxZ, red, green, blue, 225); DrawLine(curr.x, curr.y, minZ, next.x, next.y, minZ, red, green, blue, 225); DrawPoly(curr.x, curr.y, minZ, curr.x, curr.y, maxZ, next.x, next.y, maxZ, red, green, blue, alpha); DrawPoly(curr.x, curr.y, minZ, next.x, next.y, maxZ, next.x, next.y, minZ, red, green, blue, alpha); DrawPoly(curr.x, curr.y, minZ, next.x, next.y, maxZ, curr.x, curr.y, maxZ, red, green, blue, alpha); DrawPoly(curr.x, curr.y, minZ, next.x, next.y, minZ, next.x, next.y, maxZ, red, green, blue, alpha); } for (let i = 0; i < polygon.triangles.length; i++) { const [a, b, c] = polygon.triangles[i]; DrawPoly(a.x, a.y, minZ, b.x, b.y, minZ, c.x, c.y, minZ, red, green, blue, alpha); DrawPoly(a.x, a.y, maxZ, b.x, b.y, maxZ, c.x, c.y, maxZ, red, green, blue, alpha); DrawPoly(b.x, b.y, minZ, a.x, a.y, minZ, c.x, c.y, minZ, red, green, blue, alpha); DrawPoly(b.x, b.y, maxZ, a.x, a.y, maxZ, c.x, c.y, maxZ, red, green, blue, alpha); } return; } } } function startPolling() { if (cache.game === 'fxserver') return; let nearbyZones = new Set(); let insideZones = new Set(); let lastZones = new Set(); setInterval(() => { const coords = Vector3.fromArray(GetEntityCoords(cache.ped, true)); cache.coords = coords; nearbyZones = Zone.getNearby(coords); [lastZones, insideZones] = [insideZones, lastZones]; insideZones.clear(); for (const zone of nearbyZones) { if (zone.shape.contains(coords.x, coords.y, coords.z)) { insideZones.add(zone); if (!lastZones.has(zone)) { if (zone.onEnter) zone.onEnter(); } else { lastZones.delete(zone); } } } for (const zone of lastZones) { if (zone.onExit) zone.onExit(); } }, 300); setTick(() => { for (const zone of nearbyZones) { if (zone.shouldDraw) zone.draw(); } for (const zone of insideZones) { if (zone.inside) zone.inside(); } }); } startPolling();