Jump to content
Sign in to follow this  
*zeewolf*

AC-130 camera script

Recommended Posts

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.

; 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"

Edited by *Zeewolf*
Corrected restart code

Share this post


Link to post
Share on other sites

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

Thanks

Edited by Blitzen

Share this post


Link to post
Share on other sites

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.

; 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):

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).

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites
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.

; 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).

Edited by *Zeewolf*
Fixed glued script not following passed fly in height

Share this post


Link to post
Share on other sites
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.

; 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??

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×