OK so I couldn't help myself and tried this for myself. I can get the enemy's classname using typeof, but have no idea how to go from there to digging out the camouflage values from the config. Any further help on this would be much appreciated.
The reason I am interested in this is that I'm still not particularly satisfied with knowsabout, after playing some more with it. I've had cases with myself or squad getting full line of sight on a non camo enemy and knowsabout staying stubbornly on 0 for 30 seconds or more.
EDIT: worked it out
_camo = getnumber (configfile >> "CfgVehicles" >> (typeof _near) >> "Camouflage");
Normal units are 1
Camo units are 0.5
Last edited by tpw; Jun 15 2012 at 09:57.
Try this one on for size.
Thanks to everyone's help I've been able to implement a few things (and fix some bad bugs).
- The script will work for the player's group, whether they are opfor or blufor
- The LOS stuff only kicks in if enemies are closer than 100m. Beyond that, the usual AI FSM, knowsabout etc come into play
- Camouflaged units are ignored by the LOS script. Units will still shoot at snipers, but only if they can see them as part of their usual AI routines.
- I've implemented a kludgy "visibility formula", which takes into account darkness, whether unit has NV, unit movement and enemy movement, plus a bit of randomness. So even if a unit has LOS to an enemy, they may not actually "see" them....
- ...however if any enemies are closer than 25m, the LOS over-rides the visibility formula and units will serve them up a hot lead injection.
Any feedback is welcomed!
PHP Code://UNITS IN PLAYER'S GROUP WILL AUTOMATICALLY KNEEL/CROUCH AND SHOOT IF THEY HAVE LINE OF SIGHT WITH NEAR ENEMIES
// Needs beta 93666 or greater
// Line of sight stuff adapted from SaOk
// Azimuth stuff adapted from CarlGustaffa
// TPW 20120615
private ["_unit","_near","_nearunits","_a","_b","_dirTo","_eyeD","_eyePb","_eyePa","_eyeDV","_ang","_tint","_lint","_vm","_dist","_esp","_usp","_camo","_ka","_formula"];
//Start hint
sleep 1;
hintsilent "TPW / SaOk LOS active";
//Angle of sun - adapted from CarlGustaffa
[] spawn {
private ["_lat","_day","_hour"];
while {true} do
{
_lat = -1 * getNumber(configFile >> "CfgWorlds" >> worldName >> "latitude");
_day = 360 * (dateToNumber date);
_hour = (daytime / 24) * 360;
tpw_los_sunangle = round (((12 * cos(_day) - 78) * cos(_lat) * cos(_hour)) - (24 * sin(_lat) * cos(_day)));
sleep 300;
};
};
//Main function
tpw_los =
{
{
_unit = _x;
_vm = (currentVisionMode _unit); if (_vm == 1) then {_vm = -1} else {_vm = 1};
if (side _unit == east) then {tpw_enemyside = west} else {tpw_enemyside = east};
_nextTime = _unit getVariable ["NextTime", -1];
if(_nextTime == -1) then {_unit setVariable ["NextTime", diag_tickTime + random 1];};
if(diag_tickTime >= _nextTime) then
{
_unit setunitpos "AUTO";
_unit setVariable ["NextTime", diag_tickTime + random 1];
_nearunits = (getposatl _unit) nearentities [["man","car"],100];
{
_near = _x;
tpw_los_cansee = 0;
if (side _near == tpw_enemyside) then
{
//Line of sight stuff adapted from SaOk
_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 = terrainIntersect [_eyePa, _eyePb];
_lInt = lineIntersects [_eyePa, _eyePb];
if (((_ang > 120) && (_ang < 240)) && !(_lInt) && !(_tInt)) then
{
//Other factors affecting visibility of enemy
_ka = _unit knowsabout _near;
_dist = (_unit distance _near);
_esp = abs (speed _near);
_usp = abs (speed _unit);
_camo = getnumber (configfile >> "CfgVehicles" >> (typeof _near) >> "Camouflage");
//Magic visibility formula
_formula = (_vm * (tpw_los_sunangle)) + (_esp * 6) - (_usp * 2) - _dist + random 40;
if (_dist < 25) then {_formula = 200};
if (_camo > 0.5) then {tpw_los_cansee = _formula};
};
};
if (tpw_los_cansee > 0) exitwith
{
_unit setunitpos "MIDDLE";
_unit lookat _near;
_unit dofire _near;
//Debugging
//hint format ["%1 \n%2 \n%3m \n%4",(name _unit),(typeof _near),round (_unit distance _near),round tpw_los_cansee];
};
} foreach _nearunits;
};
} foreach units group player;
};
[tpw_los,0.5] call cba_fnc_addPerFrameHandler;
Last edited by tpw; Jun 15 2012 at 13:14.
Ok, nicely done!
Some further suggestions:
- Allowance for the player/leader to set stance independently of the script (at the moment, I would assume that group stances will automatically revert to "auto", which is likely to break stealth, as well as units perhaps getting up to fire). Perhaps the lines "_unit setunitpos "AUTO";" and "_unit setunitpos "MIDDLE";" should have a condition that they only activate if the unit is set to unitpos "auto", i.e. if the player has specified prone, crouched or standing, the stance changes in the script will not take effect.
- Similarly to the above, support for "hold fire" situations.
- Functionality for independent allied with east, or allied with none (basically all side combinations).
Might think of more later. Oh, here's one:
- Addon version working with all groups, not just that of the player. :P
Sorry, I am a dummy... Where do I put all that code to test this out. It looks really good though. And I agree with Cammcdonald, It will be far easier to see its effectiveness if it is activated for all units.Originally Posted by tpw
You'll need to copy all of the above code, open up the tpw_saok_los_100 PBO and replace the contents of tpw_los.sqf with it, then re-PBO and play.
PM me if you need it done.
Thanks CMcD
As far as I can tell, if the player orders a group to a stance, they hold it even if they have LOS. Only if you set "copy my stance" do they automatically kneel. TBH I'm happy about the kneeling, my initial idea for the LOS script was just to force kneeling as I hate it when units fire standing all the time.
Yes they do break "hold fire", but I find that AI tend to ignore this command regardless of the script. In any case I'm having trouble because combatmode _unit always returns "YELLOW", regardless of whether I have given them a hold fire or not. Will keep investigating that.
Independents easily implemented.
I'm experimenting with an allunits version, will try to iron out the last kinks in that.
---------- Post added at 11:27 ---------- Previous post was at 11:12 ----------
Here's an allunits version
It's set up to only work for opfor or blufor.
if ((side _x == west) || (side _x == east)) then {....
For some reason this statement doesn't fly
if ((side _x == west) || (side _x == east) || (side _x == guer)) then {..
Anyway, give it a try.
Addon version: http://www.gamefront.com/files/21851...OK_LOS_ALL.zip
PHP Code://UNITS IN PLAYER'S GROUP WILL AUTOMATICALLY KNEEL/CROUCH AND SHOOT IF THEY HAVE LINE OF SIGHT WITH NEAR ENEMIES
// Needs beta 93666 or greater
// Line of sight stuff adapted from SaOk
// Azimuth stuff adapted from CarlGustaffa
// TPW 20120616
private ["_unit","_near","_nearunits","_a","_b","_dirTo","_eyeD","_eyePb","_eyePa","_eyeDV","_ang","_tint","_lint","_vm","_dist","_esp","_usp","_camo","_ka","_formula"];
//Start hint
sleep 1;
hintsilent "TPW / SaOk LOS active";
//Angle of sun - adapted from CarlGustaffa
[] spawn {
private ["_lat","_day","_hour"];
while {true} do
{
_lat = -1 * getNumber(configFile >> "CfgWorlds" >> worldName >> "latitude");
_day = 360 * (dateToNumber date);
_hour = (daytime / 24) * 360;
tpw_los_sunangle = round (((12 * cos(_day) - 78) * cos(_lat) * cos(_hour)) - (24 * sin(_lat) * cos(_day)));
sleep 300;
};
};
//Main function
tpw_los =
{
{
if ((side _x == west) || (side _x == east)) then
{
_unit = _x;
_vm = (currentVisionMode _unit); if (_vm == 1) then {_vm = -1} else {_vm = 1};
switch (side _unit) do
{
case east: {tpw_enemyside = west};
case west: {tpw_enemyside = east};
case guer: {tpw_enemyside = east};
//case guer: {tpw_enemyside = west};
};
_nextTime = _unit getVariable ["NextTime", -1];
if(_nextTime == -1) then {_unit setVariable ["NextTime", diag_tickTime + random 1];};
if(diag_tickTime >= _nextTime) then
{
_unit setunitpos "AUTO";
_unit setVariable ["NextTime", diag_tickTime + random 1];
_nearunits = (getposatl _unit) nearentities [["man","car"],100];
{
_near = _x;
tpw_los_cansee = 0;
if (side _near == tpw_enemyside) then
{
//Line of sight stuff adapted from SaOk
_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 = terrainIntersect [_eyePa, _eyePb];
_lInt = lineIntersects [_eyePa, _eyePb];
if (((_ang > 120) && (_ang < 240)) && !(_lInt) && !(_tInt)) then
{
//Other factors affecting visibility of enemy
_ka = _unit knowsabout _near;
_dist = (_unit distance _near);
_esp = abs (speed _near);
_usp = abs (speed _unit);
_camo = getnumber (configfile >> "CfgVehicles" >> (typeof _near) >> "Camouflage");
//Magic visibility formula
_formula = (_vm * (tpw_los_sunangle)) + (_esp * 6) - (_usp * 2) - _dist + random 40;
if (_dist < 25) then {_formula = 200};
if (_camo > 0.5) then {tpw_los_cansee = _formula};
};
};
if (tpw_los_cansee > 0) exitwith
{
_unit setunitpos "MIDDLE";
_unit lookat _near;
_unit dofire _near;
//Debugging
//hint format ["%1 \n%2 \n%3m \n%4\n%5",(name _unit),(typeof _near),round (_unit distance _near),round tpw_los_cansee];
};
} foreach _nearunits;
};
};
}forEach allUnits;
};
[tpw_los,0.5] call cba_fnc_addPerFrameHandler;
Last edited by tpw; Jun 16 2012 at 01:38.
Ah! I should have thought of that. Sorry I am a bit new to this kind of stuff. Thanks for the help and offer for help, I think I should be able to manage that.Originally Posted by CameronMcDonald
--edit--
doa! Just de/re pbo'd it and then realized tpw had upldated and uploaded a new pbo. Thanks tpw, I'm going to give it a rip as soon as I get time.
Simply marvelous. I had taken a crack at CQB AI just about a year ago, but I ended up spending most of the efforts in developing my own LOS system using invisible bullets. In fact, by the time I had finished developing that system, I thought I had quite enough of that so I held it off. Never got back into it. But now, with this new system, I can definitely resume my work, although tpw here has done a wonderful job with his own script. I'll definitely give it a try and report back. Thanks for all your hard work!
Should be:(side _x == guer)
or:Code:(side _x == resistance)
Very, very fascinating is all this. Can't wait for 1.61 official.Code:((str (side _x)) == "GUER")
Spoiler: