diff --git a/resources/[ERS]/SmartFiresLite/.fxap b/resources/[ERS]/SmartFiresLite/.fxap index bd5b9a68e..0099fe9f0 100644 Binary files a/resources/[ERS]/SmartFiresLite/.fxap and b/resources/[ERS]/SmartFiresLite/.fxap differ diff --git a/resources/[ERS]/SmartFiresLite/cl_smartfires.lua b/resources/[ERS]/SmartFiresLite/cl_smartfires.lua index a4c6e88a3..7ab530c01 100644 Binary files a/resources/[ERS]/SmartFiresLite/cl_smartfires.lua and b/resources/[ERS]/SmartFiresLite/cl_smartfires.lua differ diff --git a/resources/[ERS]/SmartFiresLite/sv_smartfires.lua b/resources/[ERS]/SmartFiresLite/sv_smartfires.lua index 628b96de7..32f82356e 100644 Binary files a/resources/[ERS]/SmartFiresLite/sv_smartfires.lua and b/resources/[ERS]/SmartFiresLite/sv_smartfires.lua differ diff --git a/resources/[ERS]/SmartHoseLite/.fxap b/resources/[ERS]/SmartHoseLite/.fxap index affe7d6db..8e056a434 100644 Binary files a/resources/[ERS]/SmartHoseLite/.fxap and b/resources/[ERS]/SmartHoseLite/.fxap differ diff --git a/resources/[ERS]/SmartHoseLite/cl_hose.lua b/resources/[ERS]/SmartHoseLite/cl_hose.lua index 77300d92e..974a4887f 100644 Binary files a/resources/[ERS]/SmartHoseLite/cl_hose.lua and b/resources/[ERS]/SmartHoseLite/cl_hose.lua differ diff --git a/resources/[ERS]/SmartHoseLite/sv_exports.lua b/resources/[ERS]/SmartHoseLite/sv_exports.lua index 741f8947d..13271aff7 100644 Binary files a/resources/[ERS]/SmartHoseLite/sv_exports.lua and b/resources/[ERS]/SmartHoseLite/sv_exports.lua differ diff --git a/resources/[ERS]/SmartHoseLite/sv_hose.lua b/resources/[ERS]/SmartHoseLite/sv_hose.lua index 37c475191..5f041fdb6 100644 Binary files a/resources/[ERS]/SmartHoseLite/sv_hose.lua and b/resources/[ERS]/SmartHoseLite/sv_hose.lua differ diff --git a/resources/[ERS]/ebu_flatbeds_ers/.fxap b/resources/[ERS]/ebu_flatbeds_ers/.fxap index c3dce4805..120c11e6f 100644 Binary files a/resources/[ERS]/ebu_flatbeds_ers/.fxap and b/resources/[ERS]/ebu_flatbeds_ers/.fxap differ diff --git a/resources/[ERS]/ebu_flatbeds_ers/client/client.lua b/resources/[ERS]/ebu_flatbeds_ers/client/client.lua index f4b4e5fc0..e82b25be4 100644 Binary files a/resources/[ERS]/ebu_flatbeds_ers/client/client.lua and b/resources/[ERS]/ebu_flatbeds_ers/client/client.lua differ diff --git a/resources/[ERS]/ebu_flatbeds_ers/config.lua b/resources/[ERS]/ebu_flatbeds_ers/config.lua index ef0701638..1280acaf5 100644 --- a/resources/[ERS]/ebu_flatbeds_ers/config.lua +++ b/resources/[ERS]/ebu_flatbeds_ers/config.lua @@ -81,6 +81,10 @@ Config.flatbed = "flatbed" -- Base game flatbed Config.flatbedm2 = "flatbedm2" -- https://www.gta5-mods.com/vehicles/freightliner-m2-crew-cab-flatbed-add-on-script-beta Config.lgc19flatbed = "lgc19flatbed" -- https://forum.cfx.re/t/2019-peterbilt-flatbed/4783413 Config.biftowmfd2 = "biftowmfd2" -- https://mfd.tebex.io/package/6281210 +Config.Gtow = "Gtow" -- https://www.gta5-mods.com/vehicles/peterbilt-337-tuning-by-mfd-fivem +Config.flatbedm2 = "flatbedm2" -- https://www.gta5-mods.com/vehicles/freightliner-m2-crew-cab-flatbed-add-on-script-beta +Config.lgc19flatbed = "lgc19flatbed" -- https://forum.cfx.re/t/2019-peterbilt-flatbed/4783413 +Config.biftowmfd2 = "biftowmfd2" -- https://mfd.tebex.io/package/6281210 Config.Gtow = "Gtow" Config.towy = "towy" Config.rollback1 = "rollback1" @@ -101,11 +105,6 @@ Config.gtrailer = "gtrailer" Config.dotgooseneck = "dotgooseneck" Config.firef350 = "firef350" Config.Terrain20tahoe = "Terrain20tahoe" - - - - - -- List any vehicle models here you do not want to be able to be towed Config.BlacklistedVehs = { diff --git a/resources/[ERS]/ebu_flatbeds_ers/server/server.lua b/resources/[ERS]/ebu_flatbeds_ers/server/server.lua index eeec6d14c..9c3557834 100644 Binary files a/resources/[ERS]/ebu_flatbeds_ers/server/server.lua and b/resources/[ERS]/ebu_flatbeds_ers/server/server.lua differ diff --git a/resources/[ERS]/night_ers/.fxap b/resources/[ERS]/night_ers/.fxap index 67747aac4..ba4447520 100644 Binary files a/resources/[ERS]/night_ers/.fxap and b/resources/[ERS]/night_ers/.fxap differ diff --git a/resources/[ERS]/night_ers/NUI/main.js b/resources/[ERS]/night_ers/NUI/main.js index 38438cfd6..ad40cddc2 100644 --- a/resources/[ERS]/night_ers/NUI/main.js +++ b/resources/[ERS]/night_ers/NUI/main.js @@ -1,49 +1,2812 @@ -let resourceName=null,language=null,commands=null,firstnames={},lastnames={},isDisplayingPreCalloutInterface=!1,isDisplayingCalloutInterface=!1,isDragMode=!1,isDragging=!1,dragElement=null,dragOffset={x:0,y:0},isLayoutMode=!1,layoutElements={},visibleLayoutElements=new Set,originalStyles=new Map,layoutBoundaries={left:20,top:20,right:20,bottom:20},snapGrid={enabled:!0,size:10},collisionDetection={enabled:!0},dimensionValidation={enabled:!0};window.addEventListener("message",e=>{let t=e.data;if("playSound"==t.transactionType&&PlayNUISound(t.transactionFolder,t.transactionFile,t.transactionVolume),"init"==t.type&&("undefined"!=typeof $?(resourceName=t.resourcename,language=t.language,commands=t.commands,firstnames=t.firstnames,lastnames=t.lastnames,$.post(`https://${resourceName}/initComplete`,JSON.stringify({complete:!0}))):console.log("Script is still loading...")),"togglecalloutinfo"==t.type&&toggleCalloutInfo(),"toggleUILayoutMode"==t.type&&(console.log("Received toggleUILayoutMode message from Lua"),toggleUILayoutMode()),"emergencyUICleanup"==t.type&&(console.log("Received emergencyUICleanup message from Lua"),emergencyUICleanup()),"ersselectionmenu"==t.type){var a,n,i,o=t.display;ToggleERSSelectionMenu(o,t.permissions)}if("radialmenu"==t.type){var o=t.display;ToggleRadialMenu(o)}if("pursuitradialmenu"==t.type){var o=t.display;TogglePursuitRadialMenu(o)}if("pursuitmode"==t.type){var s,l,o=t.display,r=t.displayhotkeyhint;TogglePursuitModeUI(o,r,t.zoomhotkey,t.backuphotkey)}if("dualsteeringmode"==t.type){var o=t.display;ToggleDualSteeringMode(o)}if("hotkeyhintprompt"==t.type){var o=t.display,c=t.hotkeys,d=t.time;ToggleHotKeyHintPrompt(o,c,language,d)}if("dispatchmessage"==t.type){var u,o=t.display,c=t.hotkeys,g=t.messagetype,p=t.calloutdata,b=t.message,d=t.time;AddMessageToDispatchQueue(o,c,g,p,d,b,t.toggle)}if("calloutprompt"==t.type){var m,o=t.display,p=t.calloutdata,c=t.hotkeys,d=t.time;ToggleCalloutDisplayPrompt(o,c,language,d,p,t.serviceType)}if("calloutpreinterface"==t.type){var o=t.display,c=t.hotkeys,p=t.calloutdata;TogglePreCalloutInterface(o,c,p)}if("calloutinterface"==t.type){var h,y,o=t.display,c=t.hotkeys,f=t.pedCount,v=t.vehicleCount,x=t.objectCount,w=t.propCount,k=t.fireCount,C=t.smokeCount,p=t.calloutdata,I=t.pedOriginalCount,T=t.vehOriginalCount,S=t.objOriginalCount,P=t.propOriginalCount;ToggleCalloutInterface(o,c,f,v,x,w,k,C,p,I,T,S,P,t.fireOriginalCount,t.smokeOriginalCount)}if("unifiedprompt"==t.type){var o=t.display,E=t.promptType,R=t.hotkey,b=t.message,d=t.time;DisplayUnifiedPrompt(o,E,R,b,d)}if("interactionmodule"==t.type){var N,A,o=t.display;DisplayPedInteractionModule(o,t.ispeddeadordying,t.service)}if("idcardprompt"==t.type){var M,_,o=t.display;DisplayPedIdCard(o,t.pedpersonaldata,t.showdatabasecheck)}if("inventoryprompt"==t.type){var q,o=t.display;DisplayPedInventory(o,t.itemlist)}if("vehicleinfoprompt"==t.type){var D,O,o=t.display;DisplayVehicleInfo(o,t.vehicleData,t.DisableTaxAndMOT)}if("togglequestionsmodule"==t.type){var L,o=t.display;ToggleQuestionsModule(o,t.questions)}if("updateanswers"==t.type){var B,o=t.display;UpdateAnswers(o,t.answers)}if("addorremovewaypoint"==t.type&&AddWaypoint(t.addwaypoint),"updatewaypoint"==t.type){var U,j,F,G=t.scaleX;UpdateWaypointPosition(G,t.scaleY,t.distanceText)}if("areyousure"==t.type){var o=t.display;DisplayAreYouSurePopup(o)}if("gearmenu"==t.type){var W,o=t.display;DisplayGearMenu(o,t.locationdata)}if("updatezonechange"==t.type){UpdateZoneChangeUI(t.lastZone,t.currentZone)}"updatewaypoints"===t.type&&updateWaypoints(t)});var unifiedPromptTimeout,idCardTimeout,dbCheckTimeout,vehicleInfoTimeout,vehicleDbCheckTimeout,inventoryTimeout,zoneChangeTimeout=null;let zoneChangeQueue=[],isAnimating=!1;function UpdateZoneChangeUI(e,t){zoneChangeQueue.push({oldZone:e,newZone:t}),isAnimating||processNextZoneChange()}function processNextZoneChange(){if(0===zoneChangeQueue.length){isAnimating=!1;return}isAnimating=!0;let{oldZone:e,newZone:t}=zoneChangeQueue.shift(),a=document.getElementById("zone-change-ui");if(!a){processNextZoneChange();return}let n=a.querySelector(".old-zone"),i=a.querySelector(".new-zone");if(!n||!i){processNextZoneChange();return}zoneChangeTimeout&&clearTimeout(zoneChangeTimeout),a.classList.remove("show"),i.classList.remove("show"),n.textContent=e||"N/A",i.textContent=t||"N/A",a.offsetWidth,a.classList.add("show"),i.classList.add("show"),zoneChangeTimeout=setTimeout(()=>{a.classList.remove("show"),i.classList.remove("show"),setTimeout(processNextZoneChange,500)},4e3)}let escapeEventListenerAdded=!1;function DisplayAreYouSurePopup(e){if(e){$("#are-you-sure-modal").remove();let t=` `;$("body").append(t),$("#are-you-sure-modal").modal({backdrop:"static",keyboard:!1}),$("#are-you-sure-modal").modal("show"),$("#are-you-sure-modal").on("shown.bs.modal",function(){escapeEventListenerAdded||($(document).on("keydown",function(e){"Escape"===e.key&&($("#are-you-sure-modal").modal("hide"),handleNoClick(),e.stopPropagation())}),escapeEventListenerAdded=!0)}).on("hidden.bs.modal",function(){$(document).off("keydown"),escapeEventListenerAdded=!1})}else $("#are-you-sure-modal").remove()}function handleNoClick(){$.post(`https://${resourceName}/AreYouSure`,JSON.stringify({areyousure:!1})),$("#are-you-sure-modal").modal("hide")}function handleYesClick(){$.post(`https://${resourceName}/AreYouSure`,JSON.stringify({areyousure:!0})),$("#are-you-sure-modal").modal("hide")}function DisplayPedInteractionModule(e,t,a){if(e){if(DisplayUnifiedPrompt(!1),t)$("#ped-interaction-module").empty(),$("#ped-interaction-module").show(),$("#ped-interaction-module").append(`

${language.InteractionOptions}

${[{id:"identify",label:language.IdentifyDeadPed,explanation:language.IdentifyDeadPedExplanation},{id:"drag",label:language.DragPed,explanation:language.DragPedExplanation},{id:"massivebleeding",label:language.CheckMassiveBleeding,explanation:language.CheckMassiveExplanation},{id:"airway",label:language.CheckAirway,explanation:language.CheckAirwayExplanation},{id:"breathing",label:language.CheckBreathing,explanation:language.CheckBreathingExplanation},{id:"circulation",label:language.CheckCirculation,explanation:language.CheckCirculationExplanation},{id:"hypothermia",label:language.CheckHypothermia,explanation:language.CheckHypothermiaExplanation},{id:"cpr",label:language.PerformCPR,explanation:language.PerformCPRExplanation},{id:"putonstretcher",label:language.PutOnStretcher,explanation:language.PutOnStretcherExplanation},{id:"takeoffstretcher",label:language.TakeOffStretcher,explanation:language.TakeOffStretcherExplanation},{id:"bodybag",label:language.PutInBodyBag,explanation:language.PutInBodyBagExplanation}].map(e=>`
${e.explanation}
`).join("")}

`),applySavedPosition("ped-interaction-module"),["identify","drag","massivebleeding","airway","breathing","circulation","hypothermia","cpr","putonstretcher","takeoffstretcher","bodybag","exit"].forEach(e=>addSoundOnHoverEventListener(`p-btn-${e}`));else{$("#ped-interaction-module").empty(),$("#ped-interaction-module").show();var n={police:[{id:"greet",label:language.Greet,explanation:language.GreetExplanation},{id:"id",label:language.AskForId,explanation:language.AskForIdExplanation},{id:"questioning",label:language.Question,explanation:language.QuestionExplanation},{id:"breathalyze",label:language.Breathalyze,explanation:language.BreathalyzeExplanation},{id:"drugtest",label:language.DrugTest,explanation:language.DrugTestExplanation},{id:"warn",label:language.Warn,explanation:language.WarnExplanation},{id:"fine",label:language.Fine,explanation:language.FineExplanation},{id:"grab",label:language.Grab,explanation:language.GrabExplanation},{id:"getout",label:language.GetOut,explanation:language.GetOutExplanation},{id:"follow",label:language.AskToFollow,explanation:language.AskToFollowExplanation},{id:"wait",label:language.AskToWait,explanation:language.AskToWaitExplanation},{id:"handsup",label:language.HandsUp,explanation:language.HandsUpExplanation},{id:"search",label:language.Search,explanation:language.SearchExplanation},{id:"cuff",label:language.Cuff,explanation:language.CuffExplanation},{id:"putinvehicle",label:language.PutInVehicle,explanation:language.PutInVehicleExplanation}],ambulance:[{id:"greet",label:language.Greet,explanation:language.GreetExplanation},{id:"questioning",label:language.Question,explanation:language.QuestionExplanation},{id:"breathalyze",label:language.Breathalyze,explanation:language.BreathalyzeExplanation},{id:"drugtest",label:language.DrugTest,explanation:language.DrugTestExplanation},{id:"getout",label:language.GetOut,explanation:language.GetOutExplanation},{id:"follow",label:language.AskToFollow,explanation:language.AskToFollowExplanation},{id:"wait",label:language.AskToWait,explanation:language.AskToWaitExplanation},{id:"putinvehicle",label:language.PutInVehicle,explanation:language.PutInVehicleExplanation}],fire:[{id:"greet",label:language.Greet,explanation:language.GreetExplanation},{id:"questioning",label:language.Question,explanation:language.QuestionExplanation},{id:"breathalyze",label:language.Breathalyze,explanation:language.BreathalyzeExplanation},{id:"drugtest",label:language.DrugTest,explanation:language.DrugTestExplanation},{id:"getout",label:language.GetOut,explanation:language.GetOutExplanation},{id:"follow",label:language.AskToFollow,explanation:language.AskToFollowExplanation},{id:"wait",label:language.AskToWait,explanation:language.AskToWaitExplanation},{id:"putinvehicle",label:language.PutInVehicle,explanation:language.PutInVehicleExplanation}],tow:[{id:"greet",label:language.Greet,explanation:language.GreetExplanation},{id:"questioning",label:language.Question,explanation:language.QuestionExplanation},{id:"getout",label:language.GetOut,explanation:language.GetOutExplanation},{id:"follow",label:language.AskToFollow,explanation:language.AskToFollowExplanation},{id:"wait",label:language.AskToWait,explanation:language.AskToWaitExplanation},{id:"putinvehicle",label:language.PutInVehicle,explanation:language.PutInVehicleExplanation}]};$("#ped-interaction-module").append(`

${language.InteractionOptions}

${(n[a]||n.police).map(e=>`
${e.explanation}
`).join("")}

${"police"===a?``:""}
`);let i=n[a]||n.police,o=[...i.map(e=>e.id),"end","exit",..."police"===a?["custody"]:[]];o.forEach(e=>addSoundOnHoverEventListener(`p-btn-${e}`)),applySavedPosition("ped-interaction-module")}}else $("#ped-interaction-module").hide()}function PedInteraction(e){$.post(`https://${resourceName}/pedInteraction`,JSON.stringify({interactionType:e}))}function addSoundOnHoverEventListener(e){document.getElementById(e).addEventListener("mouseenter",function(){PlayNUISound("generic-sounds","rollover",.5)})}function DisplayUnifiedPrompt(e,t,a,n,i){if(e){$("#unified-prompt").show(),applySavedPosition("unified-prompt"),clearTimeout(unifiedPromptTimeout);let o={pedinteraction:{icon:"\uD83D\uDCAC",color:"text-warning",text:language.ToInteract,timeout:1500},injuredped:{icon:"\uD83E\uDE7A",color:"text-danger",text:language.ToPerformCPR,timeout:1500},impound:{icon:"\uD83D\uDE97",color:"text-danger",text:language.ToInteractImpound,timeout:1500},gear:{icon:"\uD83D\uDE97",color:"text-danger",text:language.ToInteractGear,timeout:1500},stretcher:{icon:"\uD83C\uDFE5",color:"text-info",text:language.ToUseStretcherVeh,timeout:1500},objectcleanup:{icon:"\uD83E\uDDF9",color:"text-success",text:language.ToCleanupObject,timeout:1500},spikesvehicle:{icon:"\uD83D\uDCA2",color:"text-warning",text:n||"",timeout:i||1500}},s=o[t]||o.pedinteraction;$("#unified-prompt").html(` -
${s.icon} ${language.Press} ${a} ${s.text}
- `),unifiedPromptTimeout=setTimeout(function(){$("#unified-prompt").hide()},s.timeout)}else $("#unified-prompt").hide()}function DisplayPedIdCard(e,t,a){if(e){$("#vehicle-info").hide(),$("#ped-interaction-inventory").hide(),clearTimeout(idCardTimeout),clearTimeout(dbCheckTimeout),$("#ped-interaction-id-card").empty();var n=t.ProfilePicture||"N/A",i=t.FirstName||"N/A",o=t.LastName||"N/A",s=t.DOB||"N/A",l=t.Gender||"N/A",r=t.Email||"N/A",c=t.PhoneNumber||"N/A",d=t.Country||"N/A",u=t.State||"N/A",g=t.City||"N/A",p=t.PostalCode||"N/A",b=t.Address||"N/A";t.AddressType;var m=t.Nationality||"N/A",h=t.FlagsOrMarkers,y=t.License_Car||"N/A",f=t.License_Car_Colour||"text-light",v=t.License_Car_Icon||"fas fa-car",x=t.License_Bike||"N/A",w=t.License_Bike_Colour||"text-light",k=t.License_Bike_Icon||"fas fa-bicycle",C=t.License_Boat||"N/A",I=t.License_Boat_Colour||"text-light",T=t.License_Boat_Icon||"fas fa-ship",S=t.License_Truck||"N/A",P=t.License_Truck_Colour||"text-light",E=t.License_Truck_Icon||"fas fa-truck",R=t.License_Pilot||"N/A",N=t.License_Pilot_Colour||"text-light",A=t.License_Pilot_Icon||"fas fa-plane";$("#ped-interaction-id-card").append(`
${language.PersonalDetails}
`),$("#ped-interaction-id-card").show(),applySavedPosition("ped-interaction-id-card"),a&&($("#ped-interaction-id-card").append(`
${language.DatabaseCheck}
Loading...

${language.RunningDatabaseCheck}

`),dbCheckTimeout=setTimeout(function(){$("#initial-check").remove(),$("#database-check").html(`
${language.DatabaseCheckResults}
${i} ${o}
Photo
(${s})
  • ${language.Nationality} ${m}
  • ${language.Gender} ${l}
  • ${language.Address} ${b}, ${g}, ${u} ${p} (${d})
  • ${language.Email} ${r} | ${language.PhoneNumber} ${c}
${language.Licenses}
${y} ${x} ${C} ${S} ${R}
${h&&Object.keys(h).some(e=>h[e])?`
${language.FlagsOrMarkers}

${h.armed_and_dangerous?` ${language.armed_and_dangerous}
`:""} ${h.assault?` ${language.assault}
`:""} ${h.burglary?` ${language.burglary}
`:""} ${h.drug_related?` ${language.drug_related}
`:""} ${h.gang_affiliation?` ${language.gang_affiliation}
`:""} ${h.homicide?` ${language.homicide}
`:""} ${h.kidnapping?` ${language.kidnapping}
`:""} ${h.mental_health_issues?` ${language.mental_health_issues}
`:""} ${h.sex_offense?` ${language.sex_offense}
`:""} ${h.terrorism?` ${language.terrorism}
`:""} ${h.theft?` ${language.theft}
`:""} ${h.traffic_violation?` ${language.traffic_violation}
`:""} ${h.wanted_person?` ${language.wanted_person}
`:""} ${h.other?` ${language.other}
`:""} ${h.active_warrant?` ${language.active_warrant}
`:""}

`:""}
`)},3e3)),idCardTimeout=setTimeout(function(){$("#ped-interaction-id-card").hide()},15e3)}else $("#ped-interaction-id-card").hide()}function DisplayVehicleInfo(e,t,a){if(e){$("#ped-interaction-id-card").hide(),$("#ped-interaction-inventory").hide(),clearTimeout(vehicleInfoTimeout),clearTimeout(vehicleDbCheckTimeout),$("#vehicle-info").empty();var n={vehNetId:t.vehNetId,license_plate:t.license_plate,model:t.model,model_hash:t.model_hash,vehicle_class:t.vehicle_class,vehicle_class_from_name:t.vehicle_class_from_name,color:t.color,color_secondary:t.color_secondary,build_year:t.build_year,tax:t.tax,mot:t.mot,insurance:t.insurance,stolen:t.stolen,bolo:t.bolo,bolo_description:t.bolo_description,owner_name:t.owner_name};$("#vehicle-info").append(`
${language.VehicleDetails}
`),$("#vehicle-info").append(`
${language.DatabaseCheck}
Loading...

${language.RunningDatabaseCheck}

`),$("#vehicle-info").show(),applySavedPosition("vehicle-info"),vehicleDbCheckTimeout=setTimeout(function(){$("#vehicle-info-database-check").html(`
${language.DatabaseCheckResults}
`)},5e3),vehicleInfoTimeout=setTimeout(function(){$("#vehicle-info").hide()},15e3)}else $("#vehicle-info").hide()}function DisplayPedInventory(e,t){e?($("#ped-interaction-id-card").hide(),$("#vehicle-info").hide(),clearTimeout(inventoryTimeout),$("#ped-interaction-inventory").empty(),$("#ped-interaction-inventory").append(`

${language.Inventory}

`),$.each(t,function(e,t){var a,n=` ${t.name} `;$("#inventory-table-body").append(n)}),$("#ped-interaction-inventory").show(),applySavedPosition("ped-interaction-inventory"),inventoryTimeout=setTimeout(function(){$("#ped-interaction-inventory").hide()},15e3)):$("#ped-interaction-inventory").hide()}var listener=!1;function setupButton(e,t,a){let n=document.getElementById(e);$(`#${e}`).html(``),n.addEventListener("mouseenter",()=>PlayNUISound("generic-sounds","rollover",.5)),n.addEventListener("mouseover",()=>{document.getElementById("instruction-text").style.display="block",$("#instruction-text").html(`

${a}

`)}),n.addEventListener("mouseout",()=>document.getElementById("instruction-text").style.display="none")}function setupRadialMenu(){if(!listener){listener=!0;let e=[{id:"middle-x",iconClass:"",instruction:language.ExitRadialMenuInstruction,hoverColour:"",function:"ToggleRadialMenu(false)"},{id:"police-transport",iconClass:language.RequestPoliceTransportIcon,instruction:language.RequestPoliceTransportInstruction,hoverColour:"#0057b9",function:"RequestOrCancelPoliceTransport()"},{id:"ambulance-request",iconClass:language.RequestAmbulanceIcon,instruction:language.RequestAmbulanceInstruction,hoverColour:"#ff0000",function:"RequestOrCancelAmbulance()"},{id:"tow-request",iconClass:language.RequestTowIcon,instruction:language.RequestTowInstruction,hoverColour:"#782323",function:"RequestOrCancelTow()"},{id:"taxi-request",iconClass:language.RequestTaxiIcon,instruction:language.RequestTaxiInstruction,hoverColour:"#FF9A18",function:"RequestOrCancelTaxi()"},{id:"road-service-request",iconClass:language.RequestRoadServiceIcon,instruction:language.RequestRoadServiceInstruction,hoverColour:"#ffbf00",function:"RequestOrCancelRoadService()"},{id:"coroner-request",iconClass:language.RequestCoronerIcon,instruction:language.RequestCoronerInstruction,hoverColour:"#3D3D3D",function:"RequestOrCancelCoroner()"},{id:"animal-rescue-request",iconClass:language.RequestAnimalRescueIcon,instruction:language.RequestAnimalRescueInstruction,hoverColour:"#9bde00",function:"RequestOrCancelAnimalRescue()"},{id:"mechanic-request",iconClass:language.RequestMechanicIcon,instruction:language.RequestMechanicInstruction,hoverColour:"#3D3D3D",function:"RequestOrCancelMechanic()"},{id:"fire-request",iconClass:language.RequestFireIcon,instruction:language.RequestFireInstruction,hoverColour:"#3D3D3D",function:"RequestOrCancelFire()"}];$("#circle-menu").html(` -
+// Global values +let resourceName = null; +let language = null; +let commands = null; +let firstnames = {}; +let lastnames = {}; + +let isDisplayingPreCalloutInterface = false; +let isDisplayingCalloutInterface = false; + +// Drag functionality variables +let isDragMode = false; +let isDragging = false; +let dragElement = null; +let dragOffset = { x: 0, y: 0 }; + +// UI Layout Mode variables +let isLayoutMode = false; +let layoutElements = {}; +let visibleLayoutElements = new Set(); + +// Enhanced layout system variables +let originalStyles = new Map(); // Store original styles before layout mode +let layoutBoundaries = { left: 20, top: 20, right: 20, bottom: 20 }; // Screen boundaries +let snapGrid = { enabled: true, size: 10 }; // Grid snapping +let collisionDetection = { enabled: true }; // Element collision detection +let dimensionValidation = { enabled: true }; // Validate element dimensions for real vs placeholder content + +window.addEventListener('message', (event) => { + const data = event.data; + + if (data.transactionType == "playSound") { + PlayNUISound(data.transactionFolder, data.transactionFile, data.transactionVolume) + } + + if (data.type == "init") { + if (typeof $ !== 'undefined') { + resourceName = data.resourcename + language = data.language + commands = data.commands + firstnames = data.firstnames + lastnames = data.lastnames + + $.post(`https://${resourceName}/initComplete`, JSON.stringify({ + complete: true + })); + } else { + console.log("Script is still loading...") + }; + } + + if (data.type == "togglecalloutinfo") { + toggleCalloutInfo(); + } + + if (data.type == "toggleUILayoutMode") { + console.log("Received toggleUILayoutMode message from Lua"); + toggleUILayoutMode(); + } + + if (data.type == "emergencyUICleanup") { + console.log("Received emergencyUICleanup message from Lua"); + clearModuleData(); + emergencyUICleanup(); + } + + if (data.type == "clearInformationModulesOnShiftEnd") { + clearModuleData(); + } + + if (data.type == "ersselectionmenu") { + var display = data.display + var permissions = data.permissions + ToggleERSSelectionMenu(display, permissions) + } + + if (data.type == "radialmenu") { + var display = data.display + ToggleRadialMenu(display) + } + + if (data.type == "pursuitradialmenu") { + var display = data.display + TogglePursuitRadialMenu(display) + } + + if (data.type == "pursuitmode") { + var display = data.display + var displayhotkeyhint = data.displayhotkeyhint + var zoomhotkey = data.zoomhotkey + var backuphotkey = data.backuphotkey + TogglePursuitModeUI(display, displayhotkeyhint, zoomhotkey, backuphotkey) + } + + if (data.type == "dualsteeringmode") { + var display = data.display + ToggleDualSteeringMode(display) + } + + if (data.type == "hotkeyhintprompt") { + var display = data.display + var hotkeys = data.hotkeys + var time = data.time + ToggleHotKeyHintPrompt(display, hotkeys, language, time) + } + + if (data.type == "dispatchmessage") { + var display = data.display + var hotkeys = data.hotkeys + var messagetype = data.messagetype + var calloutdata = data.calloutdata + var message = data.message + var time = data.time + var toggle = data.toggle + AddMessageToDispatchQueue(display, hotkeys, messagetype, calloutdata, time, message, toggle) + } + + if (data.type == "calloutprompt") { + var display = data.display + var calloutdata = data.calloutdata + var hotkeys = data.hotkeys + var time = data.time + var serviceType = data.serviceType + ToggleCalloutDisplayPrompt(display, hotkeys, language, time, calloutdata, serviceType) + } + + if (data.type == "calloutpreinterface") { + var display = data.display + var hotkeys = data.hotkeys + var calloutdata = data.calloutdata + TogglePreCalloutInterface(display, hotkeys, calloutdata) + } + + if (data.type == "calloutinterface") { + var display = data.display + var hotkeys = data.hotkeys + var pedCount = data.pedCount + var vehicleCount = data.vehicleCount + var objectCount = data.objectCount + var propCount = data.propCount + var fireCount = data.fireCount + var smokeCount = data.smokeCount + + var calloutdata = data.calloutdata + + var pedOriginalCount = data.pedOriginalCount + var vehOriginalCount = data.vehOriginalCount + var objOriginalCount = data.objOriginalCount + var propOriginalCount = data.propOriginalCount + var fireOriginalCount = data.fireOriginalCount + var smokeOriginalCount = data.smokeOriginalCount + + ToggleCalloutInterface(display, hotkeys,pedCount, vehicleCount, objectCount, propCount, fireCount, smokeCount, calloutdata, pedOriginalCount, vehOriginalCount, objOriginalCount, propOriginalCount, fireOriginalCount, smokeOriginalCount) + } + + if (data.type == "unifiedprompt") { + var display = data.display + var promptType = data.promptType + var hotkey = data.hotkey + var message = data.message + var time = data.time + DisplayUnifiedPrompt(display, promptType, hotkey, message, time) + } + + if (data.type == "interactionmodule") { + var display = data.display + var isDead = data.ispeddeadordying + var service = data.service + DisplayPedInteractionModule(display, isDead, service) + } + + if (data.type == "idcardprompt") { + var display = data.display + var personaldata = data.pedpersonaldata + var showdatabasecheck = data.showdatabasecheck + DisplayPedIdCard(display, personaldata, showdatabasecheck) + } + + if (data.type == "inventoryprompt") { + var display = data.display + var itemList = data.itemlist + DisplayPedInventory(display, itemList) + } + + if(data.type == "vehicleinfoprompt") { + var display = data.display + var vehicleData = data.vehicleData + var DisableTaxAndMOT = data.DisableTaxAndMOT + DisplayVehicleInfo(display, vehicleData, DisableTaxAndMOT) + } + + if (data.type == "redisplaylastmodule") { + redisplayLastModule() + } + + if (data.type == "togglequestionsmodule") { + var display = data.display + var questions = data.questions + ToggleQuestionsModule(display, questions) + } + + if (data.type == "updateanswers") { + var display = data.display + var answers = data.answers + UpdateAnswers(display, answers) + } + + if (data.type == "addorremovewaypoint") { + var addOrRemove = data.addwaypoint + AddWaypoint(addOrRemove); + } + + if (data.type == "updatewaypoint") { + var scaleX = data.scaleX + var scaleY = data.scaleY + var distanceText = data.distanceText + UpdateWaypointPosition(scaleX, scaleY, distanceText); + } + + if (data.type == "areyousure") { + var display = data.display + DisplayAreYouSurePopup(display) + } + + if (data.type == "gearmenu") { + var display = data.display + var locationData = data.locationdata + DisplayGearMenu(display, locationData) + } + + if (data.type == "updatezonechange") { + var lastZone = data.lastZone + var currentZone = data.currentZone + UpdateZoneChangeUI(lastZone, currentZone) + } + + if (data.type === 'updatewaypoints') { + updateWaypoints(data); + } +}); + +// FUNCTIONS + +var zoneChangeTimeout = null; +let zoneChangeQueue = []; +let isAnimating = false; + +function UpdateZoneChangeUI(oldZone, newZone) { + zoneChangeQueue.push({ oldZone, newZone }); + if (!isAnimating) { + processNextZoneChange(); + } +} + +function processNextZoneChange() { + if (zoneChangeQueue.length === 0) { + isAnimating = false; + return; + } + + isAnimating = true; + const { oldZone, newZone } = zoneChangeQueue.shift(); + + const zoneChangeUI = document.getElementById('zone-change-ui'); + if (!zoneChangeUI) { + processNextZoneChange(); + return; + } + + const oldZoneElement = zoneChangeUI.querySelector('.old-zone'); + const newZoneElement = zoneChangeUI.querySelector('.new-zone'); + + if (!oldZoneElement || !newZoneElement) { + processNextZoneChange(); + return; + } + + // Clear any existing timeout + if (zoneChangeTimeout) { + clearTimeout(zoneChangeTimeout); + } + + // Reset the animation state + zoneChangeUI.classList.remove('show'); + newZoneElement.classList.remove('show'); + + // Set the new zone values + oldZoneElement.textContent = oldZone ? oldZone : "N/A"; + newZoneElement.textContent = newZone ? newZone : "N/A"; + + // Trigger reflow to ensure the animation restarts + void zoneChangeUI.offsetWidth; + + // Start the new animation + zoneChangeUI.classList.add('show'); + newZoneElement.classList.add('show'); + + // Set a new timeout + zoneChangeTimeout = setTimeout(() => { + zoneChangeUI.classList.remove('show'); + newZoneElement.classList.remove('show'); + + // Process the next zone change after the animation is complete + setTimeout(processNextZoneChange, 500); // Add a small delay between animations + }, 4000); +} + +let escapeEventListenerAdded = false; + +function DisplayAreYouSurePopup(display) { + if (display) { + // Remove any previous modals + $('#are-you-sure-modal').remove(); + + // HTML + const modal = ` + + `; + + $('body').append(modal); + + // Initialize the modal with static backdrop and disabled keyboard interaction + $('#are-you-sure-modal').modal({ + backdrop: 'static', + keyboard: false + }); + + // Show the modal explicitly + $('#are-you-sure-modal').modal('show'); + + // Handle Escape key press only when the modal is open + $('#are-you-sure-modal').on('shown.bs.modal', function() { + if (!escapeEventListenerAdded) { + $(document).on('keydown', function(event) { + if (event.key === "Escape") { + // Close the modal + $('#are-you-sure-modal').modal('hide'); + // Trigger the same action as the "No" button click + handleNoClick(); + // Ensure the event doesn't propagate further + event.stopPropagation(); + } + }); + escapeEventListenerAdded = true; + } + }).on('hidden.bs.modal', function() { + // Remove the Escape key press event listener when the modal is closed + $(document).off('keydown'); + escapeEventListenerAdded = false; + }); + + } else { + $('#are-you-sure-modal').remove(); + } +} + + +// Function to handle 'No' button click +function handleNoClick() { + $.post(`https://${resourceName}/AreYouSure`, JSON.stringify({ + areyousure: false + })); + $('#are-you-sure-modal').modal('hide'); +} + +// Function to handle 'Yes' button click +function handleYesClick() { + $.post(`https://${resourceName}/AreYouSure`, JSON.stringify({ + areyousure: true + })); + $('#are-you-sure-modal').modal('hide'); +} + +function DisplayPedInteractionModule(display, isDead, service) { // service can be: police, fire, ambulance or tow. + if (display) { + DisplayUnifiedPrompt(false) + if (isDead) { + $("#ped-interaction-module").empty(); + $("#ped-interaction-module").show(); + + //HTML + $("#ped-interaction-module").append(` +

${language.InteractionOptions}

+
+
+ +
+ ${[ + { id: 'identify', label: language.IdentifyDeadPed, explanation: language.IdentifyDeadPedExplanation }, + { id: 'drag', label: language.DragPed, explanation: language.DragPedExplanation }, + { id: 'massivebleeding', label: language.CheckMassiveBleeding, explanation: language.CheckMassiveExplanation }, + { id: 'airway', label: language.CheckAirway, explanation: language.CheckAirwayExplanation }, + { id: 'breathing', label: language.CheckBreathing, explanation: language.CheckBreathingExplanation }, + { id: 'circulation', label: language.CheckCirculation, explanation: language.CheckCirculationExplanation }, + { id: 'hypothermia', label: language.CheckHypothermia, explanation: language.CheckHypothermiaExplanation }, + { id: 'cpr', label: language.PerformCPR, explanation: language.PerformCPRExplanation }, + { id: 'putonstretcher', label: language.PutOnStretcher, explanation: language.PutOnStretcherExplanation }, + { id: 'takeoffstretcher', label: language.TakeOffStretcher, explanation: language.TakeOffStretcherExplanation }, + { id: 'bodybag', label: language.PutInBodyBag, explanation: language.PutInBodyBagExplanation } + ].map(item => ` +
+
+ +
+
+ ${item.explanation} +
+
+ `).join('')} +
+
+ +
+ +
+
+ +
+
+
+ `); + + // Apply sound effects to all buttons + const buttonIds = [ + 'identify', 'drag', 'massivebleeding', 'airway', 'breathing', 'circulation', 'hypothermia', 'cpr', 'putonstretcher', 'takeoffstretcher', 'bodybag', + 'exit' + ]; + buttonIds.forEach(id => addSoundOnHoverEventListener(`p-btn-${id}`)); + + } else { + $("#ped-interaction-module").empty(); + $("#ped-interaction-module").show(); + + // Per service we need to show different buttons. + var buttonsPerService = { + police: [ + { id: 'greet', label: language.Greet, explanation: language.GreetExplanation }, + { id: 'id', label: language.AskForId, explanation: language.AskForIdExplanation }, + { id: 'questioning', label: language.Question, explanation: language.QuestionExplanation }, + { id: 'breathalyze', label: language.Breathalyze, explanation: language.BreathalyzeExplanation }, + { id: 'drugtest', label: language.DrugTest, explanation: language.DrugTestExplanation }, + { id: 'warn', label: language.Warn, explanation: language.WarnExplanation }, + { id: 'fine', label: language.Fine, explanation: language.FineExplanation }, + { id: 'grab', label: language.Grab, explanation: language.GrabExplanation }, + { id: 'getout', label: language.GetOut, explanation: language.GetOutExplanation }, + { id: 'follow', label: language.AskToFollow, explanation: language.AskToFollowExplanation }, + { id: 'wait', label: language.AskToWait, explanation: language.AskToWaitExplanation }, + { id: 'handsup', label: language.HandsUp, explanation: language.HandsUpExplanation }, + { id: 'search', label: language.Search, explanation: language.SearchExplanation }, + { id: 'cuff', label: language.Cuff, explanation: language.CuffExplanation }, + { id: 'putinvehicle', label: language.PutInVehicle, explanation: language.PutInVehicleExplanation } + ], + ambulance: [ + { id: 'greet', label: language.Greet, explanation: language.GreetExplanation }, + { id: 'questioning', label: language.Question, explanation: language.QuestionExplanation }, + { id: 'breathalyze', label: language.Breathalyze, explanation: language.BreathalyzeExplanation }, + { id: 'drugtest', label: language.DrugTest, explanation: language.DrugTestExplanation }, + { id: 'getout', label: language.GetOut, explanation: language.GetOutExplanation }, + { id: 'follow', label: language.AskToFollow, explanation: language.AskToFollowExplanation }, + { id: 'wait', label: language.AskToWait, explanation: language.AskToWaitExplanation }, + { id: 'putinvehicle', label: language.PutInVehicle, explanation: language.PutInVehicleExplanation } + ], + fire: [ + { id: 'greet', label: language.Greet, explanation: language.GreetExplanation }, + { id: 'questioning', label: language.Question, explanation: language.QuestionExplanation }, + { id: 'breathalyze', label: language.Breathalyze, explanation: language.BreathalyzeExplanation }, + { id: 'drugtest', label: language.DrugTest, explanation: language.DrugTestExplanation }, + { id: 'getout', label: language.GetOut, explanation: language.GetOutExplanation }, + { id: 'follow', label: language.AskToFollow, explanation: language.AskToFollowExplanation }, + { id: 'wait', label: language.AskToWait, explanation: language.AskToWaitExplanation }, + { id: 'putinvehicle', label: language.PutInVehicle, explanation: language.PutInVehicleExplanation } + ], + tow: [ + { id: 'greet', label: language.Greet, explanation: language.GreetExplanation }, + { id: 'questioning', label: language.Question, explanation: language.QuestionExplanation }, + { id: 'getout', label: language.GetOut, explanation: language.GetOutExplanation }, + { id: 'follow', label: language.AskToFollow, explanation: language.AskToFollowExplanation }, + { id: 'wait', label: language.AskToWait, explanation: language.AskToWaitExplanation }, + { id: 'putinvehicle', label: language.PutInVehicle, explanation: language.PutInVehicleExplanation } + ] + } + + // HTML + $("#ped-interaction-module").append(` +

${language.InteractionOptions}

+
+
+ +
+ ${(buttonsPerService[service] || buttonsPerService.police).map(item => ` +
+
+ +
+
+ ${item.explanation} +
+
+ `).join('')} +
+
+ +
+ +
+
+ + + ${service === 'police' ? `` : ''} +
+
+
+ `); + + // Apply sound on hover to all buttons + const serviceButtons = buttonsPerService[service] || buttonsPerService.police; + const buttonIds = [ + ...serviceButtons.map(item => item.id), + 'end', 'exit', + ...(service === 'police' ? ['custody'] : []) + ]; + buttonIds.forEach(id => addSoundOnHoverEventListener(`p-btn-${id}`)); + } + } else { + $("#ped-interaction-module").hide(); + } +} + +function PedInteraction(intType) { + $.post(`https://${resourceName}/pedInteraction`, JSON.stringify({ + interactionType: intType + })) +} + +function addSoundOnHoverEventListener(buttonId) { + var button = document.getElementById(buttonId); + button.addEventListener('mouseenter', function() { + PlayNUISound('generic-sounds', "rollover", 0.5); + }); +} + +var unifiedPromptTimeout; + +function DisplayUnifiedPrompt(display, promptType, hotkey, message, time) { + if (display) { + $("#unified-prompt").show(); + + clearTimeout(unifiedPromptTimeout); + + // Define prompt configurations + const promptConfigs = { + 'pedinteraction': { + icon: '๐Ÿ’ฌ', + color: 'text-warning', + text: language.ToInteract, + timeout: 1500 + }, + 'injuredped': { + icon: '๐Ÿฉบ', + color: 'text-danger', + text: language.ToPerformCPR, + timeout: 1500 + }, + 'impound': { + icon: '๐Ÿš—', + color: 'text-danger', + text: language.ToInteractImpound, + timeout: 1500 + }, + 'gear': { + icon: '๐Ÿš—', + color: 'text-danger', + text: language.ToInteractGear, + timeout: 1500 + }, + 'stretcher': { + icon: '๐Ÿฅ', + color: 'text-info', + text: language.ToUseStretcherVeh, + timeout: 1500 + }, + 'objectcleanup': { + icon: '๐Ÿงน', + color: 'text-success', + text: language.ToCleanupObject, + timeout: 1500 + }, + 'spikesvehicle': { + icon: '๐Ÿ’ข', + color: 'text-warning', + text: message || '', + timeout: time || 1500 + } + }; + + const config = promptConfigs[promptType] || promptConfigs['pedinteraction']; + + $("#unified-prompt").html(` +
${config.icon} ${language.Press} ${hotkey} ${config.text}
+ `); + + unifiedPromptTimeout = setTimeout(function() { + $("#unified-prompt").hide(); + }, config.timeout); + + } else { + $("#unified-prompt").hide(); + } +} + +// Track last displayed module for TAB key re-display +var lastDisplayedModule = null; // 'idcard', 'vehicle', or 'inventory' +var lastIdCardData = null; +var lastVehicleData = null; +var lastInventoryData = null; + +// Track database check completion states for each module +var idCardDbCheckCompleted = false; +var vehicleDbCheckCompleted = false; + +var idCardTimeout; +var vehicleInfoTimeout; +var dbCheckTimeout; +var vehicleDbCheckTimeout; +var moduleClearTimeout; // Timeout to clear module data if hidden for > 1 minute +var moduleProgressInterval; // Interval to update progress bar +var moduleClearStartTime; // Timestamp when module clear timer started + +function DisplayPedIdCard(display, personaldata, showdatabasecheck, skipDbCheckAnimation) { + if (display) { + // Hide vehicle info. + $("#vehicle-info").hide(); + // Hide inventory + $("#ped-interaction-inventory").hide(); + + clearTimeout(idCardTimeout); + + // Only clear dbCheckTimeout if we're not preserving state + if (!skipDbCheckAnimation) { + clearTimeout(dbCheckTimeout); + idCardDbCheckCompleted = false; + } + + $("#ped-interaction-id-card").empty(); + + var profilePicture = personaldata.ProfilePicture || 'N/A'; + var firstName = personaldata.FirstName || 'N/A'; + var lastName = personaldata.LastName || 'N/A'; + var dob = personaldata.DOB || 'N/A'; + var gender = personaldata.Gender || 'N/A'; + var email = personaldata.Email || 'N/A'; + var phone = personaldata.PhoneNumber || 'N/A'; + var country = personaldata.Country || 'N/A'; + var state = personaldata.State || 'N/A'; + var city = personaldata.City || 'N/A'; + var postalcode = personaldata.PostalCode || 'N/A'; + var address = personaldata.Address || 'N/A'; + var addressType = personaldata.AddressType || 'N/A'; + var nationality = personaldata.Nationality || 'N/A'; + var flagsOrMarkers = personaldata.FlagsOrMarkers // This is a list of keys which are true or false, I want each one to be displayed.... + var driversLicense = personaldata.License_Car || 'N/A'; + var driversLicenseColour = personaldata.License_Car_Colour || 'text-light'; + var driversLicenseIcon = personaldata.License_Car_Icon || 'fas fa-car'; + var bikeLicense = personaldata.License_Bike || 'N/A'; + var bikeLicenseColour = personaldata.License_Bike_Colour || 'text-light'; + var bikeLicenseIcon = personaldata.License_Bike_Icon || 'fas fa-bicycle'; + var boatLicense = personaldata.License_Boat || 'N/A'; + var boatLicenseColour = personaldata.License_Boat_Colour || 'text-light'; + var boatLicenseIcon = personaldata.License_Boat_Icon || 'fas fa-ship'; + var truckLicense = personaldata.License_Truck || 'N/A'; + var truckLicenseColour = personaldata.License_Truck_Colour || 'text-light'; + var truckLicenseIcon = personaldata.License_Truck_Icon || 'fas fa-truck'; + var pilotLicense = personaldata.License_Pilot || 'N/A'; + var pilotLicenseColour = personaldata.License_Pilot_Colour || 'text-light'; + var pilotLicenseIcon = personaldata.License_Pilot_Icon || 'fas fa-plane'; + + // Store data for TAB key re-display + lastDisplayedModule = 'idcard'; + lastIdCardData = { + personaldata: personaldata, + showdatabasecheck: showdatabasecheck + }; + + // Modern Bootstrap 5.2.3 Card Design + // DON'T use isolation: isolate - it causes text blurriness + $("#ped-interaction-id-card").append(` +
+
+
+ +
${language.PersonalDetails}
+
+
+
+
+ ${language.FullName} + ${firstName} ${lastName} +
+
+ ${language.DOB} + ${dob} +
+
+
+ `); + + $("#ped-interaction-id-card").show(); + + if (showdatabasecheck) { + // Always create the database-check container first + // DON'T use isolation: isolate on the card itself - it causes text blurriness + $("#ped-interaction-id-card").append(` +
+
+ `); + + // Check if database check was already completed + if (idCardDbCheckCompleted && skipDbCheckAnimation) { + // Show completed results immediately + renderIdCardDatabaseResults(personaldata, firstName, lastName, dob, profilePicture, nationality, gender, address, city, state, postalcode, country, email, phone, driversLicense, driversLicenseColour, bikeLicense, bikeLicenseColour, boatLicense, boatLicenseColour, truckLicense, truckLicenseColour, pilotLicense, pilotLicenseColour, flagsOrMarkers); + } else { + // Show loading spinner + $("#database-check").html(` +
+
+ +
${language.DatabaseCheck}
+
+
+
+
+ +
+

${language.RunningDatabaseCheck}

+
+
+
+
+ `); + + // Delay before results & Display results + dbCheckTimeout = setTimeout(function() { + idCardDbCheckCompleted = true; + $("#initial-check").remove(); + renderIdCardDatabaseResults(personaldata, firstName, lastName, dob, profilePicture, nationality, gender, address, city, state, postalcode, country, email, phone, driversLicense, driversLicenseColour, bikeLicense, bikeLicenseColour, boatLicense, boatLicenseColour, truckLicense, truckLicenseColour, pilotLicense, pilotLicenseColour, flagsOrMarkers); + }, 3000); + } + } + + // Hide the ID card after a certain period + idCardTimeout = setTimeout(function() { + $("#ped-interaction-id-card").hide(); + updateModuleIndicator(); + scheduleModuleClearIfHidden(); + }, 15000); + + updateModuleIndicator(); + + } else { + $("#ped-interaction-id-card").hide(); + updateModuleIndicator(); + } +} + +// Separate function to render ID card database results +function renderIdCardDatabaseResults(personaldata, firstName, lastName, dob, profilePicture, nationality, gender, address, city, state, postalcode, country, email, phone, driversLicense, driversLicenseColour, bikeLicense, bikeLicenseColour, boatLicense, boatLicenseColour, truckLicense, truckLicenseColour, pilotLicense, pilotLicenseColour, flagsOrMarkers) { + // Completely clear and replace content to reset rendering context + var dbCheckElement = document.getElementById('database-check'); + if (dbCheckElement) { + // Remove all content including loading indicator + dbCheckElement.innerHTML = ''; + // Force a reflow to clear any rendering contexts + void dbCheckElement.offsetHeight; + } + + $("#database-check").html(` +
+
+ +
${language.DatabaseCheckResults}
+
+
+
+
+
+
+
${firstName} ${lastName}
+ ${dob} +
+ Photo +
+
+
+
+
+ ${language.Nationality} + ${nationality} +
+
+
+
+ ${language.Gender} + ${gender} +
+
+
+
+ ${language.Address} + ${address}, ${city}
${state} ${postalcode}, ${country}
+
+
+
+
+ ${language.Email} + ${email} +
+
+ ${language.PhoneNumber} + ${phone} +
+
+
+
+
+ +
+
${language.Licenses}
+
+ + ${driversLicense} + + + ${bikeLicense} + + + ${boatLicense} + + + ${truckLicense} + + + ${pilotLicense} + +
+
+ + ${flagsOrMarkers && Object.keys(flagsOrMarkers).some(key => flagsOrMarkers[key]) ? ` +
+
${language.FlagsOrMarkers}
+
+ ${flagsOrMarkers.armed_and_dangerous ? `
${language.armed_and_dangerous}
` : ''} + ${flagsOrMarkers.assault ? `
${language.assault}
` : ''} + ${flagsOrMarkers.burglary ? `
${language.burglary}
` : ''} + ${flagsOrMarkers.drug_related ? `
${language.drug_related}
` : ''} + ${flagsOrMarkers.gang_affiliation ? `
${language.gang_affiliation}
` : ''} + ${flagsOrMarkers.homicide ? `
${language.homicide}
` : ''} + ${flagsOrMarkers.kidnapping ? `
${language.kidnapping}
` : ''} + ${flagsOrMarkers.mental_health_issues ? `
${language.mental_health_issues}
` : ''} + ${flagsOrMarkers.sex_offense ? `
${language.sex_offense}
` : ''} + ${flagsOrMarkers.terrorism ? `
${language.terrorism}
` : ''} + ${flagsOrMarkers.theft ? `
${language.theft}
` : ''} + ${flagsOrMarkers.traffic_violation ? `
${language.traffic_violation}
` : ''} + ${flagsOrMarkers.wanted_person ? `
${language.wanted_person}
` : ''} + ${flagsOrMarkers.other ? `
${language.other}
` : ''} + ${flagsOrMarkers.active_warrant ? `
${language.active_warrant}
` : ''} +
+
+ ` : ''} +
+ `); + + // Force browser reflow and repaint to ensure text renders crisply + var databaseCheck = document.getElementById('database-check'); + if (databaseCheck) { + // Force reflow + void databaseCheck.offsetHeight; + // Reset any transform that might affect rendering + databaseCheck.style.isolation = 'auto'; + // Force repaint by toggling a property + var originalTransform = databaseCheck.style.transform; + databaseCheck.style.transform = 'translateZ(0)'; + // Use requestAnimationFrame to ensure browser has processed the change + requestAnimationFrame(function() { + databaseCheck.style.transform = originalTransform || 'translateZ(0)'; + }); + } +} + +function DisplayVehicleInfo(display, vehicleData, DisableTaxAndMOT, skipDbCheckAnimation) { + if (display) { + // Hide ID card + $("#ped-interaction-id-card").hide(); + // Hide inventory + $("#ped-interaction-inventory").hide(); + + clearTimeout(vehicleInfoTimeout); + + // Only clear vehicleDbCheckTimeout if we're not preserving state + if (!skipDbCheckAnimation) { + clearTimeout(vehicleDbCheckTimeout); + vehicleDbCheckCompleted = false; + } + + $("#vehicle-info").empty(); + + // Vehicle Data + var data = { + vehNetId: vehicleData.vehNetId, + license_plate: vehicleData.license_plate, + model: vehicleData.model, + model_hash: vehicleData.model_hash, + vehicle_class: vehicleData.vehicle_class, + vehicle_class_from_name: vehicleData.vehicle_class_from_name, + color: vehicleData.color, + color_secondary: vehicleData.color_secondary, + build_year: vehicleData.build_year, + tax: vehicleData.tax, + mot: vehicleData.mot, + insurance: vehicleData.insurance, + stolen: vehicleData.stolen, + bolo: vehicleData.bolo, + bolo_description: vehicleData.bolo_description, + owner_name: vehicleData.owner_name, + } + + // Store data for TAB key re-display + lastDisplayedModule = 'vehicle'; + lastVehicleData = { + vehicleData: vehicleData, + DisableTaxAndMOT: DisableTaxAndMOT + }; + + // Modern Bootstrap 5.2.3 Vehicle Info Card + // DON'T use isolation: isolate - it causes text blurriness + $("#vehicle-info").append(` +
+
+
+ +
${language.VehicleDetails}
+
+
+
+
+ ${language.VehiclePlate} + ${data.license_plate} +
+
+ ${language.VehicleModel} + ${data.model} +
+
+
+ `); + + // Always create the database-check container first + // DON'T use isolation: isolate on the card itself - it causes text blurriness + $("#vehicle-info").append(` +
+
+ `); + + $("#vehicle-info").show(); + + // Check if database check was already completed + if (vehicleDbCheckCompleted && skipDbCheckAnimation) { + // Show completed results immediately + renderVehicleDatabaseResults(data, DisableTaxAndMOT); + } else { + // Show loading spinner + $("#vehicle-info-database-check").html(` +
+
+ +
${language.DatabaseCheck}
+
+
+
+
+ +
+

${language.RunningDatabaseCheck}

+
+
+
+
+ `); + + vehicleDbCheckTimeout = setTimeout(function() { + vehicleDbCheckCompleted = true; + renderVehicleDatabaseResults(data, DisableTaxAndMOT); + }, 5000); + } + + // Hide the vehicle info after a certain period + vehicleInfoTimeout = setTimeout(function() { + $("#vehicle-info").hide(); + updateModuleIndicator(); + scheduleModuleClearIfHidden(); + }, 15000); + + updateModuleIndicator(); + + } else { + $("#vehicle-info").hide(); + updateModuleIndicator(); + } +} + +// Separate function to render vehicle database results +function renderVehicleDatabaseResults(data, DisableTaxAndMOT) { + // Completely clear and replace content to reset rendering context + var vehicleDbCheckElement = document.getElementById('vehicle-info-database-check'); + if (vehicleDbCheckElement) { + // Remove all content including loading indicator + vehicleDbCheckElement.innerHTML = ''; + // Force a reflow to clear any rendering contexts + void vehicleDbCheckElement.offsetHeight; + } + + $("#vehicle-info-database-check").html(` +
+
+ +
${language.DatabaseCheckResults}
+
+
+
+
+
+
+ ${language.VehicleOwner} + ${data.owner_name} +
+
+
+
+ ${language.VehicleBuildYear} + ${data.build_year} +
+
+
+
+ ${language.VehicleColor} + ${data.color} +
+
+
+
+ ${language.VehicleColorSecondary} + ${data.color_secondary} +
+
+ + ${DisableTaxAndMOT ? "" : ` +
+
+ ${language.VehicleTax} + + ${data.tax ? language.Paid : language.NotPaid} + +
+
+
+
+ ${language.VehicleMOT} + + ${data.mot ? language.Passed : language.Failed} + +
+
+ `} +
+
+ ${language.VehicleInsurance} + + ${data.insurance ? language.Valid : language.Invalid} + +
+
+
+
+ ${language.VehicleStolen} + + ${data.stolen ? language.Yes : language.No} + +
+
+
+
+ ${language.VehicleBolo} + + ${data.bolo ? language.Yes : language.No} + +
+
+ ${!data.bolo ? "" : ` +
+
+
${language.VehicleBoloDescription}
+

${wrapText(data.bolo_description ? data.bolo_description : "-", 50)}

+
+
+ `} +
+
+ `); + + // Force browser reflow and repaint to ensure text renders crisply + var vehicleDbCheck = document.getElementById('vehicle-info-database-check'); + if (vehicleDbCheck) { + // Force reflow + void vehicleDbCheck.offsetHeight; + // Reset any transform that might affect rendering + vehicleDbCheck.style.isolation = 'auto'; + // Force repaint by toggling a property + var originalTransform = vehicleDbCheck.style.transform; + vehicleDbCheck.style.transform = 'translateZ(0)'; + // Use requestAnimationFrame to ensure browser has processed the change + requestAnimationFrame(function() { + vehicleDbCheck.style.transform = originalTransform || 'translateZ(0)'; + }); + } +} + +var inventoryTimeout; +function DisplayPedInventory(display, itemList) { + if (display) { + // Hide ID card + $("#ped-interaction-id-card").hide(); + // Hide vehicle info + $("#vehicle-info").hide(); + + clearTimeout(inventoryTimeout); + + $("#ped-interaction-inventory").empty(); + + // Store data for TAB key re-display + lastDisplayedModule = 'inventory'; + lastInventoryData = { + itemList: itemList + }; + + // Modern Bootstrap 5.2.3 Inventory Card + $("#ped-interaction-inventory").append(` +
+
+
+
+ +
${language.Inventory}
+
+ ${itemList.length} ${itemList.length === 1 ? 'item' : 'items'} +
+
+
+
+
+
+
+ `); + + if (itemList.length === 0) { + $("#inventory-list-body").append(` +
+ +

No items found

+
+ `); + } else { + $.each(itemList, function (key, v) { + var isIllegal = v.illegal; + var itemClass = isIllegal ? 'border-danger border-opacity-50' : 'border-secondary border-opacity-25'; + var textClass = isIllegal ? 'text-danger' : 'text-light'; + var iconClass = isIllegal ? 'fas fa-exclamation-triangle text-danger' : 'fas fa-cube text-info'; + + var listItem = ` +
+
+ + ${v.name} + ${isIllegal ? 'Illegal' : ''} +
+
+ `; + $("#inventory-list-body").append(listItem); + }); + } + + $("#ped-interaction-inventory").show(); + + inventoryTimeout = setTimeout(function() { + $("#ped-interaction-inventory").hide(); + updateModuleIndicator(); + scheduleModuleClearIfHidden(); + }, 15000); + + updateModuleIndicator(); + + } else { + $("#ped-interaction-inventory").hide(); + updateModuleIndicator(); + } +} + +// Function to clear module data when shift ends +function clearModuleData() { + // Clear stored module data + lastDisplayedModule = null; + lastIdCardData = null; + lastVehicleData = null; + lastInventoryData = null; + + // Reset database check completion states + idCardDbCheckCompleted = false; + vehicleDbCheckCompleted = false; + + // Clear any active timeouts + clearTimeout(idCardTimeout); + clearTimeout(vehicleInfoTimeout); + clearTimeout(inventoryTimeout); + clearTimeout(dbCheckTimeout); + clearTimeout(vehicleDbCheckTimeout); + clearTimeout(moduleClearTimeout); + stopModuleProgressBar(); + + // Hide any visible modules + $("#ped-interaction-id-card").hide(); + $("#vehicle-info").hide(); + $("#ped-interaction-inventory").hide(); + + // Hide the module indicator + $("#module-indicator").fadeOut(200); +} + +// Function to schedule clearing module data if hidden for > 1 minute +function scheduleModuleClearIfHidden() { + // Clear any existing timeout and interval + clearTimeout(moduleClearTimeout); + clearInterval(moduleProgressInterval); + + // Record start time for progress bar + moduleClearStartTime = Date.now(); + + // Start progress bar animation + startModuleProgressBar(); + + // Set new timeout to clear after 60 seconds + moduleClearTimeout = setTimeout(function() { + // Only clear if module is still hidden + if (lastDisplayedModule) { + var isCurrentlyVisible = false; + + if (lastDisplayedModule === 'idcard' && $("#ped-interaction-id-card").is(":visible")) { + isCurrentlyVisible = true; + } else if (lastDisplayedModule === 'vehicle' && $("#vehicle-info").is(":visible")) { + isCurrentlyVisible = true; + } else if (lastDisplayedModule === 'inventory' && $("#ped-interaction-inventory").is(":visible")) { + isCurrentlyVisible = true; + } + + // Clear module data if still hidden after 60 seconds + if (!isCurrentlyVisible) { + clearModuleData(); + } + } + }, 30000); // 30 seconds +} + +// Function to start/update progress bar animation +function startModuleProgressBar() { + // Clear any existing interval + clearInterval(moduleProgressInterval); + + // Update progress bar every 100ms for smooth animation + moduleProgressInterval = setInterval(function() { + if (!moduleClearStartTime || !lastDisplayedModule) { + clearInterval(moduleProgressInterval); + return; + } + + var elapsed = Date.now() - moduleClearStartTime; + var remaining = Math.max(0, 30000 - elapsed); + var progress = (remaining / 30000) * 100; // Percentage remaining (100% to 0%) + + // Update progress bar (shows remaining time, fills from left to right) + var progressBar = $("#module-indicator-progress"); + if (progressBar.length > 0) { + progressBar.css('width', progress + '%'); + } + + // Stop interval if timer is complete + if (progress <= 0) { + clearInterval(moduleProgressInterval); + } + }, 100); // Update every 100ms +} + +// Function to stop progress bar animation +function stopModuleProgressBar() { + clearInterval(moduleProgressInterval); + moduleClearStartTime = null; + var progressBar = $("#module-indicator-progress"); + if (progressBar.length > 0) { + progressBar.css('width', '100%'); + } +} + +// Function to update module indicator icon +function updateModuleIndicator() { + var indicator = $("#module-indicator"); + + // Check if there's a last displayed module and if it's currently hidden + if (lastDisplayedModule) { + var isCurrentlyVisible = false; + var moduleIcon = ''; + + if (lastDisplayedModule === 'idcard') { + isCurrentlyVisible = $("#ped-interaction-id-card").is(":visible"); + moduleIcon = 'fas fa-id-card'; + } else if (lastDisplayedModule === 'vehicle') { + isCurrentlyVisible = $("#vehicle-info").is(":visible"); + moduleIcon = 'fas fa-car'; + } else if (lastDisplayedModule === 'inventory') { + isCurrentlyVisible = $("#ped-interaction-inventory").is(":visible"); + moduleIcon = 'fas fa-box'; + } + + // Show indicator only if module is hidden + if (!isCurrentlyVisible) { + if (indicator.length === 0) { + // Create indicator if it doesn't exist + $('body').append(` +
+
+ + ${language.Press} TAB +
+
+
+
+
+ `); + // Show the indicator after creation + $("#module-indicator").fadeIn(200); + } else { + // Update existing indicator + indicator.find('i').attr('class', moduleIcon + ' me-2'); + indicator.find('span').html(`${language.Press} TAB`); + // Ensure progress bar container exists + if (indicator.find('.module-indicator-progress-container').length === 0) { + indicator.append(` +
+
+
+ `); + } + indicator.fadeIn(200); + } + } else { + // Hide indicator if module is visible + indicator.fadeOut(200); + stopModuleProgressBar(); + } + } else { + // Hide indicator if no last displayed module + indicator.fadeOut(200); + } +} + +// Function to re-display last shown module (called from Lua client) +function redisplayLastModule() { + // Toggle visibility: hide if visible, show if hidden + if (lastDisplayedModule) { + var isCurrentlyVisible = false; + + if (lastDisplayedModule === 'idcard' && $("#ped-interaction-id-card").is(":visible")) { + isCurrentlyVisible = true; + } else if (lastDisplayedModule === 'vehicle' && $("#vehicle-info").is(":visible")) { + isCurrentlyVisible = true; + } else if (lastDisplayedModule === 'inventory' && $("#ped-interaction-inventory").is(":visible")) { + isCurrentlyVisible = true; + } + + if (isCurrentlyVisible) { + // Hide the module and clear timeout + if (lastDisplayedModule === 'idcard') { + clearTimeout(idCardTimeout); + $("#ped-interaction-id-card").hide(); + } else if (lastDisplayedModule === 'vehicle') { + clearTimeout(vehicleInfoTimeout); + $("#vehicle-info").hide(); + } else if (lastDisplayedModule === 'inventory') { + clearTimeout(inventoryTimeout); + $("#ped-interaction-inventory").hide(); + } + updateModuleIndicator(); + scheduleModuleClearIfHidden(); + } else { + // Show the module if currently hidden + // Clear the module clear timeout since we're showing it + clearTimeout(moduleClearTimeout); + stopModuleProgressBar(); + if (lastDisplayedModule === 'idcard' && lastIdCardData) { + DisplayPedIdCard(true, lastIdCardData.personaldata, lastIdCardData.showdatabasecheck, idCardDbCheckCompleted); + } else if (lastDisplayedModule === 'vehicle' && lastVehicleData) { + DisplayVehicleInfo(true, lastVehicleData.vehicleData, lastVehicleData.DisableTaxAndMOT, vehicleDbCheckCompleted); + } else if (lastDisplayedModule === 'inventory' && lastInventoryData) { + DisplayPedInventory(true, lastInventoryData.itemList); + } + updateModuleIndicator(); + } + } +} + +// NPC Backup Request Radial Menu +var listener = false; +function setupButton(buttonId, iconClass, instructionText) { + const button = document.getElementById(buttonId); + $(`#${buttonId}`).html(``); + + button.addEventListener('mouseenter', () => PlayNUISound('generic-sounds', "rollover", 0.5)); + button.addEventListener('mouseover', () => { + document.getElementById('instruction-text').style.display = 'block'; + $("#instruction-text").html(`

${instructionText}

`); + }); + button.addEventListener('mouseout', () => document.getElementById('instruction-text').style.display = 'none'); +} + +function setupRadialMenu() { + if (!listener) { + listener = true; + + /* + TO ADD NEW BACKUP, SIMPLY ADD YOUR BACKUP TYPE TO THE BUTTONS ARRAY BELOW AND CHANGE THE VALUES! + MAKE SURE TO CREATE THE REQUIRED FUNCTION AND ADD THE CSS CODE IN STYLES.CSS! + */ + + // INSTRUCTION + // const instructionText = document.getElementById('instruction-text'); + const buttons = [ + // THIS ALWAYS NEEDS TO BE THE FIRST ITEM IN THIS ARRAY! + { id: 'middle-x', iconClass: '', instruction: language.ExitRadialMenuInstruction, hoverColour: '', function: 'ToggleRadialMenu(false)' }, + // + { id: 'police-transport', iconClass: language.RequestPoliceTransportIcon, instruction: language.RequestPoliceTransportInstruction, hoverColour: '#0057b9', function: 'RequestOrCancelPoliceTransport()' }, + { id: 'ambulance-request', iconClass: language.RequestAmbulanceIcon, instruction: language.RequestAmbulanceInstruction, hoverColour: '#ff0000', function: 'RequestOrCancelAmbulance()' }, + { id: 'tow-request', iconClass: language.RequestTowIcon, instruction: language.RequestTowInstruction, hoverColour: '#782323', function: 'RequestOrCancelTow()' }, + { id: 'taxi-request', iconClass: language.RequestTaxiIcon, instruction: language.RequestTaxiInstruction, hoverColour: '#FF9A18', function: 'RequestOrCancelTaxi()' }, + { id: 'road-service-request', iconClass: language.RequestRoadServiceIcon, instruction: language.RequestRoadServiceInstruction, hoverColour: '#ffbf00', function: 'RequestOrCancelRoadService()' }, + { id: 'coroner-request', iconClass: language.RequestCoronerIcon, instruction: language.RequestCoronerInstruction, hoverColour: '#3D3D3D', function: 'RequestOrCancelCoroner()' }, + { id: 'animal-rescue-request', iconClass: language.RequestAnimalRescueIcon, instruction: language.RequestAnimalRescueInstruction, hoverColour: '#9bde00', function: 'RequestOrCancelAnimalRescue()' }, + { id: 'mechanic-request', iconClass: language.RequestMechanicIcon, instruction: language.RequestMechanicInstruction, hoverColour: '#3D3D3D', function: 'RequestOrCancelMechanic()' }, + { id: 'fire-request', iconClass: language.RequestFireIcon, instruction: language.RequestFireInstruction, hoverColour: '#3D3D3D', function: 'RequestOrCancelFire()' } + ]; + + $('#circle-menu').html(` +
- `),e.forEach(({id:e,iconClass:t,instruction:a})=>setupButton(e,t,a))}}function ToggleRadialMenu(e){if(setupRadialMenu(),e){document.addEventListener("keyup",handleRadialMenuEscape);let t=document.getElementById("instruction-title");t.style.display="block",$("#instruction-title").html(`

${language.RadialMenuInstructionTitle}

`),$("#circle-menu").show(),$("body").append("
")}else{document.removeEventListener("keyup",handleRadialMenuEscape),PlayNUISound("generic-sounds","radialclose",.5);let a=document.getElementById("instruction-title"),n=document.getElementById("instruction-text");a&&(a.style.display="none"),n&&(n.style.display="none"),$("#circle-menu").hide(),$.post(`https://${resourceName}/closeRadialMenu`,JSON.stringify({})),$(".blur-overlay").remove()}}function handleRadialMenuEscape(e){"Escape"===e.key&&ToggleRadialMenu(!1)}function RequestOrCancelPoliceTransport(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelPoliceTransport`,JSON.stringify({}))}function RequestOrCancelAmbulance(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelAmbulance`,JSON.stringify({}))}function RequestOrCancelTow(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelTow`,JSON.stringify({}))}function RequestOrCancelTaxi(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelTaxi`,JSON.stringify({}))}function RequestOrCancelRoadService(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelRoadService`,JSON.stringify({}))}function RequestOrCancelCoroner(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelCoroner`,JSON.stringify({}))}function RequestOrCancelAnimalRescue(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelAnimalRescue`,JSON.stringify({}))}function RequestOrCancelMechanic(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelMechanic`,JSON.stringify({}))}function RequestOrCancelFire(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelFire`,JSON.stringify({}))}function TogglePursuitModeUI(e,t,a,n){$("#pursuit-mode-ui").toggle(e),e?$("#pursuit-mode-ui").html(`
${language.ActivePursuit}
${t?`
${a} (${language.PursuitHotkeyFocus}) | ${n} (${language.PursuitHotkeyBackup})
`:""}
`):$("#pursuit-mode-ui").hide()}var pursuitRadialMenuListener=!1;function setupPursuitRadialMenuButton(e,t,a){let n=document.getElementById(e);$(`#${e}`).html(``),n.addEventListener("mouseenter",()=>{PlayNUISound("generic-sounds","rollover",.5),document.getElementById("pursuit-instruction-text").style.display="block",$("#pursuit-instruction-text").html(`

${a}

`)}),n.addEventListener("mouseleave",()=>{document.getElementById("pursuit-instruction-text").style.display="none"})}function setupPursuitRadialMenu(){if(!pursuitRadialMenuListener){pursuitRadialMenuListener=!0;let e=[{id:"pursuit-middle-x",iconClass:"",instruction:language.ExitRadialMenuInstruction,hoverColour:"",function:"TogglePursuitRadialMenu(false)"},{id:"pursuit-backup-light",iconClass:language.RequestLightBackupIcon,instruction:language.RequestLightBackupInstruction,hoverColour:"#0080f8",function:"RequestPursuitBackup('light')"},{id:"pursuit-backup-medium",iconClass:language.RequestMediumBackupIcon,instruction:language.RequestMediumBackupInstruction,hoverColour:"#014b8f",function:"RequestPursuitBackup('medium')"},{id:"pursuit-backup-heavy",iconClass:language.RequestHeavyBackupIcon,instruction:language.RequestHeavyBackupInstruction,hoverColour:"#001e39",function:"RequestPursuitBackup('heavy')"},{id:"pursuit-backup-air",iconClass:language.RequestAirBackupIcon,instruction:language.RequestAirBackupInstruction,hoverColour:"#00a2dd",function:"RequestPursuitBackup('air')"},{id:"pursuit-backup-army",iconClass:language.RequestArmyBackupIcon,instruction:language.RequestArmyBackupInstruction,hoverColour:"#647b32",function:"RequestPursuitBackup('army')"},];$("#pursuit-radial-menu").html(` -
+ `) + + buttons.forEach(({ id, iconClass, instruction }) => setupButton(id, iconClass, instruction)); + } +} + +function ToggleRadialMenu(display) { + setupRadialMenu(); + + if (display) { + // Add escape key event listener + document.addEventListener('keyup', handleRadialMenuEscape); + + const instructionTitle = document.getElementById('instruction-title'); + instructionTitle.style.display = 'block'; + $("#instruction-title").html(`

${language.RadialMenuInstructionTitle}

`); + $("#circle-menu").show(); + + // Apply the blur overlay + $("body").append("
"); + + } else { + // Remove escape key event listener + document.removeEventListener('keyup', handleRadialMenuEscape); + + PlayNUISound('generic-sounds', "radialclose", 0.5); + + // Hide all instruction elements + const instructionTitle = document.getElementById('instruction-title'); + const instructionText = document.getElementById('instruction-text'); + + if (instructionTitle) { + instructionTitle.style.display = 'none'; + } + if (instructionText) { + instructionText.style.display = 'none'; + } + + $("#circle-menu").hide(); + $.post(`https://${resourceName}/closeRadialMenu`, JSON.stringify({})); + + // Remove the blur overlay + $(".blur-overlay").remove(); + } +} + +function handleRadialMenuEscape(event) { + if (event.key === 'Escape') { + ToggleRadialMenu(false); + } +} + +function RequestOrCancelPoliceTransport() { + ToggleRadialMenu(false) + $.post(`https://${resourceName}/requestOrCancelPoliceTransport`, JSON.stringify({})) +} + +function RequestOrCancelAmbulance() { + ToggleRadialMenu(false) + $.post(`https://${resourceName}/requestOrCancelAmbulance`, JSON.stringify({})) +} + +function RequestOrCancelTow() { + ToggleRadialMenu(false) + $.post(`https://${resourceName}/requestOrCancelTow`, JSON.stringify({})) +} + +function RequestOrCancelTaxi() { + ToggleRadialMenu(false) + $.post(`https://${resourceName}/requestOrCancelTaxi`, JSON.stringify({})) +} + +function RequestOrCancelRoadService() { + ToggleRadialMenu(false) + $.post(`https://${resourceName}/requestOrCancelRoadService`, JSON.stringify({})) +} + +function RequestOrCancelCoroner() { + ToggleRadialMenu(false) + $.post(`https://${resourceName}/requestOrCancelCoroner`, JSON.stringify({})) +} + +function RequestOrCancelAnimalRescue() { + ToggleRadialMenu(false) + $.post(`https://${resourceName}/requestOrCancelAnimalRescue`, JSON.stringify({})) +} + +function RequestOrCancelMechanic() { + ToggleRadialMenu(false) + $.post(`https://${resourceName}/requestOrCancelMechanic`, JSON.stringify({})) +} + +function RequestOrCancelFire() { + ToggleRadialMenu(false) + $.post(`https://${resourceName}/requestOrCancelFire`, JSON.stringify({})) +} + +// Pursuit Mode UI + +function TogglePursuitModeUI(display, displayhotkeyhint, zoomhotkey, backuphotkey) { + $("#pursuit-mode-ui").toggle(display); + if (display) { + + // MINIFY + $("#pursuit-mode-ui").html(`
${language.ActivePursuit}
${displayhotkeyhint ? `
${zoomhotkey} (${language.PursuitHotkeyFocus}) | ${backuphotkey} (${language.PursuitHotkeyBackup})
` : ''}
`); + + // HTML + // $("#pursuit-mode-ui").html(` + //
+ //
+ //
+ //
+ // ${language.ActivePursuit} + //
+ //
+ //
+ // ${displayhotkeyhint ? ` + //
+ // ${zoomhotkey} (${language.PursuitHotkeyFocus}) | ${backuphotkey} (${language.PursuitHotkeyBackup}) + //
+ // ` : ''} + //
+ //
+ //
+ // `); + + } else { + $("#pursuit-mode-ui").hide(); + } +} + +//Pursuit Radial Menu +var pursuitRadialMenuListener = false; +function setupPursuitRadialMenuButton(buttonId, iconClass, instructionText) { + const button = document.getElementById(buttonId); + $(`#${buttonId}`).html(``); + + // Use mouseenter instead of mouseover to prevent event bubbling + button.addEventListener('mouseenter', () => { + PlayNUISound('generic-sounds', "rollover", 0.5); + document.getElementById('pursuit-instruction-text').style.display = 'block'; + $("#pursuit-instruction-text").html(`

${instructionText}

`); + }); + + // Use mouseleave instead of mouseout to prevent event bubbling + button.addEventListener('mouseleave', () => { + document.getElementById('pursuit-instruction-text').style.display = 'none'; + }); +} + +function setupPursuitRadialMenu() { + if (!pursuitRadialMenuListener) { + pursuitRadialMenuListener = true; + + // INSTRUCTION + // const instructionText = document.getElementById('pursuit-instruction-text'); + const buttons = [ + // THIS ALWAYS NEEDS TO BE THE FIRST ITEM IN THIS ARRAY! + { id: 'pursuit-middle-x', iconClass: '', instruction: language.ExitRadialMenuInstruction, hoverColour: '', function: 'TogglePursuitRadialMenu(false)' }, + // + { id: 'pursuit-backup-light', iconClass: language.RequestLightBackupIcon, instruction: language.RequestLightBackupInstruction, hoverColour: '#0080f8', function: "RequestPursuitBackup('light')" }, + { id: 'pursuit-backup-medium', iconClass: language.RequestMediumBackupIcon, instruction: language.RequestMediumBackupInstruction, hoverColour: '#014b8f', function: "RequestPursuitBackup('medium')" }, + { id: 'pursuit-backup-heavy', iconClass: language.RequestHeavyBackupIcon, instruction: language.RequestHeavyBackupInstruction, hoverColour: '#001e39', function: "RequestPursuitBackup('heavy')" }, + { id: 'pursuit-backup-air', iconClass: language.RequestAirBackupIcon, instruction: language.RequestAirBackupInstruction, hoverColour: '#00a2dd', function: "RequestPursuitBackup('air')" }, + { id: 'pursuit-backup-army', iconClass: language.RequestArmyBackupIcon, instruction: language.RequestArmyBackupInstruction, hoverColour: '#647b32', function: "RequestPursuitBackup('army')" }, + ]; + + $('#pursuit-radial-menu').html(` +
- `),e.forEach(({id:e,iconClass:t,instruction:a})=>setupPursuitRadialMenuButton(e,t,a))}}function TogglePursuitRadialMenu(e){if(setupPursuitRadialMenu(),e){document.addEventListener("keyup",handlePursuitRadialMenuEscape);let t=document.getElementById("pursuit-instruction-title");t.style.display="block",$("#pursuit-instruction-title").html(`

${language.PursuitRadialMenuInstructionTitle}

`),$("#pursuit-radial-menu").show(),$("body").append("
")}else{document.removeEventListener("keyup",handlePursuitRadialMenuEscape),PlayNUISound("generic-sounds","radialclose",.5);let a=document.getElementById("pursuit-instruction-title");a&&(a.style.display="none");let n=document.getElementById("pursuit-instruction-text");n&&(n.style.display="none"),$("#pursuit-radial-menu").hide(),$.post(`https://${resourceName}/closePursuitRadialMenu`,JSON.stringify({})),$(".blur-overlay").remove()}}function handlePursuitRadialMenuEscape(e){"Escape"===e.key&&TogglePursuitRadialMenu(!1)}function RequestPursuitBackup(e){TogglePursuitRadialMenu(!1),$.post(`https://${resourceName}/requestPursuitBackup`,JSON.stringify({unitType:e}))}var isDispatchQueueProcessing=!1,dispatchMessages=[];function AddMessageToDispatchQueue(e,t,a,n,i,o,s){dispatchMessages.push({display:e,hotkeys:t,messagetype:a,calloutdata:n,timeInMS:i,message:o,toggle:s}),isDispatchQueueProcessing||ProcessDispatchQueue()}function ProcessDispatchQueue(){if(dispatchMessages.length>0){isDispatchQueueProcessing=!0;var e=dispatchMessages[0];DisplayDispatchMessage(e.display,e.hotkeys,e.messagetype,e.calloutdata,e.message,e.toggle);var t=e.toggle?e.timeInMS:3e3;StartCountdownTimer(t),setTimeout(function(){dispatchMessages.shift(),ProcessDispatchQueue()},t)}else isDispatchQueueProcessing=!1,$("#dispatch-message-prompt-container").hide()}function DisplayDispatchMessage(e,t,a,n,i,o){if(!o){$("#dispatch-message-prompt-container").empty().show().append(` + `) + + buttons.forEach(({ id, iconClass, instruction }) => setupPursuitRadialMenuButton(id, iconClass, instruction)); + } +} + +function TogglePursuitRadialMenu(display) { + setupPursuitRadialMenu(); + + if (display) { + // Add escape key event listener + document.addEventListener('keyup', handlePursuitRadialMenuEscape); + + const instructionTitle = document.getElementById('pursuit-instruction-title'); + instructionTitle.style.display = 'block'; + $("#pursuit-instruction-title").html(`

${language.PursuitRadialMenuInstructionTitle}

`); + $("#pursuit-radial-menu").show(); + + // Apply the blur overlay + $("body").append("
"); + + } else { + // Remove escape key event listener + document.removeEventListener('keyup', handlePursuitRadialMenuEscape); + + PlayNUISound('generic-sounds', "radialclose", 0.5); + const instructionTitle = document.getElementById('pursuit-instruction-title'); + if (instructionTitle) { + instructionTitle.style.display = 'none'; + } + const instructionText = document.getElementById('pursuit-instruction-text'); + if (instructionText) { + instructionText.style.display = 'none'; + } + + $("#pursuit-radial-menu").hide(); + $.post(`https://${resourceName}/closePursuitRadialMenu`, JSON.stringify({})); + + // Remove the blur overlay + $(".blur-overlay").remove(); + } +} + +function handlePursuitRadialMenuEscape(event) { + if (event.key === 'Escape') { + TogglePursuitRadialMenu(false); + } +} + +function RequestPursuitBackup(unitType) { + TogglePursuitRadialMenu(false) + $.post(`https://${resourceName}/requestPursuitBackup`, JSON.stringify({unitType: unitType})); +} + +// DISPATCH + +var isDispatchQueueProcessing = false; +var dispatchMessages = []; + +function AddMessageToDispatchQueue(display, hotkeys, messagetype, calloutdata, timeInMS, message, toggle) { + dispatchMessages.push({ display: display, hotkeys: hotkeys, messagetype: messagetype, calloutdata: calloutdata, timeInMS: timeInMS, message: message, toggle: toggle }); + if (!isDispatchQueueProcessing) { + ProcessDispatchQueue(); + } +} + +function ProcessDispatchQueue() { + if (dispatchMessages.length > 0) { + isDispatchQueueProcessing = true; + + var message = dispatchMessages[0]; // Get the first message from the queue without removing it + + DisplayDispatchMessage(message.display, message.hotkeys, message.messagetype, message.calloutdata, message.message, message.toggle); + + // Determine the timeout duration based on the message.toggle property + var timeoutDuration = message.toggle ? message.timeInMS : 3000; // Use 3000ms if toggle is false + + // Set the countdown timer for the message + StartCountdownTimer(timeoutDuration); + + setTimeout(function() { + dispatchMessages.shift(); // Remove the first message from the queue + ProcessDispatchQueue(); + }, timeoutDuration); + } else { + isDispatchQueueProcessing = false; + $("#dispatch-message-prompt-container").hide(); // Hide the message prompt container if there are no more messages + } +} + +function getDispatchIcon(messagetype) { + switch(messagetype) { + case "response": + return ''; + case "arrival": + return ''; + case "detach": + return ''; + case "shift": + return ''; + case "ambulance": + return ''; + case "police": + return ''; + case "fire": + return ''; + case "tow": + return ''; + case "taxi": + return ''; + default: + return ''; + } +} + +function DisplayDispatchMessage(display, hotkeys, messagetype, calloutdata, message, toggle) { + + if (!toggle) { + $("#dispatch-message-prompt-container").empty().show().append(`
${language.DispatchMessage}
- `),applySavedPosition("dispatch-message-prompt-container");return}"response"==a||"arrival"==a?("response"==a&&$.post(`https://${resourceName}/offerToTrackPlayer`,JSON.stringify({calloutdata:n})),$("#dispatch-message-prompt-container").empty().show().append(`
${language.DispatchMessage}
${wrapText(i,50)}
${language.Caller} ${wrapText(`${n.FirstName} ${n.LastName}`,50)}
${language.CallDescription} ${wrapText(n.Description??"N/A",50)}
${language.Location} ${wrapText(n.StreetName??"N/A",50)}
${language.Postal} ${wrapText(n.Postal??"N/A",50)}
${language.CalloutUnitsRequired} ${wrapText(n.CalloutUnitsRequired?.description??"N/A",50)}
${language.DispatchNote} ${wrapText(language.DispatchNoteResponseText??"N/A",50)}
`),applySavedPosition("dispatch-message-prompt-container"),"response"==a&&$("#dispatch-message-prompt-container").append(` `)):($("#dispatch-message-prompt-container").empty().show().append(`
${language.DispatchMessage}
${i}
`),applySavedPosition("dispatch-message-prompt-container"))}function StartCountdownTimer(e){var t=e/1e3;let a=`${language.NextDispatchMessage} ${t} ${language.Seconds}...`;$("#countdown-timer").html(`
${wrapText(a,70)}
`);var n=setInterval(function(){--t>=0?$("#countdown-timer").html(`
${wrapText(`${language.NextDispatchMessage} ${t} ${language.Seconds}...`,70)}
`):(clearInterval(n),$("#countdown-timer").html(`
${wrapText("Time's up!",70)}
`))},1e3)}function ToggleHotKeyHintPrompt(e,t,a,n){e?($("#hint-prompt-container").empty(),$("#hint-prompt-container").show(),applySavedPosition("hint-prompt-container"),$("#hint-prompt-container").append(`
${a.Hint}
${a.HotKeys}
${a.Explanation}
`),setTimeout(function(){$("#hint-prompt-container").hide(),$.post(`https://${resourceName}/reallowPromptMessages`,JSON.stringify({}))},n)):($("#hint-prompt-container").empty(),$("#hint-prompt-container").hide())}function SelectBackGroundColourByServiceType(e){var t="bg-primary",a="border-primary",n="btn-outline-primary",i="text-light";return"police"==e?(t="bg-primary",a="border-primary",n="btn-outline-primary",i="text-light"):"ambulance"==e?(t="bg-success",a="border-success",n="btn-outline-success",i="text-light"):"fire"==e?(t="bg-danger",a="border-danger",n="btn-outline-danger",i="text-light"):"tow"==e&&(t="bg-warning",a="border-warning",n="btn-outline-warning",i="text-light"),{backgroundColor:t,borderColor:a,textColor:i,buttonOutlineColor:n}}function ToggleCalloutDisplayPrompt(e,t,a,n,i,o){var s=n/1e3,{backgroundColor:l,borderColor:r,textColor:c,buttonOutlineColor:d}=SelectBackGroundColourByServiceType(o);e?($("#callout-prompt-container").empty(),$("#callout-prompt-container").show(),$("#callout-prompt-container").append(`
${wrapText(`${a.EmergencyCall} (${i.CalloutName})`,50)}
${a.Caller} ${wrapText(`${i.FirstName} ${i.LastName}`,50)}
${a.CallDescription} ${wrapText(i.Description??"N/A",50)}
${a.Location} ${wrapText(i.StreetName??"N/A",50)}
${a.Postal} ${wrapText(i.Postal??"N/A",50)}
${a.CalloutUnitsRequired} ${wrapText(i.CalloutUnitsRequired?.description??"N/A",50)}
${a.DispatchNote} ${wrapText(a.DispatchNoteResponseText??"N/A",50)}
`),applySavedPosition("callout-prompt-container"),clearInterval(window.countdownInterval),s--,window.countdownInterval=setInterval(function(){s>0?($("#callout-prompt-container").find("#countdown-text").html(` ${a.TimeRemainingToAcceptCallout} ${s} ${a.Seconds}... `),s--):(clearInterval(window.countdownInterval),$("#callout-prompt-container").hide(),$.post(`https://${resourceName}/calloutTimeout`,JSON.stringify({})))},1e3)):($("#callout-prompt-container").empty(),$("#callout-prompt-container").hide())}function ToggleCalloutInterface(e,t,a,n,i,o,s,l,r,c,d,u,g,p,b){isDisplayingCalloutInterface=e,e?($("#callout-interface-container").empty().addClass("slideInFromLeft"),$("#callout-interface-container").show(),$("#callout-interface-container").append(`
แฏฝ ${r.CalloutName}
${a>0?` `:""} ${n>0?` `:""} ${i>0?` `:""} ${o>0?` `:""} ${s>0?` `:""} ${l>0?` `:""}
โŸก ${language.InvolvedPedsRemaining} ${a}/${c}
โŸก ${language.InvolvedVehsRemaining} ${n}/${d}
โŸก ${language.InvolvedObjsRemaining} ${i}/${u}
โŸก ${language.InvolvedPropsRemaining} ${o}/${g}
โŸก ${language.ExtinguishAllFires} ${s}/${p}
โŸก ${language.ClearAreaOfSmoke} ${l}/${b}

${language.Press} ${t.ToggleCalloutInfo} ${language.ToHideOrShow}
`),applySavedPosition("callout-interface-container")):($("#callout-interface-container").empty(),$("#callout-interface-container").hide())}function TogglePreCalloutInterface(e,t,a){isDisplayingPreCalloutInterface=e,e?($("#callout-pre-interface-container").empty().addClass("slideInFromLeft"),$("#callout-pre-interface-container").show(),$("#callout-pre-interface-container").append(`
แฏฝ ${wrapText(`${language.EmergencyCall} (${a?.CalloutName??"N/A"})`,40)}
โŸก ${language.Caller}
${wrapText(`${a?.FirstName??"N/A"} ${a?.LastName??"N/A"}`,70)}
โŸก ${language.CallDescription}
${wrapText(a?.Description??"N/A",70)}
โŸก ${language.Location}
${wrapText(a?.StreetName??"N/A",70)}
โŸก ${language.Postal}
${wrapText(a?.Postal??"N/A",70)}
โŸก ${language.CalloutUnitsRequired}
${wrapText(a?.CalloutUnitsRequired?.description??"N/A",70)}
โŸก ${language.DispatchNote}
${wrapText(language.DispatchNoteResponseText,70)}

${language.Press} ${t.ToggleCalloutInfo} ${language.ToHideOrShow}
`),applySavedPosition("callout-pre-interface-container")):($("#callout-pre-interface-container").empty(),$("#callout-pre-interface-container").hide())}let Waypoints=[];function UpdateWaypointPosition(e,t,a){if(null==Waypoints[0]){$("#waypoint-container").hide();return}let n=document.getElementById("waypoint-container");$("#waypoint-distance").empty(),$("#waypoint-container").show(),$("#waypoint-distance").append(` - แฏฝ ${a} - `);let i=window.innerWidth,o=window.innerHeight,s=n.getBoundingClientRect(),l=s.width,r=s.height;n.style.left=(i-l)*e+"px",n.style.top=(o-r)*t+"px"}function AddWaypoint(e){let t=document.getElementById("waypoint-container");e?Waypoints.push({element:t}):($("#waypoint-container").hide(),Waypoints=[])}let escapeEventListenerAddedERSSelectionMenu=!1,menuSoundInstance=null;function ToggleERSSelectionMenu(e,t){if(e){let a=t.isPolice,n=t.isAmbulance,i=t.isFire,o=t.isTow;fadeOutMenuMusic(menuSoundInstance),menuSoundInstance=PlayNUISound("generic-sounds","selectionmenu",.5);let s=` `;$("body").append(s),$("#ers-selection-modal").modal({backdrop:"static",keyboard:!1}),$("#ers-selection-modal").modal("show");for(var l=1;l<=6;l++)addSoundOnHoverEventListener("s-btn-"+l);$("#ers-selection-modal").on("shown.bs.modal",function(){escapeEventListenerAddedERSSelectionMenu||($(document).on("keydown",function(e){"Escape"===e.key&&(fadeOutMenuMusic(menuSoundInstance),$("#ers-selection-modal").modal("hide"),CancelServiceSelection(),e.stopPropagation())}),escapeEventListenerAddedERSSelectionMenu=!0)}).on("hidden.bs.modal",function(){$(document).off("keydown"),escapeEventListenerAddedERSSelectionMenu=!1})}else $("#ers-selection-modal").modal("hide").on("hidden.bs.modal",function(){fadeOutMenuMusic(menuSoundInstance),$(this).remove()})}function CancelServiceSelection(){$.post(`https://${resourceName}/cancelServiceSelection`,JSON.stringify({})),$("#ers-selection-modal").modal("hide").on("hidden.bs.modal",function(){fadeOutMenuMusic(menuSoundInstance),$(this).data("bs.modal",null),$(this).remove()})}function SelectService(e){$.post(`https://${resourceName}/selectedService`,JSON.stringify({service:e})),$("#ers-selection-modal").modal("hide").on("hidden.bs.modal",function(){fadeOutMenuMusic(menuSoundInstance),$(this).data("bs.modal",null),$(this).remove()})}function fadeOutMenuMusic(e){null!==e&&(e.fade(e.volume(),0,5e3),setTimeout(function(){e.stop()},5e3))}let escapeEventListenerAddedERSGearnMenu=!1;function DisplayGearMenu(e,t){if(e){fadeOutMenuMusic(menuSoundInstance),menuSoundInstance=PlayNUISound("generic-sounds","selectionmenu",.5);let a=` `;$("body").append(a);var n=t.ClothingData;let i=function e(t){switch(t){case"police":return"primary";case"fire":return"danger";case"ambulance":return"warning";case"tow":return"info";default:return"secondary"}}(t.ServiceType);$.each(n,function(e,a){let n=encodeURIComponent(JSON.stringify(t));$("#gear-options").append(`
${a.Name}

${a.Description}

`)}),$("#ers-gear-modal").modal({backdrop:"static",keyboard:!1}),$("#ers-gear-modal").modal("show");for(var o=0;o$(e).hide(),250)}function slideIn(e){$(e).show().removeClass("slideOutToLeft").addClass("slideInFromLeft")}function toggleCalloutInfo(){if(isDisplayingPreCalloutInterface){let e=containerIDs.preCallout;$(e).is(":visible")?slideOut(e):slideIn(e)}if(isDisplayingCalloutInterface){let t=containerIDs.callout;$(t).is(":visible")?slideOut(t):slideIn(t)}}function updateWaypoints(e){let t=e.data,a=trackExistingUnitWaypoints();for(let[n,i]of Object.entries(t))null!==i&&i.distanceText>0&&processUnitWaypoint(n,i,a);removeUnusedUnitWaypoints(a)}function trackExistingUnitWaypoints(){let e=new Set;return document.querySelectorAll(".unit-waypoint-container").forEach(t=>{e.add(t.id)}),e}function processUnitWaypoint(e,t,a){let n=`unit-waypoint-container-${e}`,i=document.getElementById(n);i||(i=createUnitWaypointContainer(n)),updateUnitWaypointPosition(i,t),updateUnitWaypointContent(i,t),a.delete(n)}function createUnitWaypointContainer(e){let t=document.createElement("div");return t.classList.add("unit-waypoint-container","smooth-transition"),t.id=e,document.body.appendChild(t),t}function updateUnitWaypointPosition(e,t){let a=window.innerWidth,n=window.innerHeight,i=e.getBoundingClientRect(),o=i.width,s=i.height;t.scaleX>=0&&t.scaleX<=1&&t.scaleY>=0&&t.scaleY<=1&&(e.style.left=(a-o)*t.scaleX+"px",e.style.top=(n-s)*t.scaleY+"px")}function updateUnitWaypointContent(e,t){e.innerHTML=` - แฏฝ ${t.distanceText}${t.metrics} - `}function removeUnusedUnitWaypoints(e){e.forEach(e=>{let t=document.getElementById(e);t&&t.remove()})}function ToggleQuestionsModule(e,t){if(e){if($("#question-options-list").empty(),$("#ped-interaction-questioning").show(),t.length>0){let a=` + `); + return; + } + + + if (messagetype == "response" || messagetype == "arrival") { + + if (messagetype == "response") { + $.post(`https://${resourceName}/offerToTrackPlayer`, JSON.stringify({calloutdata: calloutdata})); + } + + // HTML + $("#dispatch-message-prompt-container").empty().show().append(` +
+
+ ${language.DispatchMessage} + + ${getDispatchIcon(messagetype)} + +
+
+ ${calloutdata.CalloutName ? ` +
+ ${calloutdata.CalloutName} +
+ ` : ''} +
+ ${message}
+ ${calloutdata.Description ? ` + ${calloutdata.Description} + ` : ''} +
+
+ ${language.Caller} + ${calloutdata.FirstName} ${calloutdata.LastName} +
+
+ ${language.Location} + ${calloutdata.StreetName ?? 'N/A'} +
+
+ ${language.Postal} + ${calloutdata.Postal ?? 'N/A'} +
+
+ +
+ `); + + if (messagetype == "response") { + + // HTML + $("#dispatch-message-prompt-container").append(` +
+ + ${language.TrackUnitProposal} + + +
+ `) + + } + + } else { // if (messagetype == "detach" || messagetype == "shift" || messagetype == "ambulance" || messagetype == "police" || messagetype == "taxi" || messagetype == "tow" etc...) + + // HTML + $("#dispatch-message-prompt-container").empty().show().append(` +
+
+ ${language.DispatchMessage} + + ${getDispatchIcon(messagetype)} + +
+
+
+ ${message} +
+
+ +
+ `); + } +} + +function StartCountdownTimer(timeInMS) { + var remainingTime = timeInMS / 1000; // Convert milliseconds to seconds + const countdownMessage = `${language.NextDispatchMessage} ${remainingTime} ${language.Seconds}...`; + + $("#countdown-timer").html(`${wrapText(countdownMessage, 70)}`); // Wrap text with max 30 characters per line + + var timerInterval = setInterval(function() { + remainingTime--; + + if (remainingTime >= 0) { + $("#countdown-timer").html(`${wrapText(`${language.NextDispatchMessage} ${remainingTime} ${language.Seconds}...`, 70)}`); // Wrap text with max 30 characters per line + } else { + clearInterval(timerInterval); + $("#countdown-timer").html(`${wrapText("Time's up!", 70)}`); // Wrap "Time's up!" with max 30 characters per line + } + }, 1000); +} + +// HINTS + +function ToggleHotKeyHintPrompt(display, hotkeys, language, time) { + if (display) { + $("#hint-prompt-container").empty(); // clear previous data + $("#hint-prompt-container").show(); + + // HTML + $("#hint-prompt-container").append(` +
+
+ ${language.Hint} +
+
+
+ ${language.Aim} + ${hotkeys.OrderOnKneesOrStandUp} + ${language.OrderOnKneesOrStandUpExplanation} +
+
+ ${hotkeys.PullOver} + ${language.PullOver} +
+
+ ${hotkeys.AcceptCallout} + ${language.AcceptCallout} +
+
+ ${hotkeys.CompleteCallout} + ${language.CompleteCallout} +
+
+ ${hotkeys.RadialMenu} + ${language.RadialMenuExplanation} +
+
+ /${commands.StopTrackingUnit} + ${language.StopTrackingUnitExplanation} +
+
+ +
+ `); + + // Auto-hide after elapsed time + setTimeout(function() { + $("#hint-prompt-container").hide(); + $.post(`https://${resourceName}/reallowPromptMessages`, JSON.stringify({})); + }, time); // 10 seconds in milliseconds + } else { + $("#hint-prompt-container").empty(); + $("#hint-prompt-container").hide(); + } +} + +// CALLOUTS (DISPATCH) + +function ToggleCalloutDisplayPrompt(display, hotkeys, language, time, calloutdata, serviceType) { + var calloutDisplayPromptTime = (time / 1000); // in s + + if (display) { + $("#callout-prompt-container").empty(); // clear previous data + $("#callout-prompt-container").show(); + + // HTML + $("#callout-prompt-container").append(` +
+
+ ${language.EmergencyCall} + ${calloutdata.CalloutName} +
+
+
+ ${language.Caller} + ${calloutdata.FirstName} ${calloutdata.LastName} +
+
+ ${language.Location} + ${calloutdata.StreetName ?? 'N/A'} +
+
+ ${language.Postal} + ${calloutdata.Postal ?? 'N/A'} +
+
+ ${calloutdata.Description ?? 'N/A'} +
+
+ +
+ `); + + // Clear any existing countdown interval + clearInterval(window.countdownInterval); + + // Initial countdown display + const countdownMessage = `${calloutDisplayPromptTime} ${language.Seconds}...`; + $("#callout-countdown-timer").html(countdownMessage); + + calloutDisplayPromptTime--; + + window.countdownInterval = setInterval(function() { + if (calloutDisplayPromptTime > 0) { + // Update countdown display + const countdownMessage = `${calloutDisplayPromptTime} ${language.Seconds}...`; + $("#callout-countdown-timer").html(countdownMessage); + + calloutDisplayPromptTime--; + } else { + clearInterval(window.countdownInterval); + $("#callout-prompt-container").hide(); + $.post(`https://${resourceName}/calloutTimeout`, JSON.stringify({})); + } + }, 1000); // update every second + + } else { + $("#callout-prompt-container").empty(); // clear previous data + $("#callout-prompt-container").hide(); + } +} + +function ToggleCalloutInterface(display, hotkeys, pedCount, vehicleCount, objectCount, propCount, fireCount, smokeCount, calloutdata, pedOriginalCount, vehOriginalCount, objOriginalCount, propOriginalCount, fireOriginalCount, smokeOriginalCount) { + isDisplayingCalloutInterface = display; + if (display) { + $("#callout-interface-container").empty().removeClass('slideOutToLeft').addClass('slideInFromLeft'); // clear previous data + $("#callout-interface-container").show(); + + // HTML + $("#callout-interface-container").append(` +
แฏฝ ${calloutdata.CalloutName}
+ + + ${pedCount > 0 ? ` + + + + ` : ''} + ${vehicleCount > 0 ? ` + + + + ` : ''} + ${objectCount > 0 ? ` + + + + ` : ''} + ${propCount > 0 ? ` + + + + ` : ''} + ${fireCount > 0 ? ` + + + + ` : ''} + ${smokeCount > 0 ? ` + + + + ` : ''} + +
โŸก ${language.InvolvedPedsRemaining}${pedCount}/${pedOriginalCount}
โŸก ${language.InvolvedVehsRemaining}${vehicleCount}/${vehOriginalCount}
โŸก ${language.InvolvedObjsRemaining}${objectCount}/${objOriginalCount}
โŸก ${language.InvolvedPropsRemaining}${propCount}/${propOriginalCount}
โŸก ${language.ExtinguishAllFires}${fireCount}/${fireOriginalCount}
โŸก ${language.ClearAreaOfSmoke}${smokeCount}/${smokeOriginalCount}
+
+
${language.Press} ${hotkeys.ToggleCalloutInfo} ${language.ToHideOrShow}
+ `); + + } else { + $("#callout-interface-container").empty(); // clear previous data + $("#callout-interface-container").hide(); + $('#minimized-indicator').fadeOut(200); // Hide indicator when interface is completely closed + } +} + + +function TogglePreCalloutInterface(display, hotkeys, calloutdata) { + isDisplayingPreCalloutInterface = display; + if (display) { + $("#callout-pre-interface-container").empty().removeClass('slideOutToLeft').addClass('slideInFromLeft'); // clear previous data + $("#callout-pre-interface-container").show(); + + // HTML + $("#callout-pre-interface-container").append(` +
+ แฏฝ + ${wrapText(`${language.EmergencyCall} (${calloutdata?.CalloutName ?? 'N/A'})`, 40)} +
+ + + + + + + + + + + + + + + + + + + + + + +
+ โŸก + ${language.Caller}
+ ${wrapText(`${calloutdata?.FirstName ?? 'N/A'} ${calloutdata?.LastName ?? 'N/A'}`, 70)} +
+ โŸก + ${language.CallDescription}
+ ${wrapText(calloutdata?.Description ?? 'N/A', 70)} +
+ โŸก + ${language.Location}
+ ${wrapText(calloutdata?.StreetName ?? 'N/A', 70)} +
+ โŸก + ${language.Postal}
+ ${wrapText(calloutdata?.Postal ?? 'N/A', 70)} +
+ โŸก + ${language.CalloutUnitsRequired}
+ ${wrapText(calloutdata?.CalloutUnitsRequired?.description ?? 'N/A', 70)} +
+ โŸก + ${language.DispatchNote}
+ ${wrapText(language.DispatchNoteResponseText, 70)} +
+
+
${language.Press} ${hotkeys.ToggleCalloutInfo} ${language.ToHideOrShow}
+ `); + + } else { + $("#callout-pre-interface-container").empty(); // clear previous data + $("#callout-pre-interface-container").hide(); + $('#minimized-indicator').fadeOut(200); // Hide indicator when interface is completely closed + } +} + +// WAYPOINTS + +let Waypoints = [] + +// Cache DOM elements and values for better performance +let waypointCache = { + container: null, + distanceElement: null, + lastDistanceText: '', + lastScaleX: -999, + lastScaleY: -999, + width: 0, + height: 0, + offsetWidth: 0, + offsetHeight: 0, + needsSizeRecalc: true +}; + +// Update window dimensions on resize +window.addEventListener('resize', function() { + waypointCache.width = window.innerWidth; + waypointCache.height = window.innerHeight; + waypointCache.needsSizeRecalc = true; +}); + +function UpdateWaypointPosition(scaleX, scaleY, distanceText) { + let waypoint = Waypoints[0]; + if (waypoint == null) { + $("#waypoint-container").hide(); + return; + } + + // Initialize cache if needed + if (!waypointCache.container) { + waypointCache.container = document.getElementById('waypoint-container'); + waypointCache.distanceElement = document.getElementById('waypoint-distance'); + waypointCache.width = window.innerWidth; + waypointCache.height = window.innerHeight; + } + + // Show container if hidden + if (waypointCache.container.style.display === 'none') { + $("#waypoint-container").show(); + waypointCache.needsSizeRecalc = true; + } + + // Only update distance text if it changed + if (distanceText !== waypointCache.lastDistanceText) { + waypointCache.distanceElement.innerHTML = `แฏฝ ${distanceText}`; + waypointCache.lastDistanceText = distanceText; + waypointCache.needsSizeRecalc = true; + } + + // Recalculate size only when needed (text changed or first time) + if (waypointCache.needsSizeRecalc) { + let positionInfo = waypointCache.container.getBoundingClientRect(); + waypointCache.offsetWidth = positionInfo.width; + waypointCache.offsetHeight = positionInfo.height; + waypointCache.needsSizeRecalc = false; + } + + // Only update position if it changed significantly (reduce jitter) + const threshold = 0.001; // ~1 pixel change threshold + if (Math.abs(scaleX - waypointCache.lastScaleX) > threshold || + Math.abs(scaleY - waypointCache.lastScaleY) > threshold) { + waypointCache.container.style.left = ((waypointCache.width - waypointCache.offsetWidth) * scaleX) + "px"; + waypointCache.container.style.top = ((waypointCache.height - waypointCache.offsetHeight) * scaleY) + "px"; + waypointCache.lastScaleX = scaleX; + waypointCache.lastScaleY = scaleY; + } +} + +function AddWaypoint(addOrRemove) { + let element = document.getElementById('waypoint-container'); + if (addOrRemove) { + Waypoints.push({ element: element }); + // Reset cache + waypointCache.needsSizeRecalc = true; + waypointCache.lastDistanceText = ''; + } else { + $("#waypoint-container").hide(); + Waypoints = []; + // Clear cache + waypointCache.lastDistanceText = ''; + waypointCache.lastScaleX = -999; + waypointCache.lastScaleY = -999; + } +} + +// ERS SELECTION MENU + +let escapeEventListenerAddedERSSelectionMenu = false; +let menuSoundInstance = null; +function ToggleERSSelectionMenu(display, permissions) { + if (display) { + const hasPoliceAccess = permissions.isPolice; + const hasAmbulanceAccess = permissions.isAmbulance; + const hasFireAccess = permissions.isFire; + const hasTowAccess = permissions.isTow; + + fadeOutMenuMusic(menuSoundInstance) + menuSoundInstance = PlayNUISound('generic-sounds', 'selectionmenu', 0.5); + + // HTML + const modal = ` + + `; + + // Add the modal to the page + $('body').append(modal); + + // Initialize the modal with static backdrop and disabled keyboard interaction + $('#ers-selection-modal').modal({ + backdrop: 'static', + keyboard: false + }); + + // Show the modal + $('#ers-selection-modal').modal('show'); + + for (var i = 1; i <= 6; i++) { + addSoundOnHoverEventListener('s-btn-' + i); + } + + // Handle Escape key press only when the modal is open + $('#ers-selection-modal').on('shown.bs.modal', function() { + if (!escapeEventListenerAddedERSSelectionMenu) { + $(document).on('keydown', function(event) { + if (event.key === "Escape") { + // Close the modal + fadeOutMenuMusic(menuSoundInstance) + $('#ers-selection-modal').modal('hide'); + // Trigger the same action as the "No" button click + CancelServiceSelection(); + // Ensure the event doesn't propagate further + event.stopPropagation(); + } + }); + escapeEventListenerAddedERSSelectionMenu = true; + } + }).on('hidden.bs.modal', function() { + // Remove the Escape key press event listener when the modal is closed + $(document).off('keydown'); + escapeEventListenerAddedERSSelectionMenu = false; + }); + + } else { + // Hide and remove the modal if display is false + $('#ers-selection-modal').modal('hide').on('hidden.bs.modal', function () { + fadeOutMenuMusic(menuSoundInstance) + $(this).remove(); + }); + } +} + +function CancelServiceSelection() { + $.post(`https://${resourceName}/cancelServiceSelection`, JSON.stringify({})); + $('#ers-selection-modal').modal('hide').on('hidden.bs.modal', function () { + fadeOutMenuMusic(menuSoundInstance) + $(this).data('bs.modal', null); // Remove data object + $(this).remove(); // Remove the modal element from DOM + }); +} + +function SelectService(serviceType) { + $.post(`https://${resourceName}/selectedService`, JSON.stringify({ + service: serviceType + })); + $('#ers-selection-modal').modal('hide').on('hidden.bs.modal', function () { + fadeOutMenuMusic(menuSoundInstance) + $(this).data('bs.modal', null); // Remove data object + $(this).remove(); // Remove the modal element from DOM + }); +} + +function fadeOutMenuMusic(soundInstance) { + if (soundInstance !== null) { + soundInstance.fade(soundInstance.volume(), 0, 5000); + setTimeout(function() { + soundInstance.stop(); + }, 5000); + } +} + +let escapeEventListenerAddedERSGearnMenu = false; + +function DisplayGearMenu(display, locationData) { + if (display) { + + fadeOutMenuMusic(menuSoundInstance); + menuSoundInstance = PlayNUISound('generic-sounds', 'selectionmenu', 0.5); + + //HTML + const modal = ` + + `; + + // Add the modal to the page + $('body').append(modal); + + var clothingOptions = locationData.ClothingData; + + function getBackgroundColour(serviceType) { + switch (serviceType) { + case 'police': return 'primary'; + case 'fire': return 'danger'; + case 'ambulance': return 'warning'; + case 'tow': return 'info'; + default: return 'secondary'; + } + } + + let backgroundColour = getBackgroundColour(locationData.ServiceType); + + // Generate the HTML for each clothing option + $.each(clothingOptions, function (key, v) { + let locationDataJson = encodeURIComponent(JSON.stringify(locationData)); + + // Minify + $("#gear-options").append(`
${v.Name}

${v.Description}

`); + + // HTML + // $("#gear-options").append(` + //
+ //
+ //
+ //
${v.Name}
+ //
+ //
+ //

+ // ${v.Description} + //

+ //
+ // + //
+ //
+ // `); + }); + + // Initialize the modal with static backdrop and disabled keyboard interaction + $('#ers-gear-modal').modal({ + backdrop: 'static', + keyboard: false + }); + + // Show the modal + $('#ers-gear-modal').modal('show'); + + for (var i = 0; i < clothingOptions.length; i++) { + addSoundOnHoverEventListener('g-btn-' + i); + } + + // Handle Escape key press only when the modal is open + $('#ers-gear-modal').on('shown.bs.modal', function() { + if (!escapeEventListenerAddedERSGearnMenu) { + $(document).on('keydown', function(event) { + if (event.key === "Escape") { + // Close the modal + fadeOutMenuMusic(menuSoundInstance); + $('#ers-gear-modal').modal('hide'); + // Trigger the same action as the "No" button click + CancelGearSelection(); + // Ensure the event doesn't propagate further + event.stopPropagation(); + } + }); + escapeEventListenerAddedERSGearnMenu = true; + } + }).on('hidden.bs.modal', function() { + // Remove the Escape key press event listener when the modal is closed + $(document).off('keydown'); + escapeEventListenerAddedERSGearnMenu = false; + }); + + } else { + // Hide and remove the modal if display is false + $('#ers-gear-modal').modal('hide').on('hidden.bs.modal', function () { + fadeOutMenuMusic(menuSoundInstance); + $(this).remove(); + }); + } +} + +function handleClick(button) { + let key = button.getAttribute('data-key'); + let locationDataJson = button.getAttribute('data-location-data'); + let locationData = JSON.parse(decodeURIComponent(locationDataJson)); + SelectedGear(key, locationData); +} + +function SelectedGear(key, locationData) { + $.post(`https://${resourceName}/selectedGear`, JSON.stringify({ + clothingIndex: key, + locationData: locationData + })); + $('#ers-gear-modal').modal('hide').on('hidden.bs.modal', function () { + fadeOutMenuMusic(menuSoundInstance); + $(this).data('bs.modal', null); // Remove data object + $(this).remove(); // Remove the modal element from DOM + }); +} + +function CancelGearSelection() { + $.post(`https://${resourceName}/cancelGearSelection`, JSON.stringify({})); + $('#ers-gear-modal').modal('hide').on('hidden.bs.modal', function () { + fadeOutMenuMusic(menuSoundInstance) + $(this).data('bs.modal', null); // Remove data object + $(this).remove(); // Remove the modal element from DOM + }); +} + +///////////////////// UNIFIED PROMPT SYSTEM ///////////////////// + +///////////////////// USER INTERFACE TOGGLE ///////////////////// + +const containerIDs = { + preCallout: "#callout-pre-interface-container", + callout: "#callout-interface-container", +}; + +function slideOut(element) { + $(element).removeClass('slideInFromLeft').addClass('slideOutToLeft'); + setTimeout(() => { + $(element).hide(); + updateMinimizedIndicator(); + }, 300); // Match duration with animation +} + +// Function to show the element with slide-in animation +function slideIn(element) { + $(element).show().removeClass('slideOutToLeft').addClass('slideInFromLeft'); + updateMinimizedIndicator(); +} + +function updateMinimizedIndicator() { + const preCalloutHidden = isDisplayingPreCalloutInterface && !$(containerIDs.preCallout).is(':visible'); + const calloutHidden = isDisplayingCalloutInterface && !$(containerIDs.callout).is(':visible'); + + // Show indicator if any interface is hidden + if (preCalloutHidden || calloutHidden) { + $('#minimized-indicator').fadeIn(200); + } else { + $('#minimized-indicator').fadeOut(200); + } +} + +function toggleCalloutInfo() { + // Toggle pre-callout interface based on its initial state + if (isDisplayingPreCalloutInterface) { + const preCalloutElement = containerIDs.preCallout; + if ($(preCalloutElement).is(':visible')) { + slideOut(preCalloutElement); + } else { + slideIn(preCalloutElement); + } + } + + // Toggle callout interface based on its initial state + if (isDisplayingCalloutInterface) { + const calloutElement = containerIDs.callout; + if ($(calloutElement).is(':visible')) { + slideOut(calloutElement); + } else { + slideIn(calloutElement); + } + } +} + +// Click handler for minimized indicator +document.addEventListener('DOMContentLoaded', function() { + const minimizedIndicator = document.getElementById('minimized-indicator'); + if (minimizedIndicator) { + minimizedIndicator.addEventListener('click', function() { + toggleCalloutInfo(); + }); + } +}); + +///////////////////// CALLOUT UNIT WAYPOINTS ///////////////////// + +function updateWaypoints(data) { + const waypointData = data.data; + const existingWaypoints = trackExistingUnitWaypoints(); + for (const [key, value] of Object.entries(waypointData)) { + if (value !== null) { + if (value.distanceText > 0) { + processUnitWaypoint(key, value, existingWaypoints); + } + } + } + removeUnusedUnitWaypoints(existingWaypoints); +} + +function trackExistingUnitWaypoints() { + const existingWaypoints = new Set(); + document.querySelectorAll('.unit-waypoint-container').forEach(container => { + existingWaypoints.add(container.id); + }); + return existingWaypoints; +} + +function processUnitWaypoint(key, value, existingWaypoints) { + const waypointId = `unit-waypoint-container-${key}`; + let waypointContainer = document.getElementById(waypointId); + + if (!waypointContainer) { + waypointContainer = createUnitWaypointContainer(waypointId); + } + + updateUnitWaypointPosition(waypointContainer, value); + updateUnitWaypointContent(waypointContainer, value); + + existingWaypoints.delete(waypointId); +} + +function createUnitWaypointContainer(waypointId) { + const waypointContainer = document.createElement('div'); + waypointContainer.classList.add('unit-waypoint-container', 'smooth-transition'); + waypointContainer.id = waypointId; + document.body.appendChild(waypointContainer); + return waypointContainer; +} + +function updateUnitWaypointPosition(container, value) { + const width = window.innerWidth; + const height = window.innerHeight; + const positionInfo = container.getBoundingClientRect(); + const offsetWidth = positionInfo.width; + const offsetHeight = positionInfo.height; + + if (value.scaleX >= 0 && value.scaleX <= 1 && value.scaleY >= 0 && value.scaleY <= 1) { + container.style.left = ((width - offsetWidth) * value.scaleX) + "px"; + container.style.top = ((height - offsetHeight) * value.scaleY) + "px"; + } +} + +function updateUnitWaypointContent(container, value) { + container.innerHTML = ` + แฏฝ ${value.distanceText}${value.metrics} + `; +} + +function removeUnusedUnitWaypoints(existingWaypoints) { + existingWaypoints.forEach(id => { + const container = document.getElementById(id); + if (container) { + container.remove(); + } + }); +} + +///////////////////// QUESTIONING ///////////////////// + +function ToggleQuestionsModule(display, questions) { + if (display) { + $("#question-options-list").empty(); + $("#ped-interaction-questioning").show(); + + if (questions.length > 0) { + + // Render the questions in a column with spacing + let html = `
- ${t.map((e,t)=>` + ${questions.map((q, index) => ` - `).join("")} + `).join('')}
- `;$("#question-options-list").append(a),applySavedPosition("ped-interaction-questioning"),t.forEach((e,t)=>{let a=`s-btn-${t+1}`;document.getElementById(a)&&addSoundOnHoverEventListener(a)}),$("#question-options-list button").off("click").on("click",function(){let e=$(this).data("target"),t=$(this).data("question-text"),a=$(this).data("sound-file"),n=$(this).data("sound-volume");e&&(PlayNUISound("generic-sounds","q_select",1),$.post(`https://${resourceName}/questionSelected`,JSON.stringify({questionData:{id:e,text:t,soundFile:a,soundVolume:n}})))})}let n=` + `; + $("#question-options-list").append(html); + + // Add sound effects to the question buttons + questions.forEach((_, index) => { + const buttonId = `s-btn-${index + 1}`; + if (document.getElementById(buttonId)) { + addSoundOnHoverEventListener(buttonId); + } + }); + + // Add click handlers + $("#question-options-list button").off("click").on("click", function() { + let target = $(this).data("target"); + let questionText = $(this).data("question-text"); + let soundFile = $(this).data("sound-file"); + let soundVolume = $(this).data("sound-volume"); + if (target) { + // Find the full question data for this button + const selectedQuestion = { + id: target, + text: questionText, + soundFile: soundFile, + soundVolume: soundVolume + }; + + PlayNUISound('generic-sounds', "q_select", 1.0); + + $.post(`https://${resourceName}/questionSelected`, JSON.stringify({ + questionData: selectedQuestion + })); + } + }); + } + + // Leave button + let leaveBtn = ` - `;$("#question-leave-btn").html(n),document.getElementById("leave-questioning-btn")&&addSoundOnHoverEventListener("leave-questioning-btn"),$("#leave-questioning-btn").off("click").on("click",function(){PlayNUISound("generic-sounds","radialclose",.5),$.post(`https://${resourceName}/leaveQuestioning`,JSON.stringify({}))})}else $("#ped-interaction-questioning").hide(),$("#question-options-list").empty(),$("#question-leave-btn").empty()}function UpdateAnswers(e,t){if(e){let a=$("#question-answers-list");a.empty(),a.html(` + `; + $("#question-leave-btn").html(leaveBtn); + + // Add sound effect to leave button + if (document.getElementById("leave-questioning-btn")) { + addSoundOnHoverEventListener("leave-questioning-btn"); + } + + // Add click handler for leave button + $("#leave-questioning-btn").off("click").on("click", function() { + PlayNUISound('generic-sounds', "radialclose", 0.5); + $.post(`https://${resourceName}/leaveQuestioning`, JSON.stringify({})); + }); + + } else { + $("#ped-interaction-questioning").hide(); + $("#question-options-list").empty(); + $("#question-leave-btn").empty(); + } +} + +function UpdateAnswers(display, answers) { + if (display) { + // Get the answers container and clear it + let answersContainer = $("#question-answers-list"); + + // Clear the answers container + answersContainer.empty(); + + // Add a title above the answers + answersContainer.html(`
@@ -53,30 +2816,42 @@ let resourceName=null,language=null,commands=null,firstnames={},lastnames={},isD
- ${Array.isArray(t)&&t.length>0?t.map((e,t)=>` + ${Array.isArray(answers) && answers.length > 0 ? answers.map((value, index) => `
- User Profile + User Profile
- ${e.question||""} + ${value.question || ''} ${new Date().toLocaleTimeString()}
-

${e.answer||""}

+

${value.answer || ''}

- `).join(""):'
...
'} + `).join('') : '
...
'}
- `)}else $("#question-answers-list").empty()}function ToggleDualSteeringMode(e){let t=$("#dual-steering-mode");t.toggle(e),e?(t.html(` + `); + } else { + $("#question-answers-list").empty(); + } +} + +///////////////////// DUAL STEERING MODE ///////////////////// + +function ToggleDualSteeringMode(display) { + const container = $("#dual-steering-mode"); + container.toggle(display); + if (display) { + container.html(`
${language.DualSteeringMode}
โ†‘${language.ReelInWinch}
@@ -84,4 +2859,45 @@ let resourceName=null,language=null,commands=null,firstnames={},lastnames={},isD
โ†’${language.SteerRight}
โ†${language.SteerLeft}
โŒซ${language.DisconnectWinch}
- `),applySavedPosition("dual-steering-mode")):t.empty()}function hideAllPrompts(){$("#unified-prompt").empty().hide()}function PlayNUISound(e,t,a){var n=null;return null!=n&&n.pause(),(n=new Howl({src:[`nui://${resourceName}/NUI/sounds/${e}/${t}.ogg`]})).volume(a),n.play(),n}function wrapText(e,t){let a=[],n="";for(let i of e.toString().split(/\s+/))n.length+i.length+(n.length>0?1:0)>t&&(a.push(n.trim()+"-"),n=""),n+=(n.length>0?" ":"")+i;return n.length>0&&a.push(n.trim()),a.join("
")}function applySavedPosition(e){} \ No newline at end of file + `); + } else { + container.empty(); + } +} + +///////////////////// OTHER FUNCTIONS ///////////////////// + +function hideAllPrompts() { + $("#unified-prompt").empty().hide(); +} + +function PlayNUISound(soundFolderPrefix, filename, filevol) { + var audioPlayer = null; + if (audioPlayer != null) { + audioPlayer.pause(); + } + audioPlayer = new Howl({ src: [`nui://${resourceName}/NUI/sounds/${soundFolderPrefix}/${filename}.ogg`] }); + audioPlayer.volume(filevol); + audioPlayer.play(); + + return audioPlayer; +} + +function wrapText(text, maxCharsPerLine) { + const lines = []; + let currentLine = ''; + + for (const word of text.toString().split(/\s+/)) { + if ((currentLine.length + word.length + (currentLine.length > 0 ? 1 : 0)) > maxCharsPerLine) { + lines.push(currentLine.trim() + '-'); // Add a dash to the end of the line + currentLine = ''; + } + currentLine += (currentLine.length > 0 ? ' ' : '') + word; + } + + if (currentLine.length > 0) { + lines.push(currentLine.trim()); + } + + return lines.join('
'); // Join lines with
+} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_ambulance_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_ambulance_f.mp3 deleted file mode 100644 index 42139be58..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_ambulance_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_animalrescue_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_animalrescue_f.mp3 deleted file mode 100644 index 19a8f5386..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_animalrescue_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_coroner_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_coroner_f.mp3 deleted file mode 100644 index 7af589a6c..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_coroner_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_fire_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_fire_f.mp3 deleted file mode 100644 index 8e25a50b5..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_fire_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_mechanic_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_mechanic_f.mp3 deleted file mode 100644 index fd5d17105..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_mechanic_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_police_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_police_f.mp3 deleted file mode 100644 index 8abc1357c..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_police_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_roadservice_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_roadservice_f.mp3 deleted file mode 100644 index ed1adf779..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_roadservice_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_taxi_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_taxi_f.mp3 deleted file mode 100644 index ac24cb5dd..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_taxi_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_tow_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_tow_f.mp3 deleted file mode 100644 index 6dacb742b..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_backup_tow_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_breathalyze_1_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_breathalyze_1_f.mp3 deleted file mode 100644 index d469c9337..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_breathalyze_1_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_breathalyze_2_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_breathalyze_2_f.mp3 deleted file mode 100644 index c2d908107..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_breathalyze_2_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_breathalyze_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_breathalyze_f.mp3 deleted file mode 100644 index 1d39882e1..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_breathalyze_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_cuffs_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_cuffs_f.mp3 deleted file mode 100644 index f4f7319da..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_cuffs_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_drugtest_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_drugtest_f.mp3 deleted file mode 100644 index 60bf1dbff..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_drugtest_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_end_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_end_f.mp3 deleted file mode 100644 index d5e67676e..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_end_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_fine_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_fine_f.mp3 deleted file mode 100644 index 3f6c72593..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_fine_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_follow_1_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_follow_1_f.mp3 deleted file mode 100644 index 27a49ffc4..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_follow_1_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_follow_2_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_follow_2_f.mp3 deleted file mode 100644 index 1ff726ed9..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_follow_2_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_follow_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_follow_f.mp3 deleted file mode 100644 index 0fb15aa4f..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_follow_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_getout_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_getout_f.mp3 deleted file mode 100644 index 0fa634331..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_getout_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_handsup_1_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_handsup_1_f.mp3 deleted file mode 100644 index d93d93aa8..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_handsup_1_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_handsup_2_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_handsup_2_f.mp3 deleted file mode 100644 index 4486c3719..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_handsup_2_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_handsup_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_handsup_f.mp3 deleted file mode 100644 index f5ad6e059..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_handsup_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_hello_1_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_hello_1_f.mp3 deleted file mode 100644 index 73b331d5f..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_hello_1_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_hello_2_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_hello_2_f.mp3 deleted file mode 100644 index 1f3f19ac6..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_hello_2_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_hello_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_hello_f.mp3 deleted file mode 100644 index a6780d367..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_hello_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_id_1_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_id_1_f.mp3 deleted file mode 100644 index bbab14a00..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_id_1_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_id_2_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_id_2_f.mp3 deleted file mode 100644 index 013639dd0..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_id_2_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_id_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_id_f.mp3 deleted file mode 100644 index f00760e1e..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_id_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_impound_class_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_impound_class_f.mp3 deleted file mode 100644 index 090b7e255..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_impound_class_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_impound_done_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_impound_done_f.mp3 deleted file mode 100644 index c347fa464..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_impound_done_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_impound_task_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_impound_task_f.mp3 deleted file mode 100644 index 644f2f6ec..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_impound_task_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_air_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_air_f.mp3 deleted file mode 100644 index 84acbb627..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_air_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_army_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_army_f.mp3 deleted file mode 100644 index 4321fab31..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_army_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_heavy_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_heavy_f.mp3 deleted file mode 100644 index 809f6637b..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_heavy_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_light_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_light_f.mp3 deleted file mode 100644 index 7e753b381..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_light_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_medium_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_medium_f.mp3 deleted file mode 100644 index 0c599a45d..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_pursuit_backup_medium_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_putinvehicle_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_putinvehicle_f.mp3 deleted file mode 100644 index 6e230822d..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_putinvehicle_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_search_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_search_f.mp3 deleted file mode 100644 index 871d7be90..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_search_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_wait_1_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_wait_1_f.mp3 deleted file mode 100644 index a53f97f39..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_wait_1_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_wait_2_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_wait_2_f.mp3 deleted file mode 100644 index f5dbc0d37..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_wait_2_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_wait_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_wait_f.mp3 deleted file mode 100644 index 7517e1845..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_wait_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/de/de_warn_f.mp3 b/resources/[ERS]/night_ers/NUI/sounds/de/de_warn_f.mp3 deleted file mode 100644 index e0b872a45..000000000 Binary files a/resources/[ERS]/night_ers/NUI/sounds/de/de_warn_f.mp3 and /dev/null differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/en/en_arrest_rights.ogg b/resources/[ERS]/night_ers/NUI/sounds/en/en_arrest_rights.ogg new file mode 100644 index 000000000..37e4a807f Binary files /dev/null and b/resources/[ERS]/night_ers/NUI/sounds/en/en_arrest_rights.ogg differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/en/en_arrest_rights_f.ogg b/resources/[ERS]/night_ers/NUI/sounds/en/en_arrest_rights_f.ogg new file mode 100644 index 000000000..13819b016 Binary files /dev/null and b/resources/[ERS]/night_ers/NUI/sounds/en/en_arrest_rights_f.ogg differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/us/us_arrest_rights.ogg b/resources/[ERS]/night_ers/NUI/sounds/us/us_arrest_rights.ogg new file mode 100644 index 000000000..3068de553 Binary files /dev/null and b/resources/[ERS]/night_ers/NUI/sounds/us/us_arrest_rights.ogg differ diff --git a/resources/[ERS]/night_ers/NUI/sounds/us/us_arrest_rights_f.ogg b/resources/[ERS]/night_ers/NUI/sounds/us/us_arrest_rights_f.ogg new file mode 100644 index 000000000..e36534038 Binary files /dev/null and b/resources/[ERS]/night_ers/NUI/sounds/us/us_arrest_rights_f.ogg differ diff --git a/resources/[ERS]/night_ers/NUI/styles.css b/resources/[ERS]/night_ers/NUI/styles.css index f2f40d955..3e4e5245b 100644 --- a/resources/[ERS]/night_ers/NUI/styles.css +++ b/resources/[ERS]/night_ers/NUI/styles.css @@ -27,6 +27,11 @@ body { } */ /* A default font */ +html, body { + background: transparent !important; + background-color: transparent !important; +} + body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; font-size: 13px; @@ -196,6 +201,30 @@ body { transition: opacity 0.25s ease-out; } +#callout-interface-container h4, +#callout-pre-interface-container h4 { + font-size: 1.5rem; + font-weight: 500; + margin-bottom: 0.5rem; + margin-top: 0; +} + +#callout-interface-container h5, +#callout-pre-interface-container h5 { + font-size: 1.25rem; + font-weight: 500; + margin-bottom: 0.5rem; + margin-top: 0; +} + +#callout-interface-container h6, +#callout-pre-interface-container h6 { + font-size: 1rem; + font-weight: 500; + margin-bottom: 0.5rem; + margin-top: 0; +} + .hint { position: absolute; margin: 5px; @@ -243,6 +272,7 @@ body { top: var(--module-default-y, 50%); transform: translate(-50%, -50%); z-index: 1; + min-width: 550px; opacity: 0; animation: fadeIn 0.25s ease forwards; background-color: var(--interaction-bg-color); @@ -259,6 +289,506 @@ body { z-index: 1; opacity: 0; animation: fadeIn 0.25s ease forwards; + max-width: 400px; + max-height: 80vh; + overflow-y: auto; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* Simple loading indicator */ +.loading-indicator { + display: flex; + align-items: center; + justify-content: center; +} + +.loading-indicator i { + animation: loading-pulse 1.5s ease-in-out infinite; +} + +@keyframes loading-pulse { + 0%, 100% { + opacity: 0.5; + } + 50% { + opacity: 1; + } +} + +/* Compact ID Card Styles */ +#ped-interaction-id-card .card { + margin: 8px !important; + font-size: 12px; +} + +#ped-interaction-id-card .card-header { + padding: 8px 12px; + font-size: 13px; +} + +#ped-interaction-id-card .card-body { + padding: 8px 12px; +} + +#ped-interaction-id-card .list-group-item { + padding: 6px 8px; + font-size: 11px; +} + +#ped-interaction-id-card .profile-picture { + max-height: 120px !important; + object-fit: cover; +} + +#ped-interaction-id-card .license-badge { + font-size: 10px; + padding: 2px 6px; + margin: 1px; +} + +#ped-interaction-id-card .fs-5 { + font-size: 14px !important; +} + +#ped-interaction-id-card .col-md-4, +#ped-interaction-id-card .col-md-8 { + padding: 0 4px; +} + +#ped-interaction-id-card .row { + margin: 0; +} + +#ped-interaction-id-card .mb-3 { + margin-bottom: 8px !important; +} + +#ped-interaction-id-card .mb-2 { + margin-bottom: 4px !important; +} + +/* Compact License Display */ +.license-compact { + display: flex; + flex-wrap: wrap; + gap: 4px; + margin-top: 4px; +} + +.license-compact-item { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 3px 8px; + background: rgba(0, 0, 0, 0.4); + border-radius: 4px; + border: 1px solid rgba(255, 255, 255, 0.3); + font-size: 11px; + font-weight: 500; + white-space: nowrap; + color: #fff !important; +} + +.license-compact-item i { + font-size: 12px; +} + +/* Icon colors only - text stays white */ +.license-compact-item.text-success i { + color: #28a745; +} + +.license-compact-item.text-danger i { + color: #dc3545; +} + +.license-compact-item.text-warning i { + color: #ffc107; +} + +.license-compact-item.text-secondary i { + color: #6c757d; +} + +/* Minimalistic Hint Styles */ +.hint-minimal { + background: rgba(0, 0, 0, 0.8); + border: 1px solid rgba(255, 193, 7, 0.6); + border-radius: 8px; + padding: 12px; + max-width: 350px; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; +} + +.hint-header { + margin-bottom: 8px; + padding-bottom: 6px; + border-bottom: 1px solid rgba(255, 193, 7, 0.3); +} + +.hint-title { + color: #ffc107; + font-size: 13px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.hint-content { + display: flex; + flex-direction: column; + gap: 4px; +} + +.hint-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 3px 0; +} + +.hint-key { + color: #fff; + font-size: 11px; + font-weight: 600; + background: rgba(255, 193, 7, 0.2); + padding: 2px 6px; + border-radius: 3px; + border: 1px solid rgba(255, 193, 7, 0.4); + font-family: 'Courier New', monospace; +} + +.hint-desc { + color: rgba(255, 255, 255, 0.8); + font-size: 10px; + text-align: right; + max-width: 60%; + line-height: 1.3; +} + +.hint-footer { + margin-top: 8px; + padding-top: 6px; + border-top: 1px solid rgba(255, 193, 7, 0.3); + text-align: center; +} + +.hint-toggle { + color: rgba(255, 193, 7, 0.7); + font-size: 9px; + font-style: italic; +} + +/* Minimalistic Callout Styles */ +.callout-minimal { + background: rgba(0, 0, 0, 0.6); + border-radius: 8px; + padding: 12px; + max-width: 400px; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + border: 1px solid rgba(255, 255, 255, 0.2); + backdrop-filter: blur(5px); +} + +/* Service-specific subtle accents */ +.callout-minimal.callout-police { + border-left: 3px solid rgba(0, 87, 185, 0.75); +} + +.callout-minimal.callout-ambulance { + border-left: 3px solid rgba(40, 167, 69, 0.75); +} + +.callout-minimal.callout-fire { + border-left: 3px solid rgba(255, 69, 0, 0.75); +} + +.callout-minimal.callout-tow { + border-left: 3px solid rgba(120, 35, 35, 0.75); +} + +.callout-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; + padding-bottom: 6px; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + +.callout-title { + color: rgba(255, 255, 255, 0.9); + font-size: 14px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.callout-type { + color: rgba(255, 255, 255, 0.8); + font-size: 11px; + font-weight: 500; + background: rgba(255, 255, 255, 0.1); + padding: 2px 6px; + border-radius: 3px; + border: 1px solid rgba(255, 255, 255, 0.2); +} + +.callout-content { + display: flex; + flex-direction: column; + gap: 6px; + margin-bottom: 10px; +} + +.callout-info { + display: flex; + justify-content: space-between; + align-items: center; + padding: 2px 0; +} + +.callout-label { + color: rgba(255, 255, 255, 0.8); + font-size: 11px; + font-weight: 600; + min-width: 60px; +} + +.callout-value { + color: #fff; + font-size: 11px; + font-weight: 500; + text-align: right; + max-width: 60%; +} + +.callout-description { + margin-top: 4px; + padding: 6px; + background: rgba(255, 255, 255, 0.05); + border-radius: 4px; + border-left: 2px solid rgba(255, 255, 255, 0.3); +} + +.callout-desc { + color: rgba(255, 255, 255, 0.9); + font-size: 11px; + line-height: 1.4; + font-style: italic; +} + +.callout-footer { + display: flex; + justify-content: space-between; + align-items: center; + padding-top: 8px; + border-top: 1px solid rgba(255, 255, 255, 0.1); +} + +.callout-countdown { + color: rgba(255, 255, 255, 0.8); + font-size: 11px; + font-weight: 500; +} + +.callout-countdown .text-warning { + color: #ffc107; + font-weight: 700; +} + +.callout-actions { + display: flex; + align-items: center; + gap: 4px; +} + +.callout-btn { + color: #ffc107; + font-size: 11px; + font-weight: 700; + background: rgba(255, 193, 7, 0.2); + padding: 4px 8px; + border-radius: 4px; + border: 1px solid #ffc107; + font-family: 'Courier New', monospace; + cursor: pointer; + transition: all 0.2s ease; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.callout-btn:hover { + background: rgba(0, 0, 0, 0.9); + border-color: #ffd43b; + color: #ffd43b; + transform: scale(1.05); +} + +.callout-separator { + color: rgba(255, 255, 255, 0.5); + font-size: 10px; + margin: 0 2px; +} + +/* Minimalistic Dispatch Message Styles */ +.dispatch-minimal { + background: rgba(0, 0, 0, 0.8); + background-color: rgba(0, 0, 0, 0.8); + border-radius: 8px; + padding: 12px; + max-width: 400px; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + border: 1px solid rgba(255, 255, 255, 0.2); + border-left: 3px solid rgba(0, 123, 255, 0.6); +} + +#dispatch-message-prompt-card { + background: rgba(0, 0, 0, 0.8); + background-color: rgba(0, 0, 0, 0.8); +} + +/* If you want backdrop blur and it works in your setup, you can enable it here */ +.dispatch-minimal.with-blur { + backdrop-filter: blur(5px); + -webkit-backdrop-filter: blur(5px); +} + +.dispatch-header { + display: flex; + justify-content: space-between; + align-items: center; + gap: 12px; + margin-bottom: 10px; + padding-bottom: 6px; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + +.dispatch-title { + color: rgba(255, 255, 255, 0.9); + font-size: 14px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.dispatch-type { + color: rgba(255, 255, 255, 0.8); + font-size: 11px; + font-weight: 500; + background: rgba(255, 255, 255, 0.1); + padding: 2px 6px; + border-radius: 3px; + border: 1px solid rgba(255, 255, 255, 0.2); +} + +.dispatch-content { + display: flex; + flex-direction: column; + gap: 6px; + margin-bottom: 10px; +} + +.dispatch-callout-badge-container { + margin-bottom: 8px; +} + +.dispatch-callout-badge { + display: inline-block; + color: rgba(255, 255, 255, 0.9); + font-size: 11px; + font-weight: 600; + background: rgba(255, 193, 7, 0.2); + padding: 4px 10px; + border-radius: 4px; + border: 1px solid rgba(255, 193, 7, 0.5); + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.dispatch-message { + margin-bottom: 4px; + padding: 6px; + background: rgba(255, 255, 255, 0.05); + border-radius: 4px; + border-left: 2px solid rgba(255, 255, 255, 0.3); +} + +.dispatch-desc { + color: rgba(255, 255, 255, 0.9); + font-size: 11px; + line-height: 1.4; + font-style: italic; +} + +.dispatch-info { + display: flex; + justify-content: space-between; + align-items: center; + padding: 2px 0; +} + +.dispatch-label { + color: rgba(255, 255, 255, 0.8); + font-size: 11px; + font-weight: 600; + min-width: 60px; +} + +.dispatch-value { + color: rgba(255, 255, 255, 0.9); + font-size: 11px; + font-weight: 500; + text-align: right; + max-width: 60%; +} + +.dispatch-footer { + padding-top: 8px; + border-top: 1px solid rgba(255, 255, 255, 0.1); + font-size: 11px; + color: rgba(255, 255, 255, 0.8); +} + +.dispatch-track { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px; + background: linear-gradient(to right, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.6)); + border-radius: 4px; + border-top: 1px solid rgba(255, 255, 255, 0.1); + margin-top: 8px; +} + +.dispatch-track-text { + color: rgba(255, 255, 255, 0.9); + font-size: 11px; + font-weight: 500; +} + +.dispatch-track-btn { + color: #ffc107; + font-size: 11px; + font-weight: 700; + background: rgba(255, 193, 7, 0.2); + padding: 4px 8px; + border-radius: 4px; + border: 1px solid #ffc107; + font-family: 'Courier New', monospace; + cursor: pointer; + transition: all 0.2s ease; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.dispatch-track-btn:hover { + background: rgba(255, 193, 7, 0.3); + border-color: #ffd43b; + color: #ffd43b; + transform: scale(1.05); } .spinner-wrapper { @@ -1232,4 +1762,143 @@ body { opacity: 0; transform: translate(-50%, -50%) scale(0.8); } +} + +/* Slide animations for callout interfaces */ +@keyframes slideInFromLeft { + from { + opacity: 0; + transform: translateY(-50%) translateX(-100%); + } + to { + opacity: 1; + transform: translateY(-50%) translateX(0); + } +} + +@keyframes slideOutToLeft { + from { + opacity: 1; + transform: translateY(-50%) translateX(0); + } + to { + opacity: 0; + transform: translateY(-50%) translateX(-100%); + } +} + +.slideInFromLeft { + animation: slideInFromLeft 0.3s ease-out forwards; +} + +.slideOutToLeft { + animation: slideOutToLeft 0.3s ease-out forwards; +} + +/* Minimized Interface Indicator */ +#minimized-indicator { + position: fixed; + left: 20px; + top: 50%; + transform: translateY(-50%); + z-index: 1000; + display: none; + background: rgba(0, 0, 0, 0.7); + border: 2px solid rgba(255, 193, 7, 0.6); + border-left: 4px solid rgba(255, 193, 7, 0.9); + border-radius: 8px; + padding: 10px 12px; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4); +} + +#minimized-indicator:hover { + background: rgba(0, 0, 0, 0.85); + border-color: rgba(255, 193, 7, 0.9); + transform: translateY(-50%) scale(1.05); + box-shadow: 0 6px 16px rgba(255, 193, 7, 0.3); +} + +#minimized-indicator i { + font-size: 20px; + color: #ffc107; + display: block; + animation: pulse 2s infinite; +} + +#minimized-indicator .indicator-text { + color: rgba(255, 255, 255, 0.9); + font-size: 10px; + text-align: center; + margin-top: 4px; + text-transform: uppercase; + letter-spacing: 0.5px; + font-weight: 600; +} + +@keyframes pulse { + 0%, 100% { + opacity: 1; + transform: scale(1); + } + 50% { + opacity: 0.7; + transform: scale(0.95); + } +} + +/* Module indicator for TAB key reminder */ +.module-indicator { + position: fixed; + top: 20px; + left: 20px; + z-index: 10000; + background: rgba(0, 0, 0, 0.85); + border: 1px solid rgba(255, 193, 7, 0.4); + border-radius: 8px; + padding: 12px 16px; + padding-bottom: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5); + display: none; + animation: fadeIn 0.3s ease; + min-width: 100px; + overflow: hidden; +} + +.module-indicator i { + color: #ffc107; + font-size: 1.1rem; +} + +.module-indicator span { + color: rgba(255, 255, 255, 0.9); + font-size: 0.875rem; +} + +.module-indicator kbd { + padding: 2px 6px; + border-radius: 4px; + font-size: 0.8rem; + font-weight: 600; + font-family: monospace; +} + +/* Progress bar container - integrated into bottom border */ +.module-indicator-progress-container { + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 3px; + background: rgba(255, 255, 255, 0.1); + overflow: hidden; +} + +/* Progress bar fill - fills from left to right */ +.module-indicator-progress { + height: 100%; + width: 0%; + background: linear-gradient(90deg, rgba(255, 193, 7, 0.6) 0%, rgba(255, 193, 7, 1) 100%); + transition: width 0.1s linear; } \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_boat_migrants.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_boat_migrants.lua new file mode 100644 index 000000000..cd6955603 --- /dev/null +++ b/resources/[ERS]/night_ers/callouts/plugins/callout_boat_migrants.lua @@ -0,0 +1,115 @@ +Config.Callouts["boat_migrants"] = { + + Enabled = true, + CalloutName = "Reports of migrants arriving on a boat", + CalloutDescriptions = { + "Investigate reports of migrants arriving on a boat; secure the area and ensure their safety.", + "Alert: dispatch units to respond to reports of migrants arriving on a boat; provide immediate assistance.", + "Units required: respond to reports of a boat carrying migrants and take necessary actions to assist them.", + "Notice: check reports of migrants arriving on a boat; implement measures to ensure their wellbeing.", + "Alert: respond promptly to reports of migrants arriving on a boat; prioritize their safety and care.", + "Incident reported: look into reports of migrants arriving on a boat to provide necessary aid and support.", + "Investigate reports of a boat carrying migrants; coordinate with relevant authorities to address the situation.", + "Situation alert: address reports of migrants arriving on a boat; ensure the area is secured and help is provided.", + "Alert: handle reports of migrants arriving on a boat and follow protocols to ensure their safety and support.", + "Response needed: investigate reports of migrants arriving on a boat and take appropriate actions to assist and protect them.", + }, + CalloutUnitsRequired = { + description = "Police", + policeRequired = true, + ambulanceRequired = false, + fireRequired = false, + towRequired = false, + }, + CalloutLocations = { + [1] = vector3(-1417.2120, -1615.8606, 0.1448), + [2] = vector3(-1809.3936, -973.8002, 1.9747), + [3] = vector3(-2076.4451, -611.0533, 1.3401), + [4] = vector3(-3030.3972, -0.8509, 1.7006), + [5] = vector3(-3169.9976, 289.5727, 2.1437), + [6] = vector3(-3265.2388, 895.5994, -0.4368), + [7] = vector3(-3125.7136, 1656.5962, 0.4893), + [8] = vector3(-2685.5750, 2533.6912, 0.7223), + [9] = vector3(-2393.0715, 2630.3701, -0.0339), + [10] = vector3(-1868.3955, 2566.3022, 0.1976), + [11] = vector3(-1549.2698, 2626.0557, 1.5337), + [12] = vector3(-2553.6880, 3923.9187, 1.6076), + [13] = vector3(-2093.0620, 4599.1460, 1.1754), + [14] = vector3(-1394.5308, 5285.9351, 0.8501), + [15] = vector3(-885.7209, 5840.6069, 0.8044), + [16] = vector3(6.6508, 7059.5547, -0.6106), + [17] = vector3(3395.8420, 5637.5762, 0.9500), + [18] = vector3(2977.9421, 1821.2184, 1.2231), + [19] = vector3(2940.1265, 311.0411, 0.7346), + [20] = vector3(1601.8865, -2747.1536, 0.9043), + }, + PedChanceToFleeFromPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. + PedChanceToAttackPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. + PedChanceToSurrender = 0, -- Value between 0 and 100 -> Lower is less chance. + PedChanceToObtainWeapons = 0, -- Value between 0 and 100 -> Lower is less chance. + PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. + PedActionMaximumTimeoutInMs = 1000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! + PedActionOnNoActionFound = "none", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" + PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. + "weapon_unarmed", + }, + + client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) + + for index, pedNetId in pairs(pedList) do + local ped = NetToPed(pedNetId) + if DoesEntityExist(ped) then + ERS_RequestNetControlForEntity(ped) + if not IsPedInAnyBoat(ped) then + ERS_SetMovementAnimClipSetToPed(ped, "move_m@injured") + TaskWanderStandard(ped, 10.0, 10) + else + TaskReactAndFleePed(ped, plyPed) + end + end + end + + ERS_CreateTemporaryBlipForEntities(pedList, 30000) + + ERS_PerformTimedActionOnPed(calloutDataClient, pedList) + + end, + server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) + + + local diameter = 20 + + -- Build vehicle + local vehModel = "dinghy" + local vehType = "boat" + local vehCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z) + local vehHeading = math.random(360) + local vehNetId = ERS_CreateVehicle(vehModel, vehType, vehCoords, vehHeading) + local vehicle = NetworkGetEntityFromNetworkId(vehNetId) + table.insert(vehicleList, vehNetId) + + -- Build boat captain + local seatIndex = -1 + local pedModel = ERS_GetRandomModel(Config.randomPeds) + local pedCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z+3.0) + local pedHeading = math.random(360) + local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) + local ped = NetworkGetEntityFromNetworkId(pedNetId) + SetPedIntoVehicle(ped, vehicle, seatIndex) + table.insert(pedList, pedNetId) + + -- Build migrant peds + local randomAmountOfPeds = math.random(2,10) + for i = 0, randomAmountOfPeds do + local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) + local pedModel = ERS_GetRandomModel(Config.randomPeds) + local pedCoords = vector3(coords.x, coords.y, coords.z + 1.0) + local pedHeading = math.random(360) + local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) + local ped = NetworkGetEntityFromNetworkId(pedNetId) + table.insert(pedList, pedNetId) + end + + return true + end +} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_aggresive_boars.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_aggresive_boars.lua deleted file mode 100644 index 754587522..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_aggresive_boars.lua +++ /dev/null @@ -1,92 +0,0 @@ -Config.Callouts["roxwood_aggresive_boars"] = { - - Enabled = true, - CalloutName = "Aggressive Boars", - CalloutDescriptions = { - "Respond to a report of aggressive boars attacking a farmer; ensure public safety and coordinate with animal control.", - "Alert: wild boars spotted attacking a farmer; deploy units to contain the animals and protect civilians.", - "Units needed: emergency call for aggressive boars; focus on securing the area and preventing any harm.", - "Notice: boars reported attacking a farmer; act promptly to control the situation and provide assistance.", - "Alert: report of aggressive boars; intervention needed to secure the scene and ensure safety.", - "Incident reported: boars sighted attacking a farmer; take action to deliver urgent response and support.", - "Respond to a situation involving aggressive boars; prioritize public safety and coordinate with wildlife experts.", - "Situation alert: boars on the loose; provide immediate assistance and ensure the area is secure.", - "Alert: report of boars attacking a farmer; respond swiftly to address the emergency and offer necessary support.", - "Response needed: aggressive boars; ensure public safety, provide aid, and secure the area.", - }, - CalloutUnitsRequired = { - description = "Police", - policeRequired = true, - ambulanceRequired = false, - fireRequired = false, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-1823.0022, 6998.0410, 34.9726), - [2] = vector3(-2387.3379, 7242.6768, 29.0290), - [3] = vector3(-2461.5059, 7537.0752, 29.0388), - [4] = vector3(-2497.2771, 7169.6704, 29.0752), - [5] = vector3(-2538.9504, 7436.2910, 28.8805), - }, - PedChanceToFleeFromPlayer = 0, -- Boars won't flee from the player. - PedChanceToAttackPlayer = 100, -- Low chance to attack the player. - PedChanceToSurrender = 0, -- Boars won't surrender. - PedChanceToObtainWeapons = 0, -- Boars don't use weapons. - PedActionMinimumTimeoutInMs = 10000, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 15000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "flee",-- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_musket", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - local farmer - local boarPedList = {} - - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - ERS_RequestNetControlForEntity(ped) - if index == 1 then - farmer = ped - ERS_PedEquipWeapon(ped, "weapon_musket", 100) - Wait(100) - TaskCombatPed(ped, NetToPed(pedList[2]), 0, 16) - else - TaskCombatPed(ped, farmer, 0, 16) - table.insert(boarPedList, pedNetId) - end - end - end - - ERS_CreateTemporaryBlipForEntities(boarPedList, 30000) - - ERS_PerformTimedActionOnPed(calloutDataClient, boarPedList) - end, - - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - local diameter = 15 - - -- Build farmer - local farmerModel = "a_m_m_farmer_01" - local farmerCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z+1.0) - local farmerHeading = math.random(360) - local farmerNetId = ERS_CreatePed(farmerModel, farmerCoords, farmerHeading) - local farmer = NetworkGetEntityFromNetworkId(farmerNetId) - table.insert(pedList, farmerNetId) - - -- Build boars - local boarModel = "a_c_boar" - local randomAmountOfBoars = math.random(3, 5) -- Randomize number of boars - for i = 1, randomAmountOfBoars do - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - local boarCoords = vector3(coords.x, coords.y, coords.z+1.0) - local boarHeading = math.random(360) - local boarNetId = ERS_CreatePed(boarModel, boarCoords, boarHeading) - local boar = NetworkGetEntityFromNetworkId(boarNetId) - table.insert(pedList, boarNetId) - end - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_animal_on_road.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_animal_on_road.lua deleted file mode 100644 index 661201833..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_animal_on_road.lua +++ /dev/null @@ -1,84 +0,0 @@ -Config.Callouts["roxwood_animal_on_road"] = { - - Enabled = true, - CalloutName = "Animal on the Road in Roxwood", - CalloutDescriptions = { - "An unexpected type of animal has appeared on the road, causing a disruption in traffic flow.", - "Emergency services have been called to intervene in a situation where an animal is impeding traffic on the road.", - "Reports indicate a disturbance on the roadway, with an unidentified creature causing a commotion.", - "A peculiar incident has unfolded on the road, requiring immediate attention to ensure public safety.", - "Emergency services have been dispatched to address an obstruction on the road, involving an animal.", - "A surprising encounter has occurred on the road, with an unknown creature causing a hindrance to traffic.", - "Witnesses report an unusual occurrence on the road, with an unidentified animal creating a hazard for motorists.", - "An incident has occurred on the road, with an animal posing a potential threat to drivers.", - "Emergency services have been alerted to a situation where an unidentified creature is obstructing the roadway.", - "Reports suggest an unexpected type of animal on the road, involving an animal that requires immediate assistance.", - }, - CalloutUnitsRequired = { - description = "Police, animal rescue.", - policeRequired = true, - ambulanceRequired = false, - fireRequired = false, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-2917.2009, 6687.8828, 24.9933), - [2] = vector3(-2385.1338, 6949.2163, 35.3990), - [3] = vector3(-1927.2576, 7528.9648, 75.0004), - [4] = vector3(-673.5764, 7669.7896, 28.7780), - [5] = vector3(-670.4109, 6713.2271, 21.3245), - [6] = vector3(-397.3026, 7055.0483, 20.4035), - [7] = vector3(-2483.4431, 7576.3521, 28.6643), - [8] = vector3(-2060.8218, 8574.8389, 36.1939), - [9] = vector3(-2706.7444, 6928.1416, 28.8962), - [10] = vector3(-2615.2388, 6572.5176, 24.5263), - }, - PedChanceToFleeFromPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 0, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 1000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "none", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_unarmed", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - ERS_RequestNetControlForEntity(ped) - ClearPedTasks(ped) - - if Config.Debug then - print("Found animal entity: "..ped) - end - - TaskWanderStandard(ped, 10.0, 10) - end - end - - ERS_CreateTemporaryBlipForEntities(pedList, 15000) - --ERS_PerformTimedActionOnPed(calloutDataClient, pedList) - - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - - local diameter = 20 - - local randomAmountOfAnimals = math.random(1, 8) - local randomAnimalPedModel = ERS_GetRandomModel(Config.calloutAnimals) - for i = 1, randomAmountOfAnimals do - -- Build animals of the same type. - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - local animalPedCoords = vector3(coords.x, coords.y, coords.z) - local animalPedHeading = math.random(360) - local animalPedNetId = ERS_CreatePed(randomAnimalPedModel, animalPedCoords, animalPedHeading) - local animalPed = NetworkGetEntityFromNetworkId(animalPedNetId) - table.insert(pedList, animalPedNetId) - end - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_arson.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_arson.lua deleted file mode 100644 index a54fdcc13..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_arson.lua +++ /dev/null @@ -1,102 +0,0 @@ -Config.Callouts["roxwood_arson"] = { - - Enabled = true, - CalloutName = "Reports of Arson in Roxwood", - CalloutDescriptions = { - "Suspected arson incidents have been reported, requiring immediate response from law enforcement and fire services.", - "Urgent assistance needed to address suspected arson, ensuring community safety and property protection.", - "Multiple suspected arson cases reported, demanding swift action to prevent further damage and risk.", - "Identified arson cases prompt the need for additional resources to investigate and control the situation.", - "Emergency services alerted to suspected arson, necessitating coordinated efforts to apprehend those responsible.", - "Authorities seek assistance in addressing suspected arson, emphasizing public vigilance and cooperation.", - "Additional units required to support law enforcement and fire teams in responding to suspected arson incidents.", - "Emergency backup needed to help manage and contain suspected arson, ensuring public safety.", - "Responders call for assistance in dealing with suspected arson, highlighting the urgency of the situation.", - "Immediate intervention crucial to manage and address suspected arson, safeguarding lives and property.", - }, - CalloutUnitsRequired = { - description = "Police, Fire", - policeRequired = true, - ambulanceRequired = false, - fireRequired = true, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-3082.4443, 7910.6416, 54.4692), - [2] = vector3(-3083.5991, 7936.8086, 54.1143), - [3] = vector3(-3044.8267, 7937.8999, 58.7173), - [4] = vector3(-3013.9849, 7916.1396, 58.6186), - [5] = vector3(-2541.5210, 7480.6040, 28.7263), - [6] = vector3(-2304.5576, 7760.9302, 44.3912), - [7] = vector3(-2281.4097, 8151.0815, 34.1373), - [8] = vector3(-1140.2708, 8119.0449, 23.1818), - [9] = vector3(-416.6748, 7650.4414, 6.3326), - [10] = vector3(-341.3544, 7396.8135, 6.4100), - }, - PedChanceToFleeFromPlayer = 50, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 50, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 10, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 60, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 5000, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 10000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "flee", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_knife", - "weapon_hammer", - "weapon_crowbar", - "weapon_bottle", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - ERS_RequestNetControlForEntity(ped) - TaskSetBlockingOfNonTemporaryEvents(ped, true) - Wait(100) - ERS_SetPedToFleeFromPlayer(ped) - end - end - - ERS_CreateTemporaryBlipForEntities(pedList, 15000) - - ERS_PerformTimedActionOnPed(calloutDataClient, pedList) - - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - - local diameter = 2 - - if UsingSmartFires then - -- Full version - local fireSize = Config.RandomSmallFireOrSmokeSize[math.random(#Config.RandomSmallFireOrSmokeSize)] - local fireType = Config.NormalFireTypes[math.random(#Config.NormalFireTypes)] - local fireId = exports['SmartFires']:CreateFire(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), fireSize, fireType) - DebugPrint("Created fire with ID: "..fireId) - table.insert(fireList, fireId) - else - -- Lite version - local fireSize = Config.RandomSmallFireOrSmokeSize[math.random(#Config.RandomSmallFireOrSmokeSize)] - local fireType = "normal" - local fireId = exports['SmartFiresLite']:CreateFire(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), fireSize, fireType) - DebugPrint("Created fire with SmartFiresLite with ID: "..fireId) - table.insert(fireList, fireId) - end - - -- Build suspect peds - local randomAmountOfSuspects = math.random(3) - for i = 1, randomAmountOfSuspects do - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - - local suspectPedModel = ERS_GetRandomModel(Config.randomPeds) - local suspectPedCoords = vector3(coords.x, coords.y, coords.z) - local suspectPedHeading = math.random(360) - local suspectPedNetId = ERS_CreatePed(suspectPedModel, suspectPedCoords, suspectPedHeading) - local suspectPed = NetworkGetEntityFromNetworkId(suspectPedNetId) - table.insert(pedList, suspectPedNetId) - end - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_bouncer_in_trouble.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_bouncer_in_trouble.lua deleted file mode 100644 index 927288021..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_bouncer_in_trouble.lua +++ /dev/null @@ -1,154 +0,0 @@ -Config.Callouts["roxwood_bouncer_in_trouble"] = { - - Enabled = true, - CalloutName = "Bouncer in Trouble", - CalloutDescriptions = { - "A bouncer is struggling to control a rowdy crowd at a nightclub, with tensions escalating quickly.", - "Security personnel have called for backup as a confrontation with patrons turns violent.", - "Reports indicate a bouncer is overwhelmed by a group of unruly individuals at a local bar.", - "A nightclub bouncer is facing resistance from aggressive patrons, requiring immediate assistance.", - "A disturbance at a bar has led to a bouncer being outnumbered, with the situation deteriorating.", - "A bouncer is attempting to defuse a volatile situation at a club, with the potential for violence.", - "Witnesses report a bouncer being attacked by patrons, with the need for urgent intervention.", - "Security at a venue is under threat as a bouncer deals with a hostile crowd, needing backup.", - "A bouncer is in distress as a confrontation with patrons escalates, requiring swift response.", - "Emergency services are needed to assist a bouncer in trouble, with the potential for further conflict.", - }, - CalloutUnitsRequired = { - description = "Police.", - policeRequired = true, - ambulanceRequired = false, - fireRequired = false, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-605.2895, 7008.7100, 24.2095), - [2] = vector3(-626.9119, 6922.6372, 24.3170), - [3] = vector3(-330.2892, 7173.5366, 6.4107), - }, - PedChanceToFleeFromPlayer = 20, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 50, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 20, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 25, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 10000,-- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 15000,-- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "flee", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_knife", - "weapon_bat", - "weapon_hammer", - "weapon_wrench", - "weapon_pistol", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - local teamBouncers = {} - local teamOthers = {} - - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - ERS_RequestNetControlForEntity(ped) - local model = GetEntityModel(ped) - - -- Check if the ped is a bouncer - if model == GetHashKey("s_m_m_bouncer_01") or model == GetHashKey("s_m_m_highsec_01") or model == GetHashKey("s_m_m_highsec_02") then - table.insert(teamBouncers, ped) - else - table.insert(teamOthers, ped) - end - - TaskSetBlockingOfNonTemporaryEvents(ped, true) - Wait(100) - ERS_SpawnConfiguredWeaponForPed(ped, calloutDataClient) - end - end - - -- Function to make peds flee - local function makePedsFlee(peds) - for _, ped in pairs(peds) do - if DoesEntityExist(ped) and not IsPedDeadOrDying(ped, true) then - TaskSmartFleePed(ped, plyPed, 100.0, -1, false, false) - end - end - end - - -- Monitor and update ped behavior - Citizen.CreateThread(function() - while true do - Citizen.Wait(1000) -- Check every second - - -- Remove dead peds from teams - for i = #teamBouncers, 1, -1 do - if IsPedDeadOrDying(teamBouncers[i], true) then - table.remove(teamBouncers, i) - end - end - - for i = #teamOthers, 1, -1 do - if IsPedDeadOrDying(teamOthers[i], true) then - table.remove(teamOthers, i) - end - end - - -- If the others team or the bouncers team is too small, make them flee (and let bouncers stay) - if #teamOthers < 3 or #teamBouncers < 2 then - makePedsFlee(teamOthers) - break - end - end - end) - - -- Initial combat setup - if #teamBouncers > 0 and #teamOthers > 0 then - for _, bouncer in pairs(teamBouncers) do - local randomTarget = teamOthers[math.random(#teamOthers)] - TaskCombatPed(bouncer, randomTarget, 0, 16) - if Config.Debug then - print("Bouncer "..bouncer.." is attacking ped "..randomTarget) - end - end - - for _, other in pairs(teamOthers) do - local randomTarget = teamBouncers[math.random(#teamBouncers)] - TaskCombatPed(other, randomTarget, 0, 16) - if Config.Debug then - print("Other ped "..other.." is attacking bouncer "..randomTarget) - end - end - end - - ERS_CreateTemporaryBlipForEntities(pedList, 15000) - ERS_PerformTimedActionOnPed(calloutDataClient, pedList) - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - local bouncerPedModels = { - "s_m_m_bouncer_01", - "s_m_m_highsec_01", - "s_m_m_highsec_02", - } - local randomBouncers = math.random(1, 3) - for i = 1, randomBouncers do - -- Build peds - local pedModel = bouncerPedModels[math.random(#bouncerPedModels)] - local pedCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z) - local pedHeading = math.random(360) - local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) - local ped = NetworkGetEntityFromNetworkId(pedNetId) - table.insert(pedList, pedNetId) - end - - local randomBrawlers = math.random(2, 8) - for i = 1, randomBrawlers do - -- Build peds - local pedModel = ERS_GetRandomModel(Config.randomPeds) - local pedCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z) - local pedHeading = math.random(360) - local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) - local ped = NetworkGetEntityFromNetworkId(pedNetId) - table.insert(pedList, pedNetId) - end - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_bridge_blockade.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_bridge_blockade.lua deleted file mode 100644 index 727890b05..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_bridge_blockade.lua +++ /dev/null @@ -1,72 +0,0 @@ -Config.Callouts["roxwood_bridge_blockade"] = { - - Enabled = true, - CalloutName = "Bridge blockade", - CalloutDescriptions = { - "Emergency: respond to reports of a bridge blockade; ensure the area is cleared to prevent accidents.", - "Urgent alert: dispatch units to address a bridge blockade; remove debris to ensure safe passage for vehicles.", - "Critical response required: attend to reports of a bridge blockade; secure the area and prevent further incidents.", - "Notice: check reports of a bridge blockade; take immediate action to clear debris and restore road safety.", - "Alert: respond promptly to reports of a bridge blockade; prioritize the safety of motorists and clear the obstruction.", - "Incident reported: investigate reports of a bridge blockade; coordinate with local authorities to manage the situation.", - "Immediate action: address reports of a bridge blockade; use appropriate methods to clear the area and ensure safety.", - "Situation alert: assist with clearing a bridge blockade; ensure the area is safe for traffic and pedestrians.", - "Emergency response: handle reports of a bridge blockade and follow protocols to remove debris and ensure road safety.", - "Response needed: investigate reports of a bridge blockade urgently; take appropriate actions to prevent accidents and ensure clear passage.", - }, - CalloutUnitsRequired = { - description = "Police.", - policeRequired = true, - ambulanceRequired = false, - fireRequired = false, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-2015.0530, 7387.4570, 53.4759), - [2] = vector3(-1930.3730, 7569.9995, 81.9424), - [3] = vector3(-2857.5974, 8359.9668, 43.2680), - [4] = vector3(-652.4728, 6653.6875, 20.9940), - [5] = vector3(-1568.6243, 6724.4087, 17.7642), - }, - PedChanceToFleeFromPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 0, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 1000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "none", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_unarmed", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - for index, objNetId in pairs(objectList) do - local obj = NetToObj(objNetId) - if DoesEntityExist(obj) then - ERS_RequestNetControlForEntity(obj) - PlaceObjectOnGroundProperly(obj) - end - end - ERS_CreateTemporaryBlipForEntities(objectList, 30000) - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - local diameter = 10 - -- Build objects - local bridgeBlockObjects = {"prop_rub_scrap_06", "prop_tree_fallen_02", "prop_rub_pile_02", "prop_rub_pile_01", "prop_pile_dirt_04", "prop_pile_dirt_02", "prop_pipe_single_01"} - local randomAmountOfObjects = math.random(5) - for i = 1, randomAmountOfObjects do - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - local objModel = ERS_GetRandomModel(bridgeBlockObjects) - local objCoords = vector3(coords.x, coords.y, coords.z) - local objHeading = math.random(360) - local objNetId = ERS_CreateObject(objModel, objCoords, objHeading) - if objNetId then - local obj = NetworkGetEntityFromNetworkId(objNetId) - table.insert(objectList, objNetId) - else - DebugPrint("^1ERROR ^7Could not create object: "..objModel) - end - end - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_crop_fire.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_crop_fire.lua deleted file mode 100644 index 853b85c57..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_crop_fire.lua +++ /dev/null @@ -1,95 +0,0 @@ -Config.Callouts["roxwood_crop_fire"] = { - Enabled = true, - CalloutName = "Roxwood Crop Fire", - CalloutDescriptions = { - "Reports of a combine harvester malfunction causing a rapidly spreading wheat field fire.", - "Lightning strike has ignited multiple dry crop fields, threatening nearby farm structures.", - "Agricultural equipment sparked a fire in drought-affected corn fields, requiring immediate response.", - "Burning embers from a controlled burn have spread to adjacent crop fields.", - "Chemical fertilizer storage caught fire near valuable crop fields, situation escalating.", - "Electrical fault in irrigation system has triggered a fire in the surrounding crop fields.", - "Severe drought conditions have led to spontaneous combustion in hay storage, threatening nearby crops.", - "Farm workers report uncontrolled fire spreading through mature wheat fields during harvest.", - "Mechanical failure in grain silo ventilation system caused fire to spread to surrounding crops.", - "Emergency response needed for crop fire threatening multiple agricultural structures and equipment.", - }, - CalloutUnitsRequired = { - description = "Police, Fire.", - policeRequired = true, - ambulanceRequired = false, - fireRequired = true, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-2399.7097, 7358.4756, 29.0479), - [2] = vector3(-2487.0852, 7449.9502, 29.0479), - [3] = vector3(-2494.1135, 7374.3760, 29.0479), - [4] = vector3(-2517.3569, 7199.2168, 29.0479), - [5] = vector3(-2652.8608, 7139.6714, 29.0479), - [6] = vector3(-2579.2705, 7414.2432, 29.0479), - [7] = vector3(-2398.9187, 7448.2280, 29.0479), - [8] = vector3(-2344.8552, 7197.0410, 29.0479), - [9] = vector3(-2189.1917, 7144.0063, 29.0479), - [10] = vector3(-2502.3936, 7176.9692, 29.0479), - }, - PedChanceToFleeFromPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 0, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 1000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "none", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_unarmed", - }, - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - - for index, objNetId in pairs(objectList) do - local obj = NetToObj(objNetId) - if DoesEntityExist(obj) then - ERS_RequestNetControlForEntity(obj) - PlaceObjectOnGroundProperly(obj) - end - end - - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - - local diameter = 30 - - -- Build Fires & smoke - local randomAmountOfFires = math.random(10) - for i = 1, randomAmountOfFires do - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - if UsingSmartFires then - -- Full version - local fireSize = Config.RandomLargeFireOrSmokeSize[math.random(#Config.RandomLargeFireOrSmokeSize)] - local fireType = Config.NormalFireTypes[math.random(#Config.NormalFireTypes)] - local fireId = exports['SmartFires']:CreateFire(vector3(coords.x, coords.y, coords.z+0.6), fireSize, fireType) - DebugPrint("Created fire with ID: "..fireId) - table.insert(fireList, fireId) - - local smokeSize = Config.RandomMediumFireOrSmokeSize[math.random(#Config.RandomMediumFireOrSmokeSize)] - local smokeType = Config.AllSmokeTypes[math.random(#Config.AllSmokeTypes)] - local smokeId = exports['SmartFires']:CreateSmoke(vector3(coords.x, coords.y, coords.z-0.5), smokeSize, smokeType) - DebugPrint("Created smoke particle with ID: "..smokeId) - table.insert(smokeList, smokeId) - else - -- Lite version - local fireSize = Config.RandomLargeFireOrSmokeSize[math.random(#Config.RandomLargeFireOrSmokeSize)] - local fireType = "normal" - local fireId = exports['SmartFiresLite']:CreateFire(vector3(coords.x, coords.y, coords.z+0.6), fireSize, fireType) - DebugPrint("Created fire with SmartFiresLite with ID: "..fireId) - table.insert(fireList, fireId) - - local smokeSize = Config.RandomMediumFireOrSmokeSize[math.random(#Config.RandomMediumFireOrSmokeSize)] - local smokeType = "normal" - local smokeId = exports['SmartFiresLite']:CreateSmoke(vector3(coords.x, coords.y, coords.z-0.5), smokeSize, smokeType) - DebugPrint("Created smoke particle with ID: "..smokeId) - table.insert(smokeList, smokeId) - end - end - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_drug_lab_incident.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_drug_lab_incident.lua deleted file mode 100644 index 04e61544a..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_drug_lab_incident.lua +++ /dev/null @@ -1,113 +0,0 @@ -Config.Callouts["roxwood_drug_lab_incident"] = { - - Enabled = true, - CalloutName = "Drug Lab Incident", - CalloutDescriptions = { - "Emergency response needed at the drug lab; individual requiring immediate medical attention.", - "Alert: medical emergency reported at drug lab facilities; units requested for immediate response.", - "Units needed: incident reported at drug lab involving an injured person.", - "Emergency situation at drug lab; medical assistance required for lab visitor.", - "Alert: drug lab incident in progress; medical response team needed on scene.", - "First responders requested at drug lab location; medical emergency reported.", - "Respond to drug lab emergency; coordinate with on-site staff for immediate assistance.", - "Situation alert: medical incident at drug lab facilities requiring urgent response.", - "Emergency services needed at drug lab; injured person requiring immediate attention.", - "Response needed: drug lab incident involving injured visitor; medical assistance required.", - }, - CalloutUnitsRequired = { - description = "Police, Ambulance, Fire.", - policeRequired = true, - ambulanceRequired = true, - fireRequired = true, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-2281.0774, 8149.1436, 31.2439), - [2] = vector3(-2280.4634, 8029.7676, 34.1530), - [3] = vector3(-3075.2825, 7893.6514, 56.5999), - }, - PedChanceToFleeFromPlayer = 30, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 30, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 30, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 30, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 1000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "none", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_pistol", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - ERS_RequestNetControlForEntity(ped) - ERS_SetPedAsDrunkPed(ped) - ERS_ApplyBloodToPed(ped) - ERS_SetPedToFleeFromPlayer(ped) - end - end - - ERS_CreateTemporaryBlipForEntities(pedList, 15000) - ERS_PerformTimedActionOnPed(calloutDataClient, pedList) - - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - - -- Build peds - local diameter = 1.5 - local randomAmountOfWorkers = math.random(1, 3) - local drugLabWorkerPedModels = {"mp_f_cocaine_01", "mp_f_meth_01", "mp_m_meth_01", "mp_m_cocaine_01"} - for i = 1, randomAmountOfWorkers do - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - local pedModel = drugLabWorkerPedModels[math.random(1, #drugLabWorkerPedModels)] - local pedCoords = vector3(coords.x, coords.y, coords.z+1.0) - local pedHeading = math.random(360) - local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) - local ped = NetworkGetEntityFromNetworkId(pedNetId) - table.insert(pedList, pedNetId) - end - - -- Build a small sized fire - if UsingSmartFires then - -- Full version - local fireSize = Config.RandomSmallFireOrSmokeSize[math.random(#Config.RandomSmallFireOrSmokeSize)] - local fireType = Config.NormalFireTypes[math.random(#Config.NormalFireTypes)] - local fireId = exports['SmartFires']:CreateFire(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), fireSize, fireType) - DebugPrint("Created fire with ID: "..fireId) - table.insert(fireList, fireId) - - -- Build smoke - local chanceOnASmoke = 50 - if math.random(1, 100) <= chanceOnASmoke then - local smokeSize = Config.RandomSmallFireOrSmokeSize[math.random(#Config.RandomSmallFireOrSmokeSize)] - local smokeType = Config.AllSmokeTypes[math.random(#Config.AllSmokeTypes)] - local smokeId = exports['SmartFires']:CreateSmoke(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), smokeSize, smokeType) - - DebugPrint("Created smoke with ID: "..smokeId) - table.insert(smokeList, smokeId) - end - else - -- Lite version - local fireSize = Config.RandomSmallFireOrSmokeSize[math.random(#Config.RandomSmallFireOrSmokeSize)] - local fireType = "normal" - local fireId = exports['SmartFiresLite']:CreateFire(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), fireSize, fireType) - DebugPrint("Created fire with SmartFiresLite with ID: "..fireId) - table.insert(fireList, fireId) - - -- Build smoke - local chanceOnASmoke = 50 - if math.random(1, 100) <= chanceOnASmoke then - local smokeSize = Config.RandomSmallFireOrSmokeSize[math.random(#Config.RandomSmallFireOrSmokeSize)] - local smokeType = "normal" - local smokeId = exports['SmartFiresLite']:CreateSmoke(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), smokeSize, smokeType) - - DebugPrint("Created smoke with ID: "..smokeId) - table.insert(smokeList, smokeId) - end - end - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_gas_station_robbery.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_gas_station_robbery.lua deleted file mode 100644 index a09a5963b..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_gas_station_robbery.lua +++ /dev/null @@ -1,112 +0,0 @@ -Config.Callouts["roxwood_gas_station_robbery"] = { - - Enabled = true, - CalloutName = "Roxwood Gas Station Robbery", - CalloutDescriptions = { - "Respond to a report of an armed robbery at a gas station; secure the area and apprehend the suspects.", - "Alert: armed robbery in progress at a gas station; deploy units to the location and ensure public safety.", - "Units needed: report of a robbery involving multiple armed suspects; focus on securing the scene and detaining the suspects.", - "Notice: armed robbery reported at a gas station; act promptly to control the situation and prevent harm.", - "Alert: report of an armed robbery; intervention needed to apprehend the suspects and ensure safety.", - "Incident reported: armed robbery at a gas station; take action to secure the premises and protect bystanders.", - "Respond to a situation involving an armed robbery; prioritize public safety and coordinate with law enforcement.", - "Situation alert: armed robbery in progress; secure the area and detain the suspects.", - "Alert: report of a robbery with weapons; respond swiftly to address the situation and ensure safety.", - "Response needed: armed robbery; secure the area, apprehend the suspects, and restore order.", - }, - CalloutUnitsRequired = { - description = "Police, Ambulance.", - policeRequired = true, - ambulanceRequired = true, - fireRequired = false, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-1228.4095, 6927.7363, 20.4751), - [2] = vector3(-522.2498, 7560.3276, 6.5205), - }, - PedChanceToFleeFromPlayer = 50, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 50, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 20, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 100, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 10000, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 15000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "attack", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_pistol", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - - local plyGroupHash = GetPedRelationshipGroupHash(plyPed) - local retval, suspectGroupHash = AddRelationshipGroup("SUSPECT_GROUP_HASH") - local victim - local suspectPedList = {} - - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - ERS_RequestNetControlForEntity(ped) - if index == 1 then - victim = ped - ERS_ClearPedTasksAndBlockEvents(ped) - Wait(100) - TaskHandsUp(ped, -1, 0, -1, true) - else - SetPedRelationshipGroupHash(ped, suspectGroupHash) - SetEntityCanBeDamagedByRelationshipGroup(ped, false, suspectGroupHash) - SetRelationshipBetweenGroups(5, suspectGroupHash, plyGroupHash) - SetRelationshipBetweenGroups(5, plyGroupHash, suspectGroupHash) - - ERS_ClearPedTasksAndBlockEvents(ped) - ERS_SpawnConfiguredWeaponForPed(ped, calloutDataClient) - Wait(100) - TaskAimGunAtEntity(ped, victim, -1, false) - table.insert(suspectPedList, pedNetId) - - Citizen.CreateThread(function() - local randomTime = math.random(5000, 9000) - Citizen.Wait(randomTime) - local chanceToShoot = math.random(1, 100) - if chanceToShoot <= 50 then - TaskShootAtEntity(ped, victim, -1, false) - else - TaskSmartFleePed(ped, plyPed, 10000, -1, false) - end - end) - end - end - end - - ERS_CreateTemporaryBlipForEntities(suspectPedList, 15000) - - ERS_PerformTimedActionOnPed(calloutDataClient, suspectPedList) - - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - - local diameter = 15 - - -- Build victim - local pedModel = ERS_GetRandomModel(Config.randomPeds) - local pedCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z+1.0) - local pedHeading = math.random(360) - local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) - local ped = NetworkGetEntityFromNetworkId(pedNetId) - table.insert(pedList, pedNetId) - - -- Build suspects - local randomAmountOfSuspects = math.random(2, 4) -- Randomize number of suspects - for i = 1, randomAmountOfSuspects do - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - local pedModel = ERS_GetRandomModel(Config.randomPeds) - local pedCoords = vector3(coords.x, coords.y, coords.z+1.0) - local pedHeading = math.random(360) - local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) - local ped = NetworkGetEntityFromNetworkId(pedNetId) - table.insert(pedList, pedNetId) - end - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_illegal_camping.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_illegal_camping.lua deleted file mode 100644 index 5695e0aee..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_illegal_camping.lua +++ /dev/null @@ -1,117 +0,0 @@ -Config.Callouts["roxwood_illegal_camping"] = { - - Enabled = true, - CalloutName = "Illegal Camping", - CalloutDescriptions = { - "Investigate reports of illegal camping in a restricted area; ensure compliance with local regulations.", - "Alert: dispatch units to handle reports of unauthorized camping; assess environmental impact.", - "Units required: respond to reports of illegal camping and evaluate potential safety hazards.", - "Notice: check reports of campers setting up in prohibited zones; enforce park rules.", - "Alert: respond promptly to reports of unauthorized camping; prioritize public safety and environmental protection.", - "Incident reported: look into reports of illegal camping activities to understand the situation.", - "Investigate reports of campers in restricted areas; coordinate with park authorities and secure the site.", - "Situation alert: address reports of illegal camping; work with local enforcement to resolve the issue.", - "Alert: handle reports of unauthorized camping and adhere to protocols for potential environmental hazards.", - "Response needed: investigate reports of illegal camping and take steps to ensure compliance with regulations.", - }, - CalloutUnitsRequired = { - description = "Police", - policeRequired = true, - ambulanceRequired = false, - fireRequired = false, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-2968.4868, 8348.0039, 43.2270), - [2] = vector3(-2376.2881, 7808.8652, 33.1581), - [3] = vector3(-2710.9854, 7801.0586, 46.5524), - [4] = vector3(-3067.7266, 7109.3135, 42.5468), - [5] = vector3(-3676.9055, 6168.9692, 24.5723), - [6] = vector3(-3588.0854, 7165.6846, 46.3299), - [7] = vector3(-3312.8560, 8835.7363, 36.2966), - [8] = vector3(-1284.6665, 8242.3164, 12.2473), - [9] = vector3(-1490.4974, -262.6434, 50.2380), - [10] = vector3(-2220.6472, 7570.6499, 56.8878), - }, - PedChanceToFleeFromPlayer = 10, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 10, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 50, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 10, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 10000, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 15000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "none", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_knife", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - - local vehicle - local driver - - for index, vehNetId in pairs(vehicleList) do - local veh = NetToVeh(vehNetId) - if DoesEntityExist(veh) then - vehicle = veh - ERS_RequestNetControlForEntity(vehicle) - - end - end - - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - if index == 1 then - driver = ped - ERS_RequestNetControlForEntity(driver) - TaskSetBlockingOfNonTemporaryEvents(driver, true) - ERS_SetPedAsDrunkPed(driver) - else - -- Play a smoking weed animation on them - ERS_SetPedAsDrunkPed(ped) - local scenario = ERS_SelectRandomSmokeScenario() - TaskStartScenarioInPlace(ped, scenario, 0, true) - end - end - end - - ERS_CreateTemporaryBlipForEntities(vehicleList, 15000) - ERS_CreateTemporaryBlipForEntities(pedList, 15000) - - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - - -- Build vehicle - local campingVehicles = {"camper", "journey", "paradise"} - local vehModel = ERS_GetRandomModel(campingVehicles) - local vehType = "automobile" - local vehCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z) - local vehHeading = math.random(360) - local vehNetId = ERS_CreateVehicle(vehModel, vehType, vehCoords, vehHeading) - local vehicle = NetworkGetEntityFromNetworkId(vehNetId) - table.insert(vehicleList, vehNetId) - - -- Build ped - local pedModel = ERS_GetRandomModel(Config.randomPeds) - local pedCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z+3.0) - local pedHeading = math.random(360) - local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) - local ped = NetworkGetEntityFromNetworkId(pedNetId) - SetPedIntoVehicle(ped, vehicle, -1) - table.insert(pedList, pedNetId) - - -- Build camping friends - local amountOfCampingFriends = math.random(1, 5) - for i = 1, amountOfCampingFriends do - local diameter = 20.0 - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - local companionModel = ERS_GetRandomModel(Config.randomPeds) - local companionCoords = vector3(coords.x, coords.y, coords.z+3.0) - local companionHeading = math.random(360) - local companionNetId = ERS_CreatePed(companionModel, companionCoords, companionHeading) - table.insert(pedList, companionNetId) - end - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_miner_panicalarm.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_miner_panicalarm.lua deleted file mode 100644 index 334814b70..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_miner_panicalarm.lua +++ /dev/null @@ -1,91 +0,0 @@ -Config.Callouts["roxwood_miner_panic_alarm"] = { - - Enabled = true, - CalloutName = "Panic alarm at the mine", - CalloutDescriptions = { - "Emergency responders are required to investigate the source of the panic alarm at the mine.", - "Authorities report panic alarm at the mine, demanding immediate investigation to ensure safety.", - "Panic alarm has been reported at the mine, necessitating urgent action to identify and address the cause.", - "Critical situation with panic alarm at the mine; additional units are needed for support.", - "Immediate response needed to address panic alarm at the mine posing potential danger.", - "Panic alarm has been detected at the mine, posing a possible threat; reinforcements are necessary to investigate and contain any hazards.", - "Emergency crews are requesting backup to assist in investigating and managing panic alarm at the mine.", - "An urgent call for help has been issued to handle panic alarm at the mine and ensure safety.", - "Responders are on the scene of panic alarm at the mine and need extra support to stabilize the situation.", - "A serious emergency involving panic alarm at the mine demands swift action to prevent a potential catastrophic outcome.", - }, - CalloutUnitsRequired = { - description = "Police, Fire.", - policeRequired = true, - ambulanceRequired = false, - fireRequired = true, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-1474.1163, 7612.5264, 90.0090), - [2] = vector3(-1498.0601, 7648.6548, 89.9406), - [3] = vector3(-1561.5817, 7478.5679, 95.6648), - [4] = vector3(-1400.6205, 7501.4053, 80.8366), - }, - PedChanceToFleeFromPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 0, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 1000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "none", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_unarmed", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - - -- No other actions required clientside. - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - ERS_RequestNetControlForEntity(ped) - TaskSetBlockingOfNonTemporaryEvents(ped, true) - ERS_ApplyBloodToPed(ped) - local scenario = ERS_SelectRandomWoundedPersonScenario() - TaskStartScenarioInPlace(ped, scenario, 0, true) - end - end - - ERS_CreateTemporaryBlipForEntities(pedList, 120000) - ERS_PerformTimedActionOnPed(calloutDataClient, pedList) - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - - -- Build smoke - if UsingSmartFires then - -- Full version - local smokeSize = Config.RandomMediumFireOrSmokeSize[math.random(#Config.RandomMediumFireOrSmokeSize)] - local smokeType = Config.FoggySmoke - local smokeId = exports['SmartFires']:CreateSmoke(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), smokeSize, smokeType) - DebugPrint("Created smoke particle with ID: "..smokeId) - table.insert(smokeList, smokeId) - else - -- Lite version - local smokeSize = Config.RandomMediumFireOrSmokeSize[math.random(#Config.RandomMediumFireOrSmokeSize)] - local smokeType = "normal" - local smokeId = exports['SmartFiresLite']:CreateSmoke(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), smokeSize, smokeType) - DebugPrint("Created smoke particle with ID: "..smokeId) - table.insert(smokeList, smokeId) - end - - -- Build wounded miner - local amountOfPeds = math.random(1, 4) - local minerPedModels = {"s_m_y_construct_01", "s_m_y_construct_02"} - for i = 1, amountOfPeds do - local pedModel = ERS_GetRandomModel(minerPedModels) - local pedCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z) - local pedHeading = math.random(360) - local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) - local ped = NetworkGetEntityFromNetworkId(pedNetId) - table.insert(pedList, pedNetId) - end - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_mysterious_egg.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_mysterious_egg.lua deleted file mode 100644 index 375653531..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_mysterious_egg.lua +++ /dev/null @@ -1,516 +0,0 @@ -Config.Callouts["roxwood_mysterious_egg"] = { - - Enabled = true, - CalloutName = "Mysterious egg(s) reported", - CalloutDescriptions = { - "Emergency: respond to reports of a mysterious egg; assess potential hazards.", - "Urgent alert: unidentified egg-like object reported requiring immediate investigation.", - "Critical response required: investigate reports of an unusual egg of unknown origin.", - "Notice: mysterious egg discovered in the area; assessment needed.", - "Alert: respond to reports of a suspicious egg-shaped object; evaluate potential risks.", - "Incident reported: mysterious egg found requiring immediate attention.", - "Immediate action: address reports of an unidentified egg; assess situation.", - "Situation alert: investigation needed for mysterious egg discovery.", - "Emergency response: handle reports of an unusual egg; ensure public safety.", - "Response needed: investigate reports of a mysterious egg; assess and secure the area.", - }, - CalloutUnitsRequired = { - description = "Police, fire.", - policeRequired = true, - ambulanceRequired = false, - fireRequired = true, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-176.0005, 7555.7231, 2.0013), - [2] = vector3(-229.1338, 7345.6353, 4.2200), - [3] = vector3(-3411.0190, 6075.2427, 2.6527), - [4] = vector3(-783.9731, 6659.8804, 2.3201), - [5] = vector3(-328.8283, 6974.1064, 2.4945), - }, - PedChanceToFleeFromPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 0, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 1000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "none", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_unarmed", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - local eggObjects = {} - for index, objNetId in pairs(objectList) do - local obj = NetToObj(objNetId) - if DoesEntityExist(obj) then - ERS_RequestNetControlForEntity(obj) - PlaceObjectOnGroundProperly(obj) - table.insert(eggObjects, obj) - - -- Make weird shit happen, like drawing lights fading in and out in green colour - local coords = GetEntityCoords(obj) - local radius = 10.0 - local intensity = 0.0 - local fadeSpeed = 0.005 -- Lower = slower fade - local increasing = true - - Citizen.CreateThread(function() - while DoesEntityExist(obj) do - -- Draw the light with current intensity - DrawLightWithRangeAndShadow( - coords.x, - coords.y, - coords.z, - 0, -- Red - math.floor(intensity * 100), -- Green (0-100 range) - 0, -- Blue - 10.0, - 0.5, -- Light intensity - 1.0 - ) - - -- Update intensity - if increasing then - intensity = intensity + fadeSpeed - if intensity >= 1.0 then - intensity = 1.0 - increasing = false - end - else - intensity = intensity - fadeSpeed - if intensity <= 0.0 then - intensity = 0.0 - increasing = true - end - end - - Wait(0) - end - end) - end - end - - -- Make UFO fly in from high altitude, then start the abduction sequence - local ufoEntityId = nil - local ufoNetId = nil - Citizen.SetTimeout(10000, function() - local ufoModel = 'imp_prop_ship_01a' - RequestModel(ufoModel) - while not HasModelLoaded(ufoModel) do - Wait(100) - end - - -- Start position high in the sky - local startCoords = vector3(calloutDataClient.Coordinates.x + 50.0, calloutDataClient.Coordinates.y + 50.0, calloutDataClient.Coordinates.z + 150.0) - local finalCoords = vector3(calloutDataClient.Coordinates.x, calloutDataClient.Coordinates.y, calloutDataClient.Coordinates.z + 30.0) - local ufoHeading = math.random(360) - - -- Create UFO at start position - ufoEntityId = CreateObject(ufoModel, startCoords.x, startCoords.y, startCoords.z, true, true, true) - while not DoesEntityExist(ufoEntityId) do - Wait(100) - end - ufoNetId = NetworkGetNetworkIdFromEntity(ufoEntityId) - - -- Play UFO approach sound - PlaySoundFrontend(-1, "Object_Dropped_Remote", "GTAO_FM_Events_Soundset", true) - - -- UFO arrival animation - Citizen.CreateThread(function() - local arrivalDuration = 5000 -- 5 seconds for arrival - local startTime = GetGameTimer() - - -- Add a slight hovering effect - local hoverOffset = 0.0 - local hoverRate = 0.003 -- Reduced from 0.01 for slower hovering - - -- Play arrival sequence - while DoesEntityExist(ufoEntityId) do - local currentTime = GetGameTimer() - local timeElapsed = currentTime - startTime - local t = math.min(timeElapsed / arrivalDuration, 1.0) - - -- Use cubic easing for natural movement - local tSquared = t * t - local tCubed = tSquared * t - local easedT = 1.0 - math.pow(1.0 - t, 3) - - -- Calculate new position - local newX = lerp(startCoords.x, finalCoords.x, easedT) - local newY = lerp(startCoords.y, finalCoords.y, easedT) - local newZ = lerp(startCoords.z, finalCoords.z, easedT) - - -- Add hovering effect - hoverOffset = math.sin(currentTime * hoverRate) * 0.5 - - -- Set UFO position - SetEntityCoords(ufoEntityId, newX, newY, newZ + hoverOffset, false, false, false, false) - - -- Rotate the UFO slightly as it comes in - local currentHeading = GetEntityHeading(ufoEntityId) - SetEntityHeading(ufoEntityId, currentHeading + 0.2) - - -- If UFO reached final position, break the loop - if t >= 1.0 then - -- Play hovering sound when UFO is in position - --PlaySoundFrontend(-1, "Altitude_Warning", "EXILE_1", true) - PlaySoundFrontend(-1, "Object_Dropped_Remote", "GTAO_FM_Events_Soundset", true) - break - end - - Wait(0) - end - - -- After arrival, continue with the spotlights and abduction - local ufoCoords = GetEntityCoords(ufoEntityId) - local isCalloutActive = true - local isUFODeparting = false -- New flag to control hover effect - - -- Create a thread to monitor callout status - Citizen.CreateThread(function() - while true do - -- Check if callout is still active - if not isAttachedToCallout then - isCalloutActive = false - - -- Clean up UFO if it exists - if DoesEntityExist(ufoEntityId) then - DeleteEntity(ufoEntityId) - end - - -- Break the monitoring loop - break - end - Wait(1000) -- Check every second - end - end) - - Citizen.CreateThread(function() - -- Light pulsing variables - local lightIntensity = 1.0 - local pulseRate = 0.005 - local minIntensity = 0.7 - local maxIntensity = 1.3 - - -- Play spotlight activation sound - PlaySoundFrontend(-1, "Beep_Red", "DLC_HEIST_HACKING_SNAKE_SOUNDS", true) - Wait(800) - PlaySoundFrontend(-1, "CHECKPOINT_PERFECT", "HUD_MINI_GAME_SOUNDSET", true) - - while DoesEntityExist(ufoEntityId) and isCalloutActive do - local gameTime = GetGameTimer() - - -- Only apply hover if not departing - if not isUFODeparting then - -- Update hover effect with slower rate - hoverOffset = math.sin(gameTime * hoverRate) * 0.5 - SetEntityCoords(ufoEntityId, ufoCoords.x, ufoCoords.y, ufoCoords.z + hoverOffset, false, false, false, false) - end - - -- Calculate pulsing light intensity - lightIntensity = lerp(minIntensity, maxIntensity, (math.sin(gameTime * pulseRate) + 1) * 0.5) - - -- Draw spotlights only if not departing - if not isUFODeparting then - -- Draw the main red spotlight with pulsing intensity - DrawSpotLightWithShadow( - ufoCoords.x, ufoCoords.y, ufoCoords.z-3.0, - 0.0, 0.0, -1.0, - 255, 0, 0, - 100.0, lightIntensity, 0.0, 100.0, 1.0 - ) - - -- White spotlight remains consistent - DrawSpotLightWithShadow( - ufoCoords.x, ufoCoords.y, ufoCoords.z-3.0, - 0.0, 0.0, -1.0, - 255, 255, 255, - 100.0, 1.0, 0.0, 20.0, 1.0 - ) - end - Wait(0) - end - end) - - -- Create a forceful push away from eggs when player gets too close - Citizen.CreateThread(function() - while true do - local playerPed = PlayerPedId() - local playerCoords = GetEntityCoords(playerPed) - - for _, eggObject in ipairs(eggObjects) do - if DoesEntityExist(eggObject) then - local eggCoords = GetEntityCoords(eggObject) - local distance = #(playerCoords - eggCoords) - - -- Strong repulsion when very close to eggs - if distance < 8.0 then -- Reduced range for more dramatic effect - -- Calculate direction AWAY from egg - local force = (playerCoords - eggCoords) - local magnitude = #force - - if magnitude > 0 then - -- Strong push at any time - local pushStrength = 10.0 - - -- Ragdoll the player for dramatic effect - SetPedGravity(playerPed, false) - SetPedToRagdoll(playerPed, 1000, 1000, 0, 0, 0, 0) - - -- Apply strong push force away from egg - SetEntityVelocity(playerPed, - force.x/magnitude * pushStrength, - force.y/magnitude * pushStrength, - pushStrength * 0.5) -- Upward component for dramatic effect - - -- Small delay to prevent sound spam - Wait(500) - SetPedGravity(playerPed, true) - end - end - end - end - Wait(0) - end - end) - - -- Make the objects fly up into the UFO and make the UFO fly away - Citizen.CreateThread(function() - local objectsRemaining = #objectList - local lastObject = nil - local shouldFlyAway = false -- New flag to control UFO departure - - -- Handle each object in the list - for _, eggObject in ipairs(eggObjects) do - if DoesEntityExist(eggObject) and isCalloutActive then - local startCoords = GetEntityCoords(eggObject) - local endCoords = GetEntityCoords(ufoEntityId) - local duration = 5000 -- 5 seconds for each object - local startTime = GetGameTimer() - - -- Animate each object - while DoesEntityExist(ufoEntityId) and DoesEntityExist(eggObject) and isCalloutActive do - local currentTime = GetGameTimer() - local timeElapsed = currentTime - startTime - - -- Calculate easing - local t = math.min(timeElapsed / duration, 1.0) - local tSquared = t * t - local tCubed = tSquared * t - local easedT = 3 * tSquared - 2 * tCubed - - -- Calculate new position - local newX = lerp(startCoords.x, endCoords.x, easedT) - local newY = lerp(startCoords.y, endCoords.y, easedT) - local newZ = lerp(startCoords.z, endCoords.z + 1.0, easedT) - - -- Add some wobble to the movement - local wobble = math.sin(timeElapsed * 0.01) * (1.0 - easedT) * 0.3 - - -- Set new position - SetEntityCoords(eggObject, newX + wobble, newY + wobble, newZ, false, false, false, false) - - -- Add rotation - local currentRotation = GetEntityRotation(eggObject, 2) - SetEntityRotation(eggObject, - currentRotation.x + 2.0, - currentRotation.y + 2.0, - currentRotation.z + 2.0, - 2, true) - - -- Draw laser beam from UFO to object - local ufoPos = GetEntityCoords(ufoEntityId) - local objPos = GetEntityCoords(eggObject) - - -- Main laser beam - DrawLine( - ufoPos.x, ufoPos.y, ufoPos.z - 2.0, -- From bottom of UFO - objPos.x, objPos.y, objPos.z, -- To object - 0, 255, 0, -- Green color - 255 -- Alpha - ) - - -- Add some additional lines for thickness effect - DrawLine( - ufoPos.x + 0.05, ufoPos.y, ufoPos.z - 2.0, - objPos.x + 0.05, objPos.y, objPos.z, - 0, 255, 0, 180 - ) - - DrawLine( - ufoPos.x - 0.05, ufoPos.y, ufoPos.z - 2.0, - objPos.x - 0.05, objPos.y, objPos.z, - 0, 255, 0, 180 - ) - - DrawLine( - ufoPos.x, ufoPos.y + 0.05, ufoPos.z - 2.0, - objPos.x, objPos.y + 0.05, objPos.z, - 0, 255, 0, 180 - ) - - DrawLine( - ufoPos.x, ufoPos.y - 0.05, ufoPos.z - 2.0, - objPos.x, objPos.y - 0.05, objPos.z, - 0, 255, 0, 180 - ) - - -- Add pulsing effect - local pulseIntensity = math.sin(timeElapsed * 0.02) * 0.5 + 0.5 - DrawLine( - ufoPos.x, ufoPos.y, ufoPos.z - 2.0, - objPos.x, objPos.y, objPos.z, - 0, 255 * pulseIntensity, 0, - 200 - ) - - -- If object reached UFO - if t >= 1.0 then - -- Play object capture sound - PlaySoundFrontend(-1, "CHECKPOINT_UNDER_THE_BRIDGE", "HUD_MINI_GAME_SOUNDSET", true) - --print("Object reached UFO, remaining: " .. objectsRemaining) -- Debug print - - objectsRemaining = objectsRemaining - 1 - - if DoesEntityExist(eggObject) then - if objectsRemaining == 0 then - --print("Last object captured, preparing UFO departure") -- Debug print - lastObject = eggObject - SetEntityVisible(eggObject, false, false) - shouldFlyAway = true -- Set flag for UFO to fly away - else - ERS_DeleteEntityFromCallout(eggObject) - end - end - break - end - - Wait(0) - end - - -- Small delay between objects - if isCalloutActive and objectsRemaining > 0 then - Wait(500) - end - end - end - - -- In the UFO departure sequence, set isUFODeparting = true before starting: - if shouldFlyAway then - --print("Starting UFO departure sequence") -- Debug print - - -- Add a delay before departure - Wait(2000) - - -- Set departing flag to true - isUFODeparting = true - - -- Create new thread specifically for UFO departure - Citizen.CreateThread(function() - if DoesEntityExist(ufoEntityId) and isCalloutActive then - --print("UFO exists and callout is active, beginning departure") -- Debug print - - -- Play UFO departure sounds - PlaySoundFrontend(-1, "Object_Dropped_Remote", "GTAO_FM_Events_Soundset", true) - - local ufoStartCoords = GetEntityCoords(ufoEntityId) - local ufoEndCoords = vector3(ufoStartCoords.x, ufoStartCoords.y, ufoStartCoords.z + 30.0) - local ufoDuration = 8000 - local ufoStartTime = GetGameTimer() - - while DoesEntityExist(ufoEntityId) and isCalloutActive do - local currentTime = GetGameTimer() - local timeElapsed = currentTime - ufoStartTime - local t = math.min(timeElapsed / ufoDuration, 1.0) - - -- Exponential easing for UFO departure - local easedT = t * t - - -- Move UFO up - local newZ = lerp(ufoStartCoords.z, ufoEndCoords.z, easedT) - --print("Moving UFO - Height: " .. newZ) -- Debug print - - SetEntityCoords(ufoEntityId, - ufoStartCoords.x, - ufoStartCoords.y, - newZ, - false, false, false, false) - - if t >= 1.0 then - --print("UFO reached max height, cleaning up") -- Debug print - TriggerServerEvent("ns_easter_egg:DeleteUFO", ufoNetId) - - -- Small delay before ending callout - Wait(1000) - - if lastObject and DoesEntityExist(lastObject) then - ERS_DeleteEntityFromCallout(lastObject) - end - break - end - - Wait(0) - end - end - end) - else - --print("shouldFlyAway flag not set, UFO departure sequence skipped") -- Debug print - end - end) - end) - end) - - ERS_CreateTemporaryBlipForEntities(objectList, 30000) - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - local diameter = 10 - -- Build objects - local alienEggObjects = {"prop_alien_egg_01"} - local randomAmountOfObjects = math.random(1, 12) - for i = 1, randomAmountOfObjects do - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - local objModel = ERS_GetRandomModel(alienEggObjects) - local objCoords = vector3(coords.x, coords.y, coords.z+2.0) - local objHeading = math.random(360) - local objNetId = ERS_CreateObject(objModel, objCoords, objHeading) - if objNetId then - local obj = NetworkGetEntityFromNetworkId(objNetId) - table.insert(objectList, objNetId) - else - DebugPrint("^1ERROR ^7Could not create object: "..objModel) - end - end - - -- Create smoke (Optionally) - -- -- Build a small sized fire - -- if UsingSmartFires then - -- -- Full version - -- -- Build smoke - -- local smokeSize = Config.RandomMediumFireOrSmokeSize[math.random(#Config.RandomMediumFireOrSmokeSize)] - -- local smokeType = "foggy" - -- local smokeId = exports['SmartFires']:CreateSmoke(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), smokeSize, smokeType) - -- DebugPrint("Created smoke with ID: "..smokeId) - -- table.insert(smokeList, smokeId) - -- else - -- -- Lite version - -- -- Build smoke - -- local smokeSize = Config.RandomMediumFireOrSmokeSize[math.random(#Config.RandomMediumFireOrSmokeSize)] - -- local smokeType = "normal" - -- local smokeId = exports['SmartFiresLite']:CreateSmoke(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), smokeSize, smokeType) - -- DebugPrint("Created smoke with ID: "..smokeId) - -- table.insert(smokeList, smokeId) - -- end - - - RegisterServerEvent("ns_easter_egg:DeleteUFO") - AddEventHandler("ns_easter_egg:DeleteUFO", function(objNetId) - local obj = NetworkGetEntityFromNetworkId(objNetId) - if DoesEntityExist(obj) then - DeleteEntity(obj) - end - end) - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_race_crash.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_race_crash.lua deleted file mode 100644 index 4600743da..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_race_crash.lua +++ /dev/null @@ -1,272 +0,0 @@ - -Config.Callouts["roxwood_race_crash"] = { - Enabled = false, - CalloutName = "Roxwood GP Race Crash", - CalloutDescriptions = { - "Reported road traffic collision, further details needed", - "Collision involving vehicles, assess scene for safety", - "Incident on road reported, extent of damage unclear", - "Traffic incident with unknown injuries, approach carefully", - "Vehicle collision reported, assistance required", - "Accident scene identified, evaluate for emergency response", - "Collision on roadway, prioritize safety and assistance", - "Traffic incident reported, coordinate response accordingly", - "Roadway blocked due to collision, assess for hazards", - "Vehicle collision with unspecified injuries, response needed", - -- Add more if you like. - }, - CalloutUnitsRequired = { - description = "Police, ambulance, fire, tow.", - policeRequired = true, - ambulanceRequired = true, - fireRequired = true, - towRequired = true, - }, - CalloutLocations = { - [1] = vector3(-2878.8276, 8350.8096, 37.0427), - [2] = vector3(-3003.3206, 8421.5879, 37.0592), - [3] = vector3(-3262.5945, 8667.0674, 37.1207), - [4] = vector3(-3020.7278, 8711.4346, 46.1127), - [5] = vector3(-2703.4087, 8518.3428, 44.1534), - [6] = vector3(-2239.3889, 8563.3916, 47.5178), - [7] = vector3(-2343.6777, 8891.8887, 51.0247), - [8] = vector3(-2524.2251, 8750.5879, 45.5379), - [9] = vector3(-2624.4514, 8621.4854, 47.0158), - [10] = vector3(-2576.6099, 8060.3647, 46.6511), - [11] = vector3(-3196.3193, 8153.2676, 47.0967), - }, - PedChanceToFleeFromPlayer = 0, -- Value between 0 and 100 -> 0 is no chance. The lower the less chance. - PedChanceToAttackPlayer = 0, -- Value between 0 and 100 -> 0 is no chance. The lower the less chance. - PedChanceToSurrender = 0, -- Value between 0 and 100 -> 0 is no chance. The lower the less chance. - PedChanceToObtainWeapons = 0, -- Value between 0 and 100 -> 0 is no chance. The lower the less chance. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 1000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "none", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_unarmed", -- Basically none. - }, - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - for index, vehNetId in pairs(vehicleList) do - local veh = NetToVeh(vehNetId) - if DoesEntityExist(veh) then - ERS_RequestNetControlForEntity(veh) - ERS_SetRandomDamageToVehicle(veh) - end - end - - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - - ERS_RequestNetControlForEntity(ped) - - local pedCoords = GetEntityCoords(ped) - local chanceToSurvive = math.random(0, 1) - - ERS_SetMovementAnimClipSetToPed(ped, "move_m@injured") - - if chanceToSurvive < 1 then - -- Dead - SetEntityHealth(ped, 0) - TaskSetBlockingOfNonTemporaryEvents(ped, true) - ERS_ApplyBloodToPed(ped) - SetPedKeepTask(ped, true) - else - -- Alive - TaskSetBlockingOfNonTemporaryEvents(ped, true) - ERS_SpawnConfiguredWeaponForPed(ped, calloutDataClient) - if IsPedInAnyVehicle(ped, false) then - TaskLeaveAnyVehicle(ped) - Wait(500) - end - TaskSetBlockingOfNonTemporaryEvents(ped, true) - SetPedKeepTask(ped, true) - - ERS_ApplyBloodToPed(ped) - - pedCoords = GetEntityCoords(ped) - local bool, safeCoords = GetSafeCoordForPed(pedCoords.x, pedCoords.y, pedCoords.z, true, 16) - if bool then - if Config.Debug then - print("Found safe coord for ped: "..safeCoords) - end - local xOffset= math.random(-2, 2) - local yOffset= math.random(-2, 2) - - if Config.Debug then - print("Could not find safe coord for ped: "..safeCoords) - end - end - - Citizen.SetTimeout(10000, function() - if DoesEntityExist(ped) then - if not IsPedDeadOrDying(ped, true) then - ERS_RequestNetControlForEntity(ped) - - TaskSetBlockingOfNonTemporaryEvents(ped, true) - - local scenario = ERS_SelectRandomWoundedPersonScenario() - TaskStartScenarioInPlace(ped, scenario, 0, true) - - ERS_PerformTimedActionOnPed(calloutDataClient, pedList) - - if Config.Debug then - print("Blocking off non-temp events for ped at safe coords for ped: "..ped) - end - end - end - end) - end - end - end - - for index, objNetId in pairs(objectList) do - local obj = NetToObj(objNetId) - if DoesEntityExist(obj) then - ERS_RequestNetControlForEntity(obj) - PlaceObjectOnGroundProperly(obj) - end - end - - ERS_CreateTemporaryBlipForEntities(vehicleList, 15000) - ERS_CreateTemporaryBlipForEntities(pedList, 15000) - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - local randomAmountOfVehicles = math.random(2,5) - local randomAmountOfObjects = math.random(1,5) - local randomAmountOfFires = math.random(1,3) - local racePedModels = { - "ig_trafficwarden", "player_zero", "ig_agatha", - "hc_driver", "hc_gunman", "hc_hacker", "ig_abigail", "ig_agent", - "ig_amandatownley", "ig_andreas", "ig_ashley", "ig_avon", "ig_ballasog", - "ig_bankman", "ig_barry", "ig_benny", "ig_bestmen", "ig_beverly", - "ig_brad", "ig_bride", "ig_car3guy1", "ig_car3guy2", "ig_casey", - "ig_chef", "ig_chef2", "ig_chengsr", "ig_chrisformage", "ig_clay", - "ig_claypain", "ig_cletus", "ig_dale", "ig_davenorton", "ig_denise", - "ig_devin", "ig_dix", "ig_djblamadon", "ig_djblamrupert", "ig_djblamryans", - "ig_djdixmanager", "ig_djgeneric_01", "ig_djsolfotios", "ig_djsoljakob", - "ig_djsolmanager", "ig_djsolmike", "ig_djsolrobt", "ig_djtalaurelia", - "ig_djtalignazio", "ig_dom", "ig_dreyfuss", "ig_drfriedlander", - "ig_englishdave", "ig_fabien", "ig_fbisuit_01", "ig_floyd", "ig_g", - "ig_groom", "ig_hao", "ig_hunter", "ig_janet", "ig_jay_norris", - "ig_jewelass", "ig_jimmyboston", "ig_jimmyboston_02", "ig_jimmydisanto", - "ig_joeminuteman", "ig_johnnyklebitz", "ig_josef", "ig_josh", - "ig_karen_daniels", "ig_kerrymcintosh", "ig_kerrymcintosh_02", - "ig_lacey_jones_02", "ig_lamardavis", "ig_lazlow", "ig_lazlow_2", - "ig_lestercrest", "ig_lestercrest_2", "ig_lifeinvad_01", "ig_lifeinvad_02", - "ig_magenta", "ig_malc", "ig_manuel", "ig_marnie", "ig_maryann", - "ig_maude", "ig_michelle", "ig_milton", "ig_molly", "ig_money", - "ig_mp_agent14", "ig_mrk", "ig_mrs_thornhill", "ig_mrsphillips", - "ig_natalia", "ig_nervousron", "ig_nigel", "ig_old_man1a", "ig_old_man2", - "ig_omega", "ig_oneil", "ig_orleans", "ig_ortega", "ig_paige", "ig_paper", - "ig_patricia", "ig_popov", "ig_priest", "ig_prolsec_02", "ig_ramp_gang", - "ig_ramp_hic", "ig_ramp_hipster", "ig_ramp_mex", "ig_rashcosvki", - "ig_roccopelosi", "ig_russiandrunk", "ig_sacha", "ig_screen_writer", - "ig_siemonyetarian", "ig_sol", "ig_solomon", "ig_stevehains", "ig_stretch", - "ig_talcc", "ig_talina", "ig_talmm", "ig_tanisha", "ig_taocheng", - "ig_taostranslator", "ig_tenniscoach", "ig_terry", "ig_tomepsilon", - "ig_tonya", "ig_tonyprince", "ig_tracydisanto", "ig_trafficwarden", - "ig_tylerdix", "ig_tylerdix_02", "ig_vagspeak", "ig_wade", "ig_zimbor", - "player_one", "player_two", "player_zero", "ig_agatha", "ig_avery", - "ig_brucie2", "ig_thornton", "ig_tomcasino", "ig_vincent" - } - local vehRaceModels = {"formula", "formula2", "openwheel1", "openwheel2"} - local carPartObjects = {"prop_car_battery_01", "prop_car_exhaust_01", "prop_rub_carpart_04", "prop_rub_carpart_05", "prop_car_engine_01"} - local diameter = 20 - - -- Car race or motorbike race chance - local carRaceChance = math.random(0, 1) - local vehType = "automobile" - if carRaceChance == 0 then - -- motorbike race - vehRaceModels = {"bati2"} - vehType = "bike" - end - - -- Build entities - for i = 1, randomAmountOfVehicles do - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - - -- Build vehicle - local vehModel = ERS_GetRandomModel(vehRaceModels) - local vehCoords = vector3(coords.x, coords.y, coords.z) - local vehHeading = math.random(360) - local vehNetId = ERS_CreateVehicle(vehModel, vehType, vehCoords, vehHeading) - local vehicle = NetworkGetEntityFromNetworkId(vehNetId) - table.insert(vehicleList, vehNetId) - - -- Build ped - coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - - local pedModel = ERS_GetRandomModel(racePedModels) - local pedCoords = vector3(coords.x, coords.y, coords.z) - local pedHeading = math.random(360) - local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) - local ped = NetworkGetEntityFromNetworkId(pedNetId) - SetPedIntoVehicle(ped, vehicle, -1) - table.insert(pedList, pedNetId) - - -- Break vehicle - SetVehicleBodyHealth(vehicle, (math.random(1000) + 0.0)) - for i = 0, 5 do - local broken = math.random(0, 1) - if broken == 1 then - SetVehicleDoorBroken(vehicle, i, false) - end - SetVehicleDirtLevel(vehicle, math.random(15) + 0.0) - end - end - - -- Build objects - for i = 1, randomAmountOfObjects do - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - - local objModel = ERS_GetRandomModel(carPartObjects) - local objCoords = vector3(coords.x, coords.y, coords.z) - local objHeading = math.random(360) - local objNetId = ERS_CreateObject(objModel, objCoords, objHeading) - if objNetId then - local obj = NetworkGetEntityFromNetworkId(objNetId) - table.insert(objectList, objNetId) - else - DebugPrint("^1ERROR ^7Could not create object: "..objModel) - end - end - - for i = 1, randomAmountOfFires do - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - if UsingSmartFires then - -- Full version - local fireSize = Config.RandomLargeFireOrSmokeSize[math.random(#Config.RandomLargeFireOrSmokeSize)] - local fireType = Config.NormalFireTypes[math.random(#Config.NormalFireTypes)] - local fireId = exports['SmartFires']:CreateFire(vector3(coords.x, coords.y, coords.z+0.6), fireSize, fireType) - DebugPrint("Created fire with ID: "..fireId) - table.insert(fireList, fireId) - - local smokeSize = Config.RandomMediumFireOrSmokeSize[math.random(#Config.RandomMediumFireOrSmokeSize)] - local smokeType = Config.AllSmokeTypes[math.random(#Config.AllSmokeTypes)] - local smokeId = exports['SmartFires']:CreateSmoke(vector3(coords.x, coords.y, coords.z-0.5), smokeSize, smokeType) - DebugPrint("Created smoke particle with ID: "..smokeId) - table.insert(smokeList, smokeId) - else - local chanceToCreateSmoke = math.random(0, 1) -- 50% chance to create smoke - if chanceToCreateSmoke == 1 then - -- Lite version - local fireSize = Config.RandomLargeFireOrSmokeSize[math.random(#Config.RandomLargeFireOrSmokeSize)] - local fireType = "normal" - local fireId = exports['SmartFiresLite']:CreateFire(vector3(coords.x, coords.y, coords.z+0.6), fireSize, fireType) - DebugPrint("Created fire with SmartFiresLite with ID: "..fireId) - table.insert(fireList, fireId) - - local smokeSize = Config.RandomMediumFireOrSmokeSize[math.random(#Config.RandomMediumFireOrSmokeSize)] - local smokeType = "normal" - local smokeId = exports['SmartFiresLite']:CreateSmoke(vector3(coords.x, coords.y, coords.z-0.5), smokeSize, smokeType) - DebugPrint("Created smoke particle with ID: "..smokeId) - table.insert(smokeList, smokeId) - end - end - end - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_racecar_theft.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_racecar_theft.lua deleted file mode 100644 index ea46f7324..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_racecar_theft.lua +++ /dev/null @@ -1,98 +0,0 @@ -Config.Callouts["roxwood_racecar_theft"] = { - Enabled = false, - CalloutName = "Theft of a Racecar", - CalloutDescriptions = { - "High-performance racecar reported stolen from local track, immediate response required", - "Professional racing vehicle theft in progress, suspect may be armed and dangerous", - "Modified racing vehicle stolen during event preparations, high-value target", - "Competition racecar reported missing from secured garage area", - "Emergency: High-speed capable vehicle theft from racing complex", - "Urgent: Racing team reports theft of competition vehicle, suspect fleeing area", - "Track security reports unauthorized removal of professional racing vehicle", - "High-priority: Racing prototype stolen, vehicle extremely valuable", - "Alert: Competition vehicle theft from pit area, immediate response needed", - "Racing team reports forced entry and theft of performance vehicle", - }, - CalloutUnitsRequired = { - description = "Police.", - policeRequired = true, - ambulanceRequired = false, - fireRequired = false, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-2901.6108, 8056.7153, 44.8517), - [2] = vector3(-2737.1699, 8028.4966, 49.4163), - [3] = vector3(-2969.1304, 7983.6553, 44.8298), - }, - PedChanceToFleeFromPlayer = 90, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 10, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 10, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 25, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 2000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "flee", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_knife", - "weapon_pistol", - }, - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - local vehicle = nil - local driver = nil - - for index, vehNetId in pairs(vehicleList) do - local veh = NetToVeh(vehNetId) - if DoesEntityExist(veh) then - vehicle = veh - ERS_RequestNetControlForEntity(vehicle) - end - end - - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - driver = ped - ERS_RequestNetControlForEntity(driver) - if not IsPedOnAnyBike(driver) then - SmashVehicleWindow(vehicle, 0) -- break driver window - end - if not IsPedInAnyVehicle(driver, true) then - TaskEnterVehicle(driver, vehicle, 5000, -1, 2.0, 1, 0) - Wait(5000) - ERS_SetPedToFleeFromPlayer(driver) - else - ERS_SetPedToFleeFromPlayer(driver) - end - end - end - - ERS_CreateTemporaryBlipForEntities(vehicleList, 15000) - ERS_CreateTemporaryBlipForEntities(pedList, 15000) - - ERS_PerformTimedActionOnPed(calloutDataClient, pedList) - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - -- Build vehicle - local vehRaceModels = {"formula", "formula2", "openwheel1", "openwheel2"} - local vehModel = ERS_GetRandomModel(vehRaceModels) - local vehType = "automobile" - local vehCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z) - local vehHeading = math.random(360) - local vehNetId = ERS_CreateVehicle(vehModel, vehType, vehCoords, vehHeading) - local vehicle = NetworkGetEntityFromNetworkId(vehNetId) - table.insert(vehicleList, vehNetId) - - -- Build ped - local pedModel = ERS_GetRandomModel(Config.randomPeds) - local pedCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z +1.0) - local pedHeading = math.random(360) - local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) - local ped = NetworkGetEntityFromNetworkId(pedNetId) - SetPedIntoVehicle(ped, vehicle, -1) - table.insert(pedList, pedNetId) - - calloutBuilt = true - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_reports_of_a_fire.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_reports_of_a_fire.lua deleted file mode 100644 index e38f8f59a..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_reports_of_a_fire.lua +++ /dev/null @@ -1,135 +0,0 @@ -Config.Callouts["roxwood_reports_of_a_fire"] = { - - Enabled = true, - CalloutName = "Reports of a Fire", - CalloutDescriptions = { - "A fire has been reported, requiring immediate attention from fire services.", - "Emergency services are needed to extinguish a reported fire.", - "Reports indicate a fire has broken out, necessitating urgent firefighting intervention.", - "A fire has been identified, and additional fire personnel are needed for containment and extinguishment.", - "Emergency services have been requested to respond to a fire.", - "A request for assistance has been made by authorities dealing with a fire.", - "Additional units are required to support fire personnel managing a fire.", - "Emergency backup is required to assist fire authorities in handling a fire.", - "A call for assistance has been issued by responders dealing with a fire.", - "Reports suggest a situation where immediate firefighting intervention is crucial to manage and address a fire.", - }, - CalloutUnitsRequired = { - description = "Fire", - policeRequired = false, - ambulanceRequired = false, - fireRequired = true, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-2542.1089, 7467.2939, 40.1682), - [2] = vector3(-2070.9167, 7103.6870, 28.5290), - [3] = vector3(-2680.5420, 6456.3721, 28.7906), - [4] = vector3(-2660.3013, 6341.2979, 20.9317), - [5] = vector3(-2920.7075, 6240.0674, 12.7980), - [6] = vector3(-2785.6145, 6105.6709, 7.2804), - [7] = vector3(-2989.0220, 6141.8804, 4.8758), - [8] = vector3(-3029.2122, 6094.7715, 16.5621), - [9] = vector3(-3289.9795, 6187.9121, 13.7178), - [10] = vector3(-3068.1689, 7862.0122, 59.1986), - [11] = vector3(-2314.8447, 7807.0688, 38.4255), - [12] = vector3(-2306.9417, 7822.5352, 44.2124), - [13] = vector3(-2163.0261, 7998.2568, 44.3750), - [14] = vector3(-2207.9578, 8031.9858, 44.2027), - [15] = vector3(-2274.9910, 8146.1890, 34.1373), - [16] = vector3(-1290.7288, 8218.0352, 12.9399), - [17] = vector3(-606.0902, 7564.0142, 11.6405), - [18] = vector3(-833.0021, 7150.1865, 104.5681), - [19] = vector3(-380.6089, 7202.0557, 18.2214), - [20] = vector3(-455.5331, 7737.0986, 6.2801), - [21] = vector3(193.0212, 7768.1797, 6.4081), - }, - PedChanceToFleeFromPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 0, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 1000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "none", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_unarmed", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - ERS_RequestNetControlForEntity(ped) - TaskSetBlockingOfNonTemporaryEvents(ped, true) - PlayPain(ped, 8, 200) - ERS_ApplyBloodToPed(ped) - Wait(2500) - SetEntityHealth(ped, 0) - - end - end - - ERS_CreateTemporaryBlipForEntities(pedList, 15000) - - ERS_PerformTimedActionOnPed(calloutDataClient, pedList) - - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - - local diameter = 2 - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - - -- Build a small sized fire - if UsingSmartFires then - -- Full version - local fireSize = Config.RandomMediumFireOrSmokeSize[math.random(#Config.RandomMediumFireOrSmokeSize)] - local fireType = Config.NormalFireTypes[math.random(#Config.NormalFireTypes)] - local fireId = exports['SmartFires']:CreateFire(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), fireSize, fireType) - DebugPrint("Created fire with ID: "..fireId) - table.insert(fireList, fireId) - - -- Build smoke - local chanceOnASmoke = 50 - if math.random(1, 100) <= chanceOnASmoke then - local smokeSize = Config.RandomMediumFireOrSmokeSize[math.random(#Config.RandomMediumFireOrSmokeSize)] - local smokeType = Config.AllSmokeTypes[math.random(#Config.AllSmokeTypes)] - local smokeId = exports['SmartFires']:CreateSmoke(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), smokeSize, smokeType) - - DebugPrint("Created smoke with ID: "..smokeId) - table.insert(smokeList, smokeId) - end - else - -- Lite version - local fireSize = Config.RandomSmallFireOrSmokeSize[math.random(#Config.RandomSmallFireOrSmokeSize)] - local fireType = "normal" - local fireId = exports['SmartFiresLite']:CreateFire(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), fireSize, fireType) - DebugPrint("Created fire with SmartFiresLite with ID: "..fireId) - table.insert(fireList, fireId) - - -- Build smoke - local chanceOnASmoke = 50 - if math.random(1, 100) <= chanceOnASmoke then - local smokeSize = Config.RandomMediumFireOrSmokeSize[math.random(#Config.RandomMediumFireOrSmokeSize)] - local smokeType = "normal" - local smokeId = exports['SmartFiresLite']:CreateSmoke(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), smokeSize, smokeType) - - DebugPrint("Created smoke with ID: "..smokeId) - table.insert(smokeList, smokeId) - end - end - - local chanceOnAVictim = 50 - if math.random(1, 100) <= chanceOnAVictim then - -- Build victim - local pedModel = ERS_GetRandomModel(Config.randomPeds) - local pedCoords = vector3(coords.x, coords.y, coords.z) - local pedHeading = math.random(360) - local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) - local ped = NetworkGetEntityFromNetworkId(pedNetId) - table.insert(pedList, pedNetId) - end - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_reports_of_theft.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_reports_of_theft.lua deleted file mode 100644 index 9065688d7..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_reports_of_theft.lua +++ /dev/null @@ -1,110 +0,0 @@ -Config.Callouts["roxwood_reports_of_theft"] = { - Enabled = false, - CalloutName = "Reports of Theft", - CalloutDescriptions = { - "Reports of theft, details pending", - "Suspected theft reported, further information needed", - "Incident involving stolen vehicle, assess situation for safety", - "Theft reported, prioritize response for recovery", - "Reported theft of motor vehicle, investigate promptly", - "Vehicle reported missing, coordinate search and recovery efforts", - "Stolen reported, assess potential risks", - "Suspected theft of vehicle, approach investigation with caution", - "Reports of theft, prioritize response for recovery", - "Theft incident reported, coordinate with authorities", - }, - CalloutUnitsRequired = { - description = "Police.", - policeRequired = true, - ambulanceRequired = false, - fireRequired = false, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-906.1519, 6810.3047, 21.3176), - [2] = vector3(-641.7461, 6866.0830, 24.2095), - [3] = vector3(-629.4213, 6988.1577, 24.3153), - [4] = vector3(-540.8360, 6718.5483, 21.2485), - [5] = vector3(-263.4102, 7058.8438, 12.0184), - [6] = vector3(-302.9133, 7167.9888, 6.3294), - [7] = vector3(-289.1859, 7225.0986, 6.3294), - [8] = vector3(-216.6804, 7675.9102, 6.3277), - [9] = vector3(-1288.2164, 8249.0859, 12.0572), - [10] = vector3(-2238.5459, 8170.4370, 33.1580), - [11] = vector3(-2554.0913, 7474.7725, 28.6994), - [12] = vector3(-3058.3174, 7338.7568, 44.0336), - [13] = vector3(-3067.8191, 6315.9731, 8.8898), - [14] = vector3(-2989.0806, 6175.4121, 8.4440), - [15] = vector3(-3684.9780, 6187.1943, 24.5932), - [16] = vector3(-3096.2888, 6538.0146, 23.5485), - }, - PedChanceToFleeFromPlayer = 90, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 10, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 10, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 25, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 2000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "flee", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_knife", - "weapon_pistol", - }, - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - local vehicle = nil - local driver = nil - - for index, vehNetId in pairs(vehicleList) do - local veh = NetToVeh(vehNetId) - if DoesEntityExist(veh) then - vehicle = veh - ERS_RequestNetControlForEntity(vehicle) - end - end - - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - driver = ped - ERS_RequestNetControlForEntity(driver) - if not IsPedOnAnyBike(driver) then - SmashVehicleWindow(vehicle, 0) -- break driver window - end - if not IsPedInAnyVehicle(driver, true) then - TaskEnterVehicle(driver, vehicle, 5000, -1, 2.0, 1, 0) - Wait(5000) - ERS_SetPedToFleeFromPlayer(driver) - else - ERS_SetPedToFleeFromPlayer(driver) - end - end - end - - ERS_CreateTemporaryBlipForEntities(vehicleList, 15000) - ERS_CreateTemporaryBlipForEntities(pedList, 15000) - - ERS_PerformTimedActionOnPed(calloutDataClient, pedList) - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - -- Build vehicle - local vehModel = ERS_GetRandomModel(Config.randomVehicles) - local vehType = "automobile" - local vehCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z) - local vehHeading = math.random(360) - local vehNetId = ERS_CreateVehicle(vehModel, vehType, vehCoords, vehHeading) - local vehicle = NetworkGetEntityFromNetworkId(vehNetId) - table.insert(vehicleList, vehNetId) - - -- Build ped - local pedModel = ERS_GetRandomModel(Config.randomPeds) - local pedCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z +1.0) - local pedHeading = math.random(360) - local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) - local ped = NetworkGetEntityFromNetworkId(pedNetId) - SetPedIntoVehicle(ped, vehicle, -1) - table.insert(pedList, pedNetId) - - calloutBuilt = true - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_rubbish_washed_up_from_sea.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_rubbish_washed_up_from_sea.lua deleted file mode 100644 index 46f8911a4..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_rubbish_washed_up_from_sea.lua +++ /dev/null @@ -1,72 +0,0 @@ -Config.Callouts["roxwood_rubbish_washed_up_from_sea"] = { - - Enabled = true, - CalloutName = "Rubbish washed up from the sea", - CalloutDescriptions = { - "Emergency: respond to reports of debris washed up on the shoreline; assess environmental hazards.", - "Urgent alert: marine debris reported on the beach requiring immediate cleanup response.", - "Critical response required: investigate reports of sea waste washing up on the coast.", - "Notice: significant amount of marine debris has washed ashore; environmental assessment needed.", - "Alert: respond to reports of ocean waste on the beach; evaluate potential hazards.", - "Incident reported: sea debris has washed up on the shoreline requiring immediate attention.", - "Immediate action: address reports of marine waste on the beach; assess environmental impact.", - "Situation alert: coastal cleanup needed for debris washed up from the ocean.", - "Emergency response: handle reports of sea waste on the shoreline; ensure public safety.", - "Response needed: investigate reports of marine debris washed ashore; assess and coordinate cleanup.", - }, - CalloutUnitsRequired = { - description = "Police, fire.", - policeRequired = true, - ambulanceRequired = false, - fireRequired = true, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-176.0005, 7555.7231, 2.0013), - [2] = vector3(-229.1338, 7345.6353, 4.2200), - [3] = vector3(-3411.0190, 6075.2427, 2.6527), - [4] = vector3(-783.9731, 6659.8804, 2.3201), - [5] = vector3(-328.8283, 6974.1064, 2.4945), - }, - PedChanceToFleeFromPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 0, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 1000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "none", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_unarmed", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - for index, objNetId in pairs(objectList) do - local obj = NetToObj(objNetId) - if DoesEntityExist(obj) then - ERS_RequestNetControlForEntity(obj) - PlaceObjectOnGroundProperly(obj) - end - end - ERS_CreateTemporaryBlipForEntities(objectList, 30000) - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - local diameter = 10 - -- Build objects - local rubbishObjects = {"prop_rub_buswreck_01", "prop_rub_carwreck_10", "prop_rub_carwreck_13", "prop_rub_pile_01", "prop_pile_dirt_04", "prop_pile_dirt_02", "prop_rub_buswreck_03", "prop_wrecked_buzzard"} - local randomAmountOfObjects = math.random(1, 6) - for i = 1, randomAmountOfObjects do - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - local objModel = ERS_GetRandomModel(rubbishObjects) - local objCoords = vector3(coords.x, coords.y, coords.z+2.0) - local objHeading = math.random(360) - local objNetId = ERS_CreateObject(objModel, objCoords, objHeading) - if objNetId then - local obj = NetworkGetEntityFromNetworkId(objNetId) - table.insert(objectList, objNetId) - else - DebugPrint("^1ERROR ^7Could not create object: "..objModel) - end - end - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_shootout.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_shootout.lua deleted file mode 100644 index c6ae1476a..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_shootout.lua +++ /dev/null @@ -1,146 +0,0 @@ -Config.Callouts["roxwood_shootout"] = { - Enabled = true, - CalloutName = "Roxwood Shootout", - CalloutDescriptions = { - "A violent shootout has erupted between two rival groups in Roxwood.", - "Reports of gunfire exchanged between two factions, immediate response required.", - "A shootout is underway in Roxwood, with multiple armed individuals involved.", - "Two rival gangs are engaged in a firefight, posing a threat to public safety.", - "Gunfire reported in Roxwood as two groups clash violently.", - "Emergency services needed to contain a shootout between two armed groups.", - "A dangerous shootout is occurring, requiring swift intervention from authorities.", - "Two factions are exchanging gunfire, escalating tensions in the area.", - "A shootout has broken out, with both sides heavily armed.", - "Immediate action required to control a shootout between rival groups.", - }, - CalloutUnitsRequired = { - description = "Police.", - policeRequired = true, - ambulanceRequired = false, - fireRequired = false, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-829.9780, 7158.2388, 99.7499), - [2] = vector3(-455.7968, 7240.3081, 17.5236), - [3] = vector3(-357.8293, 7197.4155, 6.3290), - [4] = vector3(-362.7209, 7389.6875, 6.4129), - [5] = vector3(-537.7283, 7538.1699, 6.7560), - }, - PedChanceToFleeFromPlayer = 0, -- Lower chance to flee during a shootout. - PedChanceToAttackPlayer = 100, -- High chance to attack during a shootout. - PedChanceToSurrender = 0, -- No surrender during a shootout. - PedChanceToObtainWeapons = 100, -- Ensure all peds are armed. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 1000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "attack", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- Weapons for the shootout. - "weapon_pistol", - "weapon_smg", - "weapon_assaultrifle", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - local team1 = {} - local team2 = {} - - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - ERS_RequestNetControlForEntity(ped) - local model = GetEntityModel(ped) - - -- Randomly assign peds to one of the two teams - if #team1 < 8 and (math.random(2) == 1 or #team2 >= 8) then - table.insert(team1, ped) - else - table.insert(team2, ped) - end - - TaskSetBlockingOfNonTemporaryEvents(ped, true) - Wait(100) - ERS_SpawnConfiguredWeaponForPed(ped, calloutDataClient) - end - end - - -- Function to make peds flee for this case - local function makePedsFlee(peds) - for _, ped in pairs(peds) do - if DoesEntityExist(ped) and not IsPedDeadOrDying(ped, true) then - TaskSmartFleePed(ped, plyPed, 100.0, -1, false, false) - end - end - end - - -- Monitor and update ped behavior - Citizen.CreateThread(function() - while true do - Citizen.Wait(1000) -- Check every second - - -- Remove dead peds from teams - for i = #team1, 1, -1 do - if IsPedDeadOrDying(team1[i], true) then - table.remove(team1, i) - end - end - - for i = #team2, 1, -1 do - if IsPedDeadOrDying(team2[i], true) then - table.remove(team2, i) - end - end - - -- If a team is too small, make them flee - if #team1 < 3 then - makePedsFlee(team1) - break - end - - if #team2 < 3 then - makePedsFlee(team2) - break - end - end - end) - - -- Initial combat setup - if #team1 > 0 and #team2 > 0 then - for _, ped in pairs(team1) do - local randomTarget = team2[math.random(#team2)] - TaskCombatPed(ped, randomTarget, 0, 16) - if Config.Debug then - print("Team 1 Ped "..ped.." is attacking ped "..randomTarget) - end - end - - for _, ped in pairs(team2) do - local randomTarget = team1[math.random(#team1)] - TaskCombatPed(ped, randomTarget, 0, 16) - if Config.Debug then - print("Team 2 Ped "..ped.." is attacking ped "..randomTarget) - end - end - end - - ERS_CreateTemporaryBlipForEntities(pedList, 15000) - ERS_PerformTimedActionOnPed(calloutDataClient, pedList) - end, - - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - local randomPeds = Config.randomGangPeds - local totalPeds = math.random(10, 16) -- Total peds for both teams - - for i = 1, totalPeds do - -- Build peds - local diameter = 20 - local pedModel = ERS_GetRandomModel(randomPeds) - local pedCoords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - local pedHeading = math.random(360) - local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) - local ped = NetworkGetEntityFromNetworkId(pedNetId) - table.insert(pedList, pedNetId) - end - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_silo_fire.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_silo_fire.lua deleted file mode 100644 index 3f54ac0e0..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_silo_fire.lua +++ /dev/null @@ -1,165 +0,0 @@ -Config.Callouts["roxwood_silo_fire"] = { - - Enabled = true, - CalloutName = "Silo Fire", - CalloutDescriptions = { - "A fire has been reported in an agricultural silo, requiring immediate emergency response.", - "Emergency services are needed to address a fire situation at a grain storage silo.", - "Reports indicate a fire has broken out in a farm silo, necessitating urgent firefighting intervention.", - "A silo fire has been identified, posing potential risks to stored agricultural products and nearby structures.", - "Emergency services have been requested to respond to a fire at a storage silo facility.", - "A request for assistance has been made by farm personnel dealing with a silo fire.", - "Additional units are required to support fire personnel managing a dangerous silo fire.", - "Emergency backup is needed to contain a fire that has broken out in an agricultural silo.", - "First responders report an active fire situation at a grain storage silo.", - "Reports indicate a critical fire situation at a farm silo requiring specialized firefighting equipment.", - }, - CalloutUnitsRequired = { - description = "Fire", - policeRequired = false, - ambulanceRequired = false, - fireRequired = true, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-1650.7075, 6579.6846, 30.4142), - [2] = vector3(-1757.1521, 6566.3809, 79.2261), - [3] = vector3(-1666.2078, 6543.0640, 79.2194), - [4] = vector3(-1660.5845, 6602.8188, 32.9437), - [5] = vector3(-1680.0370, 6607.5435, 34.4462), - [6] = vector3(-1707.4130, 6616.6157, 31.7320), - [7] = vector3(-1724.4045, 6619.4497, 34.8395), - [8] = vector3(-1737.7704, 6623.3125, 33.3164), - [9] = vector3(175.7780, 7849.1553, 17.2202), - [10] = vector3(175.9884, 7765.7866, 16.3057), - [11] = vector3(21.9351, 7808.2656, 31.6843), - [12] = vector3(-708.7509, 6809.5586, 35.5453), - [13] = vector3(-713.1135, 6787.7432, 38.4738), - [14] = vector3(-2898.8865, 8279.4307, 48.0824), - }, - PedChanceToFleeFromPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 0, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 1000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "none", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_unarmed", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - ERS_RequestNetControlForEntity(ped) - TaskSetBlockingOfNonTemporaryEvents(ped, true) - PlayPain(ped, 8, 200) - ERS_ApplyBloodToPed(ped) - Wait(2500) - SetEntityHealth(ped, 0) - - end - end - - local chanceOfAnExplosion = 100 - if math.random(1, 100) <= chanceOfAnExplosion then - Citizen.SetTimeout(math.random(5000, 10000), function() - local explosionCoords = vector3(calloutDataClient.Coordinates.x, calloutDataClient.Coordinates.y, calloutDataClient.Coordinates.z) - local explosionRadius = 10.0 - local explosionForce = 10.0 - local explosionValues = { - 0, -- GRENADE - 1, -- GRENADELAUNCHER - 2, -- STICKYBOMB - 3, -- MOLOTOV - 4, -- ROCKET - 5, -- TANKSHELL - 6, -- HI_OCTANE - 7, -- CAR - 8, -- PLANE - 9, -- PETROL_PUMP - 10, -- BIKE - 11, -- DIR_STEAM - 12, -- DIR_FLAME - 13, -- DIR_WATER_HYDRANT - 14, -- DIR_GAS_CANISTER - 15, -- BOAT - 16, -- SHIP_DESTROY - 17, -- TRUCK - 18, -- BULLET - 19, -- SMOKE_GRENADE_LAUNCHER - 20, -- SMOKE_GRENADE - 21, -- BZGAS - 22, -- FLARE - 23, -- GAS_CANISTER - 24, -- EXTINGUISHER - 25, -- PROGRAMMABLEAR - 26, -- TRAIN - 27, -- BARREL - 28, -- PROPANE - 29, -- BLIMP - 30, -- DIR_FLAME_EXPLODE - 31, -- TANKER - 74, -- BOMB water - 75, -- BOMB water secondary - -- Only including explosion types that make sense for a silo fire - } - local explosionType = explosionValues[math.random(#explosionValues)] - AddExplosion(explosionCoords.x, explosionCoords.y, explosionCoords.z-2.0, explosionType, explosionRadius, explosionForce, true, false, 1.0) - end) - end - - ERS_CreateTemporaryBlipForEntities(pedList, 15000) - - ERS_PerformTimedActionOnPed(calloutDataClient, pedList) - - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - - local diameter = 2 - local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) - - -- Build a medium sized fire - if UsingSmartFires then - -- Full version - local fireSize = Config.RandomMediumFireOrSmokeSize[math.random(#Config.RandomMediumFireOrSmokeSize)] - local fireType = Config.NormalFireTypes[math.random(#Config.NormalFireTypes)] - local fireId = exports['SmartFires']:CreateFire(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), fireSize, fireType) - DebugPrint("Created fire with ID: "..fireId) - table.insert(fireList, fireId) - - -- Build smoke - local chanceOnASmoke = 50 - if math.random(1, 100) <= chanceOnASmoke then - local smokeSize = Config.RandomMediumFireOrSmokeSize[math.random(#Config.RandomMediumFireOrSmokeSize)] - local smokeType = Config.AllSmokeTypes[math.random(#Config.AllSmokeTypes)] - local smokeId = exports['SmartFires']:CreateSmoke(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), smokeSize, smokeType) - - DebugPrint("Created smoke with ID: "..smokeId) - table.insert(smokeList, smokeId) - end - else - -- Lite version - local fireSize = Config.RandomSmallFireOrSmokeSize[math.random(#Config.RandomSmallFireOrSmokeSize)] - local fireType = "normal" - local fireId = exports['SmartFiresLite']:CreateFire(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), fireSize, fireType) - DebugPrint("Created fire with SmartFiresLite with ID: "..fireId) - table.insert(fireList, fireId) - - -- Build smoke - local chanceOnASmoke = 50 - if math.random(1, 100) <= chanceOnASmoke then - local smokeSize = Config.RandomMediumFireOrSmokeSize[math.random(#Config.RandomMediumFireOrSmokeSize)] - local smokeType = "normal" - local smokeId = exports['SmartFiresLite']:CreateSmoke(vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z-0.5), smokeSize, smokeType) - - DebugPrint("Created smoke with ID: "..smokeId) - table.insert(smokeList, smokeId) - end - end - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_waterpark_incident.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_waterpark_incident.lua deleted file mode 100644 index 4afbd756b..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_waterpark_incident.lua +++ /dev/null @@ -1,75 +0,0 @@ -Config.Callouts["roxwood_waterpark_incident"] = { - - Enabled = true, - CalloutName = "Waterpark Incident", - CalloutDescriptions = { - "Emergency response needed at the waterpark; individual requiring immediate medical attention.", - "Alert: medical emergency reported at waterpark facilities; units requested for immediate response.", - "Units needed: incident reported at waterpark involving an injured person.", - "Emergency situation at waterpark; medical assistance required for park visitor.", - "Alert: waterpark incident in progress; medical response team needed on scene.", - "First responders requested at waterpark location; medical emergency reported.", - "Respond to waterpark emergency; coordinate with on-site staff for immediate assistance.", - "Situation alert: medical incident at waterpark facilities requiring urgent response.", - "Emergency services needed at waterpark; injured person requiring immediate attention.", - "Response needed: waterpark incident involving injured visitor; medical assistance required.", - }, - CalloutUnitsRequired = { - description = "Ambulance.", - policeRequired = false, - ambulanceRequired = true, - fireRequired = false, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-283.4168, 7742.1196, 4.7899), - [2] = vector3(-355.4387, 7813.5391, 4.4505), - [3] = vector3(-285.5687, 7806.6489, 6.3981), - [4] = vector3(-294.5287, 7814.0903, 6.4198), - [5] = vector3(-253.2503, 7772.4219, 6.4892), - [6] = vector3(-207.7762, 7791.9185, 11.1117), - [7] = vector3(-314.7422, 7720.8774, 6.3765), - [8] = vector3(-372.0792, 7815.6128, 6.3837), - [9] = vector3(-314.7273, 7838.0542, 27.3287), - [10] = vector3(-260.1914, 7839.4521, 14.3411), - - }, - PedChanceToFleeFromPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 0, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 1000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "none", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_unarmed", - }, - - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - ERS_RequestNetControlForEntity(ped) - SetEntityHealth(ped, 0) - end - end - - ERS_CreateTemporaryBlipForEntities(pedList, 15000) - ERS_PerformTimedActionOnPed(calloutDataClient, pedList) - - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - - -- Build ped` - local bathingPedModels = {"a_f_m_beach_01", "a_f_m_bodybuild_01", "a_f_m_fatcult_01", "a_f_y_beach_01", "a_m_m_tranvest_01", "a_m_y_acult_02", "a_m_y_jetski_01", "a_m_y_musclbeac_01", "a_m_y_stwhi_01"} - local pedModel = bathingPedModels[math.random(1, #bathingPedModels)] - local pedCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z+1.0) - local pedHeading = math.random(360) - local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) - local ped = NetworkGetEntityFromNetworkId(pedNetId) - table.insert(pedList, pedNetId) - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_wounded_adventurer.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_wounded_adventurer.lua deleted file mode 100644 index 0bd6bc1c3..000000000 --- a/resources/[ERS]/night_ers/callouts/plugins/callout_roxwood_wounded_adventurer.lua +++ /dev/null @@ -1,72 +0,0 @@ -Config.Callouts["roxwood_wounded_adventurer"] = { - - Enabled = true, - CalloutName = "Wounded adventurer", - CalloutDescriptions = { - "Emergency responders have located a wounded adventurer and are providing assistance.", - "Authorities report that a wounded adventurer has been found, requiring immediate medical attention.", - "A wounded adventurer has been located, necessitating urgent action to ensure their safety.", - "Critical situation with a wounded adventurer located; medical personnel are needed for support.", - "Immediate response needed to provide medical assistance to the wounded adventurer.", - "A wounded adventurer has been found, posing a severe threat to their health; medical reinforcements are necessary.", - "Emergency crews are requesting medical backup to assist in providing care to the wounded adventurer.", - "An urgent call for help has been issued to handle a wounded adventurer and ensure their well-being.", - "Responders are on the scene with a wounded adventurer and need extra support to provide necessary care.", - "A serious emergency involving a wounded adventurer demands swift action to provide medical attention and ensure their recovery.", - }, - CalloutUnitsRequired = { - description = "Police, Ambulance, Fire.", - policeRequired = true, - ambulanceRequired = true, - fireRequired = true, - towRequired = false, - }, - CalloutLocations = { - [1] = vector3(-2018.5511, 7298.9761, 33.5327), - [2] = vector3(-1760.0613, 7586.3652, 144.0277), - [3] = vector3(-1436.0414, 7666.9263, 322.1493), - [4] = vector3(-1310.2694, 7819.0005, 112.6630), - [5] = vector3(-1512.3247, 8080.1509, 42.6374), - [6] = vector3(-1986.1616, 8326.9473, 53.5735), - [7] = vector3(-2109.8350, 8310.7412, 39.0122), - [8] = vector3(-2905.3364, 7596.4253, 14.0765), - [9] = vector3(-3712.5322, 7523.3833, 30.1363), - [10] = vector3(-3044.6580, 7873.9575, 57.8766), - }, - PedChanceToFleeFromPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToAttackPlayer = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToSurrender = 0, -- Value between 0 and 100 -> Lower is less chance. - PedChanceToObtainWeapons = 0, -- Value between 0 and 100 -> Lower is less chance. - PedActionMinimumTimeoutInMs = 0, -- Milliseconds for the minimum timeout time to start the secondary action listed above. - PedActionMaximumTimeoutInMs = 1000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! - PedActionOnNoActionFound = "none", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" - PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. - "weapon_unarmed", - }, - client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) - for index, pedNetId in pairs(pedList) do - local ped = NetToPed(pedNetId) - if DoesEntityExist(ped) then - ERS_RequestNetControlForEntity(ped) - TaskSetBlockingOfNonTemporaryEvents(ped, true) - ERS_ApplyBloodToPed(ped) - local scenario = ERS_SelectRandomWoundedPersonScenario() - TaskStartScenarioInPlace(ped, scenario, 0, true) - end - end - - ERS_CreateTemporaryBlipForEntities(pedList, 5000) -- short, to make it harder to find. :) - ERS_PerformTimedActionOnPed(calloutDataClient, pedList) - end, - server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) - -- Build ped - local pedModel = ERS_GetRandomModel(Config.randomPeds) - local pedCoords = vector3(calloutData.Coordinates.x, calloutData.Coordinates.y, calloutData.Coordinates.z) - local pedHeading = math.random(360) - local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) - local ped = NetworkGetEntityFromNetworkId(pedNetId) - table.insert(pedList, pedNetId) - - return true - end -} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/callouts/plugins/callout_smoking_weed.lua b/resources/[ERS]/night_ers/callouts/plugins/callout_smoking_weed.lua new file mode 100644 index 000000000..fa7aca48c --- /dev/null +++ b/resources/[ERS]/night_ers/callouts/plugins/callout_smoking_weed.lua @@ -0,0 +1,125 @@ +Config.Callouts["smoking_weed"] = { + + Enabled = true, + CalloutName = "Reports of a person smoking weed", + CalloutDescriptions = { + "Investigate reports of a person smoking weed; locate the individual and assess the situation.", + "Alert: dispatch units to check on reports of marijuana use in a public area; ensure compliance with laws.", + "Units required: respond to reports of someone smoking weed and evaluate the circumstances.", + "Notice: check reports of a person using marijuana; take necessary actions to maintain public order.", + "Alert: respond promptly to reports of marijuana use; prioritize community safety and proper assessment.", + "Incident reported: look into reports of a person smoking weed to understand the context and legality.", + "Investigate reports of marijuana use; coordinate with local authorities to address the situation.", + "Situation alert: address reports of a person smoking weed; work with relevant authorities if needed.", + "Alert: handle reports of marijuana use and adhere to protocols for ensuring public safety and compliance.", + "Response needed: investigate reports of a person smoking weed and take steps to ensure community standards are upheld.", + }, + CalloutUnitsRequired = { + description = "Police", + policeRequired = true, + ambulanceRequired = false, + fireRequired = false, + towRequired = false, + }, + CalloutLocations = { + [1] = vector3(558.51, -2590.25, 6.19), + [2] = vector3(314.44, -997.08, 29.18), + [3] = vector3(195.41, -948.04, 30.09), + [4] = vector3(171.31, -1077.74, 29.19), + [5] = vector3(34.17, -1025.83, 29.47), + [6] = vector3(-137.15, -1180.85, 25.25), + [7] = vector3(-306.71, -1167.35, 23.26), + [8] = vector3(-318.98, -1334.59, 31.34), + [9] = vector3(-356.58, -1483.50, 30.16), + [10] = vector3(-342.61, -1566.72, 25.22), + [11] = vector3(-429.75, -1721.61, 19.05), + [12] = vector3(-575.62, -1793.78, 22.73), + [13] = vector3(-249.28, -1939.75, 29.95), + [14] = vector3(-331.26, -2171.95, 10.32), + [15] = vector3(-809.27, -2328.58, 14.57), + [16] = vector3(-1148.01, -1984.79, 13.16), + [17] = vector3(-1247.68, -1711.14, 4.47), + [18] = vector3(-1216.14, -1525.44, 4.26), + [19] = vector3(-1285.50, -1408.50, 4.45), + [20] = vector3(-1493.06, -1369.73, 2.15), + [21] = vector3(-1817.37, -1240.33, 13.02), + [22] = vector3(-1654.58, -362.49, 49.48), + [23] = vector3(-1318.32, -152.82, 46.39), + [24] = vector3(-516.12, -446.37, 34.19), + [25] = vector3(-302.33, -262.08, 32.42), + [26] = vector3(-188.07, -88.38, 52.18), + [27] = vector3(-43.71, -12.89, 69.87), + [28] = vector3(83.45, 33.97, 73.51), + [29] = vector3(243.14, 117.53, 102.62), + [30] = vector3(323.57, 174.77, 103.61), + [31] = vector3(193.88, 296.12, 105.62), + [32] = vector3(173.28, 387.58, 109.38), + [33] = vector3(206.88, 777.59, 205.56), + [34] = vector3(1221.91, 2722.65, 38.00), + [35] = vector3(1771.69, 3306.27, 41.17), + [36] = vector3(1633.14, 3559.25, 35.15), + [37] = vector3(1646.57, 3725.12, 34.34), + [38] = vector3(1767.44, 3754.12, 33.83), + [39] = vector3(1978.10, 3759.90, 32.18), + [40] = vector3(2461.98, 4063.67, 38.06), + [41] = vector3(2108.17, 4767.26, 41.17), + [42] = vector3(1695.52, 4784.01, 42.01), + [43] = vector3(1669.93, 4768.75, 41.85), + [44] = vector3(1429.15, 4384.90, 44.18), + [45] = vector3(1684.00, 6422.10, 32.27), + [46] = vector3(131.79, 6636.05, 31.81), + [47] = vector3(76.80, 6347.70, 31.37), + [48] = vector3(-18.15, 6392.06, 31.44), + [49] = vector3(-104.94, 6256.18, 31.35), + [50] = vector3(-252.48, 6213.64, 31.49), + [51] = vector3(-329.01, 6222.01, 31.48), + }, + PedChanceToFleeFromPlayer = 25, -- Value between 0 and 100 -> Lower is less chance. + PedChanceToAttackPlayer = 25, -- Value between 0 and 100 -> Lower is less chance. + PedChanceToSurrender = 10, -- Value between 0 and 100 -> Lower is less chance. + PedChanceToObtainWeapons = 10, -- Value between 0 and 100 -> Lower is less chance. + PedActionMinimumTimeoutInMs = 10000, -- Milliseconds for the minimum timeout time to start the secondary action listed above. + PedActionMaximumTimeoutInMs = 15000, -- Milliseconds for the maximum timeout time to start the secondary action. Must be a higher number than the minimum! + PedActionOnNoActionFound = "flee", -- When no action of the above options is found. It'll perform this action after the set timeout. Options: "none", "attack", "flee", "surrender" + PedWeaponData = { -- The ped will be given one randomly selected weapon (in hand) from these weapons if PedChanceToObtainWeapons passed. + "weapon_bat", + "weapon_hammer", + "weapon_wrench", + "weapon_pistol", + }, + + client = function(plyPed, pedList, vehicleList, playersList, objectList, propList, fireList, smokeList, calloutDataClient) + + for index, pedNetId in pairs(pedList) do + local ped = NetToPed(pedNetId) + if DoesEntityExist(ped) then + ERS_RequestNetControlForEntity(ped) + local scenario = ERS_SelectRandomSmokeScenario() + TaskStartScenarioInPlace(ped, scenario, 0, true) + end + end + + ERS_CreateTemporaryBlipForEntities(pedList, 15000) + + ERS_PerformTimedActionOnPed(calloutDataClient, pedList) + + end, + server = function(request, src, calloutData, pedList, vehicleList, objectList, propList, playersList, fireList, smokeList) + + local diameter = 10 + + -- Build suspects + local suspects = math.random(1, 3) + for i = 1, suspects do + local coords = ERS_GetRandomCoordinateWithinRangeOfCoordinate(calloutData.Coordinates, diameter) + local pedModel = ERS_GetRandomModel(Config.randomGangPeds) + local pedCoords = vector3(coords.x, coords.y, coords.z+1.0) + local pedHeading = math.random(360) + local pedNetId = ERS_CreatePed(pedModel, pedCoords, pedHeading) + local ped = NetworkGetEntityFromNetworkId(pedNetId) + table.insert(pedList, pedNetId) + end + + return true + end +} \ No newline at end of file diff --git a/resources/[ERS]/night_ers/client/c_functions.lua b/resources/[ERS]/night_ers/client/c_functions.lua index 397c78bf2..c948b5287 100644 --- a/resources/[ERS]/night_ers/client/c_functions.lua +++ b/resources/[ERS]/night_ers/client/c_functions.lua @@ -190,6 +190,8 @@ function OnNPCGivesGear(data) end end +exports("OnNPCGivesGear", OnNPCGivesGear) + -- ============================================ -- FUNCTIONS -- ============================================ diff --git a/resources/[ERS]/night_ers/client/client.lua b/resources/[ERS]/night_ers/client/client.lua index b45e603de..c1585b844 100644 Binary files a/resources/[ERS]/night_ers/client/client.lua and b/resources/[ERS]/night_ers/client/client.lua differ diff --git a/resources/[ERS]/night_ers/client/ers_functions.lua b/resources/[ERS]/night_ers/client/ers_functions.lua index 94e518ccd..0898900f2 100644 Binary files a/resources/[ERS]/night_ers/client/ers_functions.lua and b/resources/[ERS]/night_ers/client/ers_functions.lua differ diff --git a/resources/[ERS]/night_ers/client/exports_client.lua b/resources/[ERS]/night_ers/client/exports_client.lua index e32ec7dcd..051c7960a 100644 --- a/resources/[ERS]/night_ers/client/exports_client.lua +++ b/resources/[ERS]/night_ers/client/exports_client.lua @@ -21,6 +21,11 @@ exports('getIsPlayerAttachedToCallout', function() return isAttachedToCallout end) +exports('getIsPlayerOfferedACallout', function() + -- Returns: true or false + return isOfferedCallout +end) + exports('getIsPlayerTrackingUnit', function() -- Returns: true or false return isTrackingUnit.isTracking @@ -82,6 +87,10 @@ exports('ERS_ConnectClosestVehicle', function() ERS_ConnectClosestVehicle() end) +exports('getIsImperialEnabled', function() + return Config.UseImperial +end) + --====================== TEST COMMANDS ======================-- -- RegisterCommand('testclientexports', function() diff --git a/resources/[ERS]/night_ers/client/gear_client.lua b/resources/[ERS]/night_ers/client/gear_client.lua index 5f9b6880f..555be2386 100644 Binary files a/resources/[ERS]/night_ers/client/gear_client.lua and b/resources/[ERS]/night_ers/client/gear_client.lua differ diff --git a/resources/[ERS]/night_ers/client/impound_client.lua b/resources/[ERS]/night_ers/client/impound_client.lua index 5565c2e70..518f2db14 100644 Binary files a/resources/[ERS]/night_ers/client/impound_client.lua and b/resources/[ERS]/night_ers/client/impound_client.lua differ diff --git a/resources/[ERS]/night_ers/client/npcbackup_client.lua b/resources/[ERS]/night_ers/client/npcbackup_client.lua index 2f079f810..e69586ab4 100644 Binary files a/resources/[ERS]/night_ers/client/npcbackup_client.lua and b/resources/[ERS]/night_ers/client/npcbackup_client.lua differ diff --git a/resources/[ERS]/night_ers/client/pedinteractions_client.lua b/resources/[ERS]/night_ers/client/pedinteractions_client.lua index 48a2a175c..5f7de0f33 100644 Binary files a/resources/[ERS]/night_ers/client/pedinteractions_client.lua and b/resources/[ERS]/night_ers/client/pedinteractions_client.lua differ diff --git a/resources/[ERS]/night_ers/client/pullover_client.lua b/resources/[ERS]/night_ers/client/pullover_client.lua index b2739083e..aa6b447c4 100644 Binary files a/resources/[ERS]/night_ers/client/pullover_client.lua and b/resources/[ERS]/night_ers/client/pullover_client.lua differ diff --git a/resources/[ERS]/night_ers/client/pursuit_client.lua b/resources/[ERS]/night_ers/client/pursuit_client.lua index 496ae3669..b8fe20ed9 100644 Binary files a/resources/[ERS]/night_ers/client/pursuit_client.lua and b/resources/[ERS]/night_ers/client/pursuit_client.lua differ diff --git a/resources/[ERS]/night_ers/client/questioning_client.lua b/resources/[ERS]/night_ers/client/questioning_client.lua index 40f950773..5f5071f13 100644 Binary files a/resources/[ERS]/night_ers/client/questioning_client.lua and b/resources/[ERS]/night_ers/client/questioning_client.lua differ diff --git a/resources/[ERS]/night_ers/client/spikestrip_client.lua b/resources/[ERS]/night_ers/client/spikestrip_client.lua index 362522679..45a572ffa 100644 Binary files a/resources/[ERS]/night_ers/client/spikestrip_client.lua and b/resources/[ERS]/night_ers/client/spikestrip_client.lua differ diff --git a/resources/[ERS]/night_ers/client/stretcher_client.lua b/resources/[ERS]/night_ers/client/stretcher_client.lua index f60af685d..f481a1442 100644 Binary files a/resources/[ERS]/night_ers/client/stretcher_client.lua and b/resources/[ERS]/night_ers/client/stretcher_client.lua differ diff --git a/resources/[ERS]/night_ers/client/target.lua b/resources/[ERS]/night_ers/client/target.lua index 462667da9..cc1e377e6 100644 Binary files a/resources/[ERS]/night_ers/client/target.lua and b/resources/[ERS]/night_ers/client/target.lua differ diff --git a/resources/[ERS]/night_ers/client/towtools_client.lua b/resources/[ERS]/night_ers/client/towtools_client.lua index b402885a0..47e6aac56 100644 Binary files a/resources/[ERS]/night_ers/client/towtools_client.lua and b/resources/[ERS]/night_ers/client/towtools_client.lua differ diff --git a/resources/[ERS]/night_ers/client/vehinteractions_client.lua b/resources/[ERS]/night_ers/client/vehinteractions_client.lua index 5e3849fc2..6c6d29076 100644 Binary files a/resources/[ERS]/night_ers/client/vehinteractions_client.lua and b/resources/[ERS]/night_ers/client/vehinteractions_client.lua differ diff --git a/resources/[ERS]/night_ers/config/config.lua b/resources/[ERS]/night_ers/config/config.lua index 799bf435c..005be1532 100644 --- a/resources/[ERS]/night_ers/config/config.lua +++ b/resources/[ERS]/night_ers/config/config.lua @@ -2,15 +2,15 @@ Config = Config or {} Config = { - ConfigVersion = "1.8.1", + ConfigVersion = "1.8.3", Debug = false, -- Enable or disable Debug, recommended to set to false for improved gameplay (resmon is very high in debug mode). EventPrefix = "night_ers", -- Leave this be. - Language = "us", -- Available languages: en | us | nl | de | fr | he | cs | pt-br | sv | (Ajust text in config/translations.lua) - SoundLanguage = "us", -- Available languages: en | us | fr | de | (Ajust text in config/sound-config.lua) - DOBFormat = "us", -- Options: en | us + Language = "US", -- Available languages: en | us | nl | de | fr | he | cs | pt-br | sv | (Ajust text in config/translations.lua) + SoundLanguage = "US", -- Available languages: en | us | fr | de | (Ajust text in config/sound-config.lua) + DOBFormat = "US", -- Options: en | us UseImperial = false, -- Options: true = feet (mi) | false = meters (km) (Determines whether to display distances in feet (true) or meters (false)) - Timezone = "Europe/London", -- Set the timezone which the script uses. https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + Timezone = "America/Los_Angeles", -- Set the timezone which the script uses. https://en.wikipedia.org/wiki/List_of_tz_database_time_zones --[[ IMPORTANT: https://docs.fivem.net/natives/?_0xA0F2201F [OPTIONS FOR ServerLockDownMode (below)] @@ -270,6 +270,9 @@ Config = { -- Tow Tools ConnectClosestVehicle = "", -- Button to connect the closest vehicle to the towing vehicle. (None by default) + + -- Redisplay Last Module + RedisplayLastModule = "TAB", -- Button to redisplay the last shown module (ID card, vehicle info, or inventory). }, Commands = { @@ -328,6 +331,9 @@ Config = { -- Tow Tools ConnectClosestVehicle = "ccv", + -- Redisplay Last Module + RedisplayLastModule = "redisplaylastmodule", + -- Hints ToggleHints = "togglehints", }, @@ -387,6 +393,9 @@ Config = { -- Tow Tools ConnectClosestVehicle = "Command used to connect the closest vehicle to the towing vehicle.", + -- Redisplay Last Module + RedisplayLastModule = "Command used to redisplay the last shown module (ID card, vehicle info, or inventory).", + -- Hints ToggleHints = "Command used to toggle hints at certain events.", }, diff --git a/resources/[ERS]/night_ers/config/sound-config.lua b/resources/[ERS]/night_ers/config/sound-config.lua index 58a5cb013..758aa7aa5 100644 --- a/resources/[ERS]/night_ers/config/sound-config.lua +++ b/resources/[ERS]/night_ers/config/sound-config.lua @@ -219,12 +219,12 @@ Config.PedInteractionSoundFiles = { -- Only adjust FileName, SoundVolume and/or }, ['cuff'] = { Male = { - [1] = {FileName = SoundFileLanguagePrefix .. "_cuffs", SoundVolume = 0.3, TTS = '"Turn around so I can work on these cuffs."'}, + [1] = {FileName = SoundFileLanguagePrefix .. "_arrest_rights", SoundVolume = 0.3, TTS = '"**Reading Rights**"'}, -- [2] = {FileName = SoundFileLanguagePrefix .. "_cuff_1", SoundVolume = 0.3, TTS = '"Make your audio file and write the subtitle here."'}, -- [3] = {FileName = SoundFileLanguagePrefix .. "_cuff_2", SoundVolume = 0.3, TTS = '"Make your audio file and write the subtitle here."'}, }, Female = { - [1] = {FileName = SoundFileLanguagePrefix .. "_cuffs_f", SoundVolume = 0.3, TTS = '"Turn around so I can work on these cuffs."'}, + [1] = {FileName = SoundFileLanguagePrefix .. "_arrest_rights_f", SoundVolume = 0.3, TTS = '"**Reading Rights**"'}, -- [2] = {FileName = SoundFileLanguagePrefix .. "_cuff_1", SoundVolume = 0.3, TTS = '"Make your audio file and write the subtitle here."'}, -- [3] = {FileName = SoundFileLanguagePrefix .. "_cuff_2", SoundVolume = 0.3, TTS = '"Make your audio file and write the subtitle here."'}, }, diff --git a/resources/[ERS]/night_ers/config/spikestrip-config.lua b/resources/[ERS]/night_ers/config/spikestrip-config.lua index e45df1b78..96bb7cf04 100644 --- a/resources/[ERS]/night_ers/config/spikestrip-config.lua +++ b/resources/[ERS]/night_ers/config/spikestrip-config.lua @@ -1225,10 +1225,8 @@ Config.Spikestrips = { "schp16piust", "schp16piu", "maxchasrt", - "safe33g", - - - + "safe33g", + "tskodae", diff --git a/resources/[ERS]/night_ers/config/stretcher-config.lua b/resources/[ERS]/night_ers/config/stretcher-config.lua index f6e7b9470..03bffeba4 100644 --- a/resources/[ERS]/night_ers/config/stretcher-config.lua +++ b/resources/[ERS]/night_ers/config/stretcher-config.lua @@ -15,7 +15,6 @@ Config.VehiclesWithStretchers = { {hash = "ambumercbox", behindVehicle = -6.0, sideways = 0.0, depth = -1.4, height = 0.28}, {hash = "ukambu1", behindVehicle = -6.0, sideways = 0.0, depth = -1.5, height = 0.28}, {hash = "ukambu2", behindVehicle = -6.0, sideways = 0.0, depth = -1.5, height = 0.28}, - -- {hash = "your_ambulance", behindVehicle = -6.0, sideways = 0.0, depth = -1.5, height = 0.28}, {hash = "lafdrambulance", behindVehicle = -6.0, sideways = 0.0, depth = -1.5, height = 0.28}, {hash = "rambulance", behindVehicle = -6.0, sideways = 0.0, depth = -1.5, height = 0.28}, {hash = "24ramambo", behindVehicle = -6.0, sideways = 0.0, depth = -1.5, height = 0.28}, @@ -27,7 +26,9 @@ Config.VehiclesWithStretchers = { {hash = "fdgator", behindVehicle = -6.0, sideways = 0.0, depth = -1.5, height = 0.28}, {hash = "medic22", behindVehicle = -6.0, sideways = 0.0, depth = -1.5, height = 0.28}, - + + -- {hash = "your_ambulance", behindVehicle = -6.0, sideways = 0.0, depth = -1.5, height = 0.28}, + -- Add more here. } Config.ShowSavedScreen = true -- Shows victim saved in GTA style, when dropping off a victim. diff --git a/resources/[ERS]/night_ers/config/towtools-config.lua b/resources/[ERS]/night_ers/config/towtools-config.lua index 0d2a1fd7c..483a01bed 100644 --- a/resources/[ERS]/night_ers/config/towtools-config.lua +++ b/resources/[ERS]/night_ers/config/towtools-config.lua @@ -19,13 +19,13 @@ Config.TowableVehicleClasses = { [10] = true, -- Industrial [11] = true, -- Utility [12] = true, -- Vans - [13] = true,-- Cycles + [13] = false,-- Cycles [14] = false,-- Boats [15] = false,-- Helicopters [16] = false,-- Planes [17] = true, -- Service [18] = true, -- Emergency - [19] = false, -- Military + [19] = true, -- Military [20] = true, -- Commercial [21] = false,-- Trains [22] = true, -- Open Wheel @@ -35,6 +35,18 @@ Config.TowableVehicleClasses = { -- TO ADD MORE VEHICLES, COPY THE FORMAT AND FILL IN THE VARIABLES Config.TowVehicles = { + [`flatbed`] = { + enginePowerMultiplier = 28.0, -- Required for some tow trucks to have more power to pull heavy vehicles. + winchAnchorOverride = { + enabled = true, -- If false, the script will use the default tow anchor position. (Which is using the suspension or wheel bones) + left = { + { bone = "suspension_lr", leftRight = 0.0, forwardBack = 0.0, upDown = 0.0 }, + }, + right = { + { bone = "suspension_rr", leftRight = 0.0, forwardBack = 0.0, upDown = 0.0 }, + } + } + }, [`flatbed`] = { enginePowerMultiplier = 28.0, -- Required for some tow trucks to have more power to pull heavy vehicles. winchAnchorOverride = { @@ -540,8 +552,5 @@ Config.TowVehicles = { } } }, - - - - + } \ No newline at end of file diff --git a/resources/[ERS]/night_ers/fxmanifest.lua b/resources/[ERS]/night_ers/fxmanifest.lua index b35ed3085..de8d4fb8d 100644 --- a/resources/[ERS]/night_ers/fxmanifest.lua +++ b/resources/[ERS]/night_ers/fxmanifest.lua @@ -4,7 +4,7 @@ games { 'gta5' } author 'Nights Software' description 'Emergency Response Simulator' -version '1.8.2' +version '1.8.3' lua54 'yes' shared_scripts { @@ -46,7 +46,7 @@ files { 'stream/*.ytyp' } -data_file 'DLC_ITYP_REQUEST' 'stream/neko_night_barrier_assets' +data_file 'DLC_ITYP_REQUEST' 'stream/neko_night_barrier_assets.ytyp' data_file 'DLC_ITYP_REQUEST' 'stream/cages/v_storage_2.ytyp' data_file 'DLC_ITYP_REQUEST' 'stream/prop_alcotest.ytyp' diff --git a/resources/[ERS]/night_ers/index.html b/resources/[ERS]/night_ers/index.html index ebadec919..38781c6bc 100644 --- a/resources/[ERS]/night_ers/index.html +++ b/resources/[ERS]/night_ers/index.html @@ -19,6 +19,10 @@ + diff --git a/resources/[ERS]/night_ers/server/connection_server.lua b/resources/[ERS]/night_ers/server/connection_server.lua index 6116c3b3c..1eb1eaf3c 100644 Binary files a/resources/[ERS]/night_ers/server/connection_server.lua and b/resources/[ERS]/night_ers/server/connection_server.lua differ diff --git a/resources/[ERS]/night_ers/server/exports_server.lua b/resources/[ERS]/night_ers/server/exports_server.lua index 7a9e46714..3a1019150 100644 --- a/resources/[ERS]/night_ers/server/exports_server.lua +++ b/resources/[ERS]/night_ers/server/exports_server.lua @@ -1,22 +1,38 @@ --====================== SERVERSIDE EXPORTS ======================-- +-- local isOnShift = exports['night_ers']:getIsPlayerOnShift(src) +exports('getIsPlayerOnShift', function(src) + return getIsPlayerOnShift(src) +end) + +-- local getPlayerActiveServiceType = exports['night_ers']:getPlayerActiveServiceType(src) +exports('getPlayerActiveServiceType', function(src) + -- Returns: "police", "ambulance", "fire", "tow" or nil + return getPlayerActiveServiceType(src) +end) + +-- exports['night_ers']:toggleShift(source, shiftType) exports('toggleShift', function(source, shiftType) ToggleShift(source, shiftType) -- shiftType can be "police", "ambulance", "fire" or "tow" end) +-- exports['night_ers']:trackPlayerCallout(source, targetSource) exports('trackPlayerCallout', function(source, targetSource) TrackUnit(source, targetSource) end) +-- exports['night_ers']:setPlayerCalloutOffersEnabled(source, enabled) exports('setPlayerCalloutOffersEnabled', function(source, enabled) SetPlayerCalloutOffersEnabled(source, enabled) end) +-- exports['night_ers']:getCallouts() exports('getCallouts', function() local jsonReadyTable = cloneWithoutFunctions(Config.Callouts) return jsonReadyTable end) +-- exports['night_ers']:createCallout(callout) exports('createCallout', function(callout) local newCalloutID = callout.id .. '-' .. os.time() Config.Callouts[newCalloutID] = Config.Callouts[callout.id] @@ -32,9 +48,4 @@ exports('createCallout', function(callout) calloutId = newCalloutID, } return returnData -end) - --- exports['night_ers']:toggleShift(source, shiftType) --- exports['night_ers']:trackPlayerCallout(source, targetSource) --- exports['night_ers']:setPlayerCalloutOffersEnabled(source, enabled) --- exports['night_ers']:createCallout(callout) \ No newline at end of file +end) \ No newline at end of file diff --git a/resources/[ERS]/night_ers/server/gear_server.lua b/resources/[ERS]/night_ers/server/gear_server.lua index da4e393c4..2a8aaf7b8 100644 Binary files a/resources/[ERS]/night_ers/server/gear_server.lua and b/resources/[ERS]/night_ers/server/gear_server.lua differ diff --git a/resources/[ERS]/night_ers/server/impound_server.lua b/resources/[ERS]/night_ers/server/impound_server.lua index 9b659495f..c0db83c8f 100644 Binary files a/resources/[ERS]/night_ers/server/impound_server.lua and b/resources/[ERS]/night_ers/server/impound_server.lua differ diff --git a/resources/[ERS]/night_ers/server/leaderboard_server.lua b/resources/[ERS]/night_ers/server/leaderboard_server.lua index fd265d343..fa4714f08 100644 Binary files a/resources/[ERS]/night_ers/server/leaderboard_server.lua and b/resources/[ERS]/night_ers/server/leaderboard_server.lua differ diff --git a/resources/[ERS]/night_ers/server/npcbackup_server.lua b/resources/[ERS]/night_ers/server/npcbackup_server.lua index 20c073fe6..418d47b42 100644 Binary files a/resources/[ERS]/night_ers/server/npcbackup_server.lua and b/resources/[ERS]/night_ers/server/npcbackup_server.lua differ diff --git a/resources/[ERS]/night_ers/server/pullover_server.lua b/resources/[ERS]/night_ers/server/pullover_server.lua index d1bbe62db..21f3ff911 100644 Binary files a/resources/[ERS]/night_ers/server/pullover_server.lua and b/resources/[ERS]/night_ers/server/pullover_server.lua differ diff --git a/resources/[ERS]/night_ers/server/pursuit_server.lua b/resources/[ERS]/night_ers/server/pursuit_server.lua index c074d758d..73c605bbf 100644 Binary files a/resources/[ERS]/night_ers/server/pursuit_server.lua and b/resources/[ERS]/night_ers/server/pursuit_server.lua differ diff --git a/resources/[ERS]/night_ers/server/server.lua b/resources/[ERS]/night_ers/server/server.lua index 5ea2e9222..20d2d57e0 100644 Binary files a/resources/[ERS]/night_ers/server/server.lua and b/resources/[ERS]/night_ers/server/server.lua differ diff --git a/resources/[ERS]/night_ers/server/spikestrip_server.lua b/resources/[ERS]/night_ers/server/spikestrip_server.lua index 034a50023..64cb29ce6 100644 Binary files a/resources/[ERS]/night_ers/server/spikestrip_server.lua and b/resources/[ERS]/night_ers/server/spikestrip_server.lua differ diff --git a/resources/[ERS]/night_ers/server/stretcher_server.lua b/resources/[ERS]/night_ers/server/stretcher_server.lua index 6969a64e6..586b7940c 100644 Binary files a/resources/[ERS]/night_ers/server/stretcher_server.lua and b/resources/[ERS]/night_ers/server/stretcher_server.lua differ diff --git a/resources/[ERS]/night_ers/server/towtools_server.lua b/resources/[ERS]/night_ers/server/towtools_server.lua index 303f7ea41..d4488ba38 100644 Binary files a/resources/[ERS]/night_ers/server/towtools_server.lua and b/resources/[ERS]/night_ers/server/towtools_server.lua differ diff --git a/resources/[ERS]/night_ers/stream/[Breathalyzer]/prop_alcotest.ydr b/resources/[ERS]/night_ers/stream/[Breathalyzer]/prop_alcotest.ydr index 8624ef879..a4daf5ab9 100644 --- a/resources/[ERS]/night_ers/stream/[Breathalyzer]/prop_alcotest.ydr +++ b/resources/[ERS]/night_ers/stream/[Breathalyzer]/prop_alcotest.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:61bec3e377ee72f14913c67fffc5ecc11f7eef5e6c3987b85a185f7dcd714049 -size 1037399 +oid sha256:47d39988db2ec8b8338e6a18c7ece73b06a42eab7681eebee9f082c85ebc3433 +size 1123652 diff --git a/resources/[ERS]/night_ers/stream/[Cages]/prop_dog_cage_03.ydr b/resources/[ERS]/night_ers/stream/[Cages]/prop_dog_cage_03.ydr index 05e00b50c..f8acdf377 100644 --- a/resources/[ERS]/night_ers/stream/[Cages]/prop_dog_cage_03.ydr +++ b/resources/[ERS]/night_ers/stream/[Cages]/prop_dog_cage_03.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:731f203a77436493b95fab862449bd8e2529cdd21bdfea7ff824b71d809d123a -size 283459 +oid sha256:f2f606f11d551978130804dad19278866b63837757cc600e2e0a7fd7f592391c +size 296951 diff --git a/resources/[ERS]/night_ers/stream/[Cages]/prop_dog_cage_04.ydr b/resources/[ERS]/night_ers/stream/[Cages]/prop_dog_cage_04.ydr index 08ecd09e9..858cc0fbd 100644 --- a/resources/[ERS]/night_ers/stream/[Cages]/prop_dog_cage_04.ydr +++ b/resources/[ERS]/night_ers/stream/[Cages]/prop_dog_cage_04.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:184087526495fe35ae71328a8895bea7dd52306120835065af117941c46edf3a -size 285657 +oid sha256:75d6d90db6786877ef1dcb83db1c3439d7d155c28ad25dc35b9eb5b4b01e02ea +size 303029 diff --git a/resources/[ERS]/night_ers/stream/[Cages]/prop_dog_cage_05.ydr b/resources/[ERS]/night_ers/stream/[Cages]/prop_dog_cage_05.ydr index e264aab6b..b07dd440c 100644 --- a/resources/[ERS]/night_ers/stream/[Cages]/prop_dog_cage_05.ydr +++ b/resources/[ERS]/night_ers/stream/[Cages]/prop_dog_cage_05.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e5e163d621ec35609913d04b8071bbb586ffd90e00c39de68c7e2a0e4046456 -size 286917 +oid sha256:34327dce44721667c7346d30f86e1d64b560e3c766df6b67ba81d3e749707c63 +size 301864 diff --git a/resources/[ERS]/night_ers/stream/[Cuffs]/p_cs_cuffs_02_s.ydr b/resources/[ERS]/night_ers/stream/[Cuffs]/p_cs_cuffs_02_s.ydr index 377b41781..48d81677e 100644 --- a/resources/[ERS]/night_ers/stream/[Cuffs]/p_cs_cuffs_02_s.ydr +++ b/resources/[ERS]/night_ers/stream/[Cuffs]/p_cs_cuffs_02_s.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0e5a7cc15baf95b3bb75b0f1ac4bb02fda1b1c8faf02d37cecef8a8b0ae98966 -size 1109675 +oid sha256:8c1d634486a048f088ffd7eb3df862bac5d15a7b35950c33c389aaad5d7e30ec +size 1837203 diff --git a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_arrow_board_00.ydr b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_arrow_board_00.ydr index b5b0a7179..7f0783317 100644 --- a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_arrow_board_00.ydr +++ b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_arrow_board_00.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b30966fb460baabd8c2521c2f49680062dc8ceaccc2048a667b109edbc718ba -size 149589 +oid sha256:20fb751141263dbe4b93ef8e8e1e34415b84f453c716a46d041efb752a654411 +size 208368 diff --git a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_arrow_board_00_l.ydr b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_arrow_board_00_l.ydr index ccbeca5d5..152406a41 100644 --- a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_arrow_board_00_l.ydr +++ b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_arrow_board_00_l.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3737b1aadccc190dfd8dfe8c033f982582ab18a2c5330f70d261a4533c0bca3 -size 148139 +oid sha256:3a305759c820b39804a0f6efdb6034c9c19a5e49071b6094354d96e74cb80c43 +size 206076 diff --git a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_arrow_board_00_r.ydr b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_arrow_board_00_r.ydr index 8de9f7608..5b22bad88 100644 --- a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_arrow_board_00_r.ydr +++ b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_arrow_board_00_r.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6248314e4a7a6f7869b7b05bc9fe3e30b3986c7d19f498df765b7b33ce6c5d4 -size 148334 +oid sha256:cdf75c1c22029c676ec190749634d0b4017dfe9ac8e77e74c92a09cd57ef14c6 +size 213444 diff --git a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_barrier_00.ydr b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_barrier_00.ydr index c40856d0a..37850be16 100644 --- a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_barrier_00.ydr +++ b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_barrier_00.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2759fd0cb064bc4f801ec5c54ccb89e936603f26f32fd6ae6ca4c3eab212b092 -size 67744 +oid sha256:f542c3b925d026a6d5ac1af458d8d256447911cf66789d75645ceb40a5db1367 +size 112759 diff --git a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_barrier_01.ydr b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_barrier_01.ydr index 3a8af988e..72a76eaf0 100644 --- a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_barrier_01.ydr +++ b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_barrier_01.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c37e7c8a9b702a93b1ce5666961293e257b58643b2e470d15184f30e10f00d03 -size 42341 +oid sha256:f97d8b321cbabe07ffb424aab5efd3f2f95fe979b6c669741e32facff0c20831 +size 96006 diff --git a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_barrier_02.ydr b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_barrier_02.ydr index 664c9fd97..7266f6fb6 100644 --- a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_barrier_02.ydr +++ b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_barrier_02.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8bfb01242b7ca2d58971b4f52f6079ef074b2fb557640e721bfed2d6b62ebd86 -size 25808 +oid sha256:2532695da81b564444d10816fa54550d7187e3a86d09ce30491a33137d0eefd8 +size 47891 diff --git a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_cone_00.ydr b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_cone_00.ydr index 08ccca062..c8ce5cb51 100644 --- a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_cone_00.ydr +++ b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_cone_00.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed574bef081fade578f99931cc82552715c20c0b28283afbb97e0db758aa1626 -size 14730 +oid sha256:08886d3dd7d6adebbd33d96e9d4872c1f881d101db4a9276a7af90f342b761af +size 25570 diff --git a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_rubber_barrier_00.ydr b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_rubber_barrier_00.ydr index c6e7de9d8..c5c92bc52 100644 --- a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_rubber_barrier_00.ydr +++ b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_rubber_barrier_00.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab7288bf10e60089b0a8fb2ce17de22307701e46a644064955244b2038ed52d0 -size 7903 +oid sha256:4f826d7dc8013db4d1ad3c182a7ceb8802562cd890d11315f4eceebfecb64e1b +size 11869 diff --git a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_warning_tri_00.ydr b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_warning_tri_00.ydr index a0d13d7d0..5010ab874 100644 --- a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_warning_tri_00.ydr +++ b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_warning_tri_00.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb34139a3c89c459e36ba464a532ef150f5c3bb649e90b107ca79345b6fe42ce -size 20166 +oid sha256:b44a901c58f6e41f92413ec41052663e70efcbcaf77620f6c5a571ee492a62a2 +size 26812 diff --git a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_water_barrier_00.ydr b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_water_barrier_00.ydr index 39a519a60..31cc3daed 100644 --- a/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_water_barrier_00.ydr +++ b/resources/[ERS]/night_ers/stream/[NXP Props]/neko_night_water_barrier_00.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c3f0d44b33206d6e8a36469538b5c9b801a5efd3f2da78619b35e07a0d65f961 -size 84742 +oid sha256:216632f5d7d484fb74df0edd7cf82b4c9ac997750fa16fe9d2eadd07660cac48 +size 148637 diff --git a/resources/[ERS]/night_ers/stream/[SmartHose]/w_ers_npc_hose.ydr b/resources/[ERS]/night_ers/stream/[SmartHose]/w_ers_npc_hose.ydr index f10279011..d0bdf3bd7 100644 --- a/resources/[ERS]/night_ers/stream/[SmartHose]/w_ers_npc_hose.ydr +++ b/resources/[ERS]/night_ers/stream/[SmartHose]/w_ers_npc_hose.ydr @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:42257e94061a1b5c24c11978c0464ba3d8a1495887ea8047e70e39578da1c47a -size 251507 +oid sha256:b75afc48c06ee9489f59862f5dad7bd156d6df8a06939fbb8ea6dcbae576d96a +size 403069 diff --git a/resources/[ERS]/night_ers/stream/[Stretcher]/stretcher.yft b/resources/[ERS]/night_ers/stream/[Stretcher]/stretcher.yft index fdb885c9e..7a6293679 100644 --- a/resources/[ERS]/night_ers/stream/[Stretcher]/stretcher.yft +++ b/resources/[ERS]/night_ers/stream/[Stretcher]/stretcher.yft @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d2a4a489f095eab9c1baf6073285021bf3f7956d711ad05faec9a42de10a584 -size 5925533 +oid sha256:44a176866171d5f5466ca7b355552d99585c8af3387f61879412af898107943d +size 10107862 diff --git a/resources/[ERS]/night_ers/stream/[Stretcher]/stretcher_hi.yft b/resources/[ERS]/night_ers/stream/[Stretcher]/stretcher_hi.yft index ae8d0a855..f903ca75d 100644 --- a/resources/[ERS]/night_ers/stream/[Stretcher]/stretcher_hi.yft +++ b/resources/[ERS]/night_ers/stream/[Stretcher]/stretcher_hi.yft @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9aac15c3a19a8e03ff99cb6c88bf2d245dbe118d9c09d6955687346c7f6e7584 -size 5925533 +oid sha256:2de3e83ab6de0c92aac121277fe8de143552e38ed2f17302e8aace2d20ff8be3 +size 10578950 diff --git a/resources/[ERS]/night_ers_k9/.fxap b/resources/[ERS]/night_ers_k9/.fxap index 7262b1378..9f04d76b4 100644 Binary files a/resources/[ERS]/night_ers_k9/.fxap and b/resources/[ERS]/night_ers_k9/.fxap differ diff --git a/resources/[ERS]/night_ers_k9/NUI/main.js b/resources/[ERS]/night_ers_k9/NUI/main.js index c42f70058..b299301ab 100644 --- a/resources/[ERS]/night_ers_k9/NUI/main.js +++ b/resources/[ERS]/night_ers_k9/NUI/main.js @@ -1,4 +1,72 @@ -let crosshairElement=null,translations=null,hotkeys=null;function togglePedControlsVisibility(s){let t=document.getElementById("ped-controls");if(t)(isPedControlsVisible=void 0===s?!isPedControlsVisible:s)?(t.classList.remove("animate-fade-out"),t.classList.add("animate-fade-in"),t.style.display="block"):(t.classList.remove("animate-fade-in"),t.classList.add("animate-fade-out"),setTimeout(()=>{t.style.display="none"},250));else{let e=document.createElement("div");e.id="ped-controls",e.classList.add("fixed","bottom-16","right-16","z-10","inline-block","text-white","bg-gray-900","bg-opacity-50","border","border-gray-700","rounded-lg","shadow-lg","w-[600px]","transition-all","duration-300","opacity-100"),e.innerHTML=` +let crosshairElement = null; +let translations = null; +let hotkeys = null; + +window.addEventListener('message', (event) => { + const data = event.data; + + if (data.action == "setTranslations") { + translations = data.translations; + } + + if (data.action == "setHotkeys") { + hotkeys = data.hotkeys; + } + + if (data.action == "drawCrosshair") { + let display = data.display; + + // Get the crosshair element + if (!crosshairElement) { + crosshairElement = document.getElementById('crosshair'); + if (!crosshairElement) { + console.log("Crosshair element not found!"); + return; + } + } + + // Set display style directly + crosshairElement.style.display = display ? 'block' : 'none'; + } + + if (data.action == "ped-controls") { + let display = data.display; + togglePedControlsVisibility(display); + } + + if (data.action == "vehicle-controls") { + let display = data.display; + toggleVehicleControlsVisibility(display); + } +}); + + +function togglePedControlsVisibility(visible) { + const controls = document.getElementById('ped-controls'); + if (controls) { + if (visible === undefined) { + isPedControlsVisible = !isPedControlsVisible; + } else { + isPedControlsVisible = visible; + } + + if (isPedControlsVisible) { + controls.classList.remove('animate-fade-out'); + controls.classList.add('animate-fade-in'); + controls.style.display = 'block'; + } else { + controls.classList.remove('animate-fade-in'); + controls.classList.add('animate-fade-out'); + setTimeout(() => { + controls.style.display = 'none'; + }, 250); + } + } else { + // Build the element + const pedControlsElement = document.createElement('div'); + pedControlsElement.id = 'ped-controls'; + pedControlsElement.classList.add('fixed', 'bottom-16', 'right-16', 'z-10', 'inline-block', 'text-white', 'bg-gray-900', 'bg-opacity-50', 'border', 'border-gray-700', 'rounded-lg', 'shadow-lg', 'w-[600px]', 'transition-all', 'duration-300', 'opacity-100'); + pedControlsElement.innerHTML = `
@@ -41,7 +109,42 @@ let crosshairElement=null,translations=null,hotkeys=null;function togglePedContr
- `,document.body.appendChild(e),togglePedControlsVisibility(s)}}function toggleVehicleControlsVisibility(s){let t=document.getElementById("vehicle-controls");if(t)(isVehicleControlsVisible=void 0===s?!isVehicleControlsVisible:s)?(t.classList.remove("animate-fade-out"),t.classList.add("animate-fade-in"),t.style.display="block"):(t.classList.remove("animate-fade-in"),t.classList.add("animate-fade-out"),setTimeout(()=>{t.style.display="none"},250));else{let e=document.createElement("div");e.id="vehicle-controls",e.classList.add("fixed","bottom-16","right-16","z-10","inline-block","text-white","bg-gray-900","bg-opacity-50","border","border-gray-700","rounded-lg","shadow-lg","w-[600px]","transition-all","duration-300","opacity-100"),e.innerHTML=` + `; + + // Append the element to the body + document.body.appendChild(pedControlsElement); + + // Toggle the visibility of the element + togglePedControlsVisibility(visible); + } +} + +function toggleVehicleControlsVisibility(visible) { + const controls = document.getElementById('vehicle-controls'); + if (controls) { + if (visible === undefined) { + isVehicleControlsVisible = !isVehicleControlsVisible; + } else { + isVehicleControlsVisible = visible; + } + + if (isVehicleControlsVisible) { + controls.classList.remove('animate-fade-out'); + controls.classList.add('animate-fade-in'); + controls.style.display = 'block'; + } else { + controls.classList.remove('animate-fade-in'); + controls.classList.add('animate-fade-out'); + setTimeout(() => { + controls.style.display = 'none'; + }, 250); + } + } else { + // Build the element + const vehicleControlsElement = document.createElement('div'); + vehicleControlsElement.id = 'vehicle-controls'; + vehicleControlsElement.classList.add('fixed', 'bottom-16', 'right-16', 'z-10', 'inline-block', 'text-white', 'bg-gray-900', 'bg-opacity-50', 'border', 'border-gray-700', 'rounded-lg', 'shadow-lg', 'w-[600px]', 'transition-all', 'duration-300', 'opacity-100'); + vehicleControlsElement.innerHTML = `
@@ -74,4 +177,12 @@ let crosshairElement=null,translations=null,hotkeys=null;function togglePedContr
- `,document.body.appendChild(e),toggleVehicleControlsVisibility(s)}}window.addEventListener("message",s=>{let t=s.data;if("setTranslations"==t.action&&(translations=t.translations),"setHotkeys"==t.action&&(hotkeys=t.hotkeys),"drawCrosshair"==t.action){let e=t.display;if(!crosshairElement&&!(crosshairElement=document.getElementById("crosshair"))){console.log("Crosshair element not found!");return}crosshairElement.style.display=e?"block":"none"}"ped-controls"==t.action&&togglePedControlsVisibility(t.display),"vehicle-controls"==t.action&&toggleVehicleControlsVisibility(t.display)}); \ No newline at end of file + `; + + // Append the element to the body + document.body.appendChild(vehicleControlsElement); + + // Toggle the visibility of the element + toggleVehicleControlsVisibility(visible); + } +} \ No newline at end of file diff --git a/resources/[ERS]/night_ers_k9/client/client.lua b/resources/[ERS]/night_ers_k9/client/client.lua index f3c11ffbf..ff0555268 100644 Binary files a/resources/[ERS]/night_ers_k9/client/client.lua and b/resources/[ERS]/night_ers_k9/client/client.lua differ diff --git a/resources/[ERS]/night_ers_k9/client/client_k9handler.lua b/resources/[ERS]/night_ers_k9/client/client_k9handler.lua index 6044f7c0d..9b8b187d4 100644 Binary files a/resources/[ERS]/night_ers_k9/client/client_k9handler.lua and b/resources/[ERS]/night_ers_k9/client/client_k9handler.lua differ diff --git a/resources/[ERS]/night_ers_k9/config/config.lua b/resources/[ERS]/night_ers_k9/config/config.lua index cc19c3eb7..6624d22c6 100644 --- a/resources/[ERS]/night_ers_k9/config/config.lua +++ b/resources/[ERS]/night_ers_k9/config/config.lua @@ -1,6 +1,6 @@ Config = { - ConfigVersion = "1.0.0", + ConfigVersion = "1.1.4", --====================== DEVELOPER SETTINGS ======================-- @@ -44,10 +44,106 @@ Config = { K9Vehicles = { -- Base game vehicle example - {hash = `policet`, spawnOffset = vector3(0.0 --[[Right/-Left]], -4.0 --[[Front/-Rear]], 0.5 --[[Up/-Down]]), dogModelName = "a_c_shepherd"}, + { + hash = `policet`, spawnOffset = vector3(0.0 --[[Right/-Left]], -4.0 --[[Front/-Rear]], 0.5 --[[Up/-Down]]), + dogModelName = "a_c_shepherd", + props = { + -- Example: {prop type (Helmet), prop type index (Motorcycle helmet), prop colour index (Black colour)} + -- { drawable, texture, palette } + { 0, 1, 1 }, -- Hats / Helments + { 1, 1, 1 }, -- Glassess + { 2, 1, 1 }, -- Misc + { 3, 1, 1 }, + }, + components = { + -- Example: {component type (Mask), component type index (Clown Mask), component colour index (White colour)} + -- { drawable, texture, palette } + { 1, 1, 1 }, -- Mask + { 2, 1, 1 }, -- Hair + { 3, 1, 1 }, -- Upper body + { 4, 1, 1 }, -- Legs / Pants + { 5, 1, 1 }, -- Bags / Parachutes + { 6, 1, 1 }, -- Shoes + { 7, 1, 1 }, -- Neck / Scarfs + { 8, 1, 1 }, -- Shirt / Accessory (This palette is commonly used for the text on the K9 vest) + { 9, 1, 1 }, -- Body Armor + { 10, 1, 1 }, -- Badges / Logos + { 11, 1, 1 }, -- Jackets + }, + }, -- Custom vehicle example - {hash = `forddsumo7`, spawnOffset = vector3(0.0, -4.0, 0.5), dogModelName = "a_c_shepherd"}, + { + hash = `forddsumo7`, spawnOffset = vector3(0.0, -4.0, 0.5), + dogModelName = "a_c_shepherd", + props = { + -- Example: {prop type (Helmet), prop type index (Motorcycle helmet), prop colour index (Black colour)} + -- { drawable, texture, palette } + { 0, 1, 1 }, -- Hats / Helments + { 1, 1, 1 }, -- Glassess + { 2, 1, 1 }, -- Misc + { 3, 1, 1 }, + }, + components = { + -- Example: {component type (Mask), component type index (Clown Mask), component colour index (White colour)} + -- { drawable, texture, palette } + { 1, 1, 1 }, -- Mask + { 2, 1, 1 }, -- Hair + { 3, 1, 1 }, -- Upper body + { 4, 1, 1 }, -- Legs / Pants + { 5, 1, 1 }, -- Bags / Parachutes + { 6, 1, 1 }, -- Shoes + { 7, 1, 1 }, -- Neck / Scarfs + { 8, 1, 3 }, -- Shirt / Accessory (This palette is commonly used for the text on the K9 vest) + { 9, 1, 1 }, -- Body Armor + { 10, 1, 1 }, -- Badges / Logos + { 11, 1, 1 }, -- Jackets + }, + }, + { + hash = `forddsumo7`, spawnOffset = vector3(0.0, -4.0, 0.5), + dogModelName = "a_c_shepherd", + props = { + -- Example: {prop type (Helmet), prop type index (Motorcycle helmet), prop colour index (Black colour)} + -- { drawable, texture, palette } + { 0, 1, 1 }, -- Hats / Helments + { 1, 1, 1 }, -- Glassess + { 2, 1, 1 }, -- Misc + { 3, 1, 1 }, + }, + components = { + -- Example: {component type (Mask), component type index (Clown Mask), component colour index (White colour)} + -- { drawable, texture, palette } + { 1, 1, 1 }, -- Mask + { 2, 1, 1 }, -- Hair + { 3, 1, 1 }, -- Upper body + { 4, 1, 1 }, -- Legs / Pants + { 5, 1, 1 }, -- Bags / Parachutes + { 6, 1, 1 }, -- Shoes + { 7, 1, 1 }, -- Neck / Scarfs + { 8, 1, 3 }, -- Shirt / Accessory (This palette is commonly used for the text on the K9 vest) + { 9, 1, 1 }, -- Body Armor + { 10, 1, 1 }, -- Badges / Logos + { 11, 1, 1 }, -- Jackets + }, + }, + + + + + + + + + + + + + + + + -- More examples + -- {hash = `police`, spawnOffset = vector3(0.0, -3.0, 0.5), dogModelName = "a_c_husky"}, {hash = `23gmcleo`, spawnOffset = vector3(0.0, -4.0, 0.5), dogModelName = "a_c_shepherd"}, {hash = `23gmcleoslick`, spawnOffset = vector3(0.0, -4.0, 0.5), dogModelName = "a_c_shepherd"}, {hash = `sahp18tahoe`, spawnOffset = vector3(0.0, -4.0, 0.5), dogModelName = "a_c_shepherd"}, @@ -134,10 +230,10 @@ Config = { {hash = `hp15fpiu2`, spawnOffset = vector3(0.0, -4.0, 0.5), dogModelName = "a_c_shepherd"}, {hash = `hp16fpiu1`, spawnOffset = vector3(0.0, -4.0, 0.5), dogModelName = "a_c_shepherd"}, {hash = `hp16fpiu2`, spawnOffset = vector3(0.0, -4.0, 0.5), dogModelName = "a_c_shepherd"}, - -- More examples - -- {hash = `police`, spawnOffset = vector3(0.0, -3.0, 0.5), dogModelName = "a_c_husky"}, - -- {hash = `police2`, spawnOffset = vector3(0.0, -3.0, 0.5), dogModelName = "a_c_husky"}, - -- {hash = `police3`, spawnOffset = vector3(0.0, -3.0, 0.5), dogModelName = "a_c_husky"}, + + + + }, --====================== CONTROLS, COMMANDS, KEYMAPPING ======================-- diff --git a/resources/[ERS]/night_ers_k9/fxmanifest.lua b/resources/[ERS]/night_ers_k9/fxmanifest.lua index 78e1d847f..f9a9c9f79 100644 --- a/resources/[ERS]/night_ers_k9/fxmanifest.lua +++ b/resources/[ERS]/night_ers_k9/fxmanifest.lua @@ -4,7 +4,7 @@ games { 'gta5' } author 'Night' description 'Nights Software - K9 Dog Handlers FiveM' -version '1.1.3' +version '1.1.4' lua54 'yes' shared_scripts { diff --git a/resources/[ERS]/night_ers_k9/server/server.lua b/resources/[ERS]/night_ers_k9/server/server.lua index c7aadbca8..07624a095 100644 Binary files a/resources/[ERS]/night_ers_k9/server/server.lua and b/resources/[ERS]/night_ers_k9/server/server.lua differ diff --git a/resources/[ERS]/night_prop_system/.fxap b/resources/[ERS]/night_prop_system/.fxap index 56d2dcd66..2994113cc 100644 Binary files a/resources/[ERS]/night_prop_system/.fxap and b/resources/[ERS]/night_prop_system/.fxap differ diff --git a/resources/[ERS]/night_prop_system/client/client.lua b/resources/[ERS]/night_prop_system/client/client.lua index ec4f4e2c2..ee0b089b1 100644 Binary files a/resources/[ERS]/night_prop_system/client/client.lua and b/resources/[ERS]/night_prop_system/client/client.lua differ diff --git a/resources/[ERS]/night_prop_system/server/server.lua b/resources/[ERS]/night_prop_system/server/server.lua index f6f7fb5df..36f929c8c 100644 Binary files a/resources/[ERS]/night_prop_system/server/server.lua and b/resources/[ERS]/night_prop_system/server/server.lua differ