terox 316 Posted April 12, 2014 (edited) It was suggested by Tankbuster that the following may be of use to you.Zeu Debugging Tutorial & Foundation TemplateLast updated 17th September 2014IntroductionEveryone that writes code suffers from bugs and we all get frustrated trying to trace the cause.This tutorial is an attempt to walk you through some methods to achieve that.I have also attached a Foundation template that has a debugging system implemented. More on that later.You may find the following tools and bookmarks useful, these are all essential to developing missions and am sure most of you have these or similar alternativesPreparationHow do I know I have an error in the first place?There are 3 areas where you can capture errors Ingame, where you dont see the effect you are expecting A black dialog pop up box Rpt file -ShowScriptErrorsYou need to add -ShowScriptErrors to your command line startup params. This will enable the popup black dialog box if a scripting error occurs.RPT FileThis is the basic logging file that arma3 dumps too.It is full of spam from B.I, however the more you read it the more familiar you get with their spam, which makes it easier to filter out the rubbish.Any popup messages that -showscripterrors displays are always dumped to the rpt fileBy default, your RPT file can be found in Windows 7 & 8 Users: c:\Users\Your Username\AppData\Local\Arma 3\You may need to enable hiddenfiles to see this folderIf a -profile is set, then the RPT will be created there insteadTools & Reference materialScript editors Poseidon Script editorPBO Tools Mikero's Eliteness3.17.0.11.Installer.exe or any later released versionBookmarksAdd these links to your Bookmarks, you will constantly need to refer to them while coding your ArmA 3 Projects Arma 3: Scripting CommandsA3 Scripting Commands by Functionality Arma 3: Event Handlers Arma 3: Event Scripts Arma 3: User Interface event handlers Arma 3: Code Optimisation BIS Official List of Arma 3 Classnames Zeu A3 classnames List BIS Functions Library (Arma_3) Killzone Kids scripting tutorial blog (Arma_3) Zeu Foundation Template ZEU Foundation TemplateTutorialThe art of debugging is being able to track down the reason why a piece of code isn't working as intended.Why do they happen in the first place?Types Of Error Syntax error: you made a spelling, grammar or typing mistake Logic error: You made an assumption that wasnt correct Locality error: You ran code on the wrong node (Server, client etc) Timing error: You expected something to have hapened that hasnt occurred yet LOGICAL ERRORYou assumed something was in a particular state when in fact it wasn'tDont assume anything is in a certain state, check it first before using itReal World Silly example.Don't assume a door is open, It can have other states, e.g: It could be closed It could be closed & Locked It could be in an interim state between open and closed It could not exist In the real world, your brain would have processed all of this, even to the point where you would have tried the door handle if it were closed to see if it was locked(Common sense (assumptions) cannot exist in the realms of programming, only definite states can exist. (On. Off or Doesnt exist)Coding example if (Isnil "MyVariable")then{MyVariable = 0}else{MyVariable = MyVariable + 1};if Myvariable does not exist, then define it as having a value of 0. if it does exist, add 1 to itLOCALITY ERRORThis is where you need knowledge on the engine's idiosyncrasies. Only experience will get you thereSome code has to be run local (on the same machine) where the object is local tooSome code can be run remotely, eg from a different machine the object is local tooIf it can be run remotely and you need to just run it on 1 machine, ideally the serverOtherwise for 10 players + 1 server you would be sending 11*10 sets of instructions over the network instead of just 10In a lot of cases, the BIS Wiki has small icons at the top of each page for the comref entriesThese will give you information on where code should be run for that command AL: Arguments of this scripting command have to be local to the client the command is executed on AG: Arguments of this scripting command don't have to be local to the client the command is executed on EL: Effects of this scripting command are NOT broadcast over the network and happen only on trhe computer where executed EG: Effects of this scripting command are broadcast over the network and happen on every computer in the network Lets take a look at this exampleaddWeaponAL: Arguments of this scripting command have to be local to the client the command is executed onEG: Effects of this scripting command are broadcast over the network and happen on every computer in the networkThe arguments for this command are1) The unit or vehicle (Object) that we are going to add a weapon to2) The classname of the weapon (A "string") that we are going to addWe need to run the code on the machine where the unit is local to. When we do run the code correctly, every machine will see that unit with that weaponTIMING ERRORIf some code requires other code to have defined something and that code hasnt run, an error will occur.Example, the paramsarray is defined on the server before preinitwhereas the paramsarray is defined on the client a few milliseconds after preinit has terminatedTherefore you cannot run any code requiring paramsarray on the client until post-init(I'll explain the timings more clearly later)SYNTAX ERRORThis can be the most frustrating of issues, searching for a missing semi colon or terminating bracket etcThis can be reduced by good formatting of your code or using a good text editor that highlights paired brackets etcI personally use Poseidon, there are plenty of alternativesAll these errors can be debugged using very simple lines of code which rely on just TWO commands diag_log systemChat There are others, but they all have some form of issue which reduces their effectiveness, so for simplicity, lets stick with these twoHow To DebugLets use the following code example throughout the rest of this tutorialThe issue is we don't know if the player is being setcaptive False. Sometimes we think he is but sometimes he never is?.And i'm new to scripting so i don't really understand this command.// INIT.SQF Player setcaptive TRUE; [20] execVM "Myscript.sqf"; // MYSCRIPT.SQF _myvariable = _this select 0; //(this should be the number 20) _myNewvariable= _myvariable + 5; //(this should be the number 25) _object = Leader (group Player); waituntil {alive player && Player distance _object < _myNewvariable}; Player setCaptive FALSE; In all the following walk through's I will give examples for both systemchat and diag_logNo.1 Prove the script is runningWe do this by adding code that will give us a visual indication that the script is running// MYSCRIPT systemchat "DEBUG: AT START OF SCRIPT"; // This will dump text to the screen diag_log text "DEBUG: AT START OF SCRIPT"; // This will dump text to the rpt file _myvariable = _this select 0; //(this should be the number 20) _myNewvariable= _myvariable + 5; //(this should be the number 25) _object = Leader (group Player); waituntil {alive player && Player distance _Object < _myNewvariable}; Player setCaptive FALSE; systemchat "DEBUG: AT END OF SCRIPT"; // This will dump text to the screen diag_log text "DEBUG: AT END OF SCRIPT"; // This will dump text to the rpt file If you see "DEBUG: AT START OF SCRIPT" on screen, or in the .rpt file, you know the script startsIf you see "DEBUG: AT END OF SCRIPT" on screen, or in the .rpt file, you know the code has been run and has got to the end of the scriptThere is an issue when using systemchat, or any other chat, side, global etc. This being that any code that is run at pre-Init or before Time == 0 (A little on this later) will not dump any chat messages to the screen.To work around this problem, we need to "spawn" this code as in the example below[] spawn {sleep 3; systemchat "DEBUG: AT THIS POINT";};You should then see this 3 seconds after you launch the mission from briefingNo.2 Return some variable valuesWe now know the script is running, but something is amiss. Sometimes we see the "DEBUG: AT END OF SCRIPT POINT" immediately, sometimes we dont see it at all.Perhaps the group leader is too close, maybe the distance measurement is wrong ?Okay, so lets see what values we actually haveSo we would now use a format command, as in the example below// MYSCRIPT _myvariable = _this select 0; //(this should be the number 20) _myNewvariable= _myvariable + 5; //(this should be the number 25) _object = Leader (group Player); waituntil {alive player && Player distance _Object < _myNewvariable}; Player setCaptive FALSE; systemchat format ["myvariable has a value of %1 ----- MyNewvariable has a value of %2",_myvariable,_myNewvariable]; diag_log text format ["myvariable has a value of %1 ----- MyNewvariable has a value of %2",_myvariable,_myNewvariable]; We could have used seperate lines to return each variable value, in this example we just combined them into 1 systemchat or diag_logFirst time we run it, we got the text on screen , it stated myvariable has a value of 20 ----- MyNewvariable has a value of 25That seems correct, however the second time we run the mission, we didn't see any text on screen or in the .rpt fileSo whats going on ?No.3 Testing a conditionCould it be the condition, waituntil {alive player && Player distance _Object < _myNewvariable}; how do we test itWhen you evaluate a condition that is correctly written it will return TRUE or FALSE. Anything else is wrongWe can see this value the same way we return any other value using a format command// MYSCRIPT _myvariable = _this select 0; //(this should be the number 20) _myNewvariable= _myvariable + 5; //(this should be the number 25) _object = Leader (group Player); systemchat format ["The condition returns: %1",(alive player && Player distance _Object < _myNewvariable)]; diag_log text format ["The condition returns: %1",(alive player && Player distance _Object < _myNewvariable)]; waituntil {alive player && Player distance _Object < _myNewvariable}; Player setCaptive FALSE;Good, at least we get a "The condition returns: FALSE" in the .rpt and on screen when we testOh, next time we run it, it returns TRUE, why are we getting these inconsistenciesWell, we have proved.1) The script runs every time2) The distance values are correct3) The condition seems to be working, but not as expectedThe only value we havent checked is the _object, so lets check thatNo.4 Checking for the type of variableWe can check what value a variable has, we can also check what type of variable it is using the typeName commandMaybe the object isn't an object, maybe its something else, array, side string and therefore we cant get a distance measurementI am also getting desperate now, so i'll return all the values just to make sure and heavily debug this script. No matter what, now i should see where the error is(Diag_log code omitted for clarity)// MYSCRIPT systemchat "DEBUG: AT START OF SCRIPT"; _myvariable = _this select 0; //(this should be the number 20) _myNewvariable= _myvariable + 5; //(this should be the number 25) _object = Leader (group Player); systemchat format ["myvariable is Type %1, Value %2", typename _myvariable, _myvariable]; systemchat format ["myNewvariable is Type %1, Value %2", typename _myNewvariable, _myNewvariable]; systemchat format ["Object is Type %1, Name %2", typename _object, name _object]; systemchat format ["The condition returns: %1",(alive player && Player distance _Object < _myNewvariable)]; diag_log text format ["The condition BEFORE returns: %1",(alive player && Player distance _Object < _myNewvariable)]; waituntil {alive player && Player distance _Object < _myNewvariable}; diag_log text format ["The condition AFTER returns: %1",(alive player && Player distance _Object < _myNewvariable)]; Player setCaptive FALSE; systemchat format ["Am I captive %1", captive player]; systemchat "DEBUG: AT END OF SCRIPT"; I run the mission, first time goes okay, I wait for the group leader to arrive and all works as expectedI run it again and i get the following debug information immediately"DEBUG: AT START OF SCRIPT";"myvariable is Type SCALAR, Value 20""myNewvariable is Type SCALAR, Value 25""Object is Type OBJECT, Name Terox""The condition returns: TRUE""Am I captive FALSE""DEBUG: AT END OF SCRIPT" Ah now i see the problem. , I am the leader of myself and therefore all the conditions are being met immediately. I Need to stop disabling AI when i testFlow of code (Timing)In order to understand any timing errors you need to understand the order in which code is run. Here it is, hopefully simply explained.When a mission is selected and started by the admin, the following events occur in the numbered orderA lot of A3 mission devs refer to Time 0 as a key point when discussing at what point code is being runSo I shall comment using Time<0, Time==0 or Time>0 to clarify what they mean by this1) Config stageAddon configs, Description.ext and any #includes will be run at this point2) Pre init stage (Time < 0) This is run after the description.ext has loaded, players have slotted up and the admin has hit continue(This is initiated from the cfgFunctions class as defined in the description.ext. It automatically runs any function that has a preinit=1 tagTypically only 1 function should have this. This should be the keystone that pre initialises all required Global variables and functions for all later run codeAny functions that are called from Unit, vehicle and object init fields in the mission editor (Mission.sqm)should be declared at this point so that they are defined ready for use.3) Mission.sqm (Time < 0)Any code in the init field of units, objects vehicles is now being processed, starting with the first East unit you placed in the editor4) Post Mission.sqm (Time == 0)Any code spawned, execvm from Preinit is now being processed and will run its entirety or will halt when it comes across anySleep Waintuntil{} command (Where the condition is not TRUE) B.I's Init.sqf will also run at this point and halt at any code with sleep or waituntil (if the waituntil condition is not true).5) Briefing is loaded (Time == 0)6) Admin starts the mission (Time > 0)7) Post INIT (Time > 0)Any code that has halted waiting for a condition to become true or a sleep will now continue to run.From now until the end of the mission, any code you have will run under the following condition For every frame every script that is running will run for a maximum of 3 millisecondsIf it hasn't completed by that time, it will halt until the next frame and then continue to run for a further 3 millisecondsIt will continue to do this until it terminates A Little about code optimisationSome general rules:1) If a script is being called more than once a) compile preprocessfilelineumbers the function at pre init stage B) Then either 1) call it every time you want it to run (If it doesn't contain any sleep or waituntil commands)2) Spawn it every time you want it to run (If it DOES contain any sleep or waituntil commands)if you use Execvm for this code, every time it is run, it compiles first then processes the codeIf you call precompiled code, it simply just processes from code stored in ram which is much faster 2) If a script is only being called once, then you could execVM, spawn or call it (There probably isn't much difference) if you precompiled then called code that is only being run once, then you can redefine the function as =nil; to remove it from memoryWe can only assume that execvm code is removed from memory by the RV engine after it has run 3) try to avoid loops, especially long ones (3 milisecond rule)4) Use eventhandlers to reduce the requirement for loops5) Try wherever possible to call or spawn a function instead of execVM or spawn a script6) Keep the total run time of a function below 3 milliseconds wherever possible Dont be too concerned if the code runs longer than 3ms, its just a best practice to try and avoid, which is not always possible 7) Dont be concerned about the length of time preinit takes, it is after all preinit and not mission real time and anything you can prepare here is good for laterIf you haven't fallen asleep reading this yet, there's something a little extra to help youZeus Foundation templateWhat is it ?Its a foundation template that would be a good starting point for anyone designing their own template for whatever mission you may want to developIts basically a structured system for running codeIt has the following functionality Structure to thread (route-filter) code to the appropriate node, eg server, headless client, player, jip etc Ability to mass Debug user defined "systems" or "modules" Defines some basic switching variables for usage in your code So if you want to have only a JIP player run specific code, there is a structure within this template to place that code.Every script is heavily commented, so it shouldn't take long to figure out what does whatDebug SystemThe debug variables are defined in the Description.ext in the Txu_Debug classThis can easily be switched to a .sqf file, such as the pre init.I just defined it here because this is part of a template I am developing where all configuration is done on #include.hpp files(Use a copy of the "script_template.sqf" for any new scripts you create, editing any necessary content).At the start of each script two variables need to be defined, _sy and _sc_sy defines the "System/module" that the script is part of. It is used as an identifier and as a filter for the debugging output_sc is a name for the script, typically this would be the actual file name less the ".sqf" and is used as an identifier in the debug logIf debugging is enabled and the "System/module" is being monitored, the following will be logged Script start any variables passed to the script any user defined variables you wish to monitor the end of the script diag tick time, recorded This is the value that comes after the "@" symbol in the debug logs Where the log is sent is user defined and can be either RPT file via diag_log Systemchat both What system are being logged/debugged is defined by the strings listed in the Txu_DebugSys arrayFor example, in this template you have Txu_DebugSys[]={"PARAMS","RESPAWN","EXAMPLE","CORE"}; What this means is that any script with an _sy variable equal to anything in the Txu_DebugSys will log data to the Txu_DebugLog outputAs it is set now,This will output data from every system that this foundation template has.Rather than delete a system from this array, simply comment it out.The rpt file is by far the best logging system, allowing you to also browse the server log if you have access to it.It also provides a permanent record of data flow and returned values etcThe systemchat is good for live monitoring (Open up the in-game chat by typing "/" and key "PAGEUP" to scroll through previous messages)Mission Code flow for this templateThis is an example of the mission code flow for the Foundation template I linked too in this threadIt is a cleaned up version of the debug log dumps to the rpt file, showing the start and end of each script in the order in which they are runThe value given after the "@" symbol is the diag_ticktimeI have added comments with the tag #****** which explains at what point in the code flow we are at### PRE INIT STARTING "|========================= ZEU_FOUNDATION_TEMPLATE_2014.Stratis =========================|" "------ CORE ------ fn_pre_Init ------> START : @ 4439.49" "------ RESPAWN ------ fget_RespawnType ------> START : @ 4439.49" "------ RESPAWN ------ fget_RespawnType ------> END : @ 4439.49" "------ CORE ------ init_Modules ------> START : @ 4439.49" "------ EXAMPLE ------ init_fnc ------> START : @ 4439.49" "------ EXAMPLE ------ init_fnc ------> END : @ 4439.49" "------ CORE ------ init_Modules ------> END : @ 4439.49" "------ CORE ------ fn_pre_Init ------> END : @ 4439.49" ### MISSION.SQM IS RUNNING any code run from the unit's init field will be shown here ### POST MISSION.SQM (TIME == 0) "------ PARAMS ------ fprocess_params ------> START : @ 4439.84" "------ PARAMS ------ fset_params ------> START : @ 4439.84" "------ PARAMS ------ fset_params ------> END : @ 4439.84" "------ PARAMS ------ fprocess_params ------> END : @ 4439.84" "------ CORE ------ init_common ------> START : @ 4439.84" "------ CORE ------ init_common ------> END : @ 4439.84" "------ CORE ------ init_Server ------> START : @ 4440.69" "------ CORE ------ init_Server ------> END : @ 4440.69" "------ CORE ------ init_Client ------> START : @ 4440.69" "------ CORE ------ init_Client ------> END : @ 4440.69" "------ EXAMPLE ------ init_Common ------> START: @ 4441.03" "------ EXAMPLE ------ init_Common ------> END : @ 4441.03" "------ CORE ------ BIS Init.sqf ------> START : @ 4441.07" "------ CORE ------ BIS Init.sqf ------> END : @ 4441.07" "------ EXAMPLE ------ init_Server ------> START: @ 4441.08" "------ EXAMPLE ------ init_Server ------> END : @ 4441.08" "------ EXAMPLE ------ init_Client ------> START: @ 4441.08" "------ EXAMPLE ------ init_Client ------> END : @ 4441.08" ### BRIEFING IS LOADED RPT Dump in fullHere is the full rpt file less BI spam showing additiona variables being returned"|========================= ZEU_FOUNDATION_TEMPLATE_2014.Stratis =========================|" "------ CORE ------ fn_pre_Init ------> START : @ 4439.49" IsDedicated: false IsServer true HasInterface true IsMultiplayer true Txu_Client true Txu_HC false Isnull Player true Txu Debug System : ENABLED Txu Debug Logging: ["PARAMS","RESPAWN","EXAMPLE","CORE"] "------ RESPAWN ------ fget_RespawnType ------> START : @ 4439.49" "------ RESPAWN ------ fget_RespawnType ------> END : @ 4439.49" "------ CORE ------ init_Modules ------> START : @ 4439.49" "------ EXAMPLE ------ init_fnc ------> START : @ 4439.49" "------ EXAMPLE ------ init_fnc ------> END : @ 4439.49" "------ CORE ------ init_Modules ------> END : @ 4439.49" "------ CORE ------ fn_pre_Init ------> END : @ 4439.49" "------ PARAMS ------ fprocess_params ------> START : @ 4439.84" " PARAMS \ fprocess_params......" " --> ParamsArray : [-100,450]" "------ PARAMS ------ fset_params ------> START : @ 4439.84" "------ PARAMS ------ fset_params ------> DATE Option selected : @ 4439.84" " PARAMS \ fset_params......" " --> Hour selected : 4" " --> Minute selected : 50" "------ PARAMS ------ fset_params ------> END : @ 4439.84" " PARAMS \ fprocess_params......" " --> ParamCompile : ['DATE',450]call Txu_Core_FsetParams" "------ PARAMS ------ fprocess_params ------> END : @ 4439.84" "------ CORE ------ init_common ------> START : @ 4439.84" " CORE \ init_common......" " --> Txu_PREInit : true" " --> Txu_client : true" " --> Txu_HC : false" " --> Txu_JIP : false" " --> IsDedicated : false" " --> IsServer : true" " --> HasInterface : true" " --> IsMultiplayer : true" " --> IsNull Player : false" " --> Txu_MPINIT : true" "------ CORE ------ init_common ------> END : @ 4439.84" "------ CORE ------ init_Server ------> START : @ 4440.69" "------ CORE ------ init_Server ------> END : @ 4440.69" "------ CORE ------ init_Client ------> START : @ 4440.69" "------ CORE ------ init_Client ------> END : @ 4440.69" "------ EXAMPLE ------ init_Common ------> START : @ 4441.03" "------ EXAMPLE ------ init_Common ------> END : @ 4441.03" "------ CORE ------ BIS Init.sqf ------> START : @ 4441.07" "------ CORE ------ BIS Init.sqf ------> END : @ 4441.07" "------ EXAMPLE ------ init_Server ------> START : @ 4441.08" "------ EXAMPLE ------ init_Server ------> END : @ 4441.08" "------ EXAMPLE ------ init_Client ------> START : @ 4441.08" "------ EXAMPLE ------ init_Client ------> END : @ 4441.08" Changelogv1.1: 17th September 2014Added a link to Killzone kid's Scripting Tutorial Blog Added instructions for -showscripterrors Added information on where to find the RPT file Edited October 28, 2015 by terox 7 1 Share this post Link to post Share on other sites
Wolfenswan 1 Posted April 13, 2014 Very nice tutorial Terox. Another page you might want to link is Arma3 Assets in the Biki? Scripting commands by functionality can also be useful sometimes. Share this post Link to post Share on other sites
terox 316 Posted April 14, 2014 Updated the links, thx m8 Share this post Link to post Share on other sites
tills13 10 Posted April 15, 2014 With regards to script timing, how would it look if I wanted to sync mission parameters to all the clients before the assets are loaded. I have global vars in vehicle inits which sometimes seem to run before the server has a chance to init these vars? I was told elsewhere that I should use cfgFunctions but I'm not sure what that would look like. I'm using the following in my init.sqf: for [{_i = 0}, {_i < count(paramsArray)}, {_i = _i + 1}] do { _param = (configName ((missionConfigFile >> "Params") select _i)); _value = (paramsArray select _i); format["%1 = %2", _param, _value] call BIS_fnc_log; call compile format ["%1 = %2; publicVariable ""%1""", (configName ((missionConfigFile >> "Params") select _i)), (paramsArray select _i)]; }; Share this post Link to post Share on other sites
terox 316 Posted April 15, 2014 (edited) check the foundation template section and take a look at the foundation template. cfgFunctions are defined in the description.ext and the preinit code is found in txu\core\fn_pre_Init.sqf this code is run before the mission.sqm, eg object init fields in the mission editor. params is also explained in the tutorial, it doesnt exist on the client until post preinit, so you would have to spawn your params code from preinit. something like [] spawn Myfunction; Myfunction would have at the top waituntil {! isnil "Paramsarray"}; when testing locally, eg when you are also the server, the code may behave differently to when testing on a dedicated server, reason being is that paramsarray exists on the server before preinit whereas on the client it doesnt exist until after preinit Edited April 17, 2014 by Terox Share this post Link to post Share on other sites
kremator 1065 Posted April 16, 2014 I vote to sticky this! Share this post Link to post Share on other sites
SilentSpike 84 Posted June 21, 2014 Second vote to sticky this! Have returned to reference different sections many times during my scripting learning process so far. Share this post Link to post Share on other sites
terox 316 Posted September 17, 2014 Changelog v1.1: 17th September 2014 Added a link to Killzone kid's Scripting Tutorial Blog Added instructions for -showscripterrors Added information on where to find the RPT file Share this post Link to post Share on other sites
SavageCDN 231 Posted September 17, 2014 This really should be a sticky Share this post Link to post Share on other sites
Tankbuster 1746 Posted November 14, 2014 Some cute stuff in here! It's amazing how much I thought I knew, but actually didn't! lol Share this post Link to post Share on other sites
amyalice32 10 Posted March 28, 2015 thank for update links i like this Share this post Link to post Share on other sites
inlesco 233 Posted March 30, 2015 Very nice beginner MP tutorial! Loved all the explanations. Keep it up, Terox. Share this post Link to post Share on other sites
orcinus 121 Posted April 12, 2015 Very useful for SP as well - thank you, Terox :) Share this post Link to post Share on other sites
j-martinez 10 Posted July 6, 2015 I am so glad I found this. Share this post Link to post Share on other sites
terox 316 Posted March 4, 2017 8 hours ago, Opt.Acer said: Nice tutorial. I'm glad to see this is still of use to some. Share this post Link to post Share on other sites
TFM Acer 1 Posted March 5, 2017 16 hours ago, terox said: I'm glad to see this is still of use to some. By the way, I am having some problem editing one mission. In that mission Zeus is cut down to only placing markers. So what I wanted to do is remove restriction because my group wants to be able to build small camps. Do you know a way to remove it or even if you could tell me what code for that would be so I could search it up? Share this post Link to post Share on other sites
Dedmen 2700 Posted June 26, 2017 If you really want to Debug your code you could just use a Debugger now. There is ArmaDebugEngine which can already be used for Debugging inside Arma.Studio. They are still in Beta but I've already used it successfully for TFAR development. Share this post Link to post Share on other sites
scottb613 284 Posted September 13, 2017 Hi Folks, Maybe this is obvious to everyone but I've found using the "windows clipboard" really helps/speeds my script debugging efforts... I just call my logging function from critical areas of code passing it whatever respective string is needed... This allows me to track the codes execution step by step - or - variable by variable if necessary... It doesn't vanish like a hint - it's not microscopic text like in the chat dialog - and I don't have to wade through the full log file... Simply open a new text document and hit paste after your codes execution... The only issue I haven't been able to figure out is - I can't pass the clipboard a carriage return - therefore the file output is delimited... It's easy in Notepad ++ to globally substitute carriage returns for your delimiter - a couple of keystrokes...// FUNCTION - Log to Clipboard //_fcLogger = {params ["_logEnt"]; private ["_logHld","_logSpc","_logPut"]; _logHld = copyfromclipboard; _logSpc = " ## "; _logPut = _logHld + _logEnt + _logSpc; copytoclipboard _logPut; };Regards,Scott Share this post Link to post Share on other sites
Gmate 3 Posted September 6, 2021 wow thats a lot of work, well done. Share this post Link to post Share on other sites