|
Post by Sa8Gecko on Oct 24, 2004 2:32:11 GMT -5
What follows are the commented beta 2.5 functions. Please give me some time to complete the project, as there are a lot of function to comment. A further reference may be found in this thread: psyproductions.proboards21.com/index.cgi?board=ScriptDis&action=display&thread=1086124622even as the functions described there are somewhat outdated. EDIT> nov. 4th, 2004 Some of the functions have been rewritten and optimized, and some others have been added, mostly regarding the Gaskin. The new code should be less CPU intensive too. EDIT> jan. 7th, 2005 Modified some of the functions shown below to reflect latest changes. Work is still in progress.
|
|
|
Post by Sa8Gecko on Oct 24, 2004 2:40:11 GMT -5
I'll start with the ones contained in the ...psy_mcar_scripts\at subdirectory. Excuse the lack of indentation, but this is due to the forum software which removes them.
PSY_MCAR_createProxyAT.sqf called by: the init eventhandler, repair.sqs,
; by Unnamed ; populates the vehicle with the proxy gamelogics used to calculate ; firing direction, find a target, adjust aim etc.
private ["_vehicle","_logics","_count","_void"];
_Vehicle=_this select 0;
_Count=0; _Logics=[];
while "_Count<3" do { _Logics=_Logics+["psy_mcar_logic" createVehicle [0,0,0]]; _Count=_Count+1; };
{_x moveInCargo _Vehicle} forEach _Logics;
_Count=0;
while "_Count<1" do { (_Logics select _Count) setPos [0,0,0]; deleteVehicle (_Logics select _Count); _Count=_Count+1; };
_void;
PSY_MCAR_deflection.sqf called by: guidmis7.sqs
; this function is used to calculate the distance as regard to the current missile ; position to which place the fake emptydetector target. This distance is set at 300 meters ; (default) if the aim has not moved as regard to the previous time this function was executed ; ; Usage: [3D array,3D array,object] call deflection ; ; returns: a number
private ["_ntpxy","_ntpxyOld","_displ","_missile"];
; _ntpxyold and _ntpxy are the previous aiming direction and the current one respectively _ntpxyold = _this select 0; _ntpxy = _this select 1; _missile = _this select 2; _displ = 300;
; if the aim direction has changed, the target is positioned nearer to the missile, so that the missile ; itself would appear to follow the aiming direction more swiftly and accurately. The '.40' value is ; the one to modify to achieve more or less steering by the missile: the displacement value is calculated ; accordingly to missile speed. That is, the .40 value dimension is a time one. Don't decrease it too much ; (less than .20) to evitate the missile to overshoot the fake target if ((_ntpxy select 0 != _ntpxyOld select 0) || (_ntpxy select 1 != _ntpxyOld select 1) || (_ntpxy select 2 != _ntpxyOld select 2)) then { _displ = (abs(speed _missile)/3.6) * .40; }; _displ
PSY_MCAR_dir.sqf called by: guidmis4.sqs (the tow2b terrain following guidance code)
; this function calculates the new direction to give the missile to hit the target ; ; Usage: [object1, object2] call dir ; ; returns: an array [number,boolean]
private ["_missile","_target","_dirMis","_newDir","_flag"]; _missile = _this select 0; _target = _this select 1; _flag = 0; _dirMis= direction _missile;
; the following calculation uses a little lead to predict the future position of the target ; and so raising the hit probability against a moving target _newDir = ((position _target select 0)+((velocity (_target) select 0)*.03) - (position _Missile select 0)) atan2 ((position _target select 1)+((velocity (_target) select 1)*.03) - (position _Missile select 1));
; the following lines make the angles consistent with each other, to evitate that, for example, a +5 ; value against a -355 one will make the following angle on target check assume the missile is ; completely off target, while in reality there's only a 10 degree difference between the two ; trajectories if (_newDir< 0) then { _newDir = _newDir +360; }; if (abs(_newDir - _dirMis) > 180 && _newDir < _dirMis) then { _newDir = _newDir + 360; }; if (abs(_newDir - _dirMis) > 180 && _newDir > _dirMis) then { _dirMis = _dirMis + 360; };
; this is the check to control if the directions of missile and target differ more than a certain ; angle (in this case 45 degrees) and so consider the missile to having lost target. In this case ; _flag is set to one if (abs(_newDir - _dirMis) > 45) then { _flag = 1; };
; the following checks if the new direction the missile should assume to hit the target is more ; than 3 degrees: in this case +- 3 degres are added (depending if the missile should steer right or ; left) if (abs (_newDir - _dirMis) > 3) then { _newDir = _dirMis + (((_newDir - _dirMis)/abs(_newDir- _dirMis))*3); };
; the following two lines should be condensed in '[_newdir - _dirMis,_flag]', eliminating a variable [_newdir - _dirMis,_flag]
|
|
|
Post by Sa8Gecko on Oct 24, 2004 2:43:55 GMT -5
PSY_MCAR_discriminate.sqf called by: search2.sqf (the real humvees search routine)
; this function choose which target among the ones passed by search2.sqf is the one to choose ; to attack ; ; Usage: object call discriminate ; ; returns: an object
private ["_angleS","_angleSOld","_pStrueH","_curtarget","_theight","_actualtarget","_svect","_cfx","_pCT","_loopcounter"];
; this value determine the 'accuracy' of the aim, that is the less this value, the more the crosshair ; should be put over the desired target to achieve a 'missile lock'. That's why is so important to keep ; initspeed of the fake bullet in the config.cpp file at least at 15'000 m/s _angleSOld = .0045;
_actualTarget = _this; _loopcounter = _exitLoop -1; _pStrueH = _shooter call PSY_MCAR_calch;
; the following is the core of the function: the various targets contained in _tarArray are examined ; and the one which 3D direction as regard to the shooter more approaches the aiming direction is ; choosen. Take note that anyway if no one is inside the _anglesold value, no target is choosen while "_loopcounter >= 0" do { _curtarget = _tarArray select (_loopcounter*3); _theight = _tarArray select ((_loopcounter*3) +1); _pCT = position _curtarget;
; _cfx is a coefficient by which is multiplied _anglesOld to take into consideration that the ; nearer the target is to the shooter, the more it will fill the solid angle determined by _anglesOld: ; that is for a very near target you don't have to aim directly at the center of it for it to be ; acquired _cfx = 1 + (1/((_curtarget distance _shooter)^2 / 150000)); if ("Air" countType [_curtarget]>0) then {_cfx =_cfx *1.25;}; _svect =[(_pCT select 0) - ((_ammopos select 0) select 0),(_pCT select 1) - ((_ammopos select 0) select 1),_theight - ((_ammopos select 0) select 2) + _pStrueH] call PSY_MCAR_vNorm;
; calculation of the solid angle between the current target and the aiming direction _angleS =sqrt( ((_svect select 0)-((_ammopos select 1) select 0))^2 + ((_svect select 1)-((_ammopos select 1) select 1))^2 + ((_svect select 2)-((_ammopos select 1) select 2))^2); if (_angleS < (_angleSOld*_cfx)) then { _actualTarget = _curtarget; _angleSOld = _angleS; }; _loopcounter = _loopcounter -1; };
_actualtarget
PSY_MCAR_distXY.sqf called by: guidmis4.sqs. guidmis7.sqs
; this function calculates the 2D distance between the two object passed. ; The calculation is pretty straightforward so it's uncommented ; ; Usage: ; [object1,object2] call distXY ; ; returns: a number - the distance in the xy plane between the two position passed as parameters
private ["_Targetpos","_Missilepos"]; _Targetpos = position (_this select 1); _Missilepos = position (_this select 0); sqrt ((((_Targetpos select 0) - (_Missilepos select 0)) ^ 2) + (((_Targetpos select 1) - (_Missilepos select 1)) ^ 2))
|
|
|
Post by Sa8Gecko on Oct 24, 2004 4:18:02 GMT -5
PSY_MCAR_jet.sqf called by: guidmis7.sqs
; This function substitute the missile with the 'killing' bullet for the tow2a real ; (the function name is somewhat misleading) ; ; Usage: object call jet ; ; returns: an object
private ["_bullet","_misPos","_misVel","_misDir","_misz"];
; the killing bullet is searched in a position where it should have been ; placed when fired (nor the AI neither the human player should be aware of the ; trick) _bullet = nearestObject [0,0,3980];
; if the bullet is found, the missile is substituted by it, conserving position, ; velocity and direction (velocity is meant as the 3D velocity vector) if (alive _bullet) then { _misPos = getpos _missile; _misVel = velocity _missile; _misDir = direction _missile; _misz = - (_missile call PSY_MCAR_calcH);
deletevehicle _missile; _bullet setPos [_misPos select 0,_misPos select 1,(_misPos select 2)+_misz] ; _bullet setvelocity _misVel; _bullet setdir _misDir; _missile = _bullet; }; _missile
PSY_MCAR_launchMissile.sqf called by: fired2.sqs, fired3.sqs
; this function launches the tow missile and modify the textures on the launcher to ; make it appear as empty. ; ; Usage: [object,3D array,3D array,string] call launchAT ; ; returns: an object
private ["_shooter","_heightShooter","_MCOP","_velmod","_misType","_missile","_vNormSh","_vCf"];
; _MCOP is the missile creation position, taken by the gamelogic position (so don't place ; them inside the weapon, or behind it) ; _velmod (name misleading) is the direction of firing, while _misType is a string containing ; the missile type to be launched (tow2a or tow2b, which differ in appearance) _shooter =_this select 0; _MCOP = _this select 1; _velmod = _this select 2; _misType = _this select 3;
; the next parameter is used in case the missile is fired from a bridge or the top of ; a building _heightShooter = _shooter call PSY_MCAR_hShooter; _vNormSh = velocity _shooter call PSY_MCAR_vNorm;
; now the solid angle between firing direction and shooting vehicle direction is calculated, and ; if found to be less than a certain value (0.30) the coefficient (_vCf) by which the creating ; position displacement is multiplied is set to 2 (normally to 1) if ( sqrt( ((_vNormSh select 0) - (_velmod select 0))^2 + ((_vNormSh select 1) - (_velmod select 1))^2 + ((_vNormSh select 2) - (_velmod select 2))^2) < .30 && speed _shooter > 25) then {_vCf = 2;} else {_vCf = 1;}; _missile= _misType createvehicle[(_MCOP select 0) + (_velmod select 0)*_vCf ,(_MCOP select 1) + (_velmod select 1)*_vCf,(_MCOP select 2) + (_velmod select 2)*_vCf + _heightShooter];
; the nissile direction is calculated accordingly to the firing direction _missile setdir ((_velmod select 0) atan2 (_velmod select 1));
; the initial velocity is 75 m/s multiplied by the current firing direction: to this result the velocity ; of the shooting vehicle is added _missile setvelocity [(75 *(_velmod select 0)) + (velocity _shooter select 0),(75 * (_velmod select 1)) + (velocity _shooter select 1), (75 * (_velmod select 2)) + (velocity _shooter select 2)];
; next two lines 'empty' the launch tube vehicle _shooter setObjectTexture [0,""]; vehicle _shooter setObjectTexture [1,""]; _missile
PSY_MCAR_meters.sqf called by: guidmis7.sqs
; this function calculates the meters travelled by the missile since its launch ; ; usage: [[number,3D array,number],object,number] call meters ; ; returns: an array [number, 3D array,number]
private ["_meters","_missilePos","_misPos","_zprev","_znow"];
; _meters is the number of meters travelled so far, while _missilePos is ; the missile current position _meters = (_this select 0) select 0; _missilePos = position (_this select 1);
; _misPos is the previous missile position (the one sent back by this same function) _misPos = (_this select 0) select 1;
; now follows the distance calculation between the previous position and the current one ; and the result is added to _meters (absolute height above sea level is used) _zprev = (_this select 0) select 2; ; (_this select 2) contains the height above sea level of the location ; just under the missile _znow = (_this select 2) + (_missilePos select 2); _meters = _meters + sqrt ( ((_missilePos select 0)-(_misPos select 0))^2 + ((_missilePos select 1)-(_misPos select 1))^2 +(_znow - _zprev)^2);
; the meters travelled so far and the current missile position are returned, so that ; they can be used next time the function is called [_meters,_missilePos,_znow]
|
|
|
Post by Sa8Gecko on Oct 24, 2004 6:21:12 GMT -5
PSY_MCAR_noCrewInHumvee.sqf called by: getammo2.sqs, getammo3.sqs, guidmis2.sqs, guidmis3.sqs, guidmis4.sqs, search2.sqf
; by Unnamed ; this function is the union of getlaunch.sqf and createproxyAT.sqf ; it's used when the vehicle is damaged in a way it can no longer ; move and so FlashPoint engine expels all the crew from the vehicle ; (gamelogic included), so we need to repopulate the vehicle if the ; player has entered it to use the weapon ; ; usage: object call noCrewInHumvee ; ; returns: an array [3D array,3D array]
private ["_vehicle","_logics","_count","_logiccount","_pos1","_pos2","_dummyobj","_hasl1","_hasl2"];
_Vehicle=_this select 0;
_Count=0; _Logics=[];
while "_Count<3" do { _Logics=_Logics+["psy_mcar_logic" createVehicle [0,0,0]]; _Count=_Count+1; };
{_x moveInCargo _Vehicle} forEach _Logics;
_Count=0;
while "_Count<1" do { (_Logics select _Count) setPos [0,0,0]; deleteVehicle (_Logics select _Count); _Count=_Count+1; };
_Logics=+(crew _Vehicle); _LogicCount=(count _Logics); if (_vehicle distance (_Logics select (_LogicCount-1)) < _vehicle distance (_Logics select (_LogicCount-2))) then { _Pos2=position (_Logics select (_LogicCount-1)); _Pos1=position (_Logics select (_LogicCount-2)); } else { _Pos1=position (_Logics select (_LogicCount-1)); _Pos2=position (_Logics select (_LogicCount-2)); }; _dummyobj = "EmptyDetector" createVehicle [0,0,0];
_dummyobj setpos [_pos1 select 0, _pos1 select 1, 0]; _hasl1 = position _dummyobj select 2; _dummyobj setpos [_pos2 select 0, _pos2 select 1, 0]; _hasl2 = position _dummyobj select 2; deletevehicle _dummyobj;
; the position of the most distant gamelogic and the firing direction (not normalized) are returned [_Pos1,[(_Pos1 select 0)-(_Pos2 select 0),(_Pos1 select 1)-(_Pos2 select 1),((_Pos1 select 2) - _hasl1)-((_Pos2 select 2) - _hasl2)]]
PSY_MCAR_realbullet.sqf called by: fired eventhandler
; this function takes the killing bullet just fired by the tow2b real ; and move it in a (should be) safe place to be used later, so that the ; (eventual) kill can appear in the stats sheet ; ; usage: in the fired eventhandler ; [object,string,number] call realbullet ; where object is the shooting vehicle, string is the ammunition type being fired ; and number is the height to which place the bullet ; ; returns: nothing
private ["_bullet"]; _bullet = nearestObject [_this select 0, _this select 1]; _bullet setpos [0 + (random 10),0,_this select 2]; _bullet setVelocity [0,0,2];
PSY_MCAR_removeInv.sqf called by: init eventhandler
; by HateR_Kint ; this function removes the weapon used to fire the killing bullet from the shooting ; vehicle, so that the human player or the AI cannot use it. ; ; it's called by some of the vehicles init eventhandler, because not all the vehicles ; have it as standard dotation. Will be revised/removed in version 1.0
private ["_shooter"]; _shooter = vehicle (_this select 0);
if (_shooter hasWeapon "psy_mcar_invWeapon") then { _shooter removeWeapon "psy_mcar_invWeapon"; };
|
|
|
Post by Sa8Gecko on Oct 24, 2004 6:26:31 GMT -5
PSY_MCAR_search.sqf called by: guidmis2.sqs, guidmis3.sqs, guidmis4,sqs
; this function is the search routine for the tow2a and tow2b (non real) missiles. ; ; usage: [number,number,3D array,object] call search ; ; returns: object
private ["_ivel","_jvel","_posArray","_missilePos","_target","_iter","_exitLoop","_i"];
; _ivel and _jvel are the x,y components of the missile direction (velocity) vector _ivel = _this select 0; _jvel = _this select 1;
; _missilePos is an array containing the missile position _missilePos = _this select 2;
; _iter is the displacement from missile position in which a suitable target is searched. ; It's incremented by 15 meters each time the following loop is executed, till it reaches ; 300 meters _iter = 30;
; _exitloop is a boolean that is set to 1 if a target has benn found, so to exit the loop _exitLoop = 0;
; _posArray contains four 2D (xy plane) directions along which, at increment of _iter meters from the ; missile actual position, a target is searched. This four direction differ by the missile's current ; one by 3,-3,9,-9 degrees rispectively _posArray = [_ivel * cos(3) + _jvel * sin(3), - _ivel * (sin(3)) + _jvel * cos(3),_ivel * cos(-3) + _jvel * sin(-3),- _ivel * sin(-3) + _jvel * cos(-3),_ivel * cos(9) + _jvel * sin(9),- _ivel * sin(9) + _jvel * cos(9),_ivel * cos(-9) + _jvel * sin(-9),- _ivel * sin(-9) + _jvel * cos(-9)]; while "_iter < 301 && _exitLoop == 0" do { _i=0;
; _i is used as index for _posArray while "_i < 8 && _exitLoop == 0" do { _Target = nearestObject [(_missilePos select 0) + (_iter * (_posArray select _i)),(_missilePos select 1) + (_iter * (_posArray select (_i+1))),12]; if ("LandVehicle" countType [_Target] > 0 && damage _target < .99 && side _target != west) then { _exitLoop = 1; }; _i = _i+2; };
_iter=_iter + 15; };
; if no target is found, the shooting vehicle (passed as the 4th parameter) is returned if (_exitLoop == 0) then { _target = _this select 3; }; _target
PSY_MCAR_search2.sqf called by: guidmis7.sqs
; this is the tow2a real and tow2b real search routine. It's more sophisticated than ; search.sqf, and more accurate ; ; usage: [object,object] call search2 ; ; returns: an array [object,3d array] ; the object is the target (or the shooting vehicle if none is found) and the ; 3d array contains the aiming direction that will be used by guidmis7.sqs to ; place the next fake target (if no target has been acquired)
private ["_ivel","_jvel","_kvel","_nPos","_ammoPos","_dummy","_vnorm","_posArray","_missile","_shooter","_missilePos","_zshooter","_zrelative","_target","_iter","_exitLoop","_i","_tarArray","_zmissile","_zpos","_isnot","_k"];
_missile = _this select 0; _missilePos = position _missile; _shooter = _this select 1; _vnorm = velocity _missile call PSY_MCAR_vNorm;
; the following three parameters are the component of the missile velocity vector and are ; used to search the target _ivel = _vnorm select 0; _jvel = _vnorm select 1; _kvel = _vnorm select 2; ; if the vehicle can or cannot move, the proper function is executed, which returns the ; aiming direction if (canMove _shooter) then {_ammoPos = ([_shooter] call PSY_MCAR_getLaunch);}; if ( !(canMove _shooter)) then {_ammoPos = ([_shooter] call PSY_MCAR_noCrewInHumvee);};
; this aiming direction is then normalized _nPos = (_ammoPos select 1) call PSY_MCAR_vNorm;
; initial step is set to 20 meters from the missile _iter = 20; _exitLoop = 0; _dummy = "EmptyDetector" createVehicle [0,0,0];
; _tarArray will contain all the targets found (up to 7) and their parameters used by discriminate.sqf _tarArray = [];
; _posArray contains three 3D directions along which the target is searched, each spaced 5 degrees _posArray = [_ivel,_jvel,_kvel,_ivel * cos(5) + _jvel * sin(5), - _ivel * (sin(5)) + _jvel * cos(5),_kvel,_ivel * cos(-5) + _jvel * sin(-5),- _ivel * sin(-5) + _jvel * cos(-5),_kvel]; _zmissile = - (_missile call PSY_MCAR_calcH) + (_missilePos select 2);
; next loop is executed until the distance from missile (_iter) reaches 95 meters or ; seven targets have been found while "_iter < 95 && _exitLoop < 7" do {
; _i is used as index for _posArray and to misplace the search positions along each direction a bit _i=0;
; next loop is executed three times each time by the outer loop or until the 7th target has been found while "_i < 9 && _exitLoop < 7" do { _dummy setpos [(_missilePos select 0) + (_iter * (_posArray select _i)),(_missilePos select 1) + (_iter * (_posArray select (_i+1))),0]; _zrelative = - (_dummy call PSY_MCAR_calcH); _zpos = ((_iter+_i) * (_posArray select (_i+2))) + _zmissile - _zrelative;
; next checks if the z position is between -18 and +8 meters as regard to ground level and set it to 8 ; to succesfully locate a target, if any, otherwise this could evade the search even if the position ; searched is the right one if (_zpos < 8 && _zpos > -18) then { _zpos = 8;}; _Target = nearestObject [(_missilePos select 0) + ((_iter+_i) * (_posArray select _i)),(_missilePos select 1) + ((_iter+_i) * (_posArray select (_i+1))),_zpos];
; if an object that is not of western side is found (IFF ?) this is achieved as target and stored ; in _tarArray if (("LandVehicle" countType [_Target] > 0 || "Air" countType [_Target] > 0) && damage _target < .99 && side _target != west) then {
; if the target found is the first of the list then it's placed in _tarArray if (_exitLoop == 0) then { _tarArray set [0,_target]; _tarArray set [1,-(_Target call PSY_MCAR_calcH) + ((position _target) select 2)]; _tarArray set [2,_Target distance _missile];
_exitLoop = _exitLoop +1; } else
; otherwise it is compared to the stored ones and if found equal to another already ; present in the array it is rejected. _isnot is the boolean controlling this (it is ; set to one if the target examined is already present in _tarArray) { _isnot = 0; _k = _exitLoop -1; while "_isnot == 0 && _k >= 0" do { if (_Target == _tarArray select (_k*3)) then { _isnot = 1;}; _k=_k -1; }; if (_isnot == 0) then { _tarArray set [(_exitLoop*3),_target]; _tarArray set [(_exitLoop*3) +1,-(_target call PSY_MCAR_calcH) + ((position _target) select 2)]; _tarArray set [(_exitLoop*3) +2,_target distance _missile];
_exitLoop = _exitLoop +1; }; }; }; _i = _i+3; };
_iter=_iter + 12; };
; if no target has been found (_exitloop equals to zero) the shooting vehicle is returned, ; otherwise the target will be chosen among the ones found by discriminate.sqf if (_exitLoop == 0) then { _Target = _this select 1; } else { _target = _shooter call PSY_MCAR_discriminate; }; deletevehicle _dummy; [_target,_nPos]
|
|
|
Post by Sa8Gecko on Oct 24, 2004 11:26:17 GMT -5
PSY_MCAR_slug.sqf called by: guidmis_4.sqs,guidmis_7.sqs
; this function is used to generate the jet of the shaped charge warhead for the tow2b ; ; usage: [object,object] call slug ; ; returns: nothing
private ["_target","_missile","_dist","_startpos","_misz","_dx","_dy","_tarz","_dz","_veltar","_bullet1","_bullet","_void"]; _target = _this select 1; _missile = _this select 0;
; the killing bullet, fired previously by firedummy.sqs, should be somewhere ; around this position _bullet = nearestObject [0,0,4980];
; next some particle effect is generate drop ["cl_fire", "", "Billboard", 3, 1, [0,0,0], [0,0,0], 2, 3, 2.4, 0, [0.5,3,1], [[1,0.7,0,0.8],[1,0.7,0,0.8],[1,0.7,0,0]], [0,1,0], 2, 2, "", "", _missile]; drop ["cl_basic", "", "Billboard", 5, 4, [0,0,0], [0,0,0], 2, 6, 4.8, 0, [1,6,7], [[0.4,0.4,0.4,0.95],[0.4,0.4,0.4,0.8],[0.4,0.4,0.4,0]], [0,1], 5, 0, "", "", _missile]; drop ["cl_fire", "", "Billboard", 3, 2.5, [0,0,0], [10,10,5], 2, 3, 0.4, 0, [0.2,0.3,0], [[0.7,1,0,0.9]], [0,1,0], 2, 2, "", "", _missile]; drop ["cl_fire", "", "Billboard", 3, 2.5, [0,0,0], [-10,-10,5], 2, 3, 0.4, 0, [0.2,0.3,0], [[0.7,1,0,0.9]], [0,1,0], 2, 2, "", "", _missile]; drop ["cl_fire", "", "Billboard", 3, 2.5, [0,0,0], [12,12,2], 2, 3, 0.4, 0, [0.2,0.3,0], [[0.7,1,0,0.9]], [0,1,0], 2, 2, "", "", _missile]; drop ["cl_fire", "", "Billboard", 3, 2.5, [0,0,0], [-12,-12,2], 2, 3, 0.4, 0, [0.2,0.3,0], [[0.7,1,0,0.9]], [0,1,0], 2, 2, "", "", _missile];
_dist = _target distance _missile; _startpos = position _missile; _misz = -(_missile call PSY_MCAR_calcH) + (_startpos select 2);
; the missile is deleted because it will no more be used as the kill will be achieved by ; the '_bullet' object deletevehicle _missile;
; _dx,_dy,_dz are the component of the missile to target direction vector _dx = (((position _target select 0) - (_startpos select 0))/_dist); _dy = (((position _target select 1) - (_startpos select 1))/_dist); _tarz = -(_target call PSY_MCAR_calcH) + (position _target select 2); _dz = ((_tarz - _misz)/_dist) ;
; modvel will be the velocity vector of the bullet that will be fired to the target _modvel = [_dx *1200,_dy*1200,_dz*1200];
; _veltar will be added to _modvel to compensate for a moving target _veltar = velocity _target; if (alive _bullet) then { _bullet setpos [_startpos select 0,_startpos select 1,_misz]; _bullet setvelocity [(_modvel select 0) + (_veltar select 0),(_modvel select 1) + (_veltar select 1),(_modvel select 2) + (_veltar select 2)]; } else
; if the bullet fired by firedummy.sqs has not been retrieved, one is created in its place: ; sorry, but this way the kill will not be recorded { _bullet1 = "RKT_Slug" camcreate _startpos; _bullet1 setvelocity [(_modvel select 0) + (_veltar select 0),(_modvel select 1) + (_veltar select 1),(_modvel select 2) + (_veltar select 2)]; };
_void;
PSY_MCAR_smokerAT.sqf called by: fired2.sqs, fired3.sqs
; this function generates the smoke during the launch of the missile ; there's not much to say, it's a particle effect ; ; usage: [_array,_array] call smokerAT ; ; returns: nothing ; the first array is the missile creating position, the second one is the direction ; of firing
private["_void"]; drop ["cl_basic", "", "Billboard", 7, 6, [(_this select 0) select 0,(_this select 0) select 1,(_this select 0) select 2], [-((_this select 1) select 0),-((_this select 1) select 1),-((_this select 1) select 2)], 2, .85, 0.7, 0, [0.2,7,12], [[0.75,0.75,0.75,0.95],[0.75,0.75,0.75,0.9],[0.75,0.75,0.75,0]], [1,1], 5, 0, "", "",""]; drop ["cl_basic", "", "Billboard", 7, 6, [(_this select 0) select 0,(_this select 0) select 1,(_this select 0) select 2], [-((_this select 1) select 0)*5.1,-((_this select 1) select 1)*5.1,-((_this select 1) select 2)*5.1], 2, 0.84, 0.7, 0.02, [.2,9,15], [[0.8,0.8,0.8,0.95],[0.8,0.8,0.8,0.9],[0.8,0.8,0.8,0]], [1,1], 5, 0, "", "",""]; drop ["cl_basic", "", "Billboard", 7, 6, [(_this select 0) select 0,(_this select 0) select 1,(_this select 0) select 2], [-((_this select 1) select 0)*5,-((_this select 1) select 1)*5,-((_this select 1) select 2)*5], 1, .8925, 0.7, 0.02, [0.5,6,12], [[0.7,0.7,0.7,0.95],[0.7,0.7,0.7,0.9],[0.7,0.7,0.7,0]], [1,1], 5, 0, "", "",""]; drop ["cl_basic", "", "Billboard", 8, 7, [(_this select 0) select 0,(_this select 0) select 1,(_this select 0) select 2], [-((_this select 1) select 0)*5.4,-((_this select 1) select 1)*5.4,-((_this select 1) select 2)*5.4], 2, .88, 0.7, 0.01, [0.2,8,12], [[0.8,0.8,0.8,0.95],[0.8,0.8,0.8,0.9],[0.8,0.8,0.8,0]], [1,1], 5, 0, "", "",""]; drop ["cl_basic", "", "Billboard", 9, 8, [(_this select 0) select 0,(_this select 0) select 1,(_this select 0) select 2], [-((_this select 1) select 0)*4.7,-((_this select 1) select 1)*4.9,-((_this select 1) select 2)*4.9], 2, .885, 0.7, 0.03, [0.2,5,11], [[0.85,0.85,0.85,0.95],[0.85,0.85,0.85,0.9],[0.85,0.85,0.85,0]], [1,1], 5, 0, "", "",""];
_void;
PSY_MCAR_stayAfloat.sqf called by: fired2.sqs
; not much to say about this function too: ; it should keep the missile from impacting the ground during the first ; moments after its launch ; ; usage: object call stayAfloat ; ; returns: nothing
private["_void"]; if ((getpos _this select 2) < 1.8) then { _this setvelocity [velocity _this select 0,velocity _this select 1,(velocity _this select 2) +1]; };
_void;
PSY_MCAR_subs.sqf called by: fired2.sqs, fired3.sqs
; this function is used to substitute the missile just launched, which ; will do little damage if it impacts a target, with the 'real' one ; at about 60 meters from the launching vehicle ; ; usage: [object, string] call subs ; ; returns: an object ; the object passed to the function is the low damage missile, and the string ; is the missile type to be crate in place of the previous missile. ; then this newly created missile is sent back to the calling script
private ["_missile","_misDir","_misPos","_misVel","_misType"]; _missile = _this select 0; _misType = _this select 1;
; the missile flying parameters are stored in some variables, then it is ; deleted and a new one created in its place, assigning to it the same ; flying parameters. If the missile type was not specified, it is assumed ; is the tow2a model the one to be create if (format ["%1",_misType] == "<null>") then {_misType = "psy_mcar_tow2a";};
_misPos = getpos _missile; _misVel = velocity _missile; _misDir = direction _missile; deletevehicle _missile; _missile = _misType createVehicle _misPos; _missile setvelocity _misVel; _missile setdir _misDir; _missile
|
|
|
Post by Sa8Gecko on Oct 24, 2004 11:32:44 GMT -5
PSY_MCAR_targetpos.sqf called by: guidmis_7.sqs
; this function is used to calculate at which angle the missile should be ; rotated as regard to its current direction to hit the target. It is a lead ; collision routine, that is it will try to predict the target future position ; and modify the missile trajectory accordingly, guiding it to the impact point ; instead of the current position of the target itself. ; ; usage: [object,object,time] call targetpos ; ; returns: an array [number,time] ; where the number returned is the angle to which steer the missile, and the time ; is used again in the next call to this same function to calculate the max angle ; admitted for turning (we don't want the missile to execute sudden turns at 90 degrees...)
private ["_missile","_target","_gamma","_alpha","_beta","_delta","_misTime","_angle"]; _missile = _this select 0; _target = _this select 1; _misTime = _this select 2;
; _delta is the angle formed by the missile velocity vector (that is, its direction) _delta = (velocity _missile select 0) atan2 (velocity _missile select 1);
; next its value is made positive, if it is not if (_delta < 0) then {_delta = _delta +360;};
; _alpha is the angle between the target and the missile (that is, the missile ; 'sees' the target at this angle as regard to its position looking towards the north direction in OFP world ; north direction in OFP world cohordinates _alpha = ((position _target select 0) - (position _missile select 0)) atan2 ((position _target select 1) - (position _missile select 1));
; _alpha is set positive, if not, to keep it consistent with -delta if (_alpha < 0) then {_alpha = _alpha +360;};
; next two lines are used to evitate results that will deviate the missile the ; wrong way if (abs(_alpha - _delta) > 180 && _alpha < _delta) then {_alpha = _alpha +360;}; if (abs(_alpha - _delta) > 180 && _alpha > _delta) then {_delta = _delta +360;};
; if the target is in motion, a further angle is calculated, that is _beta, ; otherwise the same _beta is set equal to _alpha if (speed _target != 0) then {
; the explanation of the following two lines can be found out drawing a picture of ; the missile and target with their velocity vector. For semplicity, trust me: they work. ; _beta is the additional angle to add to _alpha to steer the missile to the calculated ; impact point, rather than to the target itself _gamma = 90 - ((velocity _target select 0) atan2 (velocity _target select 1)); _beta = asin ( ((speed _target)/(speed _missile))* sin(_alpha + _gamma + 90) ) + _alpha; } else { _beta = _alpha; };
; the angle of steering is found subracting _delta to _beta (try to visualize the ; velocity vector of the missile to understand this operation) _angle = _beta - _delta;
; of course, we can no permit sharp turns, so if _angle value is more than the ; admitted turning rate (here 30 deg/s), it is set to the maximum value it could have ; during the elapsed time from the previous callto this function. ; i.e.: if the function was called previously 1/10th of a second before the actual ; moment, the missile could not have turned more than 30/10 = 3 degrees. if (abs (_angle) > (30 * (_time - _misTime))) then {_angle =(_angle/abs(_angle))*(30 * (_time - _misTime));};
; the actual time is sent back to the calling function or script along with the angle ; so that we can calculate the elapsed time since the last call to this same function ; and so the max value that _angle can achieve (see above) [_angle,_time]
PSY_MCAR_towspeed.sqf called by: guidmis_3.sqs, guidmis_7.sqs
; this function simply set the missile speed accordingly to a realistic velocity vs distance ; travelled curve stored in -velArray ; ; usage: [time] call towspeed ; ; returns: a number (the speed to be assigned to the missile) ; be careful to note that this function sets only the speed of the missile, ; not its velocity vector
private ["_speed","_misTime","_velArray","_i","_mis2Time"];
; _velArray contains the velocity curve approximate to a serie of segments for ; the first 20 seconds (the curve can not easily be represented with a simple ; function, so I chose to approximate it with line segments) ; the even elements in the array are the starting velocities at 0,2,4... seconds, ; the odd ones are the acceleration at 0,2,4,... seconds. Take note that the ; array starts with element 0 (zero) _velArray = [70,105,280,-25,230,-12.5,205,-12.5,180,-7.5,165,-7.5,150,-5,140,-5,130,-5,120,-5,112,-4,104,-4]; _misTime = _this;
; the following calculation gives us the index to retrieve the exact array element ; after (_time - _mistime) seconds have passed since launch _i = ((_time - _misTime)/2) - (((_time - _misTime)/2) mod 1); if (_i > 11) then { _i = 11;};
; next the right speed is set and returned to the calling script ; we need to subtract _i*2 seconds to (_time - _mistime) because as ; told before _velArray already contains the speed at 0,2,4... seconds: ; this way we are more sure the missile follows the right velocity vs ; distance curve rather than we would have simply added the various ; acceleration*time from the start _mis2Time = (_time - _misTime) - _i*2; _speed = (_velArray select (_i*2)) + (_velArray select ((_i*2) +1))*_mis2Time; _speed
PSY_MCAR_trail2.sqf called by: guidmis_7.sqs
; this function generates the missile trail. There's not much to say ; other than the velocity of the missile is used to generate the various ; puffs of smoke in the right direction (so they don't lie all on the ; horizontal plane) ; ; usage: object call trail2 ; ; returns: nothing
private ["_misvel","_void"]; _misvel = (velocity _this) call PSY_MCAR_vNorm; drop ["MissileSmoke", "", "Billboard", 5, 4, [0,-.8,-0.8*(_misvel select 2)], [0,0,0], 2, 0.8925, 0.7, 0, [0.15,0.75,1], [[0.7,0.7,0.7,0.01],[0.7,0.7,0.7,0.015],[0.7,0.7,0.7,0]], [1,1], 5, 0, "", "", _this]; drop ["MissileSmoke", "", "Billboard", 5, 4, [0,-1.3,-1.3*(_misvel select 2)], [0,0,0], 2, 0.8925, 0.7, 0, [0.15,0.75,1], [[0.7,0.7,0.7,0.01],[0.7,0.7,0.7,0.015],[0.7,0.7,0.7,0]], [1,1], 5, 0, "", "", _this]; drop ["MissileSmoke", "", "Billboard", 5, 4, [0,-1.8,-1.8*(_misvel select 2)], [0,0,0], 2, 0.8925, 0.7, 0, [0.15,0.75,1], [[0.7,0.7,0.7,0.01],[0.7,0.7,0.7,0.015],[0.7,0.7,0.7,0]], [1,1], 5, 0, "", "", _this]; drop ["MissileSmoke", "", "Billboard", 5, 4, [0,-2.3,-2.3*(_misvel select 2)], [0,0,0], 2, 0.8925, 0.7, 0, [0.15,0.75,1], [[0.7,0.7,0.7,0.01],[0.7,0.7,0.7,0.015],[0.7,0.7,0.7,0]], [1,1], 5, 0, "", "", _this];
_void;
PSY_MCAR_xchange.sqf called by: guidmis_3.sqs,guidmi_4.sqs,guidmis_7.sqs
; this function substitutes the missile after a certain time, so that it can ; travel long distances at relatively low speeds (missile life in OFP is about ; ten seconds) ; ; usage: [object,time,boolean,string] call xchange ; ; returns: an array [object,boolean] ; object is the missile, time is the time elapsed since missile launch, boolean is ; used to activate the missile substitution and string contains the missile type ; to be created
private ["_missile","_misTime","_misDir","_misPos","_misVel","_cond","_xchange"]; _missile = _this select 0; _misTime = _this select 1; _cond = _this select 2; _misType = _this select 3;
; _xchange is the time difference between the actual time and the time the calling script ; started depurated of its decimal part _xchange = (_time - _misTime) - ((_time - _misTime) mod 1);
; if _xchange is divisible by six (that is, the result of this division is an integer) ; and the boolean is equal to zero (and _xchange is not zero, of course) the missile is ; substituted with a brand new one, and its flight parameters are conserved if ( ((_xchange / 6 ) == ((_xchange /6) - ((_xchange / 6) mod 1)) ) && _cond == 0 && (!(_xchange == 0))) then { _cond = 1; _misPos = getpos _missile; _misVel = velocity _missile; _misDir = direction _missile; deletevehicle _missile; _missile = _misType createVehicle _misPos; _missile setvelocity _misVel; _missile setdir _misDir; } else {
; if one seconds has passed since last substitution (that is, if _xchange is equal to 7, or 13 and ; so on) the boolean is reset to zero, otherwise it wouldn't be possible to operate the next ; substitution (look above) if ( ( ((_xchange -1) / 6 ) == (((_xchange -1) /6) - (((_xchange -1) / 6) mod 1)) ) && _cond == 1) then { _cond = 0; }; };
; the boolean is sent back along with missile because otherwise we couldn't know ; if the missile has just been substituted or not (that is, in the interval ; between second 6 and second 7 the missile would be substituted each time the ; function is called, and so between second 12 and 13, and so on) [_missile,_cond]
this ends the AT subdirectory functions
|
|
|
Post by Sa8Gecko on Oct 25, 2004 6:00:12 GMT -5
AA subdirectory functions:
PSY_MCAR_angle.sqf called by: guidmis_8.sqs, guidmis_9.sqs, proximity.sqf
; for the explanations about most of this function look at the analogue targetpos.sqf ; The differences are explained here, though ; ; usage: [object,object,time,number] call angle ; ; returns: an array [number,time] ; the 'number' used to call this function is the max turn rate allowed
private ["_missile","_target","_gamma","_alpha","_beta","_delta","_misTime","_angle","_coeff","_turnRate","_vmy"]; _missile = _this select 0; _target = _this select 1; _misTime = _this select 2; _turnRate = _this select 3; if (alive _missile) then {
; if the y component of missile velocity is equal to zero, it is set to .0001 to ; evitate division by zero error _vmy = velocity _missile select 1; if (_vmy == 0) then {_vmy = .0001;}; _delta = (velocity _missile select 0) atan2 _vmy; if (_delta < 0) then {_delta = _delta +360;}; _alpha = ((getpos _target select 0) - (getpos _missile select 0)) atan2 ((getpos _target select 1) - (getpos _missile select 1)); if (_alpha < 0) then {_alpha = _alpha +360;}; if (abs(_alpha - _delta) > 180 && _alpha < _delta) then {_alpha = _alpha +360;}; if (abs(_alpha - _delta) > 180 && _alpha > _delta) then {_delta = _delta +360;}; if (speed _target != 0) then {
; the calculation of _gamma has been simplified (we will have the correct result ; if the target is not sideslipping) _gamma = 90 - (direction _target);
; _coeff takes care of the fact that if the speed of target is higher than missile speed, ; we would have a possible error in the following calculation, as ; ((speed _target)/(speed _missile))* sin(_alpha + _gamma + 90) could exceed 1 and so ; the arc sine function would return an error _coeff = abs(speed _target)/abs(speed _missile); if (_coeff >1) then {_coeff = 1;}; _beta = (asin ( _coeff * (sin(_alpha + _gamma + 90)) )) + _alpha; } else { _beta = _alpha; }; _angle = _beta - _delta; if (abs (_angle) > (_turnRate * (_time - _misTime))) then {_angle =(_angle/abs(_angle))*(_turnRate * (_time - _misTime));}; } else {
; angle is set to zero if the missile is dead _angle = 0; }; [_angle,_time]
PSY_MCAR_checkammo.sqf called by: mags.sqs
; this function is used to open the doors of the Gaskin pods ; ; usage: object call checkammo ; ; returns: nothing ; there's not much to say about this function, as it simply checks the ; ammo left in the current magazine and open the pod doors accordingly
private ["_vehicle","_void"]; _vehicle = _this; if ((_vehicle ammo "psy_mcar_9k31" == 4) && (_vehicle animationPhase "pod1" == 1 || _vehicle animationPhase "pod2" == 1 || _vehicle animationPhase "pod4" == 1 || _vehicle animationPhase "pod3" == 1)) then { _vehicle call PSY_MCAR_closepods; } else { if ((_vehicle ammo "psy_mcar_9k31" == 3) && (_vehicle animationPhase "pod2" == 1 || _vehicle animationPhase "pod4" == 1 || _vehicle animationPhase "pod3" == 1 || _vehicle animationPhase "pod1" == 0)) then { _vehicle animate ["pod1",1]; _vehicle animate ["pod2",0]; _vehicle animate ["pod3",0]; _vehicle animate ["pod4",0]; _vehicle setObjectTexture [0,"\psy_mcar_gaskin\sa9\podbcke.paa"]; _vehicle setObjectTexture [1,"\psy_mcar_gaskin\sa9\podbck.paa"]; _vehicle setObjectTexture [2,"\psy_mcar_gaskin\sa9\podbck.paa"]; _vehicle setObjectTexture [3,"\psy_mcar_gaskin\sa9\podbck.paa"]; } else { if ((_vehicle ammo "psy_mcar_9k31" == 2) && (_vehicle animationPhase "pod2" == 1 || _vehicle animationPhase "pod3" == 1 || _vehicle animationPhase "pod4" == 0 || _vehicle animationPhase "pod1" == 0)) then { _vehicle animate ["pod1",1]; _vehicle animate ["pod2",0]; _vehicle animate ["pod3",0]; _vehicle animate ["pod4",1]; _vehicle setObjectTexture [0,"\psy_mcar_gaskin\sa9\podbcke.paa"]; _vehicle setObjectTexture [3,"\psy_mcar_gaskin\sa9\podbcke.paa"]; _vehicle setObjectTexture [2,"\psy_mcar_gaskin\sa9\podbck.paa"]; _vehicle setObjectTexture [1,"\psy_mcar_gaskin\sa9\podbck.paa"]; } else { if ((_vehicle ammo "psy_mcar_9k31" == 1) && (_vehicle animationPhase "pod4" == 0 || _vehicle animationPhase "pod3" == 1 || _vehicle animationPhase "pod2" == 0 || _vehicle animationPhase "pod1" == 0)) then { _vehicle animate ["pod1",1]; _vehicle animate ["pod2",1]; _vehicle animate ["pod3",0]; _vehicle animate ["pod4",1]; _vehicle setObjectTexture [0,"\psy_mcar_gaskin\sa9\podbcke.paa"]; _vehicle setObjectTexture [1,"\psy_mcar_gaskin\sa9\podbcke.paa"]; _vehicle setObjectTexture [3,"\psy_mcar_gaskin\sa9\podbcke.paa"]; _vehicle setObjectTexture [2,"\psy_mcar_gaskin\sa9\podbck.paa"]; }; }; }; };
_void;
PSY_MCAR_checkDH.sqf called by: guidmis_8.sqs
; this function is used to know if the missile has overshoot the target or ; is doing this ; ; usage: [object,object] call checkDH ; ; returns: a boolean
private ["_dist","_missile","_target","_flag","_sq1","_sq2"]; _missile = _this select 0; _target = _this select 1; _flag = 0; if (alive _missile) then { _dist = _missile distance _target;
; the following two lines are used to calculate the approaching rate ; if the missile is approching the target from the front side _flag is set to 1 ; so to trigger the detonation of the proximity fuse, or anyway if the distance ; between missile and target is less than ten meters and the missile is ; approaching from the sides or from the rear _sq1 = sqrt(sqrt(((velocity _target select 0)- (velocity _missile select 0))^2 + ((velocity _target select 1)- (velocity _missile select 1))^2 + ((velocity _target select 2)- (velocity _missile select 2))^2)); _sq2 = sqrt(abs(speed _missile)/8); if ( (_dist < ( _sq1 - _sq2) && abs ((direction _missile) - (direction _target)) > 135) || (_dist < 10 && abs ((direction _missile) - (direction _target)) <= 135) ) then { _flag = 1; }; }; _flag
|
|
|
Post by Sa8Gecko on Oct 25, 2004 6:04:45 GMT -5
PSY_MCAR_closepods.sqf called by:checkammo.sqf, mags.sqs
; this function closes all the pod doors of the Gaskin ; ; usage: object all closepods ; ; returns: nothing
private ["_vehicle","_void"]; _vehicle = _this; _vehicle animate ["pod1",0]; _vehicle animate ["pod2",0]; _vehicle animate ["pod3",0]; _vehicle animate ["pod4",0]; _vehicle setObjectTexture [1,"\psy_mcar_gaskin\sa9\podbck.paa"]; _vehicle setObjectTexture [2,"\psy_mcar_gaskin\sa9\podbck.paa"]; _vehicle setObjectTexture [3,"\psy_mcar_gaskin\sa9\podbck.paa"]; _vehicle setObjectTexture [0,"\psy_mcar_gaskin\sa9\podbck.paa"];
_void;
PSY_MCAR_createProxyAA.sqf called by: repair.sqs
; this function is the analogue of createProxyAT, so look ; at that function for the explanation
private ["_vehicle","_logics","_count","_void"];
_Vehicle=_this select 0;
_Count=0; _Logics=[];
while "_Count<3" do { _Logics=_Logics+["psy_mcar_logic" createVehicle [0,0,0]]; _Count=_Count+1; };
{_x moveInCargo _Vehicle} ForEach _Logics;
_Count=0;
while "_Count<1" do { (_Logics select _Count) setPos [0,0,0]; deleteVehicle (_Logics select _Count); _Count=_Count+1; };
_void;
PSY_MCAR_delta.sqf called by: proximity.sqf
; function used to know if the missile is going to leave the target ; behind, and so missing it ; ; usage: [object,object] call delta ; ; returns: number ; the returned number is compared to the distance between missile and target ; and if found larger, the proximity fuse code is activated
private ["_missile","_target","_velNor","_result"]; _missile = _this select 0; _target = _this select 1; _velNor = velocity _missile call PSY_MCAR_vnorm;
; the missile direction vector is added to its current position, and then the distance ; between the target and this new point in front of the missile is taken (all is done in ; the line below). If the result is bigger than the actual distance between missile and ; target, this means that the missile is leaving the target behind. The converse, ; the missile is left going to make it possible to achieve a direct hit _result = sqrt( ((position _missile select 0)+ (_velNor select 0) - (position _target select 0))^2 + ((position _missile select 1)+ (_velNor select 1) - (position _target select 1))^2 + ((position _missile select 2)+ (_velNor select 2) - (position _target select 2))^2); _result
PSY_MCAR_detonate.sqf called by: guidmis_8.sqs, proximity.sqf
; there's not much to say about this function: ; it creates an object, a 'detonator', at missile position: ; this object has a large fire geometry, and so the missile ; always collide with it, exploding: this simulates the proximity ; fuse ; ; usage: object call detonate ; ; returns: an object ; the object passed to the function is the missile, the one ; returned is the 'detonator' being created by the function itself
private ["_chaff"]; _chaff = "RKT_detonator" createVehicle position _this; _chaff
|
|
|
Post by Sa8Gecko on Oct 25, 2004 6:07:34 GMT -5
PSY_MCAR_dz.sqf called by: guidmis_6.sqs, guidmis_9.sqs
; this function returns the difference in height between the missile ; and the target ; ; usage: [object,object,number] call dz ; ; returns: number
private ["_missile","_target","_zmiss","_ztarg","_alt","_dz"]; _missile = _this select 0; _target = _this select 1;
; _alt is a number generally varying between 0 and +10, that sets the ; height above the target: that is, it is added to the difference ; between missile and target heights so that the missile flies a little ; higher than the required trajectory. This is done for two purposes: ; the first being the fact that target height is not taken at the centre ; of the unit but well below, so we have to compensate; the second being ; that this number is reduced when the missile approaches the target, so ; the missile itself will dive on the target _alt = _this select 2;
; the absolute heights above sea level are needed for a consistent result _zmiss = - ( _missile call PSY_MCAR_calcH ); _ztarg = - ( _target call PSY_MCAR_calcH ); _dz = - _zmiss + _ztarg + _alt - (position (_missile) select 2) +(position _target select 2); _dz
PSY_MCAR_initSearchAA.sqf called by: getAmmo.sqs
; this function provides the initial target search for the gaskin missile ; ; usage: [object,3D array] call initSearchAA ; ; returns: an object ; the object returned maybe the target or an 'emptydetector' if nothing is ; found. The 3d array contains the firing direction. Remember always to ; have the target in the crossair centre (or not far off) when you pull ; the trigger. The AI does that automatically thanks to the high (10000+) ; initspeed of the bullet really fired by the Gaskin
private ["_shooter","_target","_vect","_heightShooter","_spos","_xnextpos","_ynextpos","_znextpos","_iter","_exitLoop","_dummy","_zrelative","_zshooter"]; _shooter = _this select 0; _vect = _this select 1;
_zshooter= - (_shooter call PSY_MCAR_calcH);
; the next line returns the height to be added to the one just ; returned by the line above in case the vehicle is firing from the ; top of a building (i.e.: Nogova bridges) _heightShooter = _shooter call PSY_MCAR_hShooter; _sPos = position _shooter;
_exitloop = 0;
; initial distance from the shooting vehicle where the search starts _iter = 100; _dummy = "EmptyDetector" createVehicle [0,0,0];
; the search is conducted, until a target is found, for 3000 meters at steps ; of 60 meters. For air targets this is usually enough, because generally ; there's not much around them (maybe some bullets or missiles flying). So ; we can take such large steps between each successive search position. ; This will not overcharge the CPU too. while "_exitLoop == 0 && _iter < 3000" do { ; each time the distance (_iter) is added to the initial start point (the ; shooter) to calculate next search point. This distance is added along ; the x,y,z components of the firing direction. The calculation of ; the z component is a little more complicate because we have to know ; the height of the ground of the next search position (_zrelative), ; otherwise we would not achieve a useful result. (_sPos select 2) is ; just added in case the vehicle is jumping high (!) while firing, and ; _heightShooter takes care of the possible fact the unit is firing from ; above a bridge and the like. (_iter * (_vect select 2)) is the distance ; multiplied by the z component of the firing direction, while _zshooter ; is the height above sea level of the shooting unit. _xnextpos = (_sPos select 0) + (_iter * (_vect select 0)); _ynextpos = (_sPos select 1) + (_iter * (_vect select 1)); _dummy setpos [_xnextpos,_ynextpos,0]; _zrelative = - (_dummy call PSY_MCAR_calcH);
_znextpos =(_sPos select 2) + (_iter * (_vect select 2)) + _zshooter - _zrelative + _heightShooter;
; if the z component of the next search position is negative, that means that ; the next search position itself is inside ground (a hill, or the unit was ; firing downward), so the search is interrupted setting _exitloop = 2 if (_znextpos < 0) then {_exitLoop = 2;};
; unfortunately, as you should know, you can't search with nearestObject for ; a type of unit (that is "Air" or "Helicopter" and the like): you must be ; type specific (i.e.: RKT_Mig23BN). Obviously this is not possible, so we ; must search for a 'something', and then see if this 'something' found ; is part of our possible targets: it may still happen that the aircraft ; targeted is not acquired because a bullet was flying nearer than it ; to the searching position, and so the bullet is returned by nearestObject. _target = nearestObject [[_xnextpos,_ynextpos,_znextpos],""]; if ("Air" countType [_target] > 0 && damage _target < .99 && "ParachuteBase" countType [_target]==0 && side _target != side _shooter) then {_exitLoop =1;};
_iter=_iter + 60; };
; if no target is found, a fake one is created and sent back to the calling script if (_exitLoop == 0) then { _target = "EmptyDetector" createvehicle [_xnextpos,_ynextpos,_znextpos]; };
; if the line of fire ends inside a hill and no target has been found, a fake one is ; created just outside the ground, in the previous search position if (_exitLoop == 2) then { _shooter vehiclechat "Ground, Target not found"; _target = "EmptyDetector" createvehicle [(_sPos select 0) + ((_iter - 60) * (_vect select 0)),(_sPos select 1) + ((_iter - 60) * (_vect select 1)),(_sPos select 2) + ((_iter - 60) * (_vect select 2)) + _zshooter - _zrelative + _heightShooter]; }; deletevehicle _dummy;
_target
|
|
|
Post by Sa8Gecko on Oct 26, 2004 1:16:55 GMT -5
PSY_MCAR_mcop.sqf called by: fired.sqs
; this function sets the missile starting point on the gaskin ; and open the relative pod doors ; ; usage: [3d array,object,3d array] call mcop ; ; returns: a 3d array (the missile starting point)
private ["_MCOP","_shooter","_vect","_displ"];
; _MCOP is the position of the gamelogic that will be used to calculate ; the missile start point, while _vect is the firing direction _MCOP = _this select 0; _shooter = _this select 1; _vect = _this select 2;
; in the following lines the magazine of the gaskin is examined to see how ; many ammo remain in it and so to open the right pod. _displ is used to ; set the missile in front of the right pod if ((_shooter ammo "psy_mcar_9k31") == 3) then { _displ = -.9; (vehicle _shooter) animate ["pod1",1]; (vehicle _shooter) setObjectTexture [0,"\psy_mcar_gaskin\sa9\podbcke.paa"]; } else { if ((_shooter ammo "psy_mcar_9k31") == 2) then { _displ = .9; (vehicle _shooter) animate ["pod4",1]; (vehicle _shooter) setObjectTexture [3,"\psy_mcar_gaskin\sa9\podbcke.paa"]; } else { if ((_shooter ammo "psy_mcar_9k31") == 1) then { _displ = -.5; (vehicle _shooter) animate ["pod2",1]; (vehicle _shooter) setObjectTexture [1,"\psy_mcar_gaskin\sa9\podbcke.paa"]; } else { _displ = .5; (vehicle _shooter) animate ["pod3",1]; (vehicle _shooter) setObjectTexture [2,"\psy_mcar_gaskin\sa9\podbcke.paa"]; }; }; };
; the following two lines set the x,y element of the array _MCOP, that will contain ; the missile starting point. It works pretty well on flat ground, while when the ; unit is standing on a steep hill flank the result is not so good, that is the missile ; will not start at exactly the right place. To obviate this we should know the turret ; rotation as respect to where the unit is pointing and the bank angle, so for ; simplicity I left it like this. To know the bank angle it should be sufficient ; to drop two particles, though. Maybe in a future version we will pose remedy to this. _MCOP set[0,(_MCOP select 0) - ((_displ)*cos ((_vect select 0) atan2 (_vect select 1)))]; _MCOP set[1,(_MCOP select 1) + ((_displ)*sin ((_vect select 0) atan2 (_vect select 1)))];
_MCOP
PSY_MCAR_noCrewIn.sqf called by: fired.sqs, getammo.sqs, guidmis_6.sqs, guidmis_8.sqs, guidmis_9.sqs
; this function works the same as noCrewInHumvee, so I send you ; to that function to see how it works
private ["_vehicle","_logics","_count","_logiccount","_pos1","_pos2","_dummyobj","_hasl1","_hasl2"];
_Vehicle=_this select 0;
_Count=0; _Logics=[];
while "_Count<3" do { _Logics=_Logics+["psy_mcar_logic" createVehicle [0,0,0]]; _Count=_Count+1; };
{_x moveInCargo _Vehicle} forEach _Logics;
_Count=0;
while "_Count<1" do { (_Logics select _Count) setPos [0,0,0]; deleteVehicle (_Logics select _Count); _Count=_Count+1; };
_Logics=+(crew _Vehicle); _LogicCount=(count _Logics); if (_vehicle distance (_Logics select (_LogicCount-1)) < _vehicle distance (_Logics select (_LogicCount-2))) then { _Pos2=position (_Logics select (_LogicCount-1)); _Pos1=position (_Logics select (_LogicCount-2)); } else { _Pos1=position (_Logics select (_LogicCount-1)); _Pos2=position (_Logics select (_LogicCount-2)); }; _dummyobj = "EmptyDetector" createVehicle [0,0,0];
_dummyobj setPos [_pos1 select 0, _pos1 select 1, 0]; _hasl1 = position _dummyobj select 2; _dummyobj setPos [_pos2 select 0, _pos2 select 1, 0]; _hasl2 = position _dummyobj select 2; deleteVehicle _dummyobj;
[_Pos1,[(_Pos1 select 0)-(_Pos2 select 0),(_Pos1 select 1)-(_Pos2 select 1),((_Pos1 select 2) - _hasl1)-((_Pos2 select 2) - _hasl2)]]
PSY_MCAR_proximity.sqf called by: guidmis_8.sqs
; this function is executed when the missile is near to the target, and decides ; if it's the case to go for a direct hit or else to explode the missile. In ; case the moment to explode the missile isn't arrived yet, this function ; guides further the missile to the target and sent back some parameters to ; the calling script ; ; usage: [object,object,number,number,number,[number,time]] call proximity ; ; returns: an array [number,object,number,[number,time],number]
private ["_Missile","_Target","_dist","_chaff","_radius","_vz","_vnorm","_angle","_cfx","_vx","_vy","_ds","_exit","_turnRate","_speed"];
; the following parameters are quite self explicative, a part _vz that contains ; the previous vertical velocity of the missile and the time, so that the next ; vertical (z) velocity can be calculated without exceeding the max climb rate ; admitted. ; _exit can assume three value, which are set in the course of this function: ; 0 means that the missile still has to hit the target, but it's still on the ; right course; ; 1 means that the missile has been detonated by proximity fuse; ; 2 means that the missile has flown away from the target and it's time ; to give back the control of it to the main routine for re-engagement ; _chaff is set as equal to the target because it has to be an object _Missile = _this select 0; _Target = _this select 1; _radius = _this select 2; _angle = _this select 3; _turnRate = _this select 4; _speed = _this select 5; _vz = _this select 6; _exit = 0; _chaff = _Target;
_dist = (_Missile distance _Target);
; the following line calls PSY_MCAR_delta to know if the missile is actually ; going away or more near to the target _ds = [_Missile,_Target] call PSY_MCAR_delta;
; if the distance between missile and target is less than _ds, this means ; that the missile is loosing contact with the target and it's time to ; detonate the missile itself to do some damage to the target if (_dist < _ds) then {_chaff = _Missile call PSY_MCAR_detonate ; _exit =1;};
; if the missile is now more than 16 meters from the target, control should ; be given back to the main routine, so _exit is set to 2 if (_dist > 16) then {_exit = 2;};
; the following three lines set the course of the missile, so ; to continue to guide it, otherwise it will go straight during ; the final approach to the target, widening the probability ; to miss it. For an explanation of the various parameters and ; functions below look at the relative functions _angle = [_Missile,_Target,_angle select 1,_turnRate] call PSY_MCAR_angle; _vz = [_Missile,_Target,_alt,_speed,_vz select 1,_vz select 0] call PSY_MCAR_vz;
[_missile,_speed,_vz select 0,_angle select 0] call PSY_MCAR_setVel;
[_dist,_chaff,_angle,_vz,_exit]
|
|
|
Post by Sa8Gecko on Oct 26, 2004 1:22:29 GMT -5
PSY_MCAR_searchAA.sqf called by: guidmis-6.sqs, guidmis_8.sqs, guidmis_9.sqs
; this function is used if initSearchAA, called by getammo.sqs, has not found ; a target ; ; usage: [object,object,3d array,number] call SearchAA ; ; returns: an array [object,number] ; the 3D array passed to the function contains the direction vector, while number is the ; distance from the shooting vehicle at which to start the search. The number returned ; by the function is useful only if no target has been found, because it indicates ; how far from the shooting vehicle the next phase of the search should begin
private ["_shooter","_missile","_velnorm","_mispos","_misheight","_initstep","_ivel","_jvel","_kvel","_Target","_posArray","_i","_exitLoop","_startposx","_startposy","_startposz","_step","_dummy","_zrelative"];
_shooter = _this select 0; _missile = _this select 1; _velnorm = _this select 2; _initstep = _this select 3;
_mispos = position _shooter; _misheight = - (_shooter call PSY_MCAR_calcH);
_exitLoop = 0;
; for semplicity in the subsequent formula, _velnorm is subdivided in its components _ivel = _velnorm select 0; _jvel = _velnorm select 1; _kvel = _velnorm select 2;
; this array contains the five direction along which the search is conducted ; each direction is spaced six degrees left,right,up and down from the central ; direction, that is _velnorm _posArray = [_ivel,_jvel,_kvel,_ivel * 0.9945 + _jvel * 0.1045,- _ivel * 0.1045 + _jvel * 0.9945,_kvel,_ivel * 0.9945 - _jvel * 0.1045,+ _ivel * 0.1045 + _jvel * 0.9945,_kvel,_ivel,_jvel,sin(asin(_kvel) + 6),_ivel,_jvel,sin(asin(_kvel) - 6)];
; the three components of the point where the search should start ; are calculated here: _startposx = (_mispos select 0) + (_initstep * _ivel); _startposy = (_mispos select 1) + (_initstep * _jvel); _startposz = (_mispos select 2) + (_initstep * _kvel);
; each point of this search is spaced 60 meters from the previous one _step = 60; _dummy = "EmptyDetector" createVehicle [0,0,0];
; the search is conducted for 700 meters along the five directions contained ; in _posArray while "_step < 700 && _exitLoop == 0" do {
; _i is the index for _posArray _i=0; _dummy setPos[_startposx + (_step * _ivel),_startposy + (_step * _jvel),0]; _zrelative = - (_dummy call PSY_MCAR_calcH);
while "_i < 15 && _exitLoop == 0" do { _Target = nearestObject [_startposx + (_step * (_posArray select _i)),_startposy + (_step * (_posArray select (_i+1))),_startposz + (_step * (_posArray select (_i+2))) + _misheight - _zrelative]; if ("Air" countType [_Target] > 0 && damage _target < .99 && "ParachuteBase" countType [_Target] == 0 && side _Target != side _shooter) then { _exitLoop = 1; }; _i = _i+3; };
_step=_step + 60; };
; _initstep is incremented by 550 meters before being sent back to the ; calling script. This search function is executed by guidmis_8.sqs ; until _initstep surpasses the value of 3500 meters, that means that, ; being 3300 the last useful value of _initstep before reaching 3500, ; the search is conducted until 4000 meters from the shooting vehicle ; This is the maximum acquisition range for the Gaskin. This means ; that targets beyond this distance cannot be engaged. That's not ; the missile max range, though: missile max range is something ; different and should be about 6000 meters. So you can target ; for example a plane moving away from you when it is at 3800 meters ; and hit it even if in the meantime it has moved to 5500 meters from ; your position. The missile will take 12 seconds to reach ; maximum range. Tangling with some values in the script can ; raise or lower the max range and/or the time taken to reach it. _initstep = _initstep + 550; deleteVehicle _dummy;
; if no target has been found, we need to create a fake one so that ; the missile guidance code in the meantime has something to aim at if (_exitLoop == 0) then { _dummy = "EmptyDetector" createVehicle [(_mispos select 0)+ (4000 * _ivel),(_mispos select 0) + (4000 * _jvel),0]; _zrelative = - (_dummy call PSY_MCAR_calcH); deleteVehicle _dummy; _Target = "EmptyDetector" createVehicle [_startposx,_startposy ,(_mispos select 2) + (4000 * _kvel) + _misheight - _zrelative]; }; [_Target,_initstep]
PSY_MCAR_setSpeed.sqf called by: guidmis_8.sqs
; this function sets the speed of the missile ; ; usage: time call setSpeed ; ; returns: an array [number,number] ; where the first number is the speed to assign to the missile ; and the second one is the max turning rate admitted for that ; particular speed
private ["_speed","_misTime","_turnRate"]; _misTime = _this;
; until the time elapsed since the launch reaches ten seconds, ; the missile accelerates at a rate of 100 meters per seconds, ; until it reaches a speed of 450 m/s. When the time elapsed ; is over 10 seconds, the missile starts to decelerate at a ; rate of 20 meters per second (simulating engine burnout) if ((_time -_misTime)<10) then { _speed = 70 + (100* (_time - _misTime)); } else { _speed = 450 - (20* (_time - _misTime - 10)); }; if (_speed > 450) then { _speed = 450;};
; the turning rate changes with speed: even if when a certain ; time has passed the turning rate doesn't change any more ; because it's limited at 60 deg/s by this formula, at the ; start it is noticeable cause the missile won't reach the ; maximum turning rate until about 1.5 seconds from launch _turnRate = (_speed - 65)*((_time - _misTime)/3); if (_turnRate > 60) then { _turnRate = 60;}; [_speed,_turnRate]
PSY_MCAR_setVel.sqf called by: guidmis_8.sqs, proximity.sqf
; this function sets the x,y component of the velocity vector of the missile ; ; usage: [objetc,number,number,number] call setVel ; ; returns: nothing
private ["_missile","_speed","_vz","_vx","_vy","_vnorm","_angle","_cfx"]; _missile = _this select 0;
; _speed is the speed of the missile (not the velocity) as returned by setSpeed.sqf, ; _vz is the z component of the velocity vector as returned by vz.sqf and _angle ; is the angle at which the missile shall be rotated as returned by _angle.sqf _speed = _this select 1; _vz = _this select 2; _angle = _this select 3;
; _cfx is how much of the speed is left for the x,y component after _vz ; has been removed (that is, if _vz is 90 m/s and the missile speed is 200, ; we can't divide 200 between the x,y components, as a part of this speed ; is already 'consumed' by _vz. Note that _vz has the precedence above ; the other two components of missile velocity vector _cfx = (sqrt ((_speed ^ 2) - (_vz ^ 2)) );
; _vnorm is the velocity vector taken on the x,y plane, normalized _vnorm = [velocity _Missile select 0,velocity _Missile select 1,0] call PSY_MCAR_vNorm;
; the missile is rotated by _angle: it's important that the missile as defined ; in config.cpp has a low or null acceleration, otherwise this acceleration will send ; the missile off course. _Missile setdir (direction _missile + _angle);
; _vx and _vy are calculated using the rotation formula for a vector by the ; angle _angle (it's not a repetition). That is, if a (2D) vector is rotated ; by A degrees, the formula is: ; x component of the new vector = x comp of the old vector multiplied by cos(A) + ; y comp of the old vector multiplied by sin (A) ; y component of the new vector = - (x comp of the old vector) multiplied by sin (A) + ; y comp of the old vector multiplied by cos (A) _vx= ((_vnorm select 0)*_cfx)*cos(_angle) + ((_vnorm select 1)*_cfx)*sin(_angle); _vy = -((_vnorm select 0)*_cfx)*sin(_angle) + ((_vnorm select 1)*_cfx)*cos(_angle);
; the missile is finally assigned its new velocity vector and the function exits _Missile setvelocity [_vx,_vy ,_vz];
true
|
|
|
Post by Sa8Gecko on Oct 26, 2004 1:28:07 GMT -5
PSY_MCAR_smokerAA.sqf called by: fired.sqs
; this function generates the smoke at the back of missile pods when the ; missile is launched ; ; usage: [3d array,3d array] call smokerAA ; ; returns: nothing ; the first array contains the position at which to generate the smoke, ; the second one the converse of the direction the smoke should have
private ["_void"]; drop ["cl_basic", "", "Billboard", 7, 6, [(_this select 0) select 0,(_this select 0) select 1,(_this select 0) select 2], [-((_this select 1) select 0)*5.7,-((_this select 1) select 1)*5.7,-((_this select 1) select 2)*5.7], 2, .85, 0.7, 0, [0.2,7,12], [[0.75,0.75,0.75,0.95],[0.75,0.75,0.75,0.9],[0.75,0.75,0.75,0]], [1,1], 5, 0, "", "",""]; drop ["cl_basic", "", "Billboard", 7, 6, [(_this select 0) select 0,(_this select 0) select 1,(_this select 0) select 2], [-((_this select 1) select 0)*5.1,-((_this select 1) select 1)*5.1,-((_this select 1) select 2)*5.1], 2, 0.84, 0.7, 0.02, [.2,9,15], [[0.8,0.8,0.8,0.95],[0.8,0.8,0.8,0.9],[0.8,0.8,0.8,0]], [1,1], 5, 0, "", "",""]; drop ["cl_basic", "", "Billboard", 7, 6, [(_this select 0) select 0,(_this select 0) select 1,(_this select 0) select 2], [-((_this select 1) select 0)*5,-((_this select 1) select 1)*5,-((_this select 1) select 2)*5], 1, .8925, 0.7, 0.02, [0.5,6,12], [[0.7,0.7,0.7,0.95],[0.7,0.7,0.7,0.9],[0.7,0.7,0.7,0]], [1,1], 5, 0, "", "",""]; drop ["cl_basic", "", "Billboard", 8, 7, [(_this select 0) select 0,(_this select 0) select 1,(_this select 0) select 2], [-((_this select 1) select 0)*5.4,-((_this select 1) select 1)*5.4,-((_this select 1) select 2)*5.4], 2, .88, 0.7, 0.01, [0.2,8,12], [[0.8,0.8,0.8,0.95],[0.8,0.8,0.8,0.9],[0.8,0.8,0.8,0]], [1,1], 5, 0, "", "",""]; drop ["cl_basic", "", "Billboard", 9, 8, [(_this select 0) select 0,(_this select 0) select 1,(_this select 0) select 2], [-((_this select 1) select 0)*4.7,-((_this select 1) select 1)*4.9,-((_this select 1) select 2)*4.9], 2, .885, 0.7, -3, [0.2,5,11], [[0.85,0.85,0.85,0.95],[0.85,0.85,0.85,0.9],[0.85,0.85,0.85,0]], [1,1], 5, 0, "", "",""];
_void;
PSY_MCAR_tiltmissileAA.sqf called by: fired.sqs, guidmis_6.sqs, guidmis_8.sqs, guidmis_9.sqs
; this function substitutes the current missile model with a differently tilted one so ; to look a little better (especially during the launch phase). This because otherwise ; the missile would always be horizontal ; ; usage: [object,number] call 9m31tilt (tiltmissileAA.sqf) ; ; returns: object ; the number passed to the function is used to activate the substitution even ; if it would be not necessary looking only at the pitch the missile should have
private ["_speedMiss","_phase","_missile","_vmis","_mispos","_dirmis","_misArray","_i","_mistime"];
; _misArray contains all the differently tilted missiles, in this case 13, each tilted 15 degrees ; as regard to the others (that is, one is tilted 0 deg, the other 15, another 30 deg and so on) _misArray = ["RKT_9m31_00","RKT_9m31_15","RKT_9m31_30","RKT_9m31_45","RKT_9m31_60","RKT_9m31_75","RKT_9m31_90","RKT_9m31_m15","RKT_9m31_m30","RKT_9m31_m45","RKT_9m31_m60","RKT_9m31_m75","RKT_9m31_m90"]; _missile = _this select 0;
; _mistime is misleading: it has nothing to do with time. It is instead a flag ; that is used to activate the midlife missile substitution (so to assure the ; missile will live the full 12 seconds it is supposed to stay, at least if it ; doesn't hit something before) _mistime = _this select 1; if (alive _missile) then {
; the formula below is used to calculate how many degrees the missile should be tilted ; for it to assume a natural look when climbing or descending: first is calculated ; the speed of the missile (I could have used 'speed _missile'), then, knowing that ; the components of the normalized velocity vector are the direction cosines of ; the vector itself, the inclination angle (_phase) is calculated _speedMiss = sqrt((velocity _missile select 0)^2+(velocity _missile select 1)^2+(velocity _missile select 2)^2); _phase = asin((velocity _missile select 2)/(_speedMiss));
; if the angle (_phase) is between -7.5 deg and 7.5 deg, then the index _i is ; set to zero so that it points to the first element of _misArray, the 0 degrees ; tilted (horizontal) missile if (_phase > -7.5 && _phase < 7.5) then { _i=0; } else {
; the following if then else construct is used to calculate the right index _i ; for _misArray, if _i was not set to zero previously if (_phase > 0) then { _phase = _phase -7.5; _i = _phase/15 - ( (_phase/15) mod 1) + 1; } else { _phase = - _phase; _phase =_phase - 7.5; _i = _phase/15 - ( (_phase/15) mod 1) + 7; }; };
; then the missile type is confronted with the one pointed by the index _i: ; if they're not the same type, or it is time for a sustitution all the rest ; notwithstanding (_mistime is equal to 1), the missile is substituted ; with one of the right inclination if ((typeOf _missile != _misArray select _i) || (_mistime == 1)) then { _mispos = position _missile; _vmis = velocity _missile; _dirmis = direction _missile; deleteVehicle _missile; _missile = (_misArray select _i) createVehicle _mispos; _missile setvelocity _vmis; _missile setdir _dirmis; }; }; _missile
PSY_MCAR_vz.sqf called by: guidmis_8.sqs, proximity.sqf
; this function calculate the z component of the velocity vector that will ; be subsequently assigned to the missile ; ; usage: [object,object,number,number,time,number] call vz ; ; returns: an array [number,time] ; where 'number' is the z component of the velocity vector and 'time' will ; be used next time this functionis called not to exceed the maximum climb rate
private ["_missile","_target","_zmiss","_ztarg","_alt","_dz","_speed","_vz","_sqrVel","_sqrDistXY","_misTime","_vzOld"]; _missile = _this select 0; _target = _this select 1;
; for more information about _alt see dz.sqf _alt = _this select 2; _speed = _this select 3;
; these two parameters are the values this same function returned the ; previous time it was called. Are used not to exceed max climb rate _misTime = _this select 4; _vzOld = _this select 5;
_zmiss = - ( _missile call PSY_MCAR_calcH ); _ztarg = - ( _target call PSY_MCAR_calcH );
; _dz is the difference in height between target and missile _dz = - _zmiss + _ztarg + _alt - (getpos (_missile) select 2) +(getpos _target select 2);
; this is the distance between missile and target on the x,y plane. distXY.sqf on the AT ; subdirectory does the same thing, but it's not defined for the Gaskin _sqrDistXY = sqrt(((getpos _target select 0)-(getpos _missile select 0))^2 + ((getpos _target select 1)-(getpos _missile select 1))^2);
; this is the difference between the velocities of missile and target on the x,y plane _sqrVel = sqrt (((velocity _missile select 0) - (velocity _target select 0)) ^2 + ((velocity _missile select 1) - (velocity _target select 1)) ^2);
; next two lines are used to evitate a 'division by zero' error if (_sqrDistXY == 0) then {_sqrDistXY = 0.0001;}; if (_sqrVel == 0) then {_sqrVel = 0.0001;};
; the formula below try to 'lead' the target, instead of pointing the missile ; directly (as regard to its z velocity component). ; (_dz/(_sqrDistXY/_sqrVel )) has the dimension of [m/s], that is a velocity _vz = (velocity _target select 2) + (_dz/(_sqrDistXY/_sqrVel ));
; if the calculated _vz is larger than the previously calculated missile speed, ; it is reduced accordingly if (abs(_vz) > _speed) then {_vz = (abs(_vz)/_vz)* (_speed -1);};
; next line doesn't allow the missile to lead the target if this is diving ; and the missile is lower than the target. ; In fact, if not corrected, this will very probably send the missile to ; impact ground (not to mention that would be an evasive maneuver for the ; targeted aircraft: just point the nose down and the missile will go down ; trying to lead you and will impact the ground first) if (_vz < 0 && (_dz - _alt)>0) then {_vz = _dz/((_missile distance _target)/_speed);};
; next line calculates if _vz exceeds maximum climb rate and, if so, reacts accordingly if (abs(_vz - _vzOld)> 90*(_time - _misTime)) then {_vz = _vzOld + 90*(_time - _misTime)*((abs(_vz - _vzOld))/(_vz - _vzOld));}; [_vz,_time]
This ends the AA subdirectory functions
|
|
|
Post by Sa8Gecko on Oct 28, 2004 6:05:03 GMT -5
General purpose functions They're used almost everywhere in the scripts and other functions
PSY_MCAR_calcH.sqf
; by VektorBoson ; returns absolute height above sea level (with a negative sign before it, so ; be aware) ; ; usage: object call calcH ; ; returns: number
private ["_heightResult"];
; PSY_MCAR_sensor is a 'emptydetector' defined in config.cpp to evitate ; to continuosly create and delete it PSY_MCAR_sensor setpos [position _this select 0, position _this select 1, 0];
_heightResult = position PSY_MCAR_sensor select 2;
_heightResult
PSY_MCAR_crew.sqf
; by HateR_Kint ; returns the crew of an MCAR vehicle, gamelogics excluded (they are counted ; as units by the standard BIS crew command) ; ; usage: object call crew ; ; returns: a number
private["_crw","_i"];
_crw = crew (_this select 0); _i = (count _crw) - 1;
while "_i > 0" do { if (typeOf (_crw select _i) == "psy_mcar_logic") then { _crw = _crw - [(_crw select _i)]; };
_i = _i - 1; };
_crw
PSY_MCAR_getLaunch.sqf
; by Unnamed ; This is the core of MCAR. This function and its variants are used ; for everything. ; ; Usage: object call getLaunch ; ; returns: an array [3d array, 3d array] ; the object passed to the function is the MCAR vehicle ; the first array returned is the position of the distantmost gamelogic ; the second array returned is the difference of positions between the ; distantmost gamelogic and the other one: if the things were done well in O2, ; this array contains a vector that normalized will give us the firing direction.
private ["_vehicle","_logics","_logiccount","_pos1","_pos2","_dummyobj","_hasl1","_hasl2"];
_Vehicle=_this select 0;
_Logics=+(crew _Vehicle); _LogicCount=(count _Logics); if (_vehicle distance (_Logics select (_LogicCount-1)) < _vehicle distance (_Logics select (_LogicCount-2))) then { _Pos2=position (_Logics select (_LogicCount-1)); _Pos1=position (_Logics select (_LogicCount-2)); } else { _Pos1=position (_Logics select (_LogicCount-1)); _Pos2=position (_Logics select (_LogicCount-2)); }; _dummyobj = "EmptyDetector" createVehicle [0,0,0]; _dummyobj setpos [_pos1 select 0, _pos1 select 1, 0]; _hasl1 = position _dummyobj select 2; _dummyobj setpos [_pos2 select 0, _pos2 select 1, 0]; _hasl2 = position _dummyobj select 2; deletevehicle _dummyobj;
[_Pos1,[(_Pos1 select 0)-(_Pos2 select 0),(_Pos1 select 1)-(_Pos2 select 1),((_Pos1 select 2) - _hasl1)-((_Pos2 select 2) - _hasl2)]]
PSY_MCAR_hShooter.sqf
; this function returns a number which represent an additional height ; to be added to the shooting vehicle's one, in case this one was firing ; from the top of a building ; ; usage: object call hShooter ; ; returns: a number
private ["_gamel","_height"];
; a gamelogic is created at the position of the shooting vehicle, height zero _gamel = "Logic" camCreate [position _this select 0, position _this select 1, 0];
; then the distance between this gamelogic and the vehicle is taken: -2.3 represent ; a good balance for the gaskin and humvees: every vehicle should have this own number, ; calculated putting the vehicle on flat ground and executing this function (without ; the -2.3) and with a globalchat just after this line saying the result: i.e.: ; player globalchat format ["height above ground %1",_height]; _height = (_this distance _gamel) - 2.3; deletevehicle _gamel;
; if the vehicle is 'flying' there's no need to add _height if ((position _this select 2) > .5) then {_height = 0};
; if _height is negative, the vehicle is sitting on ground and there's no need ; to add _height (_height may be negative for the -2.3 that is subtracted to it: ; the -2.3 serves the purpose to not to modify always the real height of the ; shooting vehicle, because different slopes will give different results even if ; the vehicle is placed directly above the ground if (_height < 0) then {_height = 0}; _height
PSY_MCAR_trail.sqf
; generates an additional missile trail to make it more visible ; the function is similar to trail2.sqf, so look atit for an explanation
private ["_misvel","_void"]; comment {drop ["cl_fire", "", "Billboard", 1, 0.05, [0,-1.5,0], [0,(speed _this)/3.6,velocity _this select 2], 2000, 0.382, 0.3, 0, [0.35,0.35,0], [[0.8,0.8,0,0.99]], [0,1,0], 2, 2, "", "", _this];}; _misvel = (velocity _this) call PSY_MCAR_vNorm; drop ["cl_basic", "", "Billboard", 5, 4, [0,-.8,-0.8*(_misvel select 2)], [0,0,0], 2, 0.8925, 0.7, 0, [0.25,1.75,2], [[0.7,0.7,0.7,0.4],[0.7,0.7,0.7,0.25],[0.7,0.7,0.7,0]], [1,1], 5, 0, "", "", _this]; drop ["cl_basic", "", "Billboard", 5, 4, [0,-1.3,-1.3*(_misvel select 2)], [0,0,0], 2, 0.8925, 0.7, 0, [0.25,1.75,2], [[0.7,0.7,0.7,0.4],[0.7,0.7,0.7,0.25],[0.7,0.7,0.7,0]], [1,1], 5, 0, "", "", _this]; drop ["missileSmoke", "", "Billboard", 5, 4, [0,-1.8,-1.8*(_misvel select 2)], [0,0,0], 2, 0.8925, 0.7, 0, [0.25,1.75,2], [[0.7,0.7,0.7,0.4],[0.7,0.7,0.7,0.25],[0.7,0.7,0.7,0]], [1,1], 5, 0, "", "", _this]; drop ["missileSmoke", "", "Billboard", 5, 4, [0,-2.3,-2.3*(_misvel select 2)], [0,0,0], 2, 0.8925, 0.7, 0, [0.25,1.75,2], [[0.7,0.7,0.7,0.4],[0.7,0.7,0.7,0.25],[0.7,0.7,0.7,0]], [1,1], 5, 0, "", "", _this];
_void;
PSY_MCAR_vNorm.sqf
; this function returns the vector passed to it normalized, that is ; with module equal to 1 ; usage: 3darray call vNorm ; ; returns: 3d array ; the calculations are pretty straightforward. The returned vector ; may be thought also as the direction of the passed vector
private ["_vm","_x","_y","_z"]; _x=_this select 0; _y=_this select 1; _z= _this select 2;
; this is the module of the vector passed to the function _vm=sqrt (_x^2 +_y^2 +_z^2); if (_vm == 0) then { _vm = 0.0001; };
[_x/_vm,_y/_vm,_z/_vm]
|
|