AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Unapproved Plugins (https://forums.alliedmods.net/forumdisplay.php?f=109)
-   -   [L4D2] Improved Prevent M60 Drop (https://forums.alliedmods.net/showthread.php?t=286597)

MasterMind420 08-20-2016 11:16

[L4D2] Improved Prevent M60 Drop
 
1 Attachment(s)
Firstly thanks to DeathChaos for allowing me to take over his plugin, secondly thanks to AtomicStryker for his GunControl plugin which i've also learned alot from. Thirdly thanks to Lux for all his coding guidance which has helped me become a better coder.

Without further delay I give to you [L4D2] Improved Prevent M60 Drop.
Prevents the m60 from dropping when reaching 0 ammo and allows changing clip and reserve ammo.

M60 utilizing upgraded ammo packs give wrong ammo count with more than 1 clip.
Fixed by modifying AtomicStryker's GunControl to only allow 1 clip for m60 only.
Other weapons will use the clip count set in the config for upgraded ammo clips.

Code:

---VERSION 1.1---
Complete rewrite thanks to ludastar's suggestions the code is better optimized.
Changed OnPlayerRunCmd to Event weapon_fire, which seems to work better.

---VERSION 1.2---
Rewrote and cleaned up code using new syntax
Removed dependency on GunControl plugin
Added upgrade pack ammo fix(1 clip only)
Added code to allow reloading at ammo piles

---VERSION 1.3---
Added ammo reload notification thru chat or hint
Moved ammo pile reload code to ammo_pile_weapon_cant_use_ammo event(more efficient)

---VERSION 1.4---
Converted to new syntax
Changed reload code back to player use, can reload from any weapon(thanks ngBuckWangs)

---VERSION 1.5---
Properly converted to new syntax
Corrected a mistake which caused ammo locking to effect other weapons

---VERSION 1.6---
Ammo issues should be fixed.

---VERSION 1.7---
Removed redundant code.
Reworked ammo pile code to work more naturally.
Fixed bug when reloading at ammo piles current clip would flow into reserve ammo (Shao).

-MY PLUGINS-
Auto Thirdperson Melee v1.6 - https://forums.alliedmods.net/showthread.php?t=282543
Pistol Reloading v1.0 - https://forums.alliedmods.net/showthread.php?t=286695

Lux 08-20-2016 15:48

Re: [L4D2] Improved Prevent M60 Drop
 
You forgot to let me audit your code before you released it so i'v done it here.

Stuff i'v done:
Save Memory for vars that are not used much.
Optmized weapon detection
Saved handle for cvar instead of finding it all the time.
All the parts i touched are in my style of code
Made it look cleaner yay rukia
Changed all edict checks to entity and GetEdict to GetEntity (Entities work will all stuff :3)
Not tested it so have at it, i have not coded in a while so im not confident in my code.

rukiarukiarukiarukiarukiarukiarukiarukiarukia rukiarukiarukiarukiarukiarukiarukiarukiarukia

Code:

#include <sourcemod>
#include <sdktools>

#pragma semicolon 1

static bool:InReloadM60[MAXPLAYERS+1] = {false, ...};
static iLastWeapon[MAXPLAYERS+1];
static bool:bM60[MAXPLAYERS+1] = {false, ...};

static Handle:hAmmoCvarM60 = INVALID_HANDLE;//cache the handle
static iAmmoCvarM60 = -1;//save the value instead of getting the int everytime
// hind for static vs new, use static with recursive stuff like loops ect or you will be hording useless vars for ages untill its used again
// rewritten abit with love, well i hope it works im too lazy to test :p
public Plugin:myinfo =
{
    name = "[L4D2] Perfected Prevent M60 Drop",
    author = "MasterMind420, DeathChaos25, Ludastar",
    description = "Prevents M60 from dropping and allows reloading, perfected by MasterMind420",
    version = "1.1",
    url = ""
}

public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max)
{
    decl String:sGameFolder[11];
    GetGameFolderName(sGameFolder, sizeof(sGameFolder));
    if (!StrEqual(sGameFolder, "left4dead2", false))
    {
        strcopy(error, err_max, "This plugin is for Left 4 Dead 2 Only!");
        return APLRes_Failure;
    }
    return APLRes_Success;
}

public OnPluginStart()
{
    HookEvent("receive_upgrade", Event_AmmoUpgrade);
    HookEvent("upgrade_explosive_ammo", Event_AmmoUpgrade);
    HookEvent("upgrade_incendiary_ammo", Event_AmmoUpgrade);
    HookEvent("weapon_reload", Event_WeaponReloadPre, EventHookMode_Pre);
   
    hAmmoCvarM60 = FindConVar("ammo_m60_max");//the handle we cache
    HookConVarChange(hAmmoCvarM60, eConvarChanged);//hook the cvar change so the var will change

    CreateTimer(0.1, M60AmmoCheck, _, TIMER_REPEAT);
}


public eConvarChanged(Handle:hCvar, const String:sOldVal[], const String:sNewVal[])
{
    CvarsChanged();
}

CvarsChanged()
{
    iAmmoCvarM60 = GetConVarInt(hAmmoCvarM60);
}

public Action:M60AmmoCheck(Handle:Timer)
{
    if (!IsServerProcessing())
        return Plugin_Continue;
       
    static ReserveAmmo;
    ReserveAmmo = iAmmoCvarM60;
   
    for (new client = 1; client <= MaxClients; client++)// Make sure to use continue; not return; RETURN WILL EXIT THE WHOLE LOOP not skip to the next client in the loop
    {
        if(!IsSurvivor(client) || !IsPlayerAlive(client))
            continue;
       
        static Weapon;
        Weapon = GetPlayerWeaponSlot(client, 0);
       
        if(!IsValidEntity(Weapon))
            continue;
           
        if(iLastWeapon[client] != Weapon)// this little if statment is more perf friendly
        {
            iLastWeapon[client] = Weapon;
           
            decl String:sWeapon[17];
            GetEntityClassname(Weapon, sWeapon, sizeof(sWeapon));
           
            if(sWeapon[13] != 'm' || !StrEqual(sWeapon, "weapon_rifle_m60"))
            {
                bM60[client] = false;
                continue;
            }
            bM60[client] = true;
        }
   
        if(!bM60[client])
            continue;
       
        static Clip;
        Clip = GetEntProp(Weapon, Prop_Data, "m_iClip1");
       
        static PrimType;
        PrimType = GetEntProp(Weapon, Prop_Send, "m_iPrimaryAmmoType");
       
        static Ammo;
        Ammo = GetEntProp(client, Prop_Send, "m_iAmmo", _, PrimType);
       
        //static ReserveAmmo;
        //ReserveAmmo = GetConVarInt(FindConVar("ammo_m60_max"));
        //I already told you this already finding the handle everytime is pointless and wastes time finding ite every time, save the handle instead :P
       
        if (Clip == 0 && Ammo ==0) { SetEntProp(Weapon, Prop_Send, "m_iClip1", 1); }
        else if (Clip == 0 && Ammo > ReserveAmmo + 150) { SetEntProp(client, Prop_Send, "m_iAmmo", ReserveAmmo + 150, _, PrimType); }
        else if (Clip > 0 && Ammo > ReserveAmmo) { SetEntProp(client, Prop_Send, "m_iAmmo", ReserveAmmo + (150 - Clip), _, PrimType); }
    }
    return Plugin_Continue;
}

public Action:Event_WeaponReloadPre(Handle:event, const String:name[], bool:dontBroadcast)
{
    new client = GetClientOfUserId(GetEventInt(event, "userid"));
   
    if(!IsSurvivor(client) || !IsPlayerAlive(client))
        return Plugin_Continue;

    new Weapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon");// use this the orignal method is deprecated so don't use it :P

    if(!IsValidEntity(Weapon))
        return Plugin_Continue;
   
    if(iLastWeapon[client] != Weapon)// this little if statment is more perf friendly
    {
        iLastWeapon[client] = Weapon;
           
        decl String:sWeapon[17];
        GetEntityClassname(Weapon, sWeapon, sizeof(sWeapon));
           
        if(sWeapon[13] != 'm' || !StrEqual(sWeapon, "weapon_rifle_m60"))
        {
            bM60[client] = false;
            return Plugin_Continue;
        }
        bM60[client] = true;
    }
   
    if(!bM60[client])
        return Plugin_Continue;
   
    SetEntProp(Weapon, Prop_Send, "m_releasedFireButton", 1);
    SetEntPropFloat(Weapon, Prop_Send, "m_flNextPrimaryAttack", GetGameTime() + 2.0); // + 1000.0);
   
    return Plugin_Continue;
}

public Action:Event_AmmoUpgrade(Handle:event, const String:name[], bool:dontBroadcast)
{
    new client = GetClientOfUserId(GetEventInt(event, "userid"));
   
    if (!IsSurvivor(client) || !IsPlayerAlive(client))
        return Plugin_Continue;
   
    new Weapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon");
   
    if(!IsValidEntity(Weapon))
        return Plugin_Continue;
   
    if(iLastWeapon[client] != Weapon)// this little if statment is more perf friendly
    {
        iLastWeapon[client] = Weapon;
           
        decl String:sWeapon[17];
        GetEntityClassname(Weapon, sWeapon, sizeof(sWeapon));
           
        if(sWeapon[13] != 'm' || !StrEqual(sWeapon, "weapon_rifle_m60"))
        {
            bM60[client] = false;
            return Plugin_Continue;
        }
        bM60[client] = true;
    }
   
    if(!bM60[client])
        return Plugin_Continue;
       
    new Clip = GetEntProp(Weapon, Prop_Data, "m_iClip1");
   
    if (Clip != 0)
        return Plugin_Continue;
       
    new iAmmoCount = GetEntProp(iAmmoCount, Prop_Send, "m_iClip1");// Get ammo count because getting ammo on the m60 only give you the bullets that are in the clip with upgraded ammo that is standard l4d2 anyway :P.
   
    SetEntProp(Weapon, Prop_Send, "m_nUpgradedPrimaryAmmoLoaded", iAmmoCount, 1);
    SetEntProp(Weapon, Prop_Send, "m_iClip1", iAmmoCount);
   
    return Plugin_Continue;
}

public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3])
{
    if (!IsSurvivor(client) || !IsPlayerAlive(client))
        return Plugin_Continue;
       
    static Weapon;
    Weapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon");
   
    if(!IsValidEntity(Weapon))
        return Plugin_Continue;
   
    if(iLastWeapon[client] != Weapon)// this little if statment is more perf friendly
    {
        iLastWeapon[client] = Weapon;
           
        decl String:sWeapon[17];
        GetEntityClassname(Weapon, sWeapon, sizeof(sWeapon));
           
        if(sWeapon[13] != 'm' || !StrEqual(sWeapon, "weapon_rifle_m60"))
        {
            bM60[client] = false;
            return Plugin_Continue;
        }
        bM60[client] = true;
    }
   
    if(!bM60[client])
        return Plugin_Continue;
   
    static Clip;
    Clip = GetEntProp(Weapon, Prop_Data, "m_iClip1");
   
    static PrimType;
    PrimType = GetEntProp(Weapon, Prop_Send, "m_iPrimaryAmmoType");
   
    static Ammo;
    Ammo = GetEntProp(client, Prop_Send, "m_iAmmo", _, PrimType);
   
    static Laser;
    Laser = GetEntProp(Weapon, Prop_Send, "m_upgradeBitVec");
   
    static InReload;
    InReload = GetEntProp(Weapon, Prop_Data, "m_bInReload");
   
    if (Clip == 1) { InReloadM60[client]=true; }
    if (buttons & IN_ATTACK && InReload) { return Plugin_Continue; }
    if (buttons & IN_ATTACK && Clip <= 1 && InReloadM60[client])
    {
        AcceptEntityInput(Weapon, "kill");
        new M60 = CreateEntityByName("weapon_rifle_m60");
        DispatchSpawn(M60);
        EquipPlayerWeapon(client, M60);
        SetEntProp(M60, Prop_Send, "m_iClip1", 0);
        SetEntProp(client, Prop_Send, "m_iAmmo", Ammo, _, PrimType);
        SetEntProp(M60, Prop_Send, "m_upgradeBitVec", Laser);
        InReloadM60[client]=false;
    }
    return Plugin_Continue;
}

static bool:IsSurvivor(client)
{
    return client > 0 && client <= MaxClients && IsClientInGame(client) && GetClientTeam(client) == 2;
}

I could of put this in its own callback but was too lazy
Code:

if(iLastWeapon[client] != Weapon)// this little if statment is more perf friendly
        {
            iLastWeapon[client] = Weapon;
           
            decl String:sWeapon[16];
            GetEntityClassname(Weapon, sWeapon, sizeof(sWeapon));
           
            if(sWeapon[13] != 'm' || !StrEqual(sWeapon, "weapon_rifle_m60"))
            {
                bM60[client] = false;
                continue;
            }
            bM60[client] = true;
        }

Edit 22/08/2016// Revision of 2 mistakes and now works
use 1.6 compiler because mastermind have issues with 1.7

MasterMind420 08-20-2016 17:02

Re: [L4D2] Improved Prevent M60 Drop
 
Thanks man, much appreciated :)

cravenge 08-20-2016 21:35

Re: [L4D2] Improved Prevent M60 Drop
 
MasterMind, I advice you to always check if the "m_hActiveWeapon" netprop returns -1 because it produces errors about "Entity index -1 is invalid".

Code:

new Weapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon");
if(Weapon == -1 || !IsValidEntity(Weapon))
    return Plugin_Continue;


MasterMind420 08-20-2016 23:11

Re: [L4D2] Improved Prevent M60 Drop
 
Quote:

Originally Posted by cravenge (Post 2446837)
MasterMind, I advice you to always check if the "m_hActiveWeapon" netprop returns -1 because it produces errors about "Entity index -1 is invalid".

Code:

new Weapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon");
if(Weapon == -1 || !IsValidEntity(Weapon))
    return Plugin_Continue;


hmm i've yet to see that error in this plugin, although i have in other plugins i'll keep an eye out for it, wouldn't checking if its a valid entity to begin with be enough? I haven't played through an entire map yet and fully tested it though, thanks for the heads up...I'm gonna be rewriting it abit more anyway so i'll keep that in mind...

Lux 08-20-2016 23:36

Re: [L4D2] Improved Prevent M60 Drop
 
Quote:

Originally Posted by cravenge (Post 2446837)
MasterMind, I advice you to always check if the "m_hActiveWeapon" netprop returns -1 because it produces errors about "Entity index -1 is invalid".

Code:

new Weapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon");
if(Weapon == -1 || !IsValidEntity(Weapon))
    return Plugin_Continue;


Whats the point in that O.o

If a entity is invalid it will return -1 anyway so it just becomes a useless check

Lux 08-21-2016 19:42

Re: [L4D2] Improved Prevent M60 Drop
 
Mastermind is going a different route now using Weapon_Fire event instead of command inputs.
Not sure if the legacy way will be still there.

Should be better either way

Updated second post and master is combinding them to make it all better for us :D

MasterMind420 08-21-2016 20:06

Re: [L4D2] Improved Prevent M60 Drop
 
Quote:

Originally Posted by Ludastar (Post 2447128)
Mastermind is going a different route now using Weapon_Fire event instead of command inputs.
Not sure if the legacy way will be still there.

Should be better either way

Updated second post and master is combinding them to make it all better for us :D

yah go to the second post for now until i finish the merger, thanks ludastar...i'll update the original post probably tonight or tomorrow with the weapon_fire event instead of onplayerruncmd, it seems to work a little more efficiently...

MasterMind420 08-21-2016 21:56

Re: [L4D2] Improved Prevent M60 Drop
 
---VERSION 1.1--- POSTED
Complete rewrite thanks to ludastar's suggestions the code is better optimized.
Changed OnPlayerRunCmd to Event weapon_fire, which seems to work better.

MasterMind420 03-09-2017 21:53

Re: [L4D2] Improved Prevent M60 Drop
 
---VERSION 1.2---
Rewrote and cleaned up code using new syntax
Removed dependency on GunControl plugin
Added upgrade pack ammo fix(1 clip only)
Added code to allow reloading at ammo piles


All times are GMT -4. The time now is 07:18.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.