Home   Help Search Login Register  

Author Topic: Fwatch 1.13 for CWA in action  (Read 8792 times)

0 Members and 1 Guest are viewing this topic.

Offline SoldierEPilot

  • Members
  • *
Fwatch 1.13 for CWA in action
« on: 07 Nov 2014, 18:01:46 »
There are many new possibilities 4 scripters in new Fwatch 1.13 (made by Faguss).
If you are not a happy owner yet - use this link:
http://ofp-faguss.com/fwatch/
AFAIK there are 2 versions - for CWA and for OFP 1.96, I use the first one.

One of the most cool things - :class token command.
From now on you can get almost all information from the
mission config (mission.sqm) in editor missions and unpacked campaigns.

Code: [Select]
comment{
//////////////////////////////////////////////////
Reading mission config values.
Works with editable missions and unpacked campaigns.
Сampaign mission names better not starts from "t"
//////////////////////////////////////////////////
};

private["_a", "_cmp", "_cmpgs", "_c", "_j", "_p", "_f", "_path", "_il", "_token"];

comment{
Is it a campaign?
It's possible to use queryMagazineCargo to check it out,
but some delay needed to make this check stable.
To provide delay I need a script, but I prefer immediate decision.
Here is the choice 'tween editable mission and unpacked campaign.
};
_a = (call loadFile format[":class token ""%1"" c:[Mission]", "f:mission.sqm"]) select 0;
_a=!_a;
ISCMP = _a;

comment{Safe wrapper for "... :il ..." request};

 _il={
private ["_p", "_r"];
if (_this in [_this]) then {_p=[_this]} else {_p=+_this};
_r=["il "];
{_r=_r+[format["%1",_x]]} forEach _p;
call (_r call preprocessFile {..\fwatch\data\ExecCommand.sqf})
};

comment{Campaign name};
_cmp="";
if _a then{
_cmpgs = ("..\Campaigns\*" call _il) select 4;
_c=count _cmpgs;
_j=-1;
while{_j=_j+1;_j<_c}do
  {
_p=["..\Campaigns\", _cmpgs select _j, "\missions\", missionName, ".", getWorld];
_f = (_p call _il) select 4;
if (0!=count _f) then {_cmp=_cmpgs select _j; _j=_c};
  };
};
CMPNAME = _cmp;

comment{Path to the mission config 4 ":class token" command};
if (_cmp!="")then{
_path="..\Campaigns\"+ _cmp + "\missions\";
_path=_path + missionName + "." + getWorld + "\mission.sqm";
}else{
_path="mission.sqm";
};
MNPATH = _path;

comment{Safe wrapper for "... :class token ..." request};
 _token={
private ["_t", "_r"];
if (_this in [_this]) then{_t=[_this]}else{_t=+_this};
_r=["class token ", """", "f:", _path, """", " "];
{_r=_r+[format["%1",_x]]} forEach _t;
call(_r call preprocessFile {..\fwatch\data\ExecCommand.sqf})
};

comment{Get weather info as a 4-element vector:
[start cast, start fog, forecast weather, forecast fog]};
private["_w", "_i"];
_w=[];

_a ="c:[Mission,Intel]" call _token;
A=+_a;

_i= (_a select 6) find "startWeather";
if (_i<0)then {_w set[0, 0.5]}else{_w set[0,call((_a select 7)select _i)]};
_i= (_a select 6) find "startFog";
if (_i<0)then {_w set[1, 0]}else{_w set[1,call((_a select 7)select _i)]};
_i= (_a select 6) find "forecastWeather";
if (_i<0)then {_w set[2, 0.5]}else{_w set[2,call((_a select 7)select _i)]};
_i= (_a select 6) find "forecastFog";
if (_i<0)then {_w set[3, 0]}else{_w set[3,call((_a select 7)select _i)]};
WTR = _w;

comment{Get array of all groups on the map};
private["_g","_sh","_n","_v","_o","_m"];
_g=[];
_a="c:[Mission,Groups]" call _token;
_sh=call (_a select 5);
_N=call((_a select 7)select 0);
_i=-1;while{_i=_i+1;_i<_N}do
{
_j=-1;
_M=(["c:[Mission,Groups,Item", _i, ",Vehicles"] call _token) select 7;
_M=call(_M select 0);
while{_j=_j+1;_j<_M}do
{
_a=["c:[Mission,Groups,Item", _i, ",Vehicles,Item", _j, "] ", _sh] call _token;
_sh=call (_a select 5);
_p=(_a select 7) select ((_a select 6) find "position[]");
_v=(_a select 7) select ((_a select 6) find "vehicle");
_o=nearestObject [[call (_p select 0),call (_p select 2)], call _v];
if (! isNull _o)then{_g=_g+[group _o];_j=_M;};
};
};
GRP = _g;

comment{Get array of all empty vehicles on the map};
private["_e"];
_e=[];
_a="c:[Mission,Vehicles]" call _token;
_sh=call (_a select 5);
_N=call((_a select 7)select 0);
_i=-1;while{_i=_i+1;_i<_N}do
{
_a=["c:[Mission,Vehicles,Item", _i, "] ", _sh] call _token;
_sh=call (_a select 5);
_p=(_a select 7) select ((_a select 6) find "position[]");
_v=(_a select 7) select ((_a select 6) find "vehicle");
_e=_e+[nearestObject [[call (_p select 0),call (_p select 2)], call _v]];
};
EV=_e;

comment{Get array of all mission triggers};
private["_t"];
_t=[];
_a = "c:[Mission,Sensors]" call _token;
_sh=call (_a select 5);
_N=call((_a select 7)select 0);
_i=-1;while{_i=_i+1;_i<_N}do
{
_a=["c:[Mission,Sensors,Item", _i, "] ", _sh] call _token;
_sh=call (_a select 5);
_p=(_a select 7) select ((_a select 6) find "position[]");
_t=_t+[nearestObject [[call (_p select 0),call (_p select 2)], "EmptyDetector"]];
};
TRG=_t;

comment{Array of all mission markers};
_m=[];
_a="c:[Mission,Markers]" call _token;
_sh=call (_a select 5);
_N=call((_a select 7)select 0);
_i=-1;while{_i=_i+1;_i<_N}do
{
_a=["c:[Mission,Markers,Item", _i, "] ", _sh] call _token;
_sh=call (_a select 5);
_m=_m+[call ((_a select 7) select ((_a select 6) find "name"))];
};
MRK=_m;

test={
comment{
Expression tester.
Expression ==> big string ==> OFP crash(
Expression ==> array ==> show first 20 elements
 };
private ["_r","_m","_i","_c","_c0"];
_r=call _this;
_cut=false;
if (_r in [_r]) then
{
_m=format["%1", _r];
if (_m in["<null>","[<null>]"])then
{hintC _this} else
{hintC format["%1\n=========================\n%2",_this,_m]};
}
else
{
_c=count _r;
_c0=_c;
if (20 < _c)then{
    _cut=true;
_r resize 20;
};
_c=(count _r)-1;
_m="[\n";
_i=-1;
while{_i=_i+1;_i<_c}do
{
_m=_m+format[" %1\n",_r select _i];
};
_m=_m+format[" %1\n",_r select _i];
if (_c0>20) then {_m=_m+ format[" ...\n]\n( %1 elements )",_c0]}else{_m=_m+"]"};
hintC format["%1\n=========================\n%2",_this,_m];
};
};

--MODIFIED--
2 errors fixed: error in f_getAllMarkers and another one in f_getAllEmpty.

Note: f_getWeather, f_getAllEmpty and  f_getAllGroups must be called on mission start, otherwise
you can get wrong data. Then called, they should send the resulting array to some
monitoring script, so you can check weather, groups and vehicles at every moment.

--MODIFIED 2--
Works in unpacked campaigns now, example attached.

--MODIFIED 3--
Don't crash OFP if some s...trange thing happens.
Works with long paths.
No "use me once" functions.

--MODIFIED 4--
Fixed problem with spaces in campaign/campaign mission name.



« Last Edit: 18 Jan 2015, 14:27:04 by SoldierEPilot »

Offline Lone~Wolf

  • Mission Tools & Mods
  • Members
  • *
  • Vladimir Dmitri Mikhail Andreevich Stamenov
Re: Fwatch 1.13 for CWA in action
« Reply #1 on: 12 Nov 2014, 19:40:28 »
Brilliant stuff as usual. Now all I need is time, which I might have some of in a few months.
Snarling creature, lurking in the background, still writing in .sqs

Offline faguss

  • Members
  • *
    • Faguss' Website
Re: Fwatch 1.13 for CWA in action
« Reply #2 on: 26 Nov 2014, 22:05:33 »
You have syntax error in function f_getAllEmpty (unnecessary semi-colon in the line with nearestObject) and you might want to use additional call in f_getAllMarkers (_m=_m+[call (...)]).

===

Keep in mind that the command works with unpacked / unrapified / unbinarized files so I think the use is rather limited. 1.14 will be able to unpack PBO so that may help a bit.

I wrote "class" commands specifically for the Config Editor (still unfinished) so that's why they wrap data around quotes.

Code: [Select]
cost=10 becomes
Code: [Select]
["cost"],["10"]
Later I realized that the command can be used for other things so 1.14 features option to disable stringification and hence save time.

These commands also enable prospect of a 3D Mission Editor but I don't know if I'll ever get around to create that.

Offline SoldierEPilot

  • Members
  • *
Re: Fwatch 1.13 for CWA in action
« Reply #3 on: 28 Nov 2014, 23:04:35 »
@Faguss,
is it possible somehow to implement ":class" commands 4 unpacked campaign?
I've tried the same things like with editor mission, it doesn't work.
Should I use some path or just wait 4 FW114 ???

Offline faguss

  • Members
  • *
    • Faguss' Website
Re: Fwatch 1.13 for CWA in action
« Reply #4 on: 29 Nov 2014, 01:55:54 »
You can access root dir like you would in standard OFP scripting (more info here). Target file must be plain text.

Code: [Select]
f:..\Campaigns\1985\missions\00training.abel\mission.sqm

Offline SoldierEPilot

  • Members
  • *
Re: Fwatch 1.13 for CWA in action
« Reply #5 on: 30 Dec 2014, 20:21:11 »
When I use such a code in  unpacked campaign I see OFP crash every time :o
Code: [Select]
_a = call loadFile format[":class token ""%1"" c:[Mission,Groups,Item%2,Vehicles,Item%3] %4", MissionPath,_i,_j, _sh];

Probable reason is: too long total string in the input of :class command.
MissionPath: "f:..\Campaigns\MySuperCmp\missions\First Battle.Intro\mission.sqm" - 65 symbols, and it can be longer, up to 90.

So I tried this INIT.SQS with "c:[Mission,Groups]" request
to find out if ExecCommand can help me.

Code: [Select]
~2
print1={hintC format ["%1",_this]}
print3={hintC format (["%1%2%3"]+_this)}
[b]ExecCommand = preprocessFile {..\fwatch\data\ExecCommand.sqf}[/b]
_path="f:..\Campaigns\MySuperCmp\missions\First Battle.Intro\mission.sqm"

;It doesn't work

_a = ["call loadFile "":class token """"", _path, """"" c:[Mission,Groups]"""]
;must return the same result as
;_a = call loadFile format[":class token ""%1"" c:[Mission,Groups]", MissionPath];

_a call print3
~2
(_a call ExecCommand) call print1
exit

The problem: ExecCommand must take several strings and execute
resulting string despite of Fwatch string length limitation (127 symbols).
(if array doesn't have strings longer than 110 or near this number).
I can't make working sample of ":class token" with ExecCommand -
just lost in the quotes and brackets. Please help!




« Last Edit: 31 Dec 2014, 10:18:38 by SoldierEPilot »

Offline SoldierEPilot

  • Members
  • *
Re: Fwatch 1.13 for CWA in action
« Reply #6 on: 06 Jan 2015, 20:07:16 »
Finaly I got it.
Code: [Select]
...
_a = ["class token ", _path, " c:[Mission,Groups]"]
(_a call ExecCommand) call print1
exit

The original example will be updated soon.



Offline SoldierEPilot

  • Members
  • *
Re: Fwatch 1.13 for CWA in action
« Reply #7 on: 12 Jan 2015, 23:18:06 »
The main purpose of this research is to take scripting access
to units and vehicles placed in current mission on mod level.
In mod you can use additional GUI button/active text in resource.cpp
and run any correct scripts on any units placed. This is more flexible way
than reconfigure units and give 'em embedded "Init" EHs.

However, there are some limitations with mission/campaign names
(thanks to ":class token" command).

1)
Name must be a single word.
Most of the campaign missions follow this rule,
campign like "Samson's Hero" can be renamed to "Samson_hero";

2)
If the campaign or it's mission starts from "t", error will take place because of "Campaigns\" or "missions\" before it in the full path.
The damn thing thinks it's  "\t" (tabulation) here and can't find the file :o
It's easy to rename campaign but it's more difficult to rename it's mission(s).

@Faguss, please do something with ":class token" in Fw 1.14!

P.S.
See the new code and attachments in my first post.
« Last Edit: 14 Jan 2015, 09:35:28 by SoldierEPilot »

Offline faguss

  • Members
  • *
    • Faguss' Website
Re: Fwatch 1.13 for CWA in action
« Reply #8 on: 17 Jan 2015, 16:36:07 »
Quote
if array doesn't have strings longer than 110 or near this number

116. New one will be up to 123.

Quote
Name must be a single word

No. Just wrap argument in quotation marks.

Code: [Select]
FLIB_EXEC = preProcessFile "..\fwatch\data\ExecCommand.sqf"
_data = call (["class token ","""","f:..\Campaigns\19 85\missions\00 training.abel\mission.sqm",""""," c:[Mission,Groups,Item0,Vehicles,Item0]"] call FLIB_EXEC)
hint Format ["%1\n\n\n%2", _data select 6, _data select 7]

It's like:

Code: [Select]
_data = call loadFile ":class token ""f:..\Campaigns\19 85\missions\00 training.abel\mission.sqm"" c:[Mission,Groups,Item0,Vehicles,Item0]"

Quote
ExecCommand = preprocessFile {..\fwatch\data\ExecCommand.sqf}

Please use FLIB_EXEC global variable.

Quote
The damn thing thinks it's  "\t" (tabulation) here and can't find the file

I'll look into it. Thanks for letting me know.

Offline SoldierEPilot

  • Members
  • *
Re: Fwatch 1.13 for CWA in action
« Reply #9 on: 18 Jan 2015, 14:33:08 »
Thanks 4 fast and helpful reaction.

I fixed sample in 1st topic - it works now with space-separated names.
BTW, if campaign mission ends with "mission", it doesn't work somehow.

Offline faguss

  • Members
  • *
    • Faguss' Website
Re: Fwatch 1.13 for CWA in action
« Reply #10 on: 27 Jan 2015, 22:42:23 »
I don't know when I'm going to release new version. Not any time soon. Fwatch itself is done for the most part but I want to finish scripts using it before its release. And when I see how much work there is to be done I lose motivation and start to procrastinate...

Anyway, you can play around with this test release. I recommend to make backup of the .dll, .exe and data folder (so you could go back to 1.13). For CWA version just rename executable to fwatchCWA.exe. In documentation look for commands marked upcoming and update (click on the version number for changelog).

====

THIS INFORMATION IS OBSOLETE

How to unpack PBO files:

Code: [Select]
_ok = call loadFile ":exe unpbo -F mission.sqm Missions\01takethecar.abel.pbo"
? !(_ok select 0) : hint (_ok select 3); exit

Starts the program and displays error if it failed. This will extract only a single file. To extract everything just use :exe unpbo mission.pbo. To get addon config use :exe unpbo -F config.cpp,config.bin addon.pbo.

Code: [Select]
#Wait
~0.01
_ok = call loadFile "..\fwatch\data\manage_extractpbo.sqf"
? count _ok == 0 : goto "Wait"

Wait for the program to finish unpacking by checking file with results.

Code: [Select]
? !(_ok select 0) : hint (_ok select 3); exit
? (_ok select 4) != 0 : hint "error extracting pbo"; exit

Actually Fwatch is launching custom program manage_extractpbo.exe which in turns executes extractpbo.exe. I use such redundancy in order to monitor process exit code (I won't do it with the Fwatch itself because the game is stopped when I call it).

So the array _ok now contains error information whether manage_extractpbo.exe failed to launch extractpbo.exe. Last item in the array is extractpbo.exe exit code. 0 for success and 1 for failure. I guess there are no other values.

Code: [Select]
_ok = call loadFile ":class token f:..\fwatch\tmp\01takethecar.abel\mission.sqm c:[Mission,Intel] n t:startWeather"
? !(_ok select 0) : hint (_ok select 3); exit
hint Format ["Initial Weather:\n%1", (_ok select 7) select 0]

Files are extracted to the \fwatch\tmp\ directory. Use :class token with parameter n to disable stringification.

Files are unbinarised and derapified but still there's no guarantee that you'll be able to access mission.sqm because you need to find the mission first. I'll leave this to you, people to figure out. I'll drop some tips, though:

  • use (playersNumber west + playersNumber east + playersNumber resistance + playersNumber civilian) == 0 to check for SP
  • use :mem missioninfo to get mission name
  • use :file read2 to get last campaign name from userinfo.cfg
  • use :mem modlist, :file modlist and :il to search for campaigns
  • search for files in user\Saved with :il and compare last modification times (using DateDifference) with mission starting time to perhaps find what player is playing now

OBSOLETE. See this post.

====

Initialize FLIB_EXEC (and other functions) by using:

Code: [Select]
["flib_exec"] call preProcessFile "..\fwatch\data\InitFLib.sqf"
Don't use exec function if you're sure that the command is within the limit because then you're just making redundant calls.

You can now log errors using ErrorLog.sqs. Instructions how to use it you'll find inside the file.

Things may change in the final release.

Quote
The damn thing thinks it's  "\t" (tabulation) here and can't find the file

That was an issue with the exec function. Fixed in 1.14.

Quote
BTW, if campaign mission ends with "mission", it doesn't work somehow.

I need more details. Error description? What's the path?


« Last Edit: 07 Jun 2015, 15:25:36 by faguss »

Offline SoldierEPilot

  • Members
  • *
Re: Fwatch 1.13 for CWA in action
« Reply #11 on: 29 Jan 2015, 16:22:47 »
 I don't think what BIS going to release one more patch.
 Just imagine: 20th OFP anniversary - ACWA 1.999 :
 6 functions added to readme and 4 of them - realy to CWA...
 I hope it will motivate you a bit.

 Fwatch must go on!
////////////////////////////////

With 1.14 this code
will find all active addons  and mods:

Code: [Select]
grabAddonNames={
private "_a";
_a=[];
if (_this select 0) then
{
{_a=_a+[_x select 0]} forEach (_this select 5);
};
_a
};

// [fixed]: check mod folders 4 presence
// to get only real active mods
activeAddonsAndMods={
private["_mm", "_fm", "_mods", "_add", "_tmp"];
_mm = call loadFile ":mem modlist";
_fm = call loadFile ":file modlist";
_mods=[];
{if ([_fm, _x] call findString >= 0) then {_mods=_mods+[_x]}} forEach _mm;
// Root-level 'Addons' folder
_add=(call loadFile (":il ..\addons\*.pbo")) call grabAddonNames;
{
     // Mod-level 'Addons' folder
_tmp= call loadFile (":il ..\" + _x + "\addons\*.pbo");
_add=_add+(_tmp call grabAddonNames);
} forEach _mods;
[_add, _mods]
};

activeAddonsAndMods returns nested 2-element array:
0 - active addon names (without PBO)
1- active mod folders names

Case - insensetive  function needed to check if addon loaded or not.
Syntax: [listOfAddonsFound, "BaS_TSF"] call findString.
Result>=0 means "this addon is active".

 
Code: [Select]
findString={
 private["_c","_i"];
_c=count(_this select 0);
_i=0;
 while {_i < _c} do
{
 if ((_this select 1) == ((_this select 0) select _i)) then {_c=-1} else {_i = _i + 1};
};
if(_c<0) then {_i}else{-1}
};
//////////////////////////

About "mission" in mission name issue - with stringification the problem disapeared,
as far as "space problem" so it was false alarm.
« Last Edit: 30 Jan 2015, 16:24:04 by SoldierEPilot »

Offline faguss

  • Members
  • *
    • Faguss' Website
Re: Fwatch 1.13 for CWA in action
« Reply #12 on: 29 Jan 2015, 20:45:27 »
Quote
I don't think what BIS going to release one more patch.
 Just imagine: 20th OFP anniversary - ACWA 1.999 :

I hope by that time I'll move on.

Quote
6 functions added to readme and 4 of them - realy to CWA...
 I hope it will motivate you a bit.

More like depress.

Quote
this code will find all active addons  and mods:

This is just a list of files and a list of arguments that user passed to the game. It doesn't mean that mods/addons from these lists are loaded. To check for an addon the only way is to use:

Code: [Select]
Format ["%1","objectFromAddon" createCam [0,0,0]] != "<NULL-object>"
; or
localize "stringFromAddon" != ""

As for mods use this code:

Code: [Select]
_find = "private [""_i"", ""_break""]; _i=0; _break=false; while ""!_break"" do {if (_i >= count (_this select 1)) then {_i=-1; _break=true} else {if((_this select 0)==(_this select 1) select _i)then{_break=true}else{_i=_i+1}}};_i"

_selected = call loadFile ":mem modlist"
_folders = call loadFile ":file modlist"

"if ([_x,_folders] call _find == -1) then {_selected=_selected-[_x]}" forEach _selected
« Last Edit: 29 Jan 2015, 22:13:27 by faguss »

Offline SoldierEPilot

  • Members
  • *
Re: Fwatch 1.13 for CWA in action
« Reply #13 on: 30 Jan 2015, 16:30:04 »
"Localize" rulezz, but less then 1/3 of addons have stringtables;

2 main disadvantages of "camCreate":
-Most of the infantry addons have only high-polygon models to check --> perfomance drop;
-Not all addons have cfgAmmo or at least cfgVehicles class in config;

Quote
Code: [Select]
"if ([_x,_folders] call _find == -1) then {_selected=_selected-[_x]}" forEach _selected

forEach doesn't change the length of argument, so that code won't work
properly if there is some misspelling in modnames.

Proof: similar code construction, the result will  be [1,2,3,4].
Code: [Select]
private["_a", "_b"];
_a=[1,2,3,4];
_b=[2,4];
if (_x in _b) then {_a=_a-[_x]} forEach _a;
hint format ["%1", _a];
/////////////////////////////////

The original addons/mods detection sample was fixed, thx 4 tip.

Offline faguss

  • Members
  • *
    • Faguss' Website
Re: Fwatch 1.13 for CWA in action
« Reply #14 on: 30 Jan 2015, 18:49:35 »
Quote
that code won't work properly

It will. I've tested it.

Quote
if (_x in _b) then {_a=_a-[_x]} forEach _a;

That's "if (_x in b) then {_a=_a-[_x]}" forEach _a