Krakendomes-620d58eb804845c2 0 Posted April 30 Hello all! I am new to this coding/arma scripting thing and trying my best to wrap my head around all this. Its a lot to take in lol. But after days of scouring through the wiki, forums post, and watching endless YT videos I have decided to give it a shot. I want to recreate something like in mike force where players go out and package wrecks and haul them back. Instead of trying to replicate the whole feature I decided to break it down into smaller steps to help me learn. So my first goal, when chopper is destroyed create marker on map. In the editor I placed down 5 RHS_UH60M. Gave them each a variable name, blackHawk1 - 5. I tried writing this as a script first and was struggling. Then I stumbled upon event handlers and figured to try it that way. I was able to get what I wanted to work and more by using the see also: features on the wiki. Added sounds, text, and more. So I guess my questions are: 1. Should this have been a script or EH? 2. Since this will be expanded upon, should I keep it as EH or script it? 3. The code works, but maybe there is a better way to write it up? Any help or tips would be greatly appreciated!! Spoiler /* Umm something goes here, not sure what though!! Edit later */ blackHawk1 addEventHandler [ "killed", { _unit = (_this select 0); playSound "rhsusf_dws_warning_damagecritical"; _blackHawk1CrashMarker = createMarker ["Blackhawk 1 down", _unit]; _blackHawk1CrashMarker setMarkerType "mil_pickup"; _blackHawk1CrashMarker setMarkerText "Blackhawk 1 down"; _blackHawk1CrashMarker setMarkerColor "ColorRed"; blackHawk1 commandChat "We are going down!"; }]; blackHawk2 addEventHandler [ "killed", { _unit = (_this select 0); playSound "rhsusf_dws_warning_damagecritical"; _blackHawk2CrashMarker = createMarker ["Blackhawk 2 down", _unit]; _blackHawk2CrashMarker setMarkerType "mil_pickup"; _blackHawk2CrashMarker setMarkerText "Blackhawk 2 down"; _blackHawk2CrashMarker setMarkerColor "ColorRed"; blackHawk2 commandChat "We are going down!"; }]; blackHawk3 addEventHandler [ "killed", { _unit = (_this select 0); playSound "rhsusf_dws_warning_damagecritical"; _blackHawk3CrashMarker = createMarker ["Blackhawk 3 down", _unit]; _blackHawk3CrashMarker setMarkerType "mil_pickup"; _blackHawk3CrashMarker setMarkerText "Blackhawk 3 down"; _blackHawk3CrashMarker setMarkerColor "ColorRed"; blackHawk3 commandChat "We are going down!"; }]; blackHawk4 addEventHandler [ "killed", { _unit = (_this select 0); playSound "rhsusf_dws_warning_damagecritical"; _blackHawk4CrashMarker = createMarker ["Blackhawk 4 down", _unit]; _blackHawk4CrashMarker setMarkerType "mil_pickup"; _blackHawk4CrashMarker setMarkerText "Blackhawk 4 down"; _blackHawk4CrashMarker setMarkerColor "ColorRed"; blackHawk4 commandChat "We are going down!"; }]; blackHawk5 addEventHandler [ "killed", { _unit = (_this select 0); playSound "rhsusf_dws_warning_damagecritical"; _blackHawk5CrashMarker = createMarker ["Blackhawk 5 down", _unit]; _blackHawk5CrashMarker setMarkerType "mil_pickup"; _blackHawk5CrashMarker setMarkerText "Blackhawk 5 down"; _blackHawk5CrashMarker setMarkerColor "ColorRed"; blackHawk5 commandChat "We are going down!"; }]; The init.sqf: Spoiler []execVM "eventHandlers\bhWreckMarkers.sqf"; I also found this and will try this as well. Just want to make sure im on the right path with the stuff above first I guess? Share this post Link to post Share on other sites
Larrow 2822 Posted May 1 EventHandlers are always the way to go if available. Seeing as each blackhawk is handled the same, you could simplify your code to just... //bhWreckMarkers.sqf TAG_fnc_blackHawkDown = { params[ "_vehicle" ]; _vehicleName = toLower vehicleVarName _vehicle; // "blackhawk1" _vehicleNum = _vehicleName splitString "blackhawk" select 0; // "1" playSound "rhsusf_dws_warning_damagecritical"; _blackHawkCrashMarker = createMarker[ format[ "Blackhawk %1 down", _vehicleNum ], _vehicle ]; _blackHawkCrashMarker setMarkerType "mil_pickup"; _blackHawkCrashMarker setMarkerText format[ "Blackhawk %1 down", _vehicleNum ]; _blackHawkCrashMarker setMarkerColor "ColorRed"; driver _vehicle commandChat "We are going down!"; }; //Add event to each blackhawk { _x addEventHandler[ "Killed", { params[ "_killed" ]; //Call function to create marker and radio _killed call TAG_fnc_blackHawkDown; }]; }forEach [ blackHawk1, blackHawk2, blackHawk3, blackHawk4, blackHawk5 ]; 1 Share this post Link to post Share on other sites
Krakendomes-620d58eb804845c2 0 Posted May 1 Thanks @Larrow! Works great. Trying to make sure I understand the code before I use it. Apologies if I am referring to things wrong. So we are creating a function in bhWreckers.sqf? Can we name that function something else? Like ABC_fnc_blackHawkDown? Then we pass params. Still learning this but things like _vehicle / _unit / _killed are already predefined variables? we make a public variable called _vehicleName and its equal to vehicle variable name in all lower case for _vehicleNum I am a bit lost though. Is what's inside " " not being looked at? So we are grabbing string, not looking at blackhawk and selecting first element it sees after that with select 0? //Add event to each blackhawk is _x searching the forEach array you made? Or is _x checking everything that has been killed? I am struggling with magic variables. I have built upon what I wrote from the previous post. Adding a addAction. Which brings up new questions. Do the blackhawks need their own global variable? Or are we better off just using the class name? Should the addAction be where it is? When the vehicle is deleted, is the global variable assigned to it get deleted? Spoiler blackHawk1 addEventHandler [ "killed", { //CREATE MARKER _unit = (_this select 0); deleteVehicleCrew _unit; playSound "rhsusf_dws_warning_damagecritical"; _blackHawk1CrashMarker = createMarker ["Blackhawk 1 down", _unit]; _blackHawk1CrashMarker setMarkerType "mil_pickup"; _blackHawk1CrashMarker setMarkerText "Blackhawk 1 down"; _blackHawk1CrashMarker setMarkerColor "ColorRed"; _unit commandChat "We are going down!"; //End of CREATE MARKER //Creates an AddAction on Blackhawk called Package Wreck _unit addAction [ "Package Wreck", // title (what player sees) { //defining some things that bis wiki showed private _unit = blackHawk1; private _uTypeOf = typeOf _unit; private _uGetPos = getPos _unit; private _uGetDir = getDir _unit; //switches the player stance to start the animation but does not start playing the animation player switchMove "InBaseMoves_repairVehicleKnl"; //Starts playing the animation player playMoveNow "InBaseMoves_repairVehicleKnl"; //Removes the action from blackhawk so we dont duplicate the command and make a million CARGO CONTAINERS!!!!!!! removeAllActions _unit; //Send text in game to player that they are packaging wreck hint "Packaging Wreck"; //We wait 22 seconds while animation plays out before deleting wreck/creating cargo container sleep 22; //After the wait, we delete the BlackHawk if (typeOf _unit == "RHS_UH60M_d") then {deleteVehicle _unit}; //We also delete the marker created when chopper crashed deleteMarker "Blackhawk 1 down"; //we sleep for 2/10ths of a second to give crash time to delete. NOT having sleep causes cargo container to spawn away from its intended location!! sleep 0.02; //We create the cargo container that we want our aircraft to be transported in _blackHawk1 = "B_Slingload_01_Cargo_F" createVehicle _uGetPos; //Crate spawns with items, we dont want that so we remove all the items in cargo container clearWeaponCargo _blackHawk1; clearMagazineCargo _blackHawk1; clearBackpackCargo _blackHawk1; clearItemCargo _blackHawk1; }, //Remaing code for addAction// nil, // arguments 1.5, // priority true, // showWindow true, // hideOnUse "", // shortcut "true", // condition 5, // radius false, // unconscious "", // selection "" // memoryPoint ]; // End of AddACtion to package wreck }]; Share this post Link to post Share on other sites
Larrow 2822 Posted May 2 On 5/1/2024 at 10:35 PM, Krakendomes-620d58eb804845c2 said: Trying to make sure I understand the code before I use it. Apologies if I am referring to things wrong. Yes You can name it whatever you like, TAG is just a general wording to denote replacing it with your own so for instance you could name it KRAK_fnc_## as per your username or whatever you like. predifined! params is a command for defining variables passed in _this TAG_fnc_someFunctionParams = { params[ "_var1", "_var2" ]; } TAG_fnc_someFunctionThis = { private _var1 = _this select 0; private _var2 = _this select 1; } These two functions do exactly the same thing, define private local variables _var1 and _var2 from whatever was passed to the function in _this. [ "Hello", "World" ] call TAG_fnc_someFunction# _var1 would be "Hello", _var2 would be "World" We make a public local variable called _vehicleName and its equal to vehicle variable name in all lower case. When you name some object in the editor by filling out its variable name property two things happen when the mission loads... The vehicle is given a vehicleVarName of the STRING we gave in the property A global variable of the same name is made referencing said object SplitString returns an array of STRINGs of the original string broken up by the string passed to splitString, e.g _string = "1,2,3,4,5"; _split = _string splitString ","; // _split would be [ "1", "2", "3", "4", "5" ] _string = "Hello World"; _split = _string splitString "l"; // _split would be ["He","o Wor","d"] So by splitting "blackhawk1" by "backhawk" we end up with an array of just [ "1" ]. Select 0 just chooses the first thing in the array so "1". We end up with just the STRING number for that blackHawk based on its varName. On 5/1/2024 at 10:35 PM, Krakendomes-620d58eb804845c2 said: is _x searching the forEach array you made? Or is _x checking everything that has been killed? I am struggling with magic variables. _x is just the current thing being evaluated for that iteration of the forEach. So first time round its blackHawk1, second time its blackHawk2 etc etc. On 5/1/2024 at 10:35 PM, Krakendomes-620d58eb804845c2 said: I have built upon what I wrote from the previous post. Adding a addAction. Which brings up new questions. Well each blackHawk is already a global variable. As explained for varName above in 4. Quote A global variable of the same name is made referencing said object So in the script when we say blackHawk1 or similar this IS a global variable that references the object because we gave it a variable name in the editor. You can place the addAction in the new function as the same thing happens for every blackHawk. Spoiler TAG_fnc_blackHawkDown = { params[ "_vehicle" ]; _vehicleName = toLower vehicleVarName _vehicle; // "blackhawk1" _vehicleNum = _vehicleName splitString "blackhawk" select 0; // "1" playSound "rhsusf_dws_warning_damagecritical"; _blackHawkCrashMarker = createMarker[ format[ "Blackhawk %1 down", _vehicleNum ], _vehicle ]; _blackHawkCrashMarker setMarkerType "mil_pickup"; _blackHawkCrashMarker setMarkerText format[ "Blackhawk %1 down", _vehicleNum ]; _blackHawkCrashMarker setMarkerColor "ColorRed"; driver _vehicle commandChat "We are going down!"; //Add the action to the blackhawk ( _vehicle ) _vehicle addAction [ "Package Wreck", { //_target ( object to which action is attached to ) //_caller ( unit who used the action ) //_id ( unique ID number for THIS action on the _target ) //_args ( any parameters passed to the action using arguments in the addAction ) params [ "_target", "_caller", "_id", "_args" ]; // Get the passed in marker from _args _args params[ "_crashMarker" ]; _caller switchMove "InBaseMoves_repairVehicleKnl"; _caller playMoveNow "InBaseMoves_repairVehicleKnl"; //Removes THIS action from blackhawk _target removeAction _id; // We are deleting the _target later so action would be unavailable anyway hint "Packaging Wreck"; sleep 22; //Get blackhawks location before we delete it _blackHawkPos = getPosATL _target; //After the wait, we delete the BlackHawk deleteVehicle _target; //We also delete the marker created when chopper crashed deleteMarker _crashMarker; //we sleep for 2/10ths of a second to give crash time to delete. NOT having sleep causes cargo container to spawn away from its intended location!! sleep 0.02; // could likely just waitUntil _target is null //We create the cargo container that we want our aircraft to be transported in _blackHawkContainer = "B_Slingload_01_Cargo_F" createVehicle _blackHawkPos; //Crate spawns with items, we dont want that so we remove all the items in cargo container //Globally just incase this is MP clearWeaponCargoGlobal _blackHawkContainer; clearMagazineCargoGlobal _blackHawkContainer; clearBackpackCargoGlobal _blackHawkContainer; clearItemCargoGlobal _blackHawkContainer; }, //Remaing code for addAction// [ _blackHawkCrashMarker ], // Pass the marker created for this blackhawk into the actions code in _args 1.5, // priority true, // showWindow true, // hideOnUse "", // shortcut "true", // condition 5, // radius ]; }; No, when the blackHawk gets deleted the global variable will still exist but it will be Objnull as the OBJECT it references no longer exists, is null. If you wish to clear any variable you need to set it to nil. Is this for MP or SP? There maybe some other things you need to take into consideration if this is for MP, like... Should not be initiated through init.sqf as this happens everywhere. So for each machine client/server. So should be in initServer only If so action would need remoteExec'ing to all clients and JIP Share this post Link to post Share on other sites
Krakendomes-620d58eb804845c2 0 Posted May 3 @Larrow Sorry for the late reply. I figured since I am trying to learn the basics of it all I would go with SP. For #3 I guess my confusion comes from us never defining things like _killed or _vehicle. Its like the game already knows? I appreciate all the feedback and assistance. I havent had time to go any further but will update this when I do. Share this post Link to post Share on other sites
Larrow 2822 Posted May 4 15 hours ago, Krakendomes-620d58eb804845c2 said: For #3 I guess my confusion comes from us never defining things like _killed or _vehicle. Its like the game already knows? addEventHandler Quote Syntax: target addEventHandler [type, code] Parameters: target: Object or 2.10 Group type: String - see Event Handlers for the full list of available options code: Code or String - code that should be executed when the Event Handler fires. Several Magic Variables are available: Event Handler parameters are accessible via _this So we are saying to the engine, when this vehicle is killed can you please notify us when it happens. As per the addEventHandler page, we provide the engine with some code to call to notify us by. The engine passes us some information into this code via the _this variable when the event happens. Event Handlers Quote Killed LALocal Triggered when the unit is killed. this addEventHandler ["Killed", { params ["_unit", "_killer", "_instigator", "_useEffects"]; }]; unit: Object - object the event handler is assigned to killer: Object - object that killed the unit. Contains the unit itself in case of collisions 1.66 instigator: Object - person who pulled the trigger 1.68 useEffects: Boolean - same as useEffects in setDamage alt syntax As per the Event Handlers page for killed you can see what is contained in _this. So we use params to pull the information from _this into some local variables, named whatever we like( although this page does suggest some names based on the information _this is going to contain for that particular event ). All params does is pull information from an array. Unlike when using select where you need to specifically prefix the command with the array to pull the information from, so _this... private _someLocalVar = _this select 0; ... if the prefix array for params is missing it defaults to using _this. e.g _this params[ "_someLocalVar" ]; params[ "_someLocalVar" ]; ...these two lines are exactly the same. In the first we specifically tell it to use _this. In the second the prefix array is missing so it just defaults to using _this. Share this post Link to post Share on other sites
Krakendomes-620d58eb804845c2 0 Posted May 5 @Larrow I appreciate the detailed breakdown. Definitely cleared up some things. My next goal in the post I have been following is Store the type of the wreck in the container. Will work on that and report back. Share this post Link to post Share on other sites
Krakendomes-620d58eb804845c2 0 Posted May 9 Kinda hard stuck atm. The next steps are: Store the type of the wreck in the container, see setVariable At your recovery point add a trigger to continuously check for containers which contain a vehicle, trigger should detect Anything Present and it's condition need to filter for only wreck containers, see triggers and getVariable, thisList When the trigger activates get the type of the first container, see getVariable, thisList Delete the container and replace it with a new copy of the wreck, see deleteVehicle and createVehicle Reapply the event handler from step 1 of the packing process to the newly created vehicle For Step 1 added the setVar into addAction: (not sure if this where is goes or if does not matter) _cargo setVariable ["bh1Wreck", "blackHawk1"]; Spoiler //bhWreckMarkers.sqf blackHawk1 addEventHandler [ "killed", { //CREATE MARKER _unit = (_this select 0); deleteVehicleCrew _unit; playSound "rhsusf_dws_warning_damagecritical"; _blackHawk1CrashMarker = createMarker ["Blackhawk 1 down", _unit]; _blackHawk1CrashMarker setMarkerType "mil_pickup"; _blackHawk1CrashMarker setMarkerText "Blackhawk 1 down"; _blackHawk1CrashMarker setMarkerColor "ColorRed"; _unit commandChat "We are going down!"; //End of CREATE MARKER //Creates an AddAction on Blackhawk called Package Wreck _unit addAction [ "Package Wreck", // title (what player sees) { //defining some things that bis wiki showed private _unit = blackHawk1; private _uTypeOf = typeOf _unit; private _uGetPos = getPos _unit; private _uGetDir = getDir _unit; //switches the player stance to start the animation but does not start playing the animation //player switchMove "InBaseMoves_repairVehicleKnl"; //Starts playing the animation //player playMoveNow "InBaseMoves_repairVehicleKnl"; //Removes the action from blackhawk so we dont duplicate the command and make a million CARGO CONTAINERS!!!!!!! removeAllActions _unit; //We wait 22 seconds while animation plays out before deleting wreck/creating cargo container //sleep 22; //After the wait, we delete the BlackHawk deleteVehicle _unit; //We also delete the marker created when chopper crashed deleteMarker "Blackhawk 1 down"; //we sleep for 2/10ths of a second to give crash time to delete. NOT having sleep causes cargo container to spawn away from its intended location!! sleep 0.02; //We create the cargo container that we want our aircraft to be transported in _cargo = "B_Slingload_01_Cargo_F" createVehicle _uGetPos; //Crate spawns with items, we dont want that so we remove all the items in cargo container clearWeaponCargo _cargo; clearMagazineCargo _cargo; clearBackpackCargo _cargo; clearItemCargo _cargo; //Store wreck in container _cargo setVehicleVarName "bh1Wreck"; _cargo setVariable ["blackhawk1", "blackHawk1"]; }, //Remaing code for addAction// nil, // arguments 1.5, // priority true, // showWindow true, // hideOnUse "", // shortcut "true", // condition 5, // radius false, // unconscious "", // selection "" // memoryPoint ]; // End of AddACtion to package wreck }]; Step 2: is where I am struggling. I have it to check if x object is in trigger but not sure how to make it detect a container with a wreck in it. Spoiler //recZone.sqf _recZone = createTrigger ["EmptyDetector", getPos repPad]; _recZone setTriggerArea [5, 5, 0, true, 5]; _recZone setTriggerActivation ["ANY", "PRESENT", true]; _recZone setTriggerStatements [ "thisList findIf { typeof _x isEqualTo 'B_Slingload_01_Cargo_F' && _x inArea thisTrigger} >= 0", //condition "hint 'Trigger Activated'", //activation "hint 'Trigger Deactivated'" //deactivation ]; Step 3: Not sure what he means here? like its class type? Or info from setVariable? Step 5: Instead of reapplying the EH, can we just change its Variable with missionNamespace setVariable ["VarName", _var]; back to blackHawk1 and essentially do the same thing? Share this post Link to post Share on other sites
Krakendomes-620d58eb804845c2 0 Posted May 10 @Larrow After days of struggling I am reporting back. Some progress has been made. Progress was made using my existing code. Will mess around later and figure out how to make it work with what you have wrote up. Going off last post:1 & 2: After struggling how to understand incorporating set/get variable with this, I decided to take an alternative approach and use setVehicleVarName. Would still like to know how to make this work with set/get Variable if its a better way to do it. So for trigger condition we have this: Spoiler thisList findIf {vehicleVarName _x isEqualTo 'bh1Wreck' && _x inArea thisTrigger} >= 0 3/4/5: For the life of me I could not make this work in a script. Any tips or pointers would be greatly appreciated. I put it down as a trigger in the editor instead. Which still has issues but works. On activation I do not have it getting the type of container. Instead it just deletes the first thing in thisList lol. Which in rare circumstances causes the crate to not be deleted (animal, forgotten crate, etc..) but a blackhawk still spawns. Maybe like what I wrote in step 1 but as a if statement to prevent that? I googled how to reapply a EH, led me to https://community.bistudio.com/wiki/call. Followed example 5 minus the beginning parts. Which works. I can sit in a endless loop now killing, repairing, and spawning blackHawk1. Spoiler deleteVehicle (thisList select 0); hint "Repairs Complete"; _test = createVehicle ["RHS_UH60M", bh1Pad, [], 0]; blackHawk1 = _test; _test setVehicleVarName "blackHawk1"; call compile preprocessFileLineNumbers "zOld\wreckRecovery.sqf"; recZone.sqf (script for trigger) - if you want to see what I have so far. I guess my biggest issues is making the code work using quotations. Spoiler _bh1Pad = getPos bh1Pad; _recZone = createTrigger ["EmptyDetector", getPos repPad]; _recZone setTriggerArea [5, 5, 0, true, 5]; _recZone setTriggerActivation ["ANY", "PRESENT", true]; _recZone setTriggerStatements [ "thisList findIf {vehicleVarName _x isEqualTo 'bh1Wreck' && _x inArea thisTrigger} >= 0", //condition "deleteVehicle (thisList select 0)", //activation "hint 'Repairs Complete'" //deactivation ]; Share this post Link to post Share on other sites
Krakendomes-620d58eb804845c2 0 Posted May 14 Made quite a bit of progress over the last few days. Can kill, package, repair, and respawn all 5 blackhawks over and over now. I have two things though that I could still use help with. 1. When blackhawk x is respawned, the EH is applied to all the BHs again. So x blackhawk will have 1 option to package when it is killed, but y blackhawk could have 2, 3, 4 or 5 depending on how many bhs where killed and repaired before y went down. If that makes sense? (EDITED: Fixed this but not sure if its best way, code updated) bhTest.sqf Spoiler TAG_fnc_blackHawkDown = { params[ "_vehicle"]; _vehicleName = toLower vehicleVarName _vehicle; // "blackhawk1" _vehicleNum = _vehicleName splitString "blackhawk" select 0; // "1" playSound "rhsusf_dws_warning_damagecritical"; _blackHawkCrashMarker = createMarker[ format[ "Blackhawk %1 down", _vehicleNum ], _vehicle ]; _blackHawkCrashMarker setMarkerType "mil_pickup"; _blackHawkCrashMarker setMarkerText format[ "Blackhawk %1 down", _vehicleNum ]; _blackHawkCrashMarker setMarkerColor "ColorRed"; driver _vehicle commandChat "We are going down!"; //Add the action to the blackhawk ( _vehicle ) _vehicle addAction [ "Package Wreck", { //_target ( object to which action is attached to ) //_caller ( unit who used the action ) //_id ( unique ID number for THIS action on the _target ) //_args ( any parameters passed to the action using arguments in the addAction ) params [ "_target", "_caller", "_id", "_args" ]; // Get the passed in marker from _args _args params[ "_crashMarker", "_vehNum"]; // Starts the repair animation (Need both for animation to work) //_caller switchMove "InBaseMoves_repairVehicleKnl"; //_caller playMoveNow "InBaseMoves_repairVehicleKnl"; //Removes THIS action from blackhawk _target removeAction _id; // We are deleting the _target later so action would be unavailable anyway //hint "Packaging Wreck"; //sleep 22; //Get blackhawks location before we delete it _blackHawkPos = getPosATL _target; //After the wait, we delete the BlackHawk deleteVehicle _target; //We also delete the marker created when chopper crashed deleteMarker _crashMarker; //we sleep for 2/10ths of a second to give crash time to delete. NOT having sleep causes cargo container to spawn away from its intended location!! sleep 0.02; // could likely just waitUntil _target is null //We create the cargo container that we want our aircraft to be transported in _blackHawkContainer = "B_Slingload_01_Cargo_F" createVehicle _blackHawkPos; _blackHawkContainer setVehicleVarName format ["blackHawk%1", _vehNum]; //Crate spawns with items, we dont want that so we remove all the items in cargo container //Globally just incase this is MP clearWeaponCargoGlobal _blackHawkContainer; clearMagazineCargoGlobal _blackHawkContainer; clearBackpackCargoGlobal _blackHawkContainer; clearItemCargoGlobal _blackHawkContainer; }, //Remaing code for addAction// [ _blackHawkCrashMarker, _vehicleNum], // Pass the marker created for this blackhawk into the actions code in _args 1.5, // priority true, // showWindow true, // hideOnUse "", // shortcut "true", // condition 5, // radius false, "", "" ]; }; //Removes event to blackhawks first to ensure we dont duplicate when repairing/respawning { _X removeEventHandler ["killed", 0]; }forEach [ blackHawk1, blackHawk2, blackHawk3, blackHawk4, blackHawk5 ]; //Add event to each blackhawk { _x addEventHandler[ "Killed", { params[ "_killed" ]; //Call function to create marker and radio _killed call TAG_fnc_blackHawkDown; }]; }forEach [ blackHawk1, blackHawk2, blackHawk3, blackHawk4, blackHawk5 ]; Trigger Condition: _bhVarArray = ["blackHawk1", "blackHawk2", "blackHawk3", "blackHawk4", "blackHawk5"]; thisList findIf {vehicleVarName _x in _bhVarArray && _x inArea thisTrigger} >= 0; onActivation: _container = (thisList select 0); _vehWreckName = vehicleVarName _container; _vehNum = _vehWreckName splitString "blackHawk" select 0; deleteVehicle (thisList select 0); switch (_vehNum) do { case "1": { _newbh = createVehicle ["RHS_UH60M", bh1Pad, [], 0]; _newbh setVehicleVarName format ["%1", _vehWreckName]; missionNamespace setVariable [format["%1", _vehWreckName], _newbh, true]; }; case "2": { _newbh = createVehicle ["RHS_UH60M", bh2Pad, [], 0]; _newbh setVehicleVarName format ["%1", _vehWreckName]; missionNamespace setVariable [format["%1", _vehWreckName], _newbh, true]; }; case "3": { _newbh = createVehicle ["RHS_UH60M", bh3Pad, [], 0]; _newbh setVehicleVarName format ["%1", _vehWreckName]; missionNamespace setVariable [format["%1", _vehWreckName], _newbh, true]; }; case "4": { _newbh = createVehicle ["RHS_UH60M", bh4Pad, [], 0]; _newbh setVehicleVarName format ["%1", _vehWreckName]; missionNamespace setVariable [format["%1", _vehWreckName], _newbh, true]; }; case "5": { _newbh = createVehicle ["RHS_UH60M", bh5Pad, [], 0]; _newbh setVehicleVarName format ["%1", _vehWreckName]; missionNamespace setVariable [format["%1", _vehWreckName], _newbh, true]; }; }; call compile preprocessFileLineNumbers "eventHandlers\bhTest.sqf"; Share this post Link to post Share on other sites
Larrow 2822 Posted May 17 On 5/9/2024 at 4:37 AM, Krakendomes-620d58eb804845c2 said: Store the type of the wreck in the container, see setVariable At your recovery point add a trigger to continuously check for containers which contain a vehicle, trigger should detect Anything Present and it's condition need to filter for only wreck containers, see triggers and getVariable, thisList On 5/10/2024 at 8:44 AM, Krakendomes-620d58eb804845c2 said: 1 & 2: After struggling how to understand incorporating set/get variable with this, I decided to take an alternative approach and use setVehicleVarName. Would still like to know how to make this work with set/get Variable if its a better way to do it. So for trigger condition we have this: Hide contents thisList findIf {vehicleVarName _x isEqualTo 'bh1Wreck' && _x inArea thisTrigger} >= 0 So it would be something like... Before we delete the vehicle in the action take a note of its type, I know not particularly needed for your script as they are all of the same type, but if you wanted to expand this later its easier to incorporate it now. //We create the cargo container that we want our aircraft to be transported in _blackHawkContainer = "B_Slingload_01_Cargo_F" createVehicle _blackHawkPos; //Make note of vehicle number and vehicle type on the wreck container _blackHawkContainer setVariable[ "wreckInfo", [ _vehNum, typeOf _target ] ]; Then for the trigger we do not need the inArea check, if the container is in thisList ( it must be satisfying the triggers activation settings) then it must already be in the trigger area. //Does something in the triggers thisList have a variable on it called wreckInfo thisList findIf{ !isNil ( _x getVariable "wreckInfo" ) } >= 0 On 5/9/2024 at 4:37 AM, Krakendomes-620d58eb804845c2 said: When the trigger activates get the type of the first container, see getVariable, thisList Delete the container and replace it with a new copy of the wreck, see deleteVehicle and createVehicle On 5/10/2024 at 8:44 AM, Krakendomes-620d58eb804845c2 said: 3/4: For the life of me I could not make this work in a script. Any tips or pointers would be greatly appreciated. I put it down as a trigger in the editor instead. Which still has issues but works. On activation I do not have it getting the type of container. Instead it just deletes the first thing in thisList lol. Which in rare circumstances causes the crate to not be deleted (animal, forgotten crate, etc..) but a blackhawk still spawns. Maybe like what I wrote in step 1 but as a if statement to prevent that? TBH for this I would spawn a trigger from script for each wreck container( it means they maybe a few triggers active at a time depending on how many vehicles are currently dead but should not be a problem, you can even change their polling rate to make things less resource intensive ). Each trigger can then be set to [ "VEHICLE", "PRESENT", true ] then the trigger is only looking for this particular wreck crate "VEHICLE", eliminates all the confusion about getting the right object from the trigger. Spoiler //We create the cargo container that we want our aircraft to be transported in _wreckContainer = "B_Slingload_01_Cargo_F" createVehicle _blackHawkPos; //Make note of vehicle number and vehicle type on the wreck container _wreckContainer setVariable[ "wreckInfo", [ _vehNum, typeOf _target ] ]; //Crate spawns with items, we dont want that so we remove all the items in cargo container //Globally just incase this is MP clearWeaponCargoGlobal _wreckContainer; clearMagazineCargoGlobal _wreckContainer; clearBackpackCargoGlobal _wreckContainer; clearItemCargoGlobal _wreckContainer; _repairZone = createTrigger[ "EmptyDetector", getPos repPad ]; _repairZone setTriggerArea[ 5, 5, 0, true, 5 ]; //Tell the trigger to only look for the specific attached vehicle _repairZone setTriggerActivation ["VEHICLE", "PRESENT", true]; //Attach the wreck container to the trigger _repairZone triggerAttachVehicle[ _wreckContainer ]; //Set the trigger to only check every 10 seconds rather than the default 0.5s _repairZone setTriggerInterval 10; _repairZone setTriggerStatements[ //condition - activates when the attach vehicle is in the trigger as per activation settings( this ) "this", //activation - delete the attached vehicle " deleteVehicle triggerAttachedVehicle thisTrigger; hint 'Repairs Complete' ", "" ]; On 5/9/2024 at 4:37 AM, Krakendomes-620d58eb804845c2 said: Reapply the event handler from step 1 of the packing process to the newly created vehicle On 5/10/2024 at 8:44 AM, Krakendomes-620d58eb804845c2 said: 5: I googled how to reapply a EH, led me to https://community.bistudio.com/wiki/call. Followed example 5 minus the beginning parts. Which works. I can sit in a endless loop now killing, repairing, and spawning blackHawk1. On 5/14/2024 at 1:19 AM, Krakendomes-620d58eb804845c2 said: When blackhawk x is respawned, the EH is applied to all the BHs again. So x blackhawk will have 1 option to package when it is killed, but y blackhawk could have 2, 3, 4 or 5 depending on how many bhs where killed and repaired before y went down. If that makes sense? (EDITED: Fixed this but not sure if its best way, code updated) Ok this system is getting quite large now and has many parts that are all crammed into one script. It is at this point in a project where I would start thinking about what I have and separate it out into its parts. So lets think this through, we have... Initialisation of vehicles applying eventHandler adding wreck ( marker, action ) packaging wreck ( container, trigger ) repairing vehicle ( spawning new vehicle ) ...so lets make a script for each of these independently. Run out of time for today, going to continue when a get back later this evening/tomorrow. Share this post Link to post Share on other sites
Krakendomes-620d58eb804845c2 0 Posted May 17 @Larrow Once again thank you for the detailed breakdown. It truly does help ^.^ Since my last post the code has changed a bit. Reason for change was expansion like you said lol. I have added more vehicles for the player to have access to. Total vehicle count is now around 30. vehicle init field: (info altered for each vehicle) Spoiler this addEventHandler ["Killed", { params ["_unit", "_killer"]; _spawnpad = bh1Pad; _wreckMarker = "blackHawk 1 down"; _spawnModel = "RHS_UH60M"; _name = "blackHawk1"; [_unit, _spawnPad, _wreckMarker, _spawnModel, _name] call KRA_fnc_vehRecSystem; }]; Trigger condition/Activation: Condition: (will implement your cond statement) Spoiler thisList findIf {(_x getVariable "packaged") && _x inArea thisTrigger } >= 0 Activation: Spoiler _container = (thisList select 0); _spawnPad = _container getVariable "_spawnPad"; _wreckMarker = _container getVariable "_wreckMarker"; _spawnModel = _container getVariable "_spawnModel"; _name = _container getVariable "_name"; deleteVehicle (thisList select 0); _newVeh = createVehicle [_spawnModel, _spawnPad, [], 0]; _newVeh setVariable ["_spawnPad", _spawnPad]; _newVeh setVariable ["_wreckMarker", _wreckMarker]; _newVeh setVariable ["_spawnModel", _spawnModel]; _newVeh setVariable ["_name", _name]; _newVeh addEventHandler ["Killed", { params ["_unit", "_killer"]; _spawnpad = _unit getVariable "_spawnPad"; _wreckMarker = _unit getVariable "_wreckMarker"; _spawnModel = _unit getVariable "_spawnModel"; _name = _unit getVariable "_name"; [_unit, _spawnPad, _wreckMarker, _spawnModel, _name] call KRA_fnc_vehRecSystem; }]; And our vehRecSys.sqf Spoiler /** function called when the killed event handler has been triggered when a veh is distroyed we will be adding marker to the crash sight and allow for packaging @param {Object} _object the object that has been killed (blackhawk1) @param {Object} _spawnPad the spawn pad that the object was spawned on and needs to be respawned at (bh1Pad) @param {String} _wreckMarker the name of the marker of the wreck (Blackhawk 1 down) @param {String} _spawnModel the model of the object that needs to be spawned (RHS_UGH60M) @param {String} _name the name of the object that needs to be spawned (blackhawk1) @return null */ KRA_fnc_vehRecSystem = { params ["_object" , "_spawnPad" , "_wreckMarker" , "_spawnModel" , "_name", ["_repair",false]]; _vehCrashMarker = createMarker[_wreckMarker , _object ]; _vehCrashMarker setMarkerType "mil_pickup"; _vehCrashMarker setMarkerText _wreckMarker; _vehCrashMarker setMarkerColor "ColorRed"; /** @param {Object} _target the object that the action is being added to (blackhawk1) @param {Object} _caller the object that is calling the action (player) @param {String} _id the id of the action @param {Array} _args the arguments that are being passed to the action */ _object addAction [ "Package Wreck", { params [ "_target", "_caller", "_id", "_args" ]; /** * @param {String} _crashMarker the marker that was created for the crash sight * @param {Object} _spawnPad the spawn pad that the object was spawned on and needs to be respawned at * @param {String} _spawnModel the model of the object that needs to be spawned * @param {String} _name the name of the object that needs to be spawned */ _args params[ "_crashMarker", "_spawnPad" , "_spawnModel", "_name", "_repair"]; // Starts the repair animation (Need both for animation to work) //_caller switchMove "InBaseMoves_repairVehicleKnl"; //_caller playMoveNow "InBaseMoves_repairVehicleKnl"; //sleep 22; //Get blackhawks location before we delete it _vehPos = getPosATL _target; //We also delete the marker created when chopper crashed deleteMarker _crashMarker; //thisList findIf {((vehicleVarName _x find "blackHawk") != -1 ) && _x inArea thisTrigger } >= 0 //After the wait, we delete the BlackHawk _target removeAction _id; // We are deleting the _target later so action would be unavailable anyway deleteVehicle _target; //we sleep for 2/10ths of a second to give crash time to delete. NOT having sleep causes cargo container to spawn away from its intended location!! sleep 0.02; // could likely just waitUntil _target is null //We create the cargo container that we want our aircraft to be transported in _crashContainer = "B_Slingload_01_Cargo_F" createVehicle _vehPos; _crashContainer setVariable ["_spawnPad", _spawnPad]; _crashContainer setVariable ["_wreckMarker", _crashMarker]; _crashContainer setVariable ["_spawnModel", _spawnModel]; _crashContainer setVariable ["_name", _name]; _crashContainer setVariable ["packaged", true]; //Crate spawns with items, we dont want that so we remove all the items in cargo container //Globally just incase this is MP clearWeaponCargoGlobal _crashContainer; clearMagazineCargoGlobal _crashContainer; clearBackpackCargoGlobal _crashContainer; clearItemCargoGlobal _crashContainer; }, //Remaing code for addAction// [ _vehCrashMarker, _spawnPad , _spawnModel, _name, _repair], // Pass the marker created for this blackhawk into the actions code in _args 1.5, // priority true, // showWindow true, // hideOnUse "", // shortcut "true", // condition 5, // radius false, "", "" ]; }; With these recent changes would you still split this up into separate parts? I tried practicing adding another function the way you had it setup and had no luck. So I tried this way https://community.bistudio.com/wiki/Arma_3:_Functions_Library . Took a while but managed to get a function working that hinted "this is working". I edited the code in VSC, saved, and restarted mission. ALL HELL BROKE LOSE. No errors where thrown in game, but the function was not working and crashing my game. Checked the rpt and this was everywhere :S 2:49:33 Attempt to override final function - kra_fnc_vehmaint And ofc this happens right when its me bedtime. So here we are almost 12 hours later, no sleep, but a working function again now hinting "get rekt nerd" Share this post Link to post Share on other sites