Norco321 10 Posted August 25, 2013 Hi guys, I'm new to this forum and SQF. As it stands I have been testing my scripts using the init.sqf in the Editor; however, I want to be able to distribute them as PBOs. Now I understand how to make a PBO using BinPBO but after creating my PBO, I tried to add it into game via the mod folders/launch options but it does not appear to function/run. I have seen there's a config.cpp/bin that is present in all addons and I am unsure how I am supposed to configure this for a purely script-based addon (no assets). I've searched everywhere but I can't seem to find anything. I don't know whether it's because I'm searching for the wrong terms or what but any help would be greatly appreciated. Cheers. Just for extra info, I am a programmer by day so you can assume I understand general programming constructs. Share this post Link to post Share on other sites
tpw 2315 Posted August 25, 2013 There are probably several ways to do it, but the way I was originally shown (by Das Attorney), uses CBA. Here's how I did it for an addon of mine called TPW LOS 1 - I created a directory called TPW_LOS 2- I dropped tpw_los.sqf (the actual script that does the work) into this directory // THIS SCRIPT WON'T RUN ON DEDICATED SERVERS if (isDedicated) exitWith {}; /* TPW LOS A3 Version: 1.03 Author: tpw Date: 20130818 Original Line of sight stuff: SaOk Azimuth stuff: CarlGustaffa Additional code: Ollem Features: - Works for all editor placed and spawned infantry. - Infantry units will stop and rapidly turn (stance dependent) and fire upon any visible enemies they have line of sight to. - Enemy visibility is influenced by time of day, stance, speed, camouflage and NV at night. - Enemies closer than a specified minimum distance (default 25m) are considered visible regardless. - Enemies beyond a maximum distance (default 100m) are not subject to line of sight calculations. - Debugging will enable blue balls over any units that have line of sight to an enemy. Disclaimer: Feel free to use and modify this code, on the proviso that you post back changes and improvements so that everyone can benefit from them, and acknowledge the original author (tpw) in any derivative works. */ /////////// //VARIABLES /////////// if ((count _this) < 5) exitWith {hint "TPW LOS incorrect/no config, exiting."}; tpwlos_hint = _this select 0; // Startup hint. 0 = no hint, 1 = hint tpwlos_debug = _this select 1; // Debugging. Units with los to a visible enemy will have a blue ball over their heads. 0 = no debugging, 1 = debugging. tpwlos_maxdist = _this select 2; // Maximum distance (m). LOS stuff only works for units closer than this. tpwlos_mindist = _this select 3; // Minimum distance (m). Enemies are considered "visible" no matter what, if less than this distance. tpwlos_sleep = _this select 4; // Delay before LOS functions start. ///////// //SET UP ///////// //WAIT sleep tpwlos_sleep; //START HINT if (tpwlos_hint == 1) then { [] spawn { hintsilent "TPW LOS 1.03 active"; sleep 3; hintsilent "" }; }; ////////////////////////////////////////// //ANGLE OF SUN - ADAPTED FROM CARLGUSTAFFA ////////////////////////////////////////// tpwlos_fnc_sunangle = { private ["_lat","_day","_hour"]; while {true} do { _lat = -1 * getnumber(configfile >> "cfgworlds" >> worldname >> "latitude"); _day = 360 * (datetonumber date); _hour = (daytime / 24) * 360; tpwlos_sunangle = round (((12 * cos(_day) - 78) * cos(_lat) * cos(_hour)) - (24 * sin(_lat) * cos(_day))); sleep 300; }; }; ////////////////////////////// // RAPIDLY TURN TO ENEMY ///////////////////////////// tpwlos_fnc_turn = { private ["_unit","_near","_i","_stance","_delta","_inc","_div"]; _unit = _this select 0; _near = _this select 1; _delta = _this select 2; _stance = stance _unit; switch _stance do { case "prone": { _div = 6; }; case "crouch": { _div = 4; }; case "stand": { _div = 2; }; default { _div = 2; }; }; // Turn increment (smaller for lower stances ie slower) _inc = (_delta / _div) * 0.1; _unit setvariable ["tpwlos_turning", 1]; for "_i" from 1 to 10 do { sleep 0.01; _unit setdir ((direction _unit) + _inc); }; _unit setvariable ["tpwlos_turning", 0]; }; //////////////// //MAIN FUNCTION //////////////// tpwlos_fnc_mainloop = { private ["_x","_nexttime","_unit","_near","_nearunits","_a","_b","_dirto","_eyed","_eyepb","_eyepa","_eyedv","_ang","_tint","_lint","_vm","_dist","_esp","_usp","_camo","_formula","_ball","_upos","_stance","_delta","_unitdir","_mod","_fsmtime"]; { // ONLY RUN FOR UNINJURED COMBATANT AI if ((side _x != civilian) && {(canstand _x) && (_x != player)}) then { _unit = _x; _nexttime = _unit getvariable ["tpwlos_nexttime", -1]; _fsmtime = _unit getvariable ["tpwlos_fsmtime", -1]; _turning = _unit getvariable ["tpwlos_turning", 0]; //SET UP INITIAL UNIT PARAMETERS if(_nexttime == -1) then { //ENEMY SIDE switch (side _unit) do { case east: { _unit setvariable ["tpwlos_enemyside",west]; }; case west: { _unit setvariable ["tpwlos_enemyside",east]; }; case resistance: { _unit setvariable ["tpwlos_enemyside",east]; }; }; //DEBUG BLUE BALLS if (tpwlos_debug == 1) then { _ball = "sign_sphere25cm_F" createvehicle getposatl _unit; _ball attachto [_unit,[0,0,2.3]]; _unit setvariable ["tpwlos_losball",_ball]; _ball setObjectTexture [0,"#(argb,8,8,3)color(0.2,0.2,0.9,0.5,ca)"]; _unit addeventhandler ["killed","_this call tpwlos_fnc_deadclean"]; }; _unit setvariable ["tpwlos_nexttime", diag_ticktime + random 1]; }; //ALLOW INDEPENDENT MOVEMENT AND TARGETTING if (diag_ticktime >= _fsmtime) then { //DISABLE FSM _unit enableai "AUTOTARGET"; _unit enableai "MOVE"; }; //IF ENOUGH TIME HAS PASSED SINCE LAST LOS CHECK if(diag_ticktime >= _nexttime) then { //HIDE DEBUG BALLS if (tpwlos_debug == 1) then { _ball = _unit getvariable "tpwlos_losball"; _ball hideobject true; }; _unit setvariable ["tpwlos_nexttime", diag_ticktime + random 1]; //FIND NEAR MEN AND CARS _nearunits = (getposatl _unit) nearentities [["man","car"],tpwlos_maxdist]; { _near = _x; tpwlos_cansee = 0; //IF ENEMY if (side _near == _unit getvariable "tpwlos_enemyside") then //DOES UNIT HAVE LINE OF SIGHT { _a = _unit; _b = _near; _eyedv = eyedirection _a; _eyed = ((_eyedv select 0) atan2 (_eyedv select 1)); _dirto = ([_b, _a] call bis_fnc_dirto); _ang = abs (_dirto - _eyed); _eyepa = eyepos _a; _eyepb = eyepos _b; _tint = terrainintersectasl [_eyepa, _eyepb]; _lint = lineintersects [_eyepa, _eyepb]; if (((_ang > 120) && (_ang < 240)) && {!(_lint) && !(_tint)}) then { //OTHER FACTORS AFFECTING VISIBILITY OF ENEMY _vm = (currentvisionmode _unit); if (_vm == 1) then { _vm = -1 } else { _vm = 1 }; _dist = (_unit distance _near); _esp = abs (speed _near); _usp = abs (speed _unit); _camo = getnumber (configfile >> "cfgvehicles" >> (typeof _near) >> "camouflage"); //GET ENEMY'S CURRENT STANCE _stance= stance _b; switch _stance do { case "STAND": { _upos = 1.00; }; case "CROUCH": { _upos = 0.75; }; case "PRONE": { _upos = 0.25; }; default { _upos = 1.00; }; }; //MAGIC VISIBILITY FORMULA _formula = (_vm * (tpwlos_sunangle) * _upos) + (_esp * 6) - (_usp * 2) - _dist + random 40; //ANYONE LESS THAN 25m IS FAIR GAME if (_dist < tpwlos_mindist) then { _formula = 200 }; //IGNORE CAMO ENEMY if (_camo > 0.5) then { tpwlos_cansee = _formula }; }; }; if (tpwlos_cansee > 0) exitwith //IF VISIBLE ENEMY { //DISALLOW INDEPENDENT MOVEMENT AND TARGETTING FOR NEXT 5 SEC _unit disableai "AUTOTARGET"; _unit disableai "MOVE"; _unit setvariable ["tpwlos_fsmtime", diag_ticktime + 5]; //HOW MANY DEGREES MUST UNIT TURN TO FACE ENEMY _dirto = ([_a, _b] call bis_fnc_dirto); _unitdir = direction _unit; _delta = (_dirto - _unitdir); if (_delta <= -180) then { _delta = 360 + _delta; }; // ONLY RAPID TURN AND FIRE IF NOT ALREADY TURNING, AND IF MORE THAN 15 DEGREES FROM ENEMY _unit lookat _near; if ((_turning == 0) && ((abs _delta) > 15)) then { [_unit,_near,(floor _delta)] spawn tpwlos_fnc_turn; }; if ((combatMode _x) != "BLUE") then { _unit lookat _near; _unit dotarget _near; _unit dofire _near; }; //SHOW DEBUG BALLS if (tpwlos_debug == 1) then { _ball = _unit getvariable "tpwlos_losball"; _ball hideobject false; }; }; } foreach _nearunits; }; }; } foreach allunits; }; ////////////////////////////////////// //CLEAN UP DEBUG BALLS FROM DEAD UNITS ////////////////////////////////////// tpwlos_fnc_deadclean = { _unit = _this select 0; _ball = _unit getvariable "tpwlos_losball"; detach _ball; deleteVehicle _ball; }; //RUN IT [] spawn tpwlos_fnc_sunangle; [tpwlos_fnc_mainloop,0.5] call cba_fnc_addperframehandler; 3 - Next I created a config.cpp file in the TPW_LOS directory // TPW_LOS Version 1.03 class CfgPatches { class TPW_LOS { units[] = { }; weapons[] = { }; requiredAddons[] = {"CBA_Extended_EventHandlers"}; version = "1.03"; versionStr = "1.03"; versionDesc="TPW LOS"; versionAr[] = {1,0,3}; author[] = {"tpw"}; }; }; class Extended_PostInit_EventHandlers { class TPW_LOS { clientInit = "call compile preprocessFileLineNumbers '\TPW_LOS\init.sqf'"; }; }; class TPW_LOS_Key_Setting { #include "\userconfig\TPW_LOS\TPW_LOS.hpp" }; This is where CBA comes in. It allows you to start the whole shebang off from an init.sqf file, and allows you to specify to read in settings from userconfig. 4 - I created an init.sqf file in TPW_LOS _hint = getnumber(configfile>> "tpw_los_key_setting" >> "tpw_los_hint"); _debug = getnumber(configfile>> "tpw_los_key_setting" >> "tpw_los_debug"); _max = getnumber(configfile>> "tpw_los_key_setting" >> "tpw_los_maxdist"); _min = getnumber(configfile>> "tpw_los_key_setting" >> "tpw_los_mindist"); _delay = getnumber(configfile>> "tpw_los_key_setting" >> "tpw_los_sleep"); nul = [_hint,_debug,_max,_min,_delay] execvm "\tpw_los\tpw_los.sqf"; This allowed me to read in the various variables from the TPW_LOS.hpp, and pass them to tpw_los.sqf at launch time Once I had all these files in place it was just a matter of firing up binpbo, pointing it at TPW_LOS, and hitting "pack" to create the pbo. I hope this helps you. Please PM if you need anything else. 1 Share this post Link to post Share on other sites
kylania 568 Posted August 25, 2013 Great post! The next question is, how to do it without requiring CBA. :) I'd tried this once before and only way I could get anything to work was by using CBA. Share this post Link to post Share on other sites
Norco321 10 Posted August 25, 2013 Thanks a lot mate, that worked an absolute treat. I appreciate the well structured response. Share this post Link to post Share on other sites
mrflay 4 Posted August 25, 2013 Non-CBA way: http://community.bistudio.com/wiki/Functions_Library_(Arma_3) Eg. This will execute the script "\FOO_MyScriptAddon\scripts\fn_init.sqf" when the mission is started. class CfgPatches { class FOO_MyScriptAddon { units[] = {}; weapons[] = {}; requiredAddons[] = {}; }; }; class CfgFunctions { class FOO { class MyCategory { class MyInit { postInit=1; file = "\FOO_MyScriptAddon\scripts\fn_init.sqf"; description = "script run after mission started and object initialization is complete"; }; }; }; }; Share this post Link to post Share on other sites
gammadust 12 Posted August 25, 2013 ^^ nice call mrflay, nothing wrong with CBA, but i don't like dependencies even if this one would generaly be installed. Share this post Link to post Share on other sites
Norco321 10 Posted August 25, 2013 (edited) Perfect mrflay, even better :). Edited August 25, 2013 by Norco321 Share this post Link to post Share on other sites
tpw 2315 Posted August 25, 2013 Non-CBA way: http://community.bistudio.com/wiki/Functions_Library_(Arma_3)Eg. This will execute the script "\FOO_MyScriptAddon\scripts\fn_init.sqf" when the mission is started. class CfgPatches { class FOO_MyScriptAddon { units[] = {}; weapons[] = {}; requiredAddons[] = {}; }; }; class CfgFunctions { class FOO { class MyCategory { class MyInit { postInit=1; file = "\FOO_MyScriptAddon\scripts\fn_init.sqf"; description = "script run after mission started and object initialization is complete"; }; }; }; }; Thanks very much for that. What's the simplest non CBA to read in variables from a config hpp? Share this post Link to post Share on other sites
mrflay 4 Posted August 26, 2013 Thanks very much for that. What's the simplest non CBA to read in variables from a config hpp? I'm pretty sure the way you do it in your example above also works without CBA. Share this post Link to post Share on other sites
Norco321 10 Posted August 26, 2013 The only thing with using CfgFunctions does mean that other people will be able to use the function you've defined. Is there a way to make it non-accessible? Share this post Link to post Share on other sites