Results 1 to 7 of 7

Thread: AC-130 camera script

  1. #1

    AC-130 camera script

    Recalibrate your azimuth sweep angle and adjust your elevation scan. That's right it's (another) AC-130 thread. As an alternative to the existing aircraft based solution, this one is a camera only script like my predator UAV script (I didn't see any script listings for a pure camera implementation like this one).

    The script deliberately limits the weapons to fire in bursts for multiplayer balancing and exits after 40 seconds. I quickly tested it MP and it seemed ok. I commented out the playsound and cutrscs, so you can try it without setting up a description.ext.

    V1.99 users could probably optimise this considerably by using getposASL for the firing calculations, rather than the trig workaround required for 1.96. It's probably adaptable to work on a real aircraft model by replacing the orbit section with script to keep it attached to the side of the plane.

    Code:
    ; AC-130 script
    ; move forward/move backward/move left/move right pans camera
    ; move up changes weapon (105mm M102, 40mm Bofors L/60, 25mm GAU-12)
    ; move down fires weapon
    ; position to orbit
    _pos = _this select 0
    ; sea level reference for manual ASL calculation
    _sealevelref = "logic" camcreate [0,0,0]
    ; target marker for manual ASL calculation
    _target = "logic" camcreate _pos
    ; selected weapon number
    _currentWeapon = 0
    ; on screen weapon names
    _weaponNames = ["105mm","40mm","25mm"]
    ; sound class names defined by descrition.ext or config cfgSounds
    _sounds = ["m102","bofors","gau12"]
    ; cfgammo class names
    _weaponClasses = ["shell125","shell73","Bullet4x23"]
    ; FOVs
    _zoom = [0.4,0.15,0.05]
    ; Pan/tilt sensitivity to compensate for change in FOV
    _panGain = [60,30,15]
    ; muzzle velocities in m/s
    _MuzzleVelocity = [472,881,1040]
    ; time between bursts/seconds
    _BurstReloadTime = [5,4,3]
    ; timers for weapon burst cooldown
    _BurstReload = [0,0,0]
    ; rounds per burst
    _burst = [1,4,20]
    ; rounds left in burst
    _roundsLeft = [1,4,20]
    ; time between shots in a burst
    _ReloadTime = [0,0.5,0.15]
    ; timers for reloading
    _reload = [0,0,0]
    ; dead time timer for switching weapon
    _switchDeadTime = 0
    ; on screen weapon status
    _reloading = "         "
    ; Laptop opening animation defined by description.ext
    ;cutrsc["RscLaptopOpen","PLAIN"]
    ; remember if the player had NVGs
    _removeGogs = false
    ?((Daytime < 17) and (Daytime > 7)) : goto "start"
    ; night time, force night vision by giving player goggles
    ?!(player hasweapon "NVGoggles"): _removeGogs = true;
    player removeweapon "NVGoggles"
    player addweapon "NVGoggles"
    player action["NVGoggles"]
    #start
    ~0.5
    ; orbit spherical coodinate variables
    ; azimuth
    _theta = random 360
    ; radial distance
    _r = 500
    ; polar angle
    _phi = 30
    ; cartesian conversion variables
    _rx = _r * (sin _theta) * (cos _phi)
    _ry = _r * (cos _theta) * (cos _phi)
    _rz = _r * (sin _phi)
    ; setup camera
    _camera = "camera" camCreate [(_pos select 0) + _rx, (_pos select 1) + _ry, _rz]
    _camera cameraEffect ["internal","back"]
    _camera camSetTarget _pos
    _camera camSetFOV 0.7
    _camera camCommit 0
    @camCommitted _camera
    ; remove laptop cutrsc
    cutrsc["Default","PLAIN"]
    _campos = GetPos _camera
    ; time on station
    _timeout = _time + 40
    ; camera target coordinates
    _tx = _pos select 0
    _ty = _pos select 1
    ; frame counter for on screen text
    _i = 0
    #orbit
    ; if weapon burst cooldown time over, reset burst counter and update on screen status
    ?((_roundsLeft select _currentWeapon == 0) and (_BurstReload select _currentWeapon < _time)): _roundsLeft set[_currentWeapon, _burst select _currentWeapon]; _reloading = "       "
    ; compute new azimuth
    _theta = _theta + 0.0344
    _theta = _theta mod 360
    ; convert to cartesian
    _rx = _r * (sin _theta) * (cos _phi)
    _ry = _r * (cos _theta) * (cos _phi)
    ; update camera position
    _camera camSetPos [(_pos select 0) + _rx, (_pos select 1) + _ry, _rz]
    ; update camera target
    _camera camSetTarget [_tx,_ty,0]
    ; update FOV
    _camera camsetFOV (_zoom select _currentWeapon)
    _camera camcommit 0
    @camCommitted _camera
    ; switch to manual
    _camera camCommand "Manual on"
    ; save old camera position
    _campos = getpos _camera
    ; wait for next frame
    ~0.02
    ; increment frame counter
    _i = _i + 1
    ; display on screen text every ten frames
    ?(_i == 10): _i = 0; titletext[Format["\n%1                                            %2                                %3\nAGL: %4                                                                                          %5", _WeaponNames select _currentWeapon,_reloading,(_timeout - _time),_campos select 2],"PLAIN DOWN",0.05] 
    ; detect if V pressed (camera killed), if so, restart
    ?(_camera != _camera):  goto "restart"
    ; switch manual mode off
    _camera camCommand "Manual off"
    ; check for changes in camera position due to user input
    _cx = (_panGain select _currentWeapon)*((getpos _camera select 0)-(_campos select 0))
    _cy = (_panGain select _currentWeapon)*((getpos _camera select 1)-(_campos select 1))
    _cz = ((getpos _camera select 2)-(_campos select 2))
    ; calculate distance of camera target to orbit datum
    _rx = (_pos select 0)-(_tx+_cx)
    _ry = (_pos select 1)-(_ty+_cy)
    _distance = sqrt((_rx^2)+(_ry^2))
    ; limit pan and tilt of camera
    ?(_distance < 300): _tx = _tx + _cx; _ty = _ty + _cy
    ; check for increase in camera AGL due to "move up" pressed
    ?((_cz > 0.05) and (_switchDeadTime < _time) and (_cx == 0) and (_cy == 0)): goto "switchWeapon"
    ; check for decrease in camera AGL due to "move down" pressed
    ?((_cz < -0.05) and (_cx == 0) and (_cy == 0)): goto "fire"
    ?((_timeout > _time) and (alive player)) : goto "orbit"
    #end
    ; if player didn't have goggles remove them
    ?(_removeGogs) : player removeweapon "NVGoggles"
    _camera cameraEffect ["Terminate","back"]
    _camera camcommit 0
    @camcommitted _camera
    camDestroy _camera
    ; Laptop closing animation defined in description.ext, requires custom .rtm file
    ;cutrsc["RscLaptopClose","PLAIN"]
    ~0.5
    ; destroy local objects
    cutrsc["Default","PLAIN"]
    camdestroy _sealevelref
    camdestroy _target
    exit
    #switchWeapon
    _currentWeapon = _currentWeapon + 1
    ; clip index
    ?(_currentWeapon == 3): _currentWeapon = 0
    ; set deadtime timer
    _switchDeadTime = _time + 0.5
    ; update on screen status
    _reloading = "       "
    ?((_roundsLeft select _currentWeapon == 0) or (_time < _reload select _currentWeapon)): _reloading = "RELOADING"
    goto "orbit"
    #fire
    ; check if any rounds are left in the gun
    ?((_roundsLeft select _currentWeapon == 0) or (_time < _reload select _currentWeapon)): goto "orbit"
    ; update target position
    _target setpos [_tx,_ty,0]
    _reloading = "        "
    ; set the reload timer (time between shots)
    _reload set[_currentWeapon, _time + (_ReloadTime select _currentWeapon)]
    ; decrement rounds left in burst
    _roundsLeft set[_currentWeapon,(_roundsLeft select _currentWeapon) - 1]
    ; calculate ASL (manually for v1.96 compatiblility)
    _distance = _camera distance _sealevelref
    _cameraHeight = sqrt((_distance^2) - (((_campos select 0)^2) + ((_campos select 1)^2)))
    _distance = _target distance _sealevelref
    _targetHeight = sqrt((_distance^2) - ((_tx^2) + (_ty^2)))
    ; calculate distance to target
    _rx = (_campos select 0)-_tx
    _ry = (_campos select 1)-_ty
    _distance = (sqrt((_rx^2)+(_ry^2)))
    ; calculate polar angle of target to camera
    _gunPhi = ((_cameraHeight - _targetHeight) atan2 _distance)
    ; calculate azimuth of target to camera
    _gunTheta = _rx atan2 _ry
    ; calculate velocity vector
    _vx = (_MuzzleVelocity select _currentWeapon)*(cos _gunPhi)*-(sin _gunTheta)
    _vy = (_MuzzleVelocity select _currentWeapon)*(cos _gunPhi)*-(cos _gunTheta)
    _vz = (_MuzzleVelocity select _currentWeapon)*-(sin _gunPhi)
    ; spawn round
    _round = (_WeaponClasses select _currentWeapon) createvehicle _campos
    ; "fire" the round
    _round setdir _gunTheta
    _round setvelocity [_vx,_vy,_vz]
    ; play the weapon sound
    ;playsound (_sounds select _currentWeapon)
    ; check burst status
    ?(_roundsLeft select _currentWeapon != 0): goto "orbit"
    ; burst completed update on screen status and set cooldown timer
    _reloading = "RELOADING"
    _BurstReload set[_currentWeapon, _time + (_BurstReloadTime select _currentWeapon)]
    goto "orbit"
    #restart
    titletext["","BLACK IN",10];
    ~0.1
    titletext["","BLACK IN",0.1];
    ?(alive _camera): camDestroy _camera
    _camera = "camera" camCreate [(_pos select 0) + _rx, (_pos select 1) + _ry, _rz]
    _camera cameraEffect ["internal","back"]
    _camera camSetTarget [_tx,_ty,0]
    _camera camsetFOV (_zoom select _currentWeapon)
    _camera camcommit 0
    @camcommitted _camera
    goto "orbit"
    Last edited by *Zeewolf*; May 19 2012 at 15:37. Reason: Corrected restart code

  2. #2
    Is this multiplayer only? If not, how do you install/run it for singleplayer?

    Thanks
    Last edited by Blitzen; May 19 2012 at 01:17.

  3. #3
    The script is designed to be used as a multiplayer killstreak reward but it will work in single player, the main things you may want to change are the 40 second time limit (_timeout = _time + 40) and the weapon burst limits (_burst).

    If you're planning on recreating a certain classic COD4 mission then you'll also need to create a method of moving the position that the camera orbits in response to the player's progress, the easiest way to do this would be to make _pos global and move it around (very slowly) using a second script. As I mentioned above, you could also replace the orbit spherical coordinate code with code to "attach" the camera to the side of an aircraft which is controlled with standard waypoints. If you're thinking of adding audio commentary then that too would best be done by a second script.

    For a quick test just call the script using a trigger from the mission editor. It depends on where you want the camera to orbit when it spawns. If you just want it to orbit the player's position then call it with [getpos player] exec "ac130.sqs" (assuming you save the script as ac130.sqs in the mission folder).

    Alternatively you can use the map to specify the orbit position by calling it from a second script and adding OnMapSingleClick{} to the first line of the ac130 script.

    Code:
    ; request_ac130.sqs
    [side player,"AIRBASE"] sidechat "AC-130 ready for deployment."
    ~1
    [side player,"AIRBASE"] sidechat "Click on map to provide coordinates."
    onMapSingleClick {[_pos] exec "ac130.sqs"}
    The request script could be then called from a radio trigger. For example (as it would appear in mission.sqm):

    Code:
    class Sensors
    {
    	items=1;
    	class Item0
    	{
    		position[]={6144.855469,178.128052,9559.442383};
    		a=0.000000;
    		b=0.000000;
    		activationBy="JULIET";
    		repeating=1;
    		age="UNKNOWN";
    		text="Request AC130";
    		expActiv="[] exec ""request_ac130.sqs""";
    		class Effects
    		{
    		};
    	};
    };
    As I've mentioned before, if I do release an example of this it will be part of the much larger killstreak/create-a-class framework I've been working on, but lots needs to happen before that project can be released publicly (if I even decide to do so).

  4. #4
    Quote Originally Posted by *Zeewolf* View Post
    As I mentioned above, you could also replace the orbit spherical coordinate code with code to "attach" the camera to the side of an aircraft which is controlled with standard waypoints.
    How would this be done? I have an AC-130 Gunship addon and Im interested in attaching this camera/script to it.

    Thanks for the help!

  5. #5
    Quote Originally Posted by Blitzen View Post
    How would this be done? I have an AC-130 Gunship addon and Im interested in attaching this camera/script to it.

    Thanks for the help!
    Well...

    There are a number of limitations if you try to attach the camera to the object. The main problem is the script relies on the camera height being kept almost constant from one frame to another. If you tie the height of the camera to the height of the plane then it will falsely trigger the weapon selection and firing. Fortunately there is a solution which will work for single player (and multiplayer as long as the pilot is AI), since the AI pilots always fly at or very near their set FlyInHeight (default 100) then the script can simply glue to their X and Y positions while following their ideal AGL flight path.

    Usage for this "glued" version is [plane,plane width, plane flyInHeight] exec "ac130glued.sqs".

    So for an example mission set an AI cessna named plane flying in a loose circle anti-clockwise around a village (six cycled waypoints should do). Then add a radio trigger with [plane,3,100] exec "ac130glued.sqs".

    For larger planes you'll need to adjust the width setting so that the camera remains "outside" of the aircraft.

    Code:
    ; AC-130 Glue script
    ; move forward/move backward/move left/move right pans camera
    ; move up changes weapon (105mm M102, 40mm Bofors L/60, 25mm GAU-12)
    ; move down fires weapon
    ; plane to tie camera to
    _plane = _this select 0
    ; distance from centre of plane to place camera
    _planeWidth = _this select 1
    ; flyinheight of the plane
    _planeFlyInHeight = _this select 2
    ; sea level reference for manual ASL calculation
    _sealevelref = "logic" camcreate [0,0,0]
    ; selected weapon number
    _currentWeapon = 0
    ; on screen weapon names
    _weaponNames = ["105mm","40mm","25mm"]
    ; sound class names defined by descrition.ext or config cfgSounds
    _sounds = ["m102","bofors","gau12"]
    ; cfgammo class names
    _weaponClasses = ["shell125","shell73","Bullet4x23"]
    ; FOVs
    _zoom = [0.4,0.15,0.05]
    ; Pan/tilt sensitivity to compensate for change in FOV
    _panGain = [60,30,15]
    ; muzzle velocities in m/s
    _MuzzleVelocity = [737,881,1040]
    ; time between bursts/seconds
    _BurstReloadTime = [5,4,3]
    ; timers for weapon burst cooldown
    _BurstReload = [0,0,0]
    ; rounds per burst
    _burst = [1,4,20]
    ; rounds left in burst
    _roundsLeft = [1,4,20]
    ; time between shots in a burst
    _ReloadTime = [0,0.5,0.15]
    ; timers for reloading
    _reload = [0,0,0]
    ; dead time timer for switching weapon
    _switchDeadTime = 0
    ; on screen weapon status
    _reloading = "         "
    ; Laptop opening animation defined by description.ext
    ;cutrsc["RscLaptopOpen","PLAIN"]
    ; remember if the player had NVGs
    _removeGogs = false
    ?((Daytime < 17) and (Daytime > 7)) : goto "start"
    ; night time, force night vision by giving player goggles
    ?!(player hasweapon "NVGoggles"): _removeGogs = true;
    player removeweapon "NVGoggles"
    player addweapon "NVGoggles"
    player action["NVGoggles"]
    #start
    ~0.5
    ; distance to initial target
    _r = 500
    ; get plane position and direction
    _direction = getdir _plane
    _campos = [(getpos _plane select 0) + (_planeWidth * sin (_direction - 90)),(getpos _plane select 1) + (_planeWidth * cos (_direction - 90)),_planeFlyInHeight]
    ; set target position
    _pos = [(_campos select 0) + (_r*sin (_direction - 90)),(_campos select 1)+(_r*cos (_direction-90)),0]
    ; target marker for manual ASL calculation
    _target = "logic" camcreate _pos
    ; setup camera
    _camera = "camera" camCreate _campos
    _camera cameraEffect ["internal","back"]
    _camera camSetTarget _pos
    _camera camSetFOV 0.7
    _camera camCommit 0
    @camCommitted _camera
    ; remove laptop cutrsc
    cutrsc["Default","PLAIN"]
    _campos = GetPos _camera
    ; time on station
    _timeout = _time + 40
    ; camera target coordinates
    _tx = _pos select 0
    _ty = _pos select 1
    ; frame counter for on screen text
    _i = 0
    #orbit
    ; if weapon burst cooldown time over, reset burst counter and update on screen status
    ?((_roundsLeft select _currentWeapon == 0) and (_BurstReload select _currentWeapon < _time)): _roundsLeft set[_currentWeapon, _burst select _currentWeapon]; _reloading = "       "
    ; calculate new positions
    _direction = getdir _plane
    _campos = [(getpos _plane select 0) + (_planeWidth * sin (_direction - 90)),(getpos _plane select 1) + (_planeWidth * cos (_direction - 90)),_planeFlyInHeight]
    _pos = [(_campos select 0) + (_r*sin (_direction - 90)),(_campos select 1)+(_r*cos (_direction-90)),0]
    ; update camera position
    _camera camSetPos _campos
    ; update camera target
    _camera camSetTarget [_tx,_ty,0]
    ; update FOV
    _camera camsetFOV (_zoom select _currentWeapon)
    _camera camcommit 0
    @camCommitted _camera
    ; switch to manual
    _camera camCommand "Manual on"
    ; wait for next frame
    _campos = getpos _camera
    ~0.02
    ; increment frame counter
    _i = _i + 1
    ; display on screen text every ten frames
    ?(_i == 10): _i = 0; titletext[Format["\n%1                                            %2                                %3\nAGL: %4                                                                                          %5", _WeaponNames select _currentWeapon,_reloading,(_timeout - _time),getpos plane select 2],"PLAIN DOWN",0.05] 
    ; detect if V pressed (camera killed), if so, restart
    ?(_camera != _camera):  goto "restart"
    ; switch manual mode off
    _camera camCommand "Manual off"
    ; check for changes in camera position due to user input
    _cx = (_panGain select _currentWeapon)*((getpos _camera select 0)-(_campos select 0))
    _cy = (_panGain select _currentWeapon)*((getpos _camera select 1)-(_campos select 1))
    _cz = ((getpos _camera select 2)-(_campos select 2))
    ; calculate distance of camera target to orbit datum
    _rx = (_pos select 0)-(_tx+_cx)
    _ry = (_pos select 1)-(_ty+_cy)
    _distance = sqrt((_rx^2)+(_ry^2))
    ; limit pan and tilt of camera
    ?(_distance < 300): _tx = _tx + _cx; _ty = _ty + _cy
    ?(_distance > 350): titletext["","BLACK IN",0.1]; _tx = _pos select 0; _ty = _pos select 1
    ; check for increase in camera AGL due to "move up" pressed
    ?((_cz > 0.05) and (_switchDeadTime < _time) and (_cx == 0) and (_cy == 0)): goto "switchWeapon"
    ; check for decrease in camera AGL due to "move down" pressed
    ?((_cz < -0.1) and (_cx == 0) and (_cy == 0)): goto "fire"
    ?((_timeout > _time) and (alive player) and (alive plane)) : goto "orbit"
    #end
    ; if player didn't have goggles remove them
    ?(_removeGogs) : player removeweapon "NVGoggles"
    _camera cameraEffect ["Terminate","back"]
    _camera camcommit 0
    @camcommitted _camera
    camDestroy _camera
    ; Laptop closing animation defined in description.ext, requires custom .rtm file
    ;cutrsc["RscLaptopClose","PLAIN"]
    ~0.5
    ; destroy local objects
    cutrsc["Default","PLAIN"]
    camdestroy _sealevelref
    camdestroy _target
    exit
    #switchWeapon
    _currentWeapon = _currentWeapon + 1
    ; clip index
    ?(_currentWeapon == 3): _currentWeapon = 0
    ; set deadtime timer
    _switchDeadTime = _time + 0.5
    ; update on screen status
    _reloading = "       "
    ?((_roundsLeft select _currentWeapon == 0) or (_time < _reload select _currentWeapon)): _reloading = "RELOADING"
    goto "orbit"
    #fire
    ; check if any rounds are left in the gun
    ?((_roundsLeft select _currentWeapon == 0) or (_time < _reload select _currentWeapon)): goto "orbit"
    ; update target position
    _target setpos [_tx,_ty,0]
    _reloading = "        "
    ; set the reload timer (time between shots)
    _reload set[_currentWeapon, _time + (_ReloadTime select _currentWeapon)]
    ; decrement rounds left in burst
    _roundsLeft set[_currentWeapon,(_roundsLeft select _currentWeapon) - 1]
    ; calculate ASL (manually for v1.96 compatiblility)
    _distance = _camera distance _sealevelref
    _cameraHeight = sqrt((_distance^2) - (((_campos select 0)^2) + ((_campos select 1)^2)))
    _distance = _target distance _sealevelref
    _targetHeight = sqrt((_distance^2) - ((_tx^2) + (_ty^2)))
    ; calculate distance to target
    _rx = (_campos select 0)-_tx
    _ry = (_campos select 1)-_ty
    _distance = (sqrt((_rx^2)+(_ry^2)))
    ; calculate polar angle of target to camera
    _gunPhi = ((_cameraHeight - _targetHeight) atan2 _distance)
    ; calculate azimuth of target to camera
    _gunTheta = _rx atan2 _ry
    ; calculate velocity vector
    _vx = (_MuzzleVelocity select _currentWeapon)*(cos _gunPhi)*-(sin _gunTheta)
    _vy = (_MuzzleVelocity select _currentWeapon)*(cos _gunPhi)*-(cos _gunTheta)
    _vz = (_MuzzleVelocity select _currentWeapon)*-(sin _gunPhi)
    ; spawn round
    _round = (_WeaponClasses select _currentWeapon) createvehicle _campos
    ; "fire" the round
    _round setdir _gunTheta
    _round setvelocity [_vx,_vy,_vz]
    ; play the weapon sound
    ;playsound (_sounds select _currentWeapon)
    ; check burst status
    ?(_roundsLeft select _currentWeapon != 0): goto "orbit"
    ; burst completed update on screen status and set cooldown timer
    _reloading = "RELOADING"
    _BurstReload set[_currentWeapon, _time + (_BurstReloadTime select _currentWeapon)]
    goto "orbit"
    #restart
    titletext["","BLACK IN",10];
    ~0.1
    titletext["","BLACK IN",0.1];
    ?(alive _camera): camDestroy _camera
    _camera = "camera" camCreate _campos
    _camera cameraEffect ["internal","back"]
    _camera camSetTarget [_tx,_ty,0]
    _camera camsetFOV (_zoom select _currentWeapon)
    _camera camcommit 0
    @camcommitted _camera
    goto "orbit"
    You can see how closely the plane sticks to it's flyinheight from the AGL display. A human pilot would need to do the same for this version of the script to work on a player piloted aircraft. I wrote this version in about two hours so consider it a fudge. There are many ways it could be enhanced, for example; using the aircraft's bank angle to set the target position and running the plane's height through a low pass filter, then use the filtered version of the height to glue the camera to the plane.

    Addendum: I forgot to mention about muzzle velocities. Since the script does not compensate for bullet drop, using a (realistic) muzzle velocity of 472ms-1 (as done in the version shown in the first post) you will find the howitzer requires significant adjustment when attacking targets. To eliminate this, increase it to something like 700ms-1. Also, the 40mm really needs a custom cfgAmmo entry, since the 73mm heat round is over-powered and doesn't provide tracers (I think the real gun uses 40mm HEI-T).
    Last edited by *Zeewolf*; Jun 17 2012 at 16:54. Reason: Fixed glued script not following passed fly in height

  6. #6
    Quote Originally Posted by *Zeewolf* View Post
    Well...

    There are a number of limitations if you try to attach the camera to the object. The main problem is the script relies on the camera height being kept almost constant from one frame to another. If you tie the height of the camera to the height of the plane then it will falsely trigger the weapon selection and firing. Fortunately there is a solution which will work for single player (and multiplayer as long as the pilot is AI), since the AI pilots always fly at or very near their set FlyInHeight (default 100) then the script can simply glue to their X and Y positions while following their ideal AGL flight path.

    Usage for this "glued" version is [plane,plane width, plane flyInHeight] exec "ac130glued.sqs".

    So for an example mission set an AI cessna named plane flying in a loose circle anti-clockwise around a village (six cycled waypoints should do). Then add a radio trigger with [plane,3,100] exec "ac130glued.sqs".

    For larger planes you'll need to adjust the width setting so that the camera remains "outside" of the aircraft.

    Code:
    ; AC-130 Glue script
    ; move forward/move backward/move left/move right pans camera
    ; move up changes weapon (105mm M102, 40mm Bofors L/60, 25mm GAU-12)
    ; move down fires weapon
    ; plane to tie camera to
    _plane = _this select 0
    ; distance from centre of plane to place camera
    _planeWidth = _this select 1
    ; flyinheight of the plane
    _planeFlyInHeight = _this select 2
    ; sea level reference for manual ASL calculation
    _sealevelref = "logic" camcreate [0,0,0]
    ; selected weapon number
    _currentWeapon = 0
    ; on screen weapon names
    _weaponNames = ["105mm","40mm","25mm"]
    ; sound class names defined by descrition.ext or config cfgSounds
    _sounds = ["m102","bofors","gau12"]
    ; cfgammo class names
    _weaponClasses = ["shell125","shell73","Bullet4x23"]
    ; FOVs
    _zoom = [0.4,0.15,0.05]
    ; Pan/tilt sensitivity to compensate for change in FOV
    _panGain = [60,30,15]
    ; muzzle velocities in m/s
    _MuzzleVelocity = [737,881,1040]
    ; time between bursts/seconds
    _BurstReloadTime = [5,4,3]
    ; timers for weapon burst cooldown
    _BurstReload = [0,0,0]
    ; rounds per burst
    _burst = [1,4,20]
    ; rounds left in burst
    _roundsLeft = [1,4,20]
    ; time between shots in a burst
    _ReloadTime = [0,0.5,0.15]
    ; timers for reloading
    _reload = [0,0,0]
    ; dead time timer for switching weapon
    _switchDeadTime = 0
    ; on screen weapon status
    _reloading = "         "
    ; Laptop opening animation defined by description.ext
    ;cutrsc["RscLaptopOpen","PLAIN"]
    ; remember if the player had NVGs
    _removeGogs = false
    ?((Daytime < 17) and (Daytime > 7)) : goto "start"
    ; night time, force night vision by giving player goggles
    ?!(player hasweapon "NVGoggles"): _removeGogs = true;
    player removeweapon "NVGoggles"
    player addweapon "NVGoggles"
    player action["NVGoggles"]
    #start
    ~0.5
    ; distance to initial target
    _r = 500
    ; get plane position and direction
    _direction = getdir _plane
    _campos = [(getpos _plane select 0) + (_planeWidth * sin (_direction - 90)),(getpos _plane select 1) + (_planeWidth * cos (_direction - 90)),_planeFlyInHeight]
    ; set target position
    _pos = [(_campos select 0) + (_r*sin (_direction - 90)),(_campos select 1)+(_r*cos (_direction-90)),0]
    ; target marker for manual ASL calculation
    _target = "logic" camcreate _pos
    ; setup camera
    _camera = "camera" camCreate _campos
    _camera cameraEffect ["internal","back"]
    _camera camSetTarget _pos
    _camera camSetFOV 0.7
    _camera camCommit 0
    @camCommitted _camera
    ; remove laptop cutrsc
    cutrsc["Default","PLAIN"]
    _campos = GetPos _camera
    ; time on station
    _timeout = _time + 40
    ; camera target coordinates
    _tx = _pos select 0
    _ty = _pos select 1
    ; frame counter for on screen text
    _i = 0
    #orbit
    ; if weapon burst cooldown time over, reset burst counter and update on screen status
    ?((_roundsLeft select _currentWeapon == 0) and (_BurstReload select _currentWeapon < _time)): _roundsLeft set[_currentWeapon, _burst select _currentWeapon]; _reloading = "       "
    ; calculate new positions
    _direction = getdir _plane
    _campos = [(getpos _plane select 0) + (_planeWidth * sin (_direction - 90)),(getpos _plane select 1) + (_planeWidth * cos (_direction - 90)),_planeFlyInHeight]
    _pos = [(_campos select 0) + (_r*sin (_direction - 90)),(_campos select 1)+(_r*cos (_direction-90)),0]
    ; update camera position
    _camera camSetPos _campos
    ; update camera target
    _camera camSetTarget [_tx,_ty,0]
    ; update FOV
    _camera camsetFOV (_zoom select _currentWeapon)
    _camera camcommit 0
    @camCommitted _camera
    ; switch to manual
    _camera camCommand "Manual on"
    ; wait for next frame
    _campos = getpos _camera
    ~0.02
    ; increment frame counter
    _i = _i + 1
    ; display on screen text every ten frames
    ?(_i == 10): _i = 0; titletext[Format["\n%1                                            %2                                %3\nAGL: %4                                                                                          %5", _WeaponNames select _currentWeapon,_reloading,(_timeout - _time),getpos plane select 2],"PLAIN DOWN",0.05] 
    ; detect if V pressed (camera killed), if so, restart
    ?(_camera != _camera):  goto "restart"
    ; switch manual mode off
    _camera camCommand "Manual off"
    ; check for changes in camera position due to user input
    _cx = (_panGain select _currentWeapon)*((getpos _camera select 0)-(_campos select 0))
    _cy = (_panGain select _currentWeapon)*((getpos _camera select 1)-(_campos select 1))
    _cz = ((getpos _camera select 2)-(_campos select 2))
    ; calculate distance of camera target to orbit datum
    _rx = (_pos select 0)-(_tx+_cx)
    _ry = (_pos select 1)-(_ty+_cy)
    _distance = sqrt((_rx^2)+(_ry^2))
    ; limit pan and tilt of camera
    ?(_distance < 300): _tx = _tx + _cx; _ty = _ty + _cy
    ?(_distance > 350): titletext["","BLACK IN",0.1]; _tx = _pos select 0; _ty = _pos select 1
    ; check for increase in camera AGL due to "move up" pressed
    ?((_cz > 0.05) and (_switchDeadTime < _time) and (_cx == 0) and (_cy == 0)): goto "switchWeapon"
    ; check for decrease in camera AGL due to "move down" pressed
    ?((_cz < -0.1) and (_cx == 0) and (_cy == 0)): goto "fire"
    ?((_timeout > _time) and (alive player) and (alive plane)) : goto "orbit"
    #end
    ; if player didn't have goggles remove them
    ?(_removeGogs) : player removeweapon "NVGoggles"
    _camera cameraEffect ["Terminate","back"]
    _camera camcommit 0
    @camcommitted _camera
    camDestroy _camera
    ; Laptop closing animation defined in description.ext, requires custom .rtm file
    ;cutrsc["RscLaptopClose","PLAIN"]
    ~0.5
    ; destroy local objects
    cutrsc["Default","PLAIN"]
    camdestroy _sealevelref
    camdestroy _target
    exit
    #switchWeapon
    _currentWeapon = _currentWeapon + 1
    ; clip index
    ?(_currentWeapon == 3): _currentWeapon = 0
    ; set deadtime timer
    _switchDeadTime = _time + 0.5
    ; update on screen status
    _reloading = "       "
    ?((_roundsLeft select _currentWeapon == 0) or (_time < _reload select _currentWeapon)): _reloading = "RELOADING"
    goto "orbit"
    #fire
    ; check if any rounds are left in the gun
    ?((_roundsLeft select _currentWeapon == 0) or (_time < _reload select _currentWeapon)): goto "orbit"
    ; update target position
    _target setpos [_tx,_ty,0]
    _reloading = "        "
    ; set the reload timer (time between shots)
    _reload set[_currentWeapon, _time + (_ReloadTime select _currentWeapon)]
    ; decrement rounds left in burst
    _roundsLeft set[_currentWeapon,(_roundsLeft select _currentWeapon) - 1]
    ; calculate ASL (manually for v1.96 compatiblility)
    _distance = _camera distance _sealevelref
    _cameraHeight = sqrt((_distance^2) - (((_campos select 0)^2) + ((_campos select 1)^2)))
    _distance = _target distance _sealevelref
    _targetHeight = sqrt((_distance^2) - ((_tx^2) + (_ty^2)))
    ; calculate distance to target
    _rx = (_campos select 0)-_tx
    _ry = (_campos select 1)-_ty
    _distance = (sqrt((_rx^2)+(_ry^2)))
    ; calculate polar angle of target to camera
    _gunPhi = ((_cameraHeight - _targetHeight) atan2 _distance)
    ; calculate azimuth of target to camera
    _gunTheta = _rx atan2 _ry
    ; calculate velocity vector
    _vx = (_MuzzleVelocity select _currentWeapon)*(cos _gunPhi)*-(sin _gunTheta)
    _vy = (_MuzzleVelocity select _currentWeapon)*(cos _gunPhi)*-(cos _gunTheta)
    _vz = (_MuzzleVelocity select _currentWeapon)*-(sin _gunPhi)
    ; spawn round
    _round = (_WeaponClasses select _currentWeapon) createvehicle _campos
    ; "fire" the round
    _round setdir _gunTheta
    _round setvelocity [_vx,_vy,_vz]
    ; play the weapon sound
    ;playsound (_sounds select _currentWeapon)
    ; check burst status
    ?(_roundsLeft select _currentWeapon != 0): goto "orbit"
    ; burst completed update on screen status and set cooldown timer
    _reloading = "RELOADING"
    _BurstReload set[_currentWeapon, _time + (_BurstReloadTime select _currentWeapon)]
    goto "orbit"
    #restart
    titletext["","BLACK IN",10];
    ~0.1
    titletext["","BLACK IN",0.1];
    ?(alive _camera): camDestroy _camera
    _camera = "camera" camCreate _campos
    _camera cameraEffect ["internal","back"]
    _camera camSetTarget [_tx,_ty,0]
    _camera camsetFOV (_zoom select _currentWeapon)
    _camera camcommit 0
    @camcommitted _camera
    goto "orbit"
    You can see how closely the plane sticks to it's flyinheight from the AGL display. A human pilot would need to do the same for this version of the script to work on a player piloted aircraft. I wrote this version in about two hours so consider it a fudge. There are many ways it could be enhanced, for example; using the aircraft's bank angle to set the target position and running the plane's height through a low pass filter, then use the filtered version of the height to glue the camera to the plane.

    Addendum: I forgot to mention about muzzle velocities. Since the script does not compensate for bullet drop, using a (realistic) muzzle velocity of 472ms-1 (as done in the version shown in the first post) you will find the howitzer requires significant adjustment when attacking targets. To eliminate this, increase it to something like 700ms-1. Also, the 40mm really needs a custom cfgAmmo entry, since the 73mm heat round is over-powered and doesn't provide tracers (I think the real gun uses 40mm HEI-T).
    How i can control the weapon and can increase time for this camera??

  7. #7
    Quote Originally Posted by azharbehind View Post
    How i can control the weapon and can increase time for this camera??
    If you read the comment lines in the script you will notice it says ";Move up changes weapon (105mm M102, 40mm Bofors L/60, 25mm GAU-12)" This means that if you press the move up key ("Q" by default) it will cycle through the weapons in that order. Move down fires the selected weapon ("Z" by default).

    If you look a bit further down (line 75) you will see the "time on station" setting is currently "_timeout = _time + 40" which means 40 seconds. This is just to match the equivalent Modern Warfare 2 killstreak time, increase it to whatever value you want.

    Fans of this script may be interested to know that the version to be included in my MWC mod will include support for AC-130 commentary. Specifically a "Shot!" announcement when the 105mm is fired and a "Gun ready!" announcement when the 105mm has been reloaded. It will also support idle intercom chatter (e.g. such classics as "Recalibrate azimuth sweep angle, adjust elevation scan"). The released mod will not include the audio files for these voices for obvious reasons, but I'll provide some basic instructions on how to add your own audio files to the mod to enable this feature and the audio for the faction multiplayer commentators.

Similar Threads

  1. AC-130 Script for ARMA2 (0.3)
    By LurchiDerLurch in forum ARMA 2 & OA - ADDONS & MODS: COMPLETE
    Replies: 688
    Last Post: Feb 23 2013, 13:13
  2. AC-130 script
    By resistance-rat in forum ARMA 2 & OA : MISSIONS - Editing & Scripting
    Replies: 11
    Last Post: Dec 10 2010, 21:45
  3. C-130 Carpet bomb script
    By G-Man-853 in forum ARMA 2 & OA : MISSIONS - Editing & Scripting
    Replies: 5
    Last Post: Dec 1 2010, 10:31
  4. Camera script not entering camera loop with Attachto command in it.
    By Omnicide_Perez in forum ARMA 2 & OA : MISSIONS - Editing & Scripting
    Replies: 2
    Last Post: Nov 21 2010, 21:11
  5. AC-130 script
    By ruff in forum OFP : MISSION EDITING & SCRIPTING
    Replies: 0
    Last Post: Oct 17 2004, 04:37

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •