import { Menu, Point, UIMenuSliderItem, UIMenuItem, Color, UIMenuListItem, ItemsCollection } from "../libs/NativeUI"; import { createMenuItem } from "../util"; import moneyformat from "../moneyformat"; import { getAnimFromId } from "../util/animationSync"; import { getCreatedPedByName } from "../Ped/PedCreator"; import KeyBinder from 'ragemp-better-bindings'; export const hanfPlantObjects = { stage1: mp.game.joaat('bkr_prop_weed_bud_pruned_01a'), stage2: mp.game.joaat('bkr_prop_weed_bud_01b'), stage3: mp.game.joaat('prop_weed_02'), stage4: mp.game.joaat('prop_weed_01') }; const hanfTimeToObject = [ { minutes: 15, object: hanfPlantObjects.stage1, }, { minutes: 60 * 1, object: hanfPlantObjects.stage2 }, { minutes: 60 * 3, object: hanfPlantObjects.stage3 }, { minutes: 60 * 4, object: hanfPlantObjects.stage4 } ] const minimumPlantDistance = 2; const maximumPlantDuration = 6 * 60 * 60 * 1000; // 6 Stunden / 360 Minuten / 21600 Sekunden / 21600000 Millisekunden const timeToHarvestPlant = 4 * 60 * 60 * 1000; // 4 Stunden export default function hanfSystem(globalData: IGlobalData) { let currentPlantingPreviewObject: ObjectMp = null; let currentPlantingMarkerPreview: MarkerMp = null; let currentlyPlanting: boolean = false; let lastPlantingState = true; mp.events.add("SERVER:Hanf_BuySeed", (maxSeedsToBuy, price) => { if (globalData.InMenu || globalData.InChat) { return; } globalData.InMenu = true; var menu = new Menu("Samen kaufen", "Kaufe dir Hanfsamen", new Point(50, 50)); var seedsToBuy = 0; var countItems = [...Array(maxSeedsToBuy).keys()].map(x => x + 1); var soloPriceItem = createMenuItem("Einzelpreis", "Preis pro Samen", item => { item.SetRightLabel("$" + moneyformat(price)); }); menu.AddItem(soloPriceItem); var countItem = new UIMenuListItem("Anzahl", "Wähle die Anzahl der Samen aus", new ItemsCollection(countItems), 0); menu.AddItem(countItem); var buyItem = new UIMenuItem("Kaufen", "Kaufe die Samen"); buyItem.BackColor = new Color(0, 100, 0); buyItem.HighlightedBackColor = new Color(0, 150, 0); menu.AddItem(buyItem); var completePriceItem = new UIMenuItem("Gesamtpreis", "Preis für alle Samen"); menu.AddItem(completePriceItem); menu.ListChange.on((item, index) => { if (item === countItem) { seedsToBuy = Number(countItem.SelectedValue); completePriceItem.SetRightLabel("$" + moneyformat(seedsToBuy * price)); } }); menu.ItemSelect.on((item, index) => { if (item === buyItem) { mp.events.callRemote("CLIENT:Hanf_BuySeeds", seedsToBuy); menu.Close(); } }); menu.MenuClose.on(() => { globalData.InMenu = false; }); menu.Open(); }); mp.events.add("SERVER:Hanf_SellCannabisMenu", (maxCannabisToSell, price) => { if (globalData.InMenu || globalData.InChat) { return; } globalData.InMenu = true; var menu = new Menu("Cannabis verkaufen", "Verkaufe dein Cannabis", new Point(50, 50)); var cannabisToSell = 0; var countItems = [...Array(maxCannabisToSell).keys()].map(x => x + 1); var soloPriceItem = createMenuItem("Einzelpreis", "Preis pro Hanfblüte", item => { item.SetRightLabel("$" + moneyformat(price)); }); menu.AddItem(soloPriceItem); var countItem = new UIMenuListItem("Anzahl", "Wähle die Anzahl der Blüten aus", new ItemsCollection(countItems), 0); menu.AddItem(countItem); var buyItem = new UIMenuItem("Verkaufen", "Verkaufe dein Cannabis"); buyItem.BackColor = new Color(0, 100, 0); buyItem.HighlightedBackColor = new Color(0, 150, 0); menu.AddItem(buyItem); var completePriceItem = new UIMenuItem("Gesamtpreis", "Preis für alle Blüten"); menu.AddItem(completePriceItem); menu.ListChange.on((item, index) => { if (item === countItem) { cannabisToSell = Number(countItem.SelectedValue); completePriceItem.SetRightLabel("$" + moneyformat(cannabisToSell * price)); } }); menu.ItemSelect.on((item, index) => { if (item === buyItem) { mp.events.callRemote("CLIENT:Hanf_SellCannabis", cannabisToSell); menu.Close(); } }); menu.MenuClose.on(() => { globalData.InMenu = false; }); menu.Open(); }); mp.events.add("SERVER:Hanf_PlayManufacturerAnim", animId => { var anim = getAnimFromId(animId); var npc = getCreatedPedByName("hanf_verarbeiter_typ"); npc.taskPlayAnim(anim.dict, anim.name, 1, 0, 1000 * 10, 1, 0, !1, !1, !1); setTimeout(() => { npc.stopAnim(anim.name, anim.dict, 3); npc.stopAnimTask(anim.dict, anim.name, 3); }, 1000 * 10); }); mp.events.add("SERVER:Hanf_StartPlanting", _ => { let player = mp.players.local; currentPlantingPreviewObject = mp.objects.new(hanfPlantObjects.stage1, player.position, { alpha: 255 }); currentPlantingPreviewObject.notifyStreaming = true; currentlyPlanting = true; }); mp.events.add(RageEnums.EventKey.RENDER, _ => { if (!currentlyPlanting) { return; } var player = mp.players.local; lastPlantingState = isAbleToPlant(); var markerColor: [number, number, number, number] = [0, 255, 0, 255]; if (!lastPlantingState) { markerColor = [255, 0, 0, 255]; } if (currentPlantingMarkerPreview) { currentPlantingMarkerPreview.destroy(); } var playerPos = player.position; var objectPos = new mp.Vector3(playerPos.x, playerPos.y, playerPos.z - 1.0); currentPlantingMarkerPreview = mp.markers.new(25, objectPos, 0.7, { color: markerColor, visible: true, rotation: new mp.Vector3(1, 0, 0) }); }); mp.events.add(RageEnums.EventKey.ENTITY_STREAM_IN, entity => { if (entity === currentPlantingPreviewObject) { currentPlantingPreviewObject.attachTo(Number(mp.players.local.handle), 0, 0, 0.2, -0.95, 0, 0, 0, true, false, false, false, 0, true); } }); function isAbleToPlant() { var player = mp.players.local; if (isNearPlant(minimumPlantDistance)) { return false; } if (!isSurfaceAllowed()) { return false; } if (currentPlantingPreviewObject) { var objectPos = getPlantPreviewPosition(); var realZ = mp.game.gameplay.getGroundZFor3dCoord(objectPos.x, objectPos.y, objectPos.z + 1, 0, false); if (realZ > objectPos.z + 1) { return false; } } if (player.isSwimming() || player.isSwimmingUnderWater() || !player.isOnFoot() || player.isSprinting() || player.isShooting()) { return false; } return true; } const RAYCAST_POINT_TO_POINT_NATIVE = "0x377906D8A31E5586"; const GET_RAYCAST_RESULT_NATIVE = "0x65287525D951F6BE"; function isSurfaceAllowed() { return true; const player = mp.players.local; var position = getPlantPreviewPosition(); var raycast = mp.game.invoke(RAYCAST_POINT_TO_POINT_NATIVE, position.x, position.y, position.z + 5, position.x, position.y, position.z - 5, 1, 0, 7); mp.gui.chat.push("raycast = " + raycast); var resultObj = { hit: [false], coord: [new mp.Vector3()], surface: [new mp.Vector3()], material: [0], entityHit: [null] }; var raycastResult = -1; var retries = 10; do { raycastResult = mp.game.invoke(GET_RAYCAST_RESULT_NATIVE, raycast, resultObj.hit, resultObj.coord, resultObj.surface, resultObj.material, resultObj.entityHit); retries--; } while (raycastResult != 0 && raycastResult != 2 && retries > 0); mp.gui.chat.push("result: " + raycastResult + ", result = " + JSON.stringify(resultObj)); return true; } KeyBinder.bind('e', _ => { if (globalData.InChat) { return; } if (!currentlyPlanting) { var nearPlant = isNearPlant(0.5); if (!nearPlant) { return; } mp.events.callRemote("CLIENT:Hanf_HarvestHanf", nearPlant.Id); return; } if (!lastPlantingState) { mp.game.graphics.notify("~r~Hier kann kein Hanf platziert werden"); return; } currentlyPlanting = false; var player = mp.players.local; if (currentPlantingPreviewObject) { currentPlantingPreviewObject.destroy(); currentPlantingPreviewObject = null; } if (currentPlantingMarkerPreview) { currentPlantingMarkerPreview.destroy(); currentPlantingMarkerPreview = null; } var position = getPlantPreviewPosition(); var realZ = mp.game.gameplay.getGroundZFor3dCoord(position.x, position.y, position.z + 2, 0, false); mp.events.callRemote("CLIENT:Hanf_PlantHanf", position.x, position.y, realZ); }); function getPlantPreviewPosition(): Vector3Mp { return mp.players.local.getOffsetFromInWorldCoords(0, 0.2, -1); } function getPlantText(plant: CannabisData) { var time = Date.now() - Date.parse(plant.Time); if (time > maximumPlantDuration) { return ("~g~Hanf~n~~r~Verrottet"); } return (`~g~Hanf~n~Fortschritt: ${getPlantPercentage(plant).toFixed(2)}%`); } function getPlantPercentage(plant: CannabisData) { var time = Date.now() - Date.parse(plant.Time); return Math.min((time / timeToHarvestPlant) * 100, 100); } function isNearPlant(distance: number): CannabisData { var pos = getPlantPreviewPosition(); var nearPlants = currentHanfData.filter(h => mp.game.gameplay.getDistanceBetweenCoords(pos.x, pos.y, pos.z, h.X, h.Y, h.Z, true) < distance); if (!nearPlants || nearPlants.length == 0) { return null; } nearPlants = nearPlants.sort((a, b) => Number(mp.game.gameplay.getDistanceBetweenCoords(pos.x, pos.y, pos.z, a.X, a.Y, a.Z, true) < mp.game.gameplay.getDistanceBetweenCoords(pos.x, pos.y, pos.z, b.X, b.Y, b.Z, true))); return nearPlants[0]; } let currentHanfData: Array = []; let hanfDataIdToObjectMap: Map = new Map(); let hanfDataIdToTextLabelMap: Map = new Map(); let currentHanfUpdateJsonData: Map = new Map(); mp.events.add("SERVER:Hanf_UpdateHanf", (currentIndex: number, totalData: number, currentData: string) => { currentHanfUpdateJsonData.set(currentIndex, currentData); if (currentHanfUpdateJsonData.size == totalData) { var jsonData: string = ""; for (var i = 0; i < totalData; i++) { jsonData += currentHanfUpdateJsonData.get(i); } currentHanfUpdateJsonData.clear(); var data: Array = >JSON.parse(jsonData) var newPlants = data.filter(d => currentHanfData.filter(x => x.Id === d.Id).length == 0); var removedPlants = currentHanfData.filter(d => data.filter(x => x.Id === d.Id).length == 0); var existingPlants = data.filter(d => currentHanfData.filter(x => x.Id === d.Id).length == 1); newPlants.forEach(plant => { var model = getPlantModel(plant); var object = mp.objects.new(getPlantModel(plant), new mp.Vector3(plant.X, plant.Y, plant.Z)); hanfDataIdToObjectMap.set(plant.Id, object); var textLabel = mp.labels.new(getPlantText(plant), new mp.Vector3(plant.X, plant.Y, plant.Z + 1), { los: true, drawDistance: 2 }); hanfDataIdToTextLabelMap.set(plant.Id, textLabel); }); removedPlants.forEach(plant => { var object = hanfDataIdToObjectMap.get(plant.Id); hanfDataIdToObjectMap.delete(plant.Id); object.destroy(); var textLabel = hanfDataIdToTextLabelMap.get(plant.Id); textLabel.destroy(); hanfDataIdToTextLabelMap.delete(plant.Id); }); existingPlants.forEach(plant => { var object = hanfDataIdToObjectMap.get(plant.Id); var model = getPlantModel(plant); if (model != object.model) { object.destroy(); var object = mp.objects.new(model, new mp.Vector3(plant.X, plant.Y, plant.Z)); hanfDataIdToObjectMap.delete(plant.Id); hanfDataIdToObjectMap.set(plant.Id, object); } var textLabel = hanfDataIdToTextLabelMap.get(plant.Id); textLabel.text = getPlantText(plant); }); currentHanfData = data; } }); function getPlantModel(plant: CannabisData): number { var diff = Date.now() - Date.parse(plant.Time); var model = -1; var dbgTxt; if (diff <= 30 * 60 * 1000) { // 0 - 30 Minuten model = hanfPlantObjects.stage1; dbgTxt = "30 Minuten"; } else if (diff <= 4 * 60 * 60 * 1000) { // 30 - 240 Minuten / 4 Stunden model = hanfPlantObjects.stage3; dbgTxt = "3 Stunden"; } else { // Ausgewachsen / Ab 4 Stunden model = hanfPlantObjects.stage4; dbgTxt = "4 Stunden"; } //mp.gui.chat.push("plant id = " + plant.Id + ", age = " + dbgTxt); return model; } mp.events.addProc("SERVER:Hanf_GetModelToGivePlayer", id => { var plant = currentHanfData.filter(x => x.Id == id)[0]; var model = getPlantModel(plant); if (model == hanfPlantObjects.stage1) { return 1; } else if (model == hanfPlantObjects.stage3) { return 2; } else if (model == hanfPlantObjects.stage4) { return 3; } }); //var rotationTestObject: ObjectMp = null; //var a1: number, a2: number, a3: number, a4: number, a5: number, a6: number; //mp.events.add(RageEnums.EventKey.PLAYER_COMMAND, (f) => { // var args = f.split(' '); // if (args[0] != "a") { // return; // } // a1 = parseFloat(args[1] || "0"); // a2 = parseFloat(args[2] || "0"); // a3 = parseFloat(args[3] || "0"); // a4 = parseFloat(args[4] || "0"); // a5 = parseFloat(args[5] || "0"); // a6 = parseFloat(args[6] || "0"); // mp.gui.chat.push(`a1: ${a1.toFixed(2)}, a2: ${a2.toFixed(2)}, a3: ${a3.toFixed(2)}, a4: ${a4.toFixed(2)}, a5: ${a5.toFixed(2)}, a6: ${a6.toFixed(2)},`) // if (rotationTestObject != null) { // rotationTestObject.attachTo(Number(mp.players.local.handle), mp.players.local.getBoneIndex(57005), a1, a2, a3, a4, a5, a6, true, false, false, false, 0, true); // return; // } // rotationTestObject = mp.objects.new(mp.game.joaat("prop_cs_trowel"), mp.players.local.position, { // alpha: 255 // }); //}); }