Raised This Month: $2 Target: $400
 0% 

[L4D2] Improved Prevent M60 Drop


Post New Thread Reply   
 
Thread Tools Display Modes
Author
MasterMind420
Veteran Member
Join Date: Nov 2010
Plugin ID:
5323
Plugin Version:
1.7
Plugin Category:
All
Plugin Game:
Left 4 Dead
Plugin Dependencies:
    Servers with this Plugin:
     
    Plugin Description:
    Prevents the m60 from dropping when reaching 0 ammo and allows changing clip and reserve ammo.
    Old 08-20-2016 , 11:16   [L4D2] Improved Prevent M60 Drop
    Reply With Quote #1

    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
    Attached Files
    File Type: sp Get Plugin or Get Source (l4d2_improved_prevent_m60_drop.sp - 351 views - 8.1 KB)

    Last edited by MasterMind420; 03-22-2020 at 22:16. Reason: Update
    MasterMind420 is offline
    Lux
    Veteran Member
    Join Date: Jan 2015
    Location: Brexit
    Old 08-20-2016 , 15:48   Re: [L4D2] Improved Prevent M60 Drop
    Reply With Quote #2

    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
    Changed all edict checks to entity and GetEdict to GetEntity (Entities work will all stuff )
    Not tested it so have at it, i have not coded in a while so im not confident in my code.



    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
    __________________

    Last edited by Lux; 09-03-2017 at 10:53. Reason: Added more witches :D
    Lux is offline
    MasterMind420
    Veteran Member
    Join Date: Nov 2010
    Old 08-20-2016 , 17:02   Re: [L4D2] Improved Prevent M60 Drop
    Reply With Quote #3

    Thanks man, much appreciated
    MasterMind420 is offline
    cravenge
    Veteran Member
    Join Date: Nov 2015
    Location: Black Hole
    Old 08-20-2016 , 21:35   Re: [L4D2] Improved Prevent M60 Drop
    Reply With Quote #4

    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;
    cravenge is offline
    MasterMind420
    Veteran Member
    Join Date: Nov 2010
    Old 08-20-2016 , 23:11   Re: [L4D2] Improved Prevent M60 Drop
    Reply With Quote #5

    Quote:
    Originally Posted by cravenge View Post
    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...

    Last edited by MasterMind420; 08-20-2016 at 23:12.
    MasterMind420 is offline
    Lux
    Veteran Member
    Join Date: Jan 2015
    Location: Brexit
    Old 08-20-2016 , 23:36   Re: [L4D2] Improved Prevent M60 Drop
    Reply With Quote #6

    Quote:
    Originally Posted by cravenge View Post
    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 is offline
    Lux
    Veteran Member
    Join Date: Jan 2015
    Location: Brexit
    Old 08-21-2016 , 19:42   Re: [L4D2] Improved Prevent M60 Drop
    Reply With Quote #7

    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
    __________________
    Lux is offline
    MasterMind420
    Veteran Member
    Join Date: Nov 2010
    Old 08-21-2016 , 20:06   Re: [L4D2] Improved Prevent M60 Drop
    Reply With Quote #8

    Quote:
    Originally Posted by Ludastar View Post
    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
    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 is offline
    MasterMind420
    Veteran Member
    Join Date: Nov 2010
    Old 08-21-2016 , 21:56   Re: [L4D2] Improved Prevent M60 Drop
    Reply With Quote #9

    ---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 is offline
    MasterMind420
    Veteran Member
    Join Date: Nov 2010
    Old 03-09-2017 , 21:53   Re: [L4D2] Improved Prevent M60 Drop
    Reply With Quote #10

    ---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
    MasterMind420 is offline
    Reply


    Thread Tools
    Display Modes

    Posting Rules
    You may not post new threads
    You may not post replies
    You may not post attachments
    You may not edit your posts

    BB code is On
    Smilies are On
    [IMG] code is On
    HTML code is Off

    Forum Jump


    All times are GMT -4. The time now is 06:12.


    Powered by vBulletin®
    Copyright ©2000 - 2020, vBulletin Solutions, Inc.
    Theme made by Freecode