d3nn16 3 Posted July 29, 2009 (edited) Hi This mission is a simple tool intended to help people new to ArmA2 scripting language quickly test commands to see their effect in a MP environment. When you start mission select "Options" from action menu. An edit box will spawn and you can type script commands in it. Once you have written commands you want to execute click OK button. INSTALLING : Download mission from http://zdrob.perso.neuf.fr/missions To do this you have to copy ArmA2Server.exe (the ArmA beta server) from http://www.arma2.com/support/updates/folder.html?lang=en to your ArmA installation folder and put a shortcut to your Desktop. The target field in the shortcut should look like this C:\arma2\ArmA2Server.exe "-config=C:\arma2\server\server.cfg" "-profiles=C:\arma2\server\server.ArmA2Profile". -config= is followed by the path to server.cfg file and -profiles= is followed by the path to server.ArmA2Profile file. You can get these files from http://zdrob.perso.neuf.fr/misc/server.zip Then start your server and your game. In ArmA switch to LAN network and you should see the server in the list. Join and type #login in the chatbox. Now add dynamic_script_execution_1.utes.pbo into the MPMissions folder (found in arma install folder) and type #missions in chatbox. The dynamic script execution mission should appear in the list. TESTING : Here is a simple test. We want to see if processInitCommands command has global effects. Type this in the edit box : myveh = "hmmwv" createVehicle position player or "hmmwv" createVehicle position player; myveh = nearestObject [player, "hmmwv"] This will create a vehicle near you and will reference it with myveh variable (that is you can use the variable to refer to this object in other scripting commands) then myveh setVehicleInit "toto = 123"; processInitCommands then EXECS = {SERV_DONE = str toto; publicvariable "SERV_DONE"}; publicvariable "EXECS" At the end you should see a hint telling you what the SERV_DONE variable contains : 123. EXPLANATION : setVehicleInit has local effect, and processInitCommands has global effect. setVehicleInit will add another Init string to the vehicle without overwriting previous Init strings. this happens only in your ArmA program not on the server program (even if it's running on the same PC) - it is called local effect ;-). When processInitCommands is executed in ArmA ("client program") the init string is broadcasted to the server and all the other ArmA "clients" connected to server and playing the mission. Code found in the init string is executed by all after it is received. The EXECS variable contains code that will be executed by the server after it receives the variable, which is broadcast by : publicvariable "EXECS" There is a PV event handler on your ArmA client which detects broadcasts of SERV_DONE variable (done by the server) and will pop up hints displaying text contained in SERV_DONE variable. So this is a way to see what values the variables on the server really have (very powerful feature ;-). Server being equivalent to another ArmA client that would be connected to the server (except "player" command doesn't return a reference to a player unit on a dedicated server which is what we have here). NOTES : To test if changes are broadcast to JIP players just reconnect to the server and test variables values, or if changes are visible just look out for them. It is possible to avoid using EXECS system by running two ArmA clients and joining the same server on your PC (could hurt performance). You do changes in one program and switch to the other see the if those changes are broadcast. Edited August 14, 2009 by d3nn16 Share this post Link to post Share on other sites
Tajin 349 Posted July 29, 2009 setVehicleInit will add another Init string to the vehicle without overwriting previous Init strings. I've not direclty tested this yet, but I believe that setVehicleInitit does overwrite the previous init. (only that this has already been executed at that time) Should test that someday, it may have impact on JIP in that case. Share this post Link to post Share on other sites
xeno 234 Posted July 29, 2009 I've not direclty tested this yet, but I believe that setVehicleInitit does overwrite the previous init. Nope, it doesn't. If you want to remove previously added inits you have to use clearVehicleInit. Xeno Share this post Link to post Share on other sites
Tajin 349 Posted July 29, 2009 Ok, good. That makes things much easier anyway. Share this post Link to post Share on other sites
d3nn16 3 Posted July 29, 2009 (edited) forgot to put link to mission Edited August 14, 2009 by d3nn16 Share this post Link to post Share on other sites
eddyaod 10 Posted July 29, 2009 Nope, it doesn't.If you want to remove previously added inits you have to use clearVehicleInit. Xeno Are you saying setVehicleInit only appends it's arguments to any already existing init code? :eek: Share this post Link to post Share on other sites
d3nn16 3 Posted July 29, 2009 Each time you use setVehicleInit the string gets longer (or there is an array of strings that gets bigger). And on top of all that when you delete a vehicle the init string is still transmitted to JIP players and executed. Imagine you create hundreds of vehicles dyanmically after mission started and you use setVehicleInit intensively on each vehicle. Could explain why some missions take alot of time to JIP into. Xeno use my mission to test clearVehicleInit, I did and for me the command didn't clear the vehicle's init. Maybe I am wrong in that case I would like to know how you use the command Share this post Link to post Share on other sites
xeno 234 Posted July 29, 2009 intensively on each vehicle. Could explain why some missions take alot of time to JIP into. Exactly. And remember, it's the same for code that you add into the init line of editor placed objects and units. Xeno use my mission to test clearVehicleInit, I did and for me the command didn't clear the vehicle's init. Maybe I am wrong in that case I would like to know how you use the command Maybe I'm blind but I can't find any clearVehicleInit command in the test mission. To be on the safe side execute the clearVehicleInit command on the server. If you only execute it on a client it will not automatically clear the inits on the server side and vice versa. Xeno Share this post Link to post Share on other sites
d3nn16 3 Posted July 29, 2009 There is no command to be found in the test mission. You have to type commands you want to execute in the edit box that you open by selecting OPTIONS from action menu. Using this mission I did the following tests : created hmmwv, added init "toto=123", processinitcommands checked server : toto was correctly initialized exeuted clearVehicleinit on client; then processInitcommands to be sure reconnected to server : toto still initialized to 123 restarted mission and did same test again except I used EXECS to execute clearVehicleInit on server then i reconnected but still toto was initialized to 123 So executing clearVehicleInit (followed by processInitCommands just in case it is needed) had no effect whether this executes on client or server. Share this post Link to post Share on other sites
xeno 234 Posted July 29, 2009 (edited) So executing clearVehicleInit (followed by processInitCommands just in case it is needed) had no effect whether this executes on client or server. Well, you still execute the clearVehicleInit command on the client and not on the server, processInitCommands doesn't help nor is it needed :) The init doesn't get changed on the server and will get transfered to you when you connect again. Xeno ---------- Post added at 22:15 ---------- Previous post was at 21:41 ---------- Tested it again, you are right. ClearVehicleInit doesn't do anything. Then you have found a nice A2 bug. Xeno Edited July 29, 2009 by Xeno Share this post Link to post Share on other sites
d3nn16 3 Posted July 29, 2009 I knew about the bug from http://community.bistudio.com/wiki/Talk:clearVehicleInit :cool: Share this post Link to post Share on other sites
xeno 234 Posted July 29, 2009 I knew about the bug from http://community.bistudio.com/wiki/Talk:clearVehicleInit :cool: :) So it's not a good idea to use many vehicle inits. Might cause troubles for JIP players. Would be better if clearVehicleInit really clears all inits, not just the pending ones. Xeno Share this post Link to post Share on other sites
d3nn16 3 Posted July 29, 2009 (edited) Personally I use setVehicleInit in my C&H mission because I couldn't figure out any other solution to unload the default ammunition cargo from vehicles and still allow JIP players to see exactly what other players added/retrieved from ammo cargos. That is because clearWeaponCargo and clearMagazineCargo only have local effects. I use _v setVehicleInit "clearWeaponCargo; clearMagazineCargo"; processInitCommands on all vehicles that spawn. I think in general this problem affects missions that last many hours like Evolution. On a side note I noticed a possible problem with group objects not being deleted properly from game sometimes and still being present while having no units in them, a memory leak. I noticed it because I used allGroups command to display a list of all units sorted by groups in a dialog and I could see "Error : no unit" message instead of players names, even after checking my own group creating/deleting system was OK and refreshing the list. ---------- Post added at 11:33 PM ---------- Previous post was at 09:46 PM ---------- Pasting files contents here in case link to mission gets broken. description.ext respawn = "base"; respawnDelay = 5; disabledAI = 1; class Header { minPlayers = 1; maxPlayers = 1; }; #define _CT_STATIC_ 0 #define _CT_BUTTON_ 1 #define _CT_EDIT_ 2 #define _ST_LEFT_ 0 #define _ST_CENTER_ 2 #define _ST_LIST_ 0 #define _FONT_ "Zeppelin32" #define _FONTSIZE_ 0.025 #define _BLACK_ {0, 0, 0, 1} #define _GRAYDARK_ {0.3, 0.3, 0.3, 1} #define _GRAY_ {0.5, 0.5, 0.5, 1} #define _WHITE_ {1, 1, 1, 1} #define _ORANGERED_ {1, 0.4, 0, 1} #define _DIAG_X_ 0.05 #define _DIAG_Y_ 0.8 #define _DIAG_W_ 0.9 #define _DIAG_H_ 0.2 #define _DX_ 0.01 #define _DY_ 0.01 #define _BTN_W_ (_DIAG_W_ - 2 * _DX_) #define _BTN_H_ ((_DIAG_H_ - 3 * _DY_) / 2) #define _BTN_FONT_ _FONT_ #define _BTN_FONTSIZE_ _FONTSIZE_ #define _CONT_X_ _DIAG_X_ + _DX_ #define _CONT_Y_ _DIAG_Y_ + _DY_ class TEMPL_STATIC { idc = -1; moving = true; type = _CT_STATIC_; style = _ST_CENTER_; x = 0; y = 0; w = 0; h = 0; sizeEx = _FONTSIZE_; font = _FONT_; text = ""; colorText[] = _BLACK_; colorBackground[] = _WHITE_; }; class TEMPL_BUTTON { idc = -1; type = _CT_BUTTON_; style = _ST_CENTER_; x = 0; y = 0; w = _BTN_W_; h = _BTN_H_; sizeEx = _BTN_FONTSIZE_; font = _BTN_FONT_; text = ""; colorText[] = _ORANGERED_; colorBackground[] = _BLACK_; default = false; borderSize = 0; colorDisabled[] = _GRAY_; colorFocused[] = _GRAYDARK_; colorShadow[] = _ORANGERED_; colorBorder[] = _ORANGERED_; colorBackgroundActive[] = _GRAYDARK_; colorBackgroundDisabled[] = _GRAYDARK_; offsetX = 0; offsetY = 0.004; offsetPressedX = 0; offsetPressedY = 0.002; soundEnter[] = {}; soundPush[] = {}; soundClick[] = {}; soundEscape[] = {}; }; class TEMPL_EDIT { idc = -1; type = _CT_EDIT_; style = _ST_LEFT_; x = 0; y = 0; w = _BTN_W_; h = _BTN_H_; sizeEx = _FONTSIZE_; font = _FONT_; text = ""; colorText[] = _WHITE_; autocomplete = true; colorSelection[] = _BLACK_; }; class DIAG_OPTIONS { idd = 1; movingEnable = true; controlsBackground[] = {BACKGROUND, EDIT_SCRIPT_B}; controls[] = {EDIT_SCRIPT, BTN_OK}; objects[] = {}; class BACKGROUND : TEMPL_STATIC { idc = 30; x = _DIAG_X_; y = _DIAG_Y_; w = _DIAG_W_; h = _DIAG_H_; colorBackground[] = _BLACK_; }; class EDIT_SCRIPT : TEMPL_EDIT { idc = 10; x = _CONT_X_; y = _CONT_Y_; text = ""; }; class EDIT_SCRIPT_B : TEMPL_STATIC { idc = 11; x = _CONT_X_; y = _CONT_Y_; w = _BTN_W_; h = _BTN_H_; colorBackground[] = _ORANGERED_; }; class BTN_OK : TEMPL_BUTTON { idc = 20; x = _CONT_X_; y = _CONT_Y_ + _BTN_H_ + _DY_; text = "OK"; action = "call compile ctrlText 10"; }; }; init.sqf enableSaving [false, false]; if (! (isServer && isNull player)) then { waitUntil {! isNull player}; _trig = createTrigger ["emptydetector", [0,0,0]]; _trig setTriggerArea [0, 0, 0, false]; _trig setTriggerActivation ["none", "present", true]; _trig setTriggerStatements ["vehicle player != player", "VEHICLE_PLAYER = vehicle player; OPTIONS_IDX = VEHICLE_PLAYER addAction ['OPTIONS', 'options.sqf', 0, 0, false, true]", "VEHICLE_PLAYER removeAction OPTIONS_IDX"]; OPTIONS_IDX = player addAction ["OPTIONS", "options.sqf", 0, 0, false, true]; player addEventHandler [ "killed", { [] spawn { cutText ["", "black out"]; player removeAction OPTIONS_IDX; waitUntil {alive player}; OPTIONS_IDX = player addAction ["OPTIONS", "options.sqf", 0, 0, false, true]; cutText ["", "black in"]; }; } ]; }; if (isServer) then { "EXECS" addPublicVariableEventHandler { call (_this select 1); }; } else { "SERV_DONE" addPublicVariableEventHandler { hint (_this select 1); }; }; options.sqf createDialog "DIAG_OPTIONS"; mission.sqm version=11; class Mission { addOns[]= { "utes", "cacharacters2", "CAWheeled2_HMMWV_Ambulance", "CAWheeled2_MTVR", "CAWheeled2_Kamaz", "CAWheeled2_GAZ39371", "CAWheeled", "cawheeled2_m1114_armored", "CAWheeled3_M1030", "CATracked2_AAV", "CAWheeled2_LAV25", "CAWheeled2_BTR90", "CATracked", "cawheeled2_m998a2_avenger", "CATracked2_T90", "CATracked2_2S6M_Tunguska", "CAA10", "ca_air2_su25", "CAAir", "Arma2_Ka52", "CAAir2_UH1Y", "caweapons_ammoboxes" }; addOnsAuto[]= { "cacharacters2", "utes" }; randomSeed=2047616; class Intel { briefingName="DYNAMIC SCRIPT EXECUTION 1a"; briefingDescription="Eraser [ZDROB]"; startWeather=0.39999998; forecastWeather=0.25; year=2008; month=10; day=11; hour=14; minute=20; }; class Groups { items=2; class Item0 { side="EAST"; class Vehicles { items=1; class Item0 { position[]={3151.3999,16.825634,4438.853}; id=0; side="EAST"; vehicle="RU_Soldier_Medic"; leader=1; skill=0.60000002; }; }; }; class Item1 { side="EAST"; class Vehicles { items=1; class Item0 { position[]={3159.7507,16.41205,4436.7324}; id=1; side="EAST"; vehicle="RU_Soldier_SL"; player="PLAYER COMMANDER"; leader=1; skill=0.60000002; }; }; }; }; }; class Intro { addOns[]= { "utes" }; addOnsAuto[]= { "utes" }; randomSeed=16685155; class Intel { startWeather=0.40000001; forecastWeather=0.25; year=2008; month=10; day=11; hour=14; minute=20; }; }; class OutroWin { addOns[]= { "utes" }; addOnsAuto[]= { "utes" }; randomSeed=2031883; class Intel { startWeather=0.40000001; forecastWeather=0.25; year=2008; month=10; day=11; hour=14; minute=20; }; }; class OutroLoose { addOns[]= { "utes" }; addOnsAuto[]= { "utes" }; randomSeed=5245889; class Intel { startWeather=0.40000001; forecastWeather=0.25; year=2008; month=10; day=11; hour=14; minute=20; }; }; Edited July 29, 2009 by d3nn16 Share this post Link to post Share on other sites
d3nn16 3 Posted August 5, 2009 This can be useful to avoid useless brackets when writing code: For instance, if you want to select an item from an array randomly you can write this : _array = [p1, p2, p3, p4]; _elem = _array select floor random count _array; avoiding useless brackets _elem = _array select (floor random count _array); The interpreter looks for the first command starting from left, here it is "select". "select" takes two arguments : one to its left returning an array and a second to its right. If the first element to the right of "select" is another command then the interpreter interprets that command and looks for its arguments, and so on, until it reaches a command with arguments returning a value and not calling other commands. Sequence : _elem [color="Red"]=[/color] _array select floor random count _array; [color="Blue"]_elem[/color] [color="Red"]=[/color] _array select floor random count _array; [color="Blue"]_elem[/color] [color="Red"]=[/color] [color="Blue"]_array select floor random count _array[/color]; _elem = _array [color="Red"]select[/color] floor random count _array; _elem = [color="Blue"]_array[/color] [color="Red"]select[/color] floor random count _elem = _array; _elem = [color="Blue"]_array[/color] [color="Red"]select[/color] [color="Blue"]floor[/color] random count _array; _elem = [color="Green"][p1, p2, p3, p4][/color] select [color="Red"]floor[/color] random count _array; _elem = [color="Green"][p1, p2, p3, p4][/color] select [color="Red"]floor[/color] [color="Blue"]random[/color] count _array; _elem = [color="Green"][p1, p2, p3, p4][/color] select floor [color="Red"]random[/color] count _array; _elem = [color="Green"][p1, p2, p3, p4][/color] select floor [color="Red"]random[/color] [color="Blue"]count[/color] _array; _elem = [color="Green"][p1, p2, p3, p4][/color] select floor random [color="Red"]count[/color] _array; _elem = [color="Green"][p1, p2, p3, p4][/color] select floor random [color="Red"]count[/color] [color="Blue"]_array[/color]; Bottom of recursion, now returning back : _elem = [color="Green"][p1, p2, p3, p4][/color] select floor random [color="Red"]count[/color] [color="Green"][p1, p2, p3, p4][/color]; _elem = [color="Green"][p1, p2, p3, p4][/color] select floor [color="Red"]random[/color] [color="Green"]4[/color]; _elem = [color="Green"][p1, p2, p3, p4][/color] select [color="Red"]floor[/color] [color="Green"]2.356879[/color]; _elem = [color="Green"][p1, p2, p3, p4][/color] [color="Red"]select[/color] [color="Green"]2[/color]; _elem = [color="Green"]p3[/color]; You should now know when to use brackets and when they are useless. _indexarray = [0, 10, 13, 5]; _elem = _playerslist select _indexarray select floor random count _indexarray; _elem = _playerslist select (_indexarray select floor random count _indexarray); because the first select expects a number to its right and not an array Scripting commands have also priorities which determine which commands are interpreted before the rest of commands (highest priority first): This is what I could find out (I didn't test it much) : highest priority : - (unary operator : 10 + -5, result 5), ! script command (like count), *, /, % +, - ==, <=, >=, <, > && || = This example myvar = 5 * count [] - 9 / 30 == -10 % 8 + -0.1 * 3 && player in [player] || 5 >= 15 % 10 - 2 / 1 && ! ! true hint str myvar; returns true Share this post Link to post Share on other sites
d3nn16 3 Posted August 6, 2009 select seems to have priority below + and - [5, 6] select 0 + 1 returns 6 Share this post Link to post Share on other sites