This is a simple filterscript that provides autocannon for air vehicles (tested with maverick)
By pressing fire button, chopper fires series of cannon rounds which explode on impact onto ground.
Shots are fired into camera direction.
pawn Код:
/*
* 30mm Autocannon for SA:MP air vehicles
*
*
*/
#include <a_samp>
#include <mapandreas>
#define AC_PROJECTILE_DRAW_DISTANCE 150.0
#define AC_EXPLOSION_TYPE 2
#define AC_EXPLOSION_RADIUS 10.0
#define AC_AIM_SWAY 0.02
#define AC_EXPLOSION_SWAY 1.0
#define AC_SPEED 100.0
#define AC_TIMER_INTERVAL 100
#define AC_PROJECTILES_PER_TICK 1
#define AC_PROJECTILE_OBJECT_ID 354
#define AC_KEY_GUN KEY_FIRE
#define AC_SCALE 5.0
#define AC_MAX_PROJECTILES_PER_PLAYER 50
#define AC_MAX_STEPS 200 // max timer ticks projectile alive
#define AC_BURST_SIZE 10
#define AC_COOLDOWN 3000
#define FSTR(%0,%1) new %0[128]; \
format(%0, 128, %1)
forward ACUpdate();
forward ACBlow(playerid, projId, Float:PX, Float:PY, Float:PZ);
forward Float:ac_floatrand(Float:max, Float:min = 0.0, dp = 4);
stock Float:GetGroundZ(Float:x, Float:y);
enum AC_PROJECTILE
{
bool:enabled,
Float:pos[3],
Float:vector[3],
objectId,
steps,
bool:explode
}
new acProjectiles[MAX_PLAYERS][AC_MAX_PROJECTILES_PER_PLAYER][AC_PROJECTILE];
new acProjectileCount[MAX_PLAYERS];
new acIsFiring[MAX_PLAYERS];
new acFiredLastTime[MAX_PLAYERS];
new acFireCount[MAX_PLAYERS];
public OnFilterScriptInit()
{
print("\n--------------------------------------");
print(" Autocannon script by Teprey");
print("--------------------------------------\n");
SetTimer("ACUpdate", AC_TIMER_INTERVAL, true);
return 1;
}
public ACBlow(playerid, projId, Float:PX, Float:PY, Float:PZ)
{
DestroyObject(acProjectiles[playerid][projId][objectId]);
acProjectiles[playerid][projId][enabled] = false;
CreateExplosion(ac_floatrand(PX + AC_EXPLOSION_SWAY, PX - AC_EXPLOSION_SWAY),
ac_floatrand(PY + AC_EXPLOSION_SWAY, PY - AC_EXPLOSION_SWAY),
ac_floatrand(PZ + AC_EXPLOSION_SWAY, PZ) + 1.0, AC_EXPLOSION_TYPE, AC_EXPLOSION_RADIUS);
}
public ACUpdate()
{
for (new playerid = 0 ; playerid < MAX_PLAYERS ; playerid++)
{
if (acIsFiring[playerid] == 1)
{
if ((acFiredLastTime[playerid] - tickcount() + AC_COOLDOWN) < 0) {
if (acFireCount[playerid] > AC_BURST_SIZE) { acFireCount[playerid] = 0; acFiredLastTime[playerid] = tickcount(); }
if (IsPlayerInAnyVehicle(playerid))
{
new vehId = GetPlayerVehicleID(playerid);
if (IsVehicleAirVehicle(GetVehicleModel(vehId)))
{
new
Float:fPX, Float:fPY, Float:fPZ;
//GetVehiclePos(vehId, fPX, fPY, fPZ);
GetPlayerCameraPos(playerid, fPX, fPY, fPZ);
for (new it = 0 ; it < AC_PROJECTILES_PER_TICK ; it++)
{
ac_Fire(playerid, fPX, fPY, fPZ);
acFireCount[playerid]++;
}
}
}
}
}
for (new projId = 0 ; projId < AC_MAX_PROJECTILES_PER_PLAYER ; projId++)
{
if (acProjectiles[playerid][projId][enabled] == false) { continue; }
if (acProjectiles[playerid][projId][explode]) continue;
new
Float:PX, Float:PY, Float:PZ,
Float:fVX, Float:fVY, Float:fVZ,
Float:object_x, Float:object_y, Float:object_z, bool:fire;
fVX = acProjectiles[playerid][projId][vector][0];
fVY = acProjectiles[playerid][projId][vector][1];
fVZ = acProjectiles[playerid][projId][vector][2];
PX = acProjectiles[playerid][projId][pos][0];
PY = acProjectiles[playerid][projId][pos][1];
PZ = acProjectiles[playerid][projId][pos][2];
object_x = PX + floatmul(fVX, AC_SPEED);
object_y = PY + floatmul(fVY, AC_SPEED);
new Float:groundZ = GetGroundZ(object_x, object_y);
object_z = PZ + floatmul(fVZ, AC_SPEED);
if (groundZ > object_z)
{
fire = true;
}
acProjectiles[playerid][projId][pos][0] = object_x;
acProjectiles[playerid][projId][pos][1] = object_y;
acProjectiles[playerid][projId][pos][2] = object_z;
new time = MoveObject(acProjectiles[playerid][projId][objectId], object_x, object_y, object_z, AC_SPEED);
if (fire == true) { SetTimerEx("ACBlow", time, false, "iifff", playerid, projId, object_x, object_y, groundZ); }
acProjectiles[playerid][projId][steps]++;
if (acProjectiles[playerid][projId][steps] > AC_MAX_STEPS) { DestroyObject(acProjectiles[playerid][projId][objectId]);
acProjectiles[playerid][projId][steps] =0;
acProjectiles[playerid][projId][enabled] = false;
}
}
}
}
public OnFilterScriptExit()
{
return 1;
}
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
if ((newkeys & AC_KEY_GUN))
{
acIsFiring[playerid] = 1;
}
if (!(newkeys & AC_KEY_GUN) && (oldkeys & AC_KEY_GUN))
{
acIsFiring[playerid] = 0;
}
return 1;
}
stock ac_Fire(playerid, Float:posX, Float:posY, Float:posZ)
{
new
Float:fVX, Float:fVY, Float:fVZ,
Float:object_x, Float:object_y, Float:object_z;
GetPlayerCameraFrontVector(playerid, fVX, fVY, fVZ);
fVX = floatadd(fVX, ac_floatrand(AC_AIM_SWAY, floatsub(0.0, AC_AIM_SWAY)));
fVY = floatadd(fVY, ac_floatrand(AC_AIM_SWAY, floatsub(0.0, AC_AIM_SWAY)));
fVZ = floatadd(fVZ, ac_floatrand(AC_AIM_SWAY, floatsub(0.0, AC_AIM_SWAY)));
object_x = posX + floatmul(fVX, AC_SCALE);
object_y = posY + floatmul(fVY, AC_SCALE);
object_z = posZ + floatmul(fVZ, AC_SCALE);
new objId = CreateObject(AC_PROJECTILE_OBJECT_ID, object_x, object_y, object_z, 0, 0, 0, AC_PROJECTILE_DRAW_DISTANCE);
acProjectiles[playerid][acProjectileCount[playerid]][pos][0] = object_x;
acProjectiles[playerid][acProjectileCount[playerid]][pos][1] = object_y;
acProjectiles[playerid][acProjectileCount[playerid]][pos][2] = object_z;
acProjectiles[playerid][acProjectileCount[playerid]][vector][0] = fVX;
acProjectiles[playerid][acProjectileCount[playerid]][vector][1] = fVY;
acProjectiles[playerid][acProjectileCount[playerid]][vector][2] = fVZ;
acProjectiles[playerid][acProjectileCount[playerid]][objectId] = objId;
acProjectiles[playerid][acProjectileCount[playerid]][enabled] = true;
acProjectiles[playerid][acProjectileCount[playerid]][explode] = false;
acProjectileCount[playerid] = acProjectileCount[playerid] + 1;
if (acProjectileCount[playerid] == AC_MAX_PROJECTILES_PER_PLAYER) { acProjectileCount[playerid] = 0; }
}
stock Float:GetGroundZ(Float:x, Float:y)
{
new Float:gz;
new Float:highest = 0.0;
MapAndreas_FindZ_For2DCoord(x, y, gz); if (gz > highest) highest = gz;
MapAndreas_FindZ_For2DCoord(x+1, y, gz); if (gz > highest) highest = gz;
MapAndreas_FindZ_For2DCoord(x-1, y, gz); if (gz > highest) highest = gz;
MapAndreas_FindZ_For2DCoord(x, y+1, gz); if (gz > highest) highest = gz;
MapAndreas_FindZ_For2DCoord(x, y-1, gz); if (gz > highest) highest = gz;
return highest;
}
stock Float:ac_floatrand(Float:max, Float:min = 0.0, dp = 4)
{
new
// Get the multiplication for storing fractional parts.
Float:mul = floatpower(10.0, dp),
// Get the max and min as integers, with extra dp.
imin = floatround(floatmul(min, mul)),
imax = floatround(floatmul(max, mul));
// Get a random int between two bounds and convert it to a float.
return floatdiv(float(random(imax - imin) + imin), mul);
}
stock IsVehicleAirVehicle(vehid)
{
switch(vehid)
{
case 592, 577, 511, 512, 593, 520, 553, 476, 519, 460, 513, 548, 425, 417, 487, 488, 498, 563, 447, 469: return true;
}
return false;
}
Added little inaccuracy for explosions for more realistic behavior. Also now all explosions should be visible over the ground.
EDIT: or just enable y shooting straight down from the vehicles like a airstrike/bomb drop on 3 pair bombs per button press? that would fit a air vehicles better
The "r" parameter seems to have the same issues as the "u" parameter before it got updated (you have to type whole name or just the ID. The part-name feature doesn't work). And I'm not sure but I think you need to write it case-sensetive too!