Archived
Private
Public Access
1
0
This repository has been archived on 2026-02-04. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
ProjectBackup/C#/FiveM/CardealerClient/CarDealer.cs
2022-09-04 12:45:01 +02:00

318 lines
14 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using CardealerClient.Exhibits;
using CardealerClient.Menus;
using CitizenFX.Core;
using CitizenFX.Core.Native;
using static CitizenFX.Core.Native.API;
using Nexd.ESX.Client;
namespace CardealerClient {
public class CarDealer : BaseScript {
public static CarDealer Instance;
public static ExhibitCar[] RealExhibitCars;
public static bool[] SlotReady;
public static string[] CarNames;
public static bool ExhibitsSpawned;
public static bool MenuOpen;
public static bool DigitalMenuOpen;
private static TaskCompletionSource<bool> _dialogTask;
public CarDealer() {
RealExhibitCars = new ExhibitCar[Config.CarSlots.Length];
SlotReady = new bool[Config.CarSlots.Length];
CarNames = new string[Config.CarSlots.Length];
ExhibitsSpawned = false;
EventHandlers["onClientResourceStart"] += new Action<string>(OnStart);
EventHandlers["onResourceStop"] += new Action<string>(OnStop);
EventHandlers["cardealer:spawnVehicle"] += new Action<int>(SpawnExhibit);
EventHandlers["cardealer:openmenu"] += new Action(SellMenu.Open);
EventHandlers["cardealer:testDriveClient"] += new Action<int, bool>((slot, value) => RealExhibitCars[slot]?.SetTestDrive(value));
EventHandlers["cardealer:openManageMenu"] += new Action(OwnerMenu.Open);
EventHandlers["cardealer:dialog_accept"] += new Action(() => _dialogTask?.TrySetResult(true));
EventHandlers["cardealer:dialog_deny"] += new Action(() => _dialogTask?.TrySetResult(false));
Instance = this;
}
public static Task<dynamic> ServerCallback(string name, dynamic args = null) {
var source = new TaskCompletionSource<dynamic>();
ESX.TriggerServerCallback(name, new Action<dynamic>(o => {
source.TrySetResult(o);
}), args);
return source.Task;
}
public static Task<int> SpawnVehicle(dynamic model, Vector3 coords, float heading, bool local = false) {
var source = new TaskCompletionSource<int>();
if (local) {
ESX.Game.Raw.SpawnLocalVehicle(model, coords, heading, new Action<int>(vehicle => {
source.TrySetResult(vehicle);
}));
}
else {
ESX.Game.Raw.SpawnVehicle(model, coords, heading, new Action<int>(vehicle => {
source.TrySetResult(vehicle);
}));
}
return source.Task;
}
public static Task<List<string>> GetVehicleNames(dynamic models) {
var source = new TaskCompletionSource<List<string>>();
TriggerEvent("cardealer:getCarNames", models, new Action<dynamic>(o => {
source.TrySetResult((o as List<object>).Select(val => val.ToString()).ToList());
}));
return source.Task;
}
public static Task<string> DisplayTextDialog(string placeholder, int maxLength) {
var source = new TaskCompletionSource<string>();
DisplayOnscreenKeyboard(0, "FMMC_KEY_TIP8", "", placeholder, "", "", "", maxLength);
new Thread(() => {
bool input = true;
while (input) {
if (UpdateOnscreenKeyboard() == 3 || UpdateOnscreenKeyboard() == 2)
input = false;
else if (UpdateOnscreenKeyboard() == 1) {
input = false;
source.TrySetResult(GetOnscreenKeyboardResult());
}
Thread.Sleep(0);
}
}).Start();
return source.Task;
}
public static Task<bool> DisplayConfirmationDialog(string title) {
_dialogTask = new TaskCompletionSource<bool>();
TriggerEvent("okokRequests:RequestMenuData", -1, Config.MenuTitle, title, "cardealer:dialog_accept", "client", "", 0, "cardealer:dialog_deny");
return _dialogTask.Task;
}
public static void DrawText3D(Vector3 pos, string text, float scale = 1, bool rotate = true) {
OutputArgument screenX = new OutputArgument(), screenY = new OutputArgument();
bool onScreen = Function.Call<bool>(Hash.GET_SCREEN_COORD_FROM_WORLD_COORD , pos.X, pos.Y, pos.Z, screenX, screenY);
if (onScreen) {
Vector3 cam = GetGameplayCamCoord();
float dist = GetDistanceBetweenCoords(cam.X, cam.Y, cam.Z, pos.X, pos.Y, pos.Z, true);
if (rotate)
scale = (((1 / dist) * 2) * (1 / GetGameplayCamFov()) * 100) * scale;
SetTextColour(220, 220, 220, 255);
SetTextScale(0.0f * scale, 0.40f * scale);
SetTextFont(4);
SetTextProportional(true);
SetTextCentre(true);
SetTextEntry("STRING");
AddTextComponentString(text);
EndTextCommandDisplayText(screenX.GetResult<float>(), screenY.GetResult<float>());
}
}
private void ShowText(int slot) {
Exhibit exhibit = RealExhibitCars[slot].Exhibit;
float x = exhibit.Location.X;
float y = exhibit.Location.Y;
float z = exhibit.Location.Z;
if (RealExhibitCars[slot].TestDrive)
DrawText3D(new Vector3(x, y, z + 0.8f), "[~r~Dieses Auto ist gerade bei einer Probefahrt~s~]");
else {
VehicleData data = RealExhibitCars[slot].Data;
string turbo = "~r~Nein";
if (Convert.ToBoolean(data.Properties.Raw.modTurbo)) turbo = "~g~Ja";
string line1 = "[~b~" + CarNames[slot] + "~s~]";
string line2 = "[Turbo : " + turbo + "~s~] [Motor : ~r~" + data.Properties.modEngine + "~s~] [Getriebe : ~r~" + data.Properties.modTransmission + "~s~]";
string line3 = "[Federung : ~r~" + data.Properties.modSuspension + "~s~] [Panzerung : ~r~" + data.Properties.modArmor + "~s~] [Bremsen : ~r~" + data.Properties.modBrakes + "~s~]";
string line4 = "[Beschreibung : ~r~" + data.Description + "~s~]";
string line5 = "Drücke [~r~E~s~] zum kaufen [$~r~" + data.Price + "~s~]";
string line6 = "Drücke [~r~F~s~] zum probefahren [~r~90 sek~s~]";
DrawText3D(new Vector3(x, y, z + 1.1f), line6);
DrawText3D(new Vector3(x, y, z + 1.2f), line5);
DrawText3D(new Vector3(x, y, z + 1.3f), line4);
DrawText3D(new Vector3(x, y, z + 1.4f), line3);
DrawText3D(new Vector3(x, y, z + 1.5f), line2);
DrawText3D(new Vector3(x, y, z + 1.6f), line1);
}
}
public static void SendNotification(string message) {
SetNotificationTextEntry("STRING");
AddTextComponentString(message);
DrawNotification(false, false);
}
public static void Notify(string message, string type, int duration = 5000) {
TriggerEvent("okokNotify:Alert", Config.MenuTitle, message, duration, type);
}
public static void AddTickHandler(Func<Task> handler) {
Instance.Tick += handler;
}
public static void RemoveTickHandler(Func<Task> handler) {
Instance.Tick -= handler;
}
private void DisplayHelpTextThisFrame(string text) {
SetTextComponentFormat("STRING");
AddTextComponentString(text);
EndTextCommandDisplayHelp(0, false, true, -1);
}
private void SpawnRealExhibits() {
if (ExhibitsSpawned) return;
for (int i = 1; i < Config.CarSlots.Length; i++) {
TriggerEvent("cardealer:spawnVehicle", i);
}
ExhibitsSpawned = true;
}
private void DeleteRealExhibits() {
if (!ExhibitsSpawned) return;
for (int i = 1; i < Config.CarSlots.Length; i++) {
if (SlotReady[i])
RealExhibitCars[i].Despawn();
}
ExhibitsSpawned = false;
}
// EVENT FUNCTIONS
private void OnStart(string resourceName) {
if (resourceName != GetCurrentResourceName()) return;
for (int i = 1; i < Config.CarSlots.Length; i++)
SlotReady[i] = false;
Tick += async () => {
ExhibitCar.RepairVehicles();
//EXHIBIT INTERACTION
Vector3 player = GetEntityCoords(GetPlayerPed(-1), IsDecalAlive(GetPlayerPed(-1)));
bool playerIsInRadius = GetDistanceBetweenCoords(
player.X, player.Y, player.Z,
Config.BlipLocation.X, Config.BlipLocation.Y,
Config.BlipLocation.Z, false) <
Config.SpawnRadius;
if (!ExhibitsSpawned && playerIsInRadius) SpawnRealExhibits();
if (ExhibitsSpawned && !playerIsInRadius) DeleteRealExhibits();
bool found = false;
float closestDist = float.MaxValue;
int closestSlot = 0;
for (int i = 0; i < RealExhibitCars.Length; i++) {
if (!SlotReady[i]) continue;
Vector4 exPos = RealExhibitCars[i].Exhibit.Location;
float dist =
GetDistanceBetweenCoords(player.X, player.Y, player.Z, exPos.X, exPos.Y, exPos.Z, true);
if (closestDist > dist) {
closestDist = dist;
found = true;
closestSlot = RealExhibitCars[i].Exhibit.Slot;
}
}
if (found) {
if (closestDist < 5) {
ShowText(closestSlot);
if (!RealExhibitCars[closestSlot].TestDrive) {
if (IsControlJustReleased(0, 38) && !RealExhibitCars[closestSlot].TestDrive)
RealExhibitCars[closestSlot].Buy();
if (IsControlJustReleased(0, 23) && !RealExhibitCars[closestSlot].TestDrive)
RealExhibitCars[closestSlot].StartTestDrive();
}
}
}
DigitalExhibit.ShowDigitalText();
//BLIP INTERACTION
if (IsPedInAnyVehicle(GetPlayerPed(-1), false)) {
DrawMarker(1, Config.BlipLocation.X, Config.BlipLocation.Y, Config.BlipLocation.Z, 0, 0, 0, 0, 0, 0,
3.7f, 3.7f, 0.2f, 3, 155, 229, 255, false, false, 0, false, null, null, false);
float distanceToMarker = GetDistanceBetweenCoords(player.X, player.Y, player.Z, Config.BlipLocation.X,
Config.BlipLocation.Y, Config.BlipLocation.Z, true);
if (distanceToMarker <= 4f) {
if (!MenuOpen)
DisplayHelpTextThisFrame("Drücke ~INPUT_CONTEXT~ um das Menü zu öffnen");
if (IsControlJustReleased(0, 38) && !MenuOpen)
SellMenu.Open();
}
}
float digiDist = GetDistanceBetweenCoords(player.X, player.Y, player.Z, Config.DigitalShowPoint.X, Config.DigitalShowPoint.Y, Config.DigitalShowPoint.Z, true);
if (digiDist < 2 && !DigitalMenuOpen) {
DrawText3D(Config.DigitalShowPoint, "Drücke ~g~E~s~ um den Katalog zu öffnen");
if (IsControlJustReleased(0, 38))
DigitalExhibit.HandleDigitalExhibit();
}
};
}
private void OnStop(string resourceName) {
if (resourceName != GetCurrentResourceName()) return;
DeleteRealExhibits();
}
private async void SpawnExhibit(int slot) {
Exhibit exhibit = Config.CarSlots[slot];
ExhibitCar old = RealExhibitCars[slot];
if (old != null) ESX.Game.DeleteVehicle(old.Vehicle.ToString());
var vehicle = await ServerCallback("cardealer:getVehicleData", slot);
if (vehicle is List<object>) {
if (RealExhibitCars[slot] != null) {
RealExhibitCars[slot].Despawn();
}
RealExhibitCars[slot] = null;
return;
}
VehicleData data = new VehicleData(vehicle);
if (data.Properties == null) {
if (RealExhibitCars[slot] != null) {
RealExhibitCars[slot].Despawn();
}
RealExhibitCars[slot] = null;
return;
}
ExhibitCar car = new ExhibitCar(exhibit, data);
car.SetTestDrive(await ServerCallback("cardealer:getTestDrive", slot));
RealExhibitCars[slot] = car;
}
}
}