diff --git a/apps/game/client/cl_contacts.ts b/apps/game/client/cl_contacts.ts index 991e151cb..d349ca92c 100644 --- a/apps/game/client/cl_contacts.ts +++ b/apps/game/client/cl_contacts.ts @@ -1,8 +1,72 @@ import { ContactEvents } from '@typings/contact'; import { RegisterNuiProxy } from './cl_utils'; +const QBCore = global.exports['qb-core'].GetCoreObject(); +const npwdExports = global.exports['npwd']; + +type Vector = { + x: number; + y: number; + z: number; + }; + RegisterNuiProxy(ContactEvents.PAY_CONTACT); RegisterNuiProxy(ContactEvents.GET_CONTACTS); RegisterNuiProxy(ContactEvents.ADD_CONTACT); RegisterNuiProxy(ContactEvents.DELETE_CONTACT); RegisterNuiProxy(ContactEvents.UPDATE_CONTACT); + +const getVector = (coords: number[]) => { + const [x, y, z] = coords; + return { + x, + y, + z, + }; +} + +const getDistance = (v1: Vector, v2: Vector) => { + const dx = v1.x - v2.x; + const dy = v1.y - v2.y; + const dz = v1.z - v2.z; + return Math.sqrt(dx * dx + dy * dy + dz * dz); +} + +const GetClosestPlayer = () => { + const closestPlayers = QBCore.Functions.GetPlayersFromCoords() + let closestDistance = -1 + let closestPlayer = -1 + const coords = GetEntityCoords(PlayerPedId(), true) + + for (let i = 0; i < closestPlayers.length; i++) { + if (closestPlayers[i] !== PlayerId()) { + const pos = GetEntityCoords(GetPlayerPed(closestPlayers[i]), true) + const distance = getDistance(getVector(pos), getVector(coords)) + + if (closestDistance === -1 || closestDistance > distance) { + closestPlayer = closestPlayers[i] + closestDistance = distance + } + } + } + + return [closestPlayer, closestDistance] +} + +on(ContactEvents.GIVE_CONTACT_DETAILS, () => { + const [player, distance] = GetClosestPlayer() + + if (player !== -1 && distance < 2.5) { + const PlayerId = GetPlayerServerId(player) + emitNet(ContactEvents.GIVE_CONTACT_DETAILS, PlayerId) + } else { + QBCore.Functions.Notify("No one nearby!", "error") + } +}); + +// Opens the phone on the new contacts page with the number and name prefilled out +onNet(ContactEvents.RECEIVE_CONTACT_DETAILS, (sendingPlayerNumber: string, sendingPlayerName: string) => { + npwdExports.setPhoneVisible(true); + + npwdExports.fillNewContact({ name: sendingPlayerName, number: sendingPlayerNumber }) +}); diff --git a/apps/game/server/contacts/contacts.controller.ts b/apps/game/server/contacts/contacts.controller.ts index bedfbae98..d13a83e08 100644 --- a/apps/game/server/contacts/contacts.controller.ts +++ b/apps/game/server/contacts/contacts.controller.ts @@ -3,6 +3,7 @@ import { Contact, ContactDeleteDTO, ContactEvents, PreDBContact, ContactPay } fr import PlayerService from '../players/player.service'; import ContactService from './contacts.service'; import { contactsLogger } from './contacts.utils'; +import { getSource } from '../utils/miscUtils'; import { onNetPromise } from '../lib/PromiseNetEvents/onNetPromise'; const exps = global.exports; @@ -60,3 +61,12 @@ onNetPromise(ContactEvents.DELETE_CONTACT, (reqObj, resp resp({ status: 'error', errorMsg: 'INTERNAL_ERROR' }); }); }); + +onNet(ContactEvents.GIVE_CONTACT_DETAILS, (targetPlayerId: number) => { + const src = getSource(); + const sendingPlayer = PlayerService.getPlayer(src); + const sendingPlayerNumber = sendingPlayer.getPhoneNumber(); + const sendingPlayerName = sendingPlayer.getName(); + + emitNet(ContactEvents.RECEIVE_CONTACT_DETAILS, targetPlayerId, sendingPlayerNumber, sendingPlayerName); +}) diff --git a/typings/contact.ts b/typings/contact.ts index 5102dc5ff..67cde116f 100644 --- a/typings/contact.ts +++ b/typings/contact.ts @@ -45,6 +45,8 @@ export enum ContactEvents { DELETE_CONTACT = 'npwd:deleteContact', // Used to fill in information through an export event ADD_CONTACT_EXPORT = 'npwd:addContactExport', + GIVE_CONTACT_DETAILS = 'npwd:GiveContactDetails', // Make sure to update your radial menu to use this event + RECEIVE_CONTACT_DETAILS = 'npwd:ReceiveContactDetails', } export interface AddContactExportData {