diff --git a/ReallifeGamemode.Client/Player/position.ts b/ReallifeGamemode.Client/Player/position.ts index 8c8cf4a3..3e2d802d 100644 --- a/ReallifeGamemode.Client/Player/position.ts +++ b/ReallifeGamemode.Client/Player/position.ts @@ -8,6 +8,15 @@ export function isPlayerInNoDMZone(pos) { } export default function positionHandler() { + + mp.events.add('playerEnterPolygon', (polygon) => { + mp.gui.chat.push("entered"); + }); + + mp.events.add('playerLeavePolygon', (polygon) => { + mp.gui.chat.push("entered"); + }); + setInterval(() => { mp.events.call('toggleNoDmZone', isPlayerInNoDMZone(mp.players.local.position)); }, 200); diff --git a/ReallifeGamemode.Client/index.ts b/ReallifeGamemode.Client/index.ts index 724e857f..d8e3350f 100644 --- a/ReallifeGamemode.Client/index.ts +++ b/ReallifeGamemode.Client/index.ts @@ -271,6 +271,7 @@ ammunation(globalData); require('./Gui/policedepartment'); require('./Gui/helptext'); require('./admin/spectate'); +require('./polygons/index'); interface VehicleData { EngineState: boolean; diff --git a/ReallifeGamemode.Client/polygons/events.js b/ReallifeGamemode.Client/polygons/events.js new file mode 100644 index 00000000..9f5f7584 --- /dev/null +++ b/ReallifeGamemode.Client/polygons/events.js @@ -0,0 +1,20 @@ +setInterval(() => { + const { position, dimension } = mp.players.local; + + mp.polygons.pool.map((polygon) => { + + if (polygon.colliding) { + if (!mp.polygons.isPositionWithinPolygon(position, polygon, dimension)) { + polygon.colliding = false; + mp.events.call('playerLeavePolygon', polygon); + } + } + else { + if (mp.polygons.isPositionWithinPolygon(position, polygon, dimension)) { + polygon.colliding = true; + mp.events.call('playerEnterPolygon', polygon); + } + } + }); + +}, 100); \ No newline at end of file diff --git a/ReallifeGamemode.Client/polygons/helpers.js b/ReallifeGamemode.Client/polygons/helpers.js new file mode 100644 index 00000000..6de4afb8 --- /dev/null +++ b/ReallifeGamemode.Client/polygons/helpers.js @@ -0,0 +1,53 @@ +const isPointInArea2D = (point, area) => { + let x = point[0], y = point[1]; + + let inside = false; + + for (let i = 0, j = area.length - 1; i < area.length; j = i++) { + let xi = area[i][0], yi = area[i][1]; + let xj = area[j][0], yj = area[j][1]; + + let intersect = ((yi > y) != (yj > y)) + && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + + if (intersect) + inside = !inside; + } + + return inside; +}; + +const TWOPI = 6.283185307179586476925287; +const EPSILON = 0.0000001; + +const modulus = (p) => Math.sqrt((p.x * p.x) + (p.y * p.y) + (p.z *p.z)); + +const getAngleSumBetweenPositionAndVertices = (position, vertices) => { + let i; + let m1, m2; + let anglesum=0, costheta; + + for (i = 0; i < vertices.length; i++) { + + const p1 = new mp.Vector3(vertices[i].x - position.x, vertices[i].y - position.y, vertices[i].z - position.z); + const p2 = new mp.Vector3(vertices[(i+1)%vertices.length].x - position.x, vertices[(i+1)%vertices.length].y - position.y, vertices[(i+1)%vertices.length].z - position.z); + + m1 = modulus(p1); + m2 = modulus(p2); + + if (m1*m2 <= EPSILON) + return(TWOPI); + else + costheta = (p1.x*p2.x + p1.y*p2.y + p1.z*p2.z) / (m1*m2); + + anglesum += Math.acos(costheta); + } + return(anglesum); +} + +const generateUniquePolygonId = () => { + const timestamp = Date.now(); + return mp.polygons.pool.some(p => p.id === timestamp) ? generateUniquePolygonId() : timestamp; +}; + +export { isPointInArea2D, generateUniquePolygonId, getAngleSumBetweenPositionAndVertices }; \ No newline at end of file diff --git a/ReallifeGamemode.Client/polygons/render.js b/ReallifeGamemode.Client/polygons/render.js new file mode 100644 index 00000000..7e9288f1 --- /dev/null +++ b/ReallifeGamemode.Client/polygons/render.js @@ -0,0 +1,27 @@ +mp.events.add('render', () => { + + mp.polygons.pool?.forEach(polygon => { + if (!polygon.visible) return; + + const { vertices, height, lineColorRGBA } = polygon; + + vertices.forEach((vertex, index) => { + + const nextVertex = index === (vertices.length - 1) ? vertices[0] : vertices[index + 1]; + + // Deepness lower line + mp.game.graphics.drawLine(vertex.x, vertex.y, vertex.z, nextVertex.x, nextVertex.y, nextVertex.z, ...lineColorRGBA); + + // Current vertex height line + mp.game.graphics.drawLine(vertex.x, vertex.y, vertex.z, vertex.x, vertex.y, vertex.z + height, ...lineColorRGBA); + + // Next vertex height line + mp.game.graphics.drawLine(nextVertex.x, nextVertex.y, nextVertex.z, nextVertex.x, nextVertex.y, nextVertex.z + height, ...lineColorRGBA); + + // Deepness higher line + mp.game.graphics.drawLine(vertex.x, vertex.y, vertex.z + height, nextVertex.x, nextVertex.y, nextVertex.z + height, ...lineColorRGBA); + }); + + }); + +}); \ No newline at end of file