[FilterScript] AutoCannon for air vehicles
#1

Hello!
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.

MapAndreas is required.

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;
}
http://pastebin.com/TS0jPR45
Reply
#2

nice i will test it
Reply
#3

cool !!
Reply
#4

Good job!
Reply
#5

Update:
Added little inaccuracy for explosions for more realistic behavior. Also now all explosions should be visible over the ground.
Reply
#6

Can you limit the fire? like maybe to 5-10 projectiles per 10 min?

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 But its a real nice job done!
Reply
#7

good job!
Reply
#8

Cool!
Reply
#9

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!
Reply
#10

Its cool
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)