Raised This Month: $429 Target: $400
 107% 

[L4D & L4D2] Target Override (2.3) [26-Mar-2020]


Post New Thread Reply   
 
Thread Tools Display Modes
Author
Silvers
AlliedModders Donor
Join Date: Aug 2010
Location: SpaceX
Plugin ID:
6996
Plugin Version:
2.3
Plugin Category:
Gameplay
Plugin Game:
Left 4 Dead
Plugin Dependencies:
    Servers with this Plugin:
     
    Plugin Description:
    Overrides Special Infected targeting of Survivors
    Old 03-23-2020 , 10:20   [L4D & L4D2] Target Override (2.3) [26-Mar-2020]
    Reply With Quote #1

    About:
    • This overrides the ChooseVictim function for each Special Infected according to your preferences.
    • Prioritise who to attack first, vomited survivors, vomited specials, incapped, pinned etc.
    • Can prevent specific Special Infected from targeting incapacitated survivors.
    • Can restore L4D1 game behaviour in L4D2 so the Hunter and Tank can attack incapacitated and vomited players.
    • Benchmarking shows the function/plugin is highly optimized and extremely quick (0.058 ms think time).


    Thanks:
    • Sev - For the idea and request.
    • BlackSabbarh - Also for the request.
    • Lux - For fixing God Frames detour which is similar to this, and would not be possible without.
    • hoanganh81097 - For testing version 2.0.


    Example Data Config:

    Saved to l4d_target_override.cfg in your servers \addons\sourcemod\data\ folder.

    PHP Code:
    // Rearrange order to your preference for each Special Infected class. Don't delete any values, must contain all 6.

    // Order:     Prioritise who to attack first: 1=Normal Survivor. 2=Vomited Survivor. 3=Incapped. 4=Pinned. 5=Ledge. 6=Vomited Special Infected. 7=Last Attacker.
    // Pinned:    Ignore attacking target when they're pinned by: 1=Smoker. 2=Hunter. 4=Jockey. 8=Charger. 15=All. Add numbers together.
    // Incap:     0=Ignore incapacitated players. 1=Allow attacking incapacitated players. 2=Only attack incapacitated players when they are vomited. 3=Only attack incapacitated when everyones incapacitated.
    // Voms:      0=Off. 1=Allow attacking vomited Special Infected (order number 6).
    // Wait:      How many seconds to target someone before being allowed to switch to another target. They will switch before if the player is no longer valid or allowed to be targeted.
    // Last:      0=Off. 1=Allow targeting the last attacker using order value 7. Does not change if a target is already very close (250 units).

    "target_patch"
    {
        
    "tank"
        
    {
            
    "order"     "7,6,2,3,1,4,5" // Preference: Last attacker, Vomited Special Infected, then Vomited Survivors, then Incapped then normal Survivors.
            
    "pinned"    "15"
            "incap"     "1"
            "voms"      "1"
            "wait"      "2"
            "last"      "1"
        
    }



    Admin Commands: (requires "z" flag)

    PHP Code:
    sm_to_reload   // Reloads the data config
    sm_to_stats    // Displays benchmarking stats (min/avg/max). (Requires plugin recompile with DEBUG_BENCHMARK set to 1 or 2). 


    Cvars:

    Saved to l4d_target_override.cfg in your servers \cfg\sourcemod\ folder.

    PHP Code:
    // 0=Plugin off, 1=Plugin on.
    l4d_target_override_allow "1"

    // Turn on the plugin in these game modes, separate by commas (no spaces). (Empty = all).
    l4d_target_override_modes ""

    // Turn off the plugin in these game modes, separate by commas (no spaces). (Empty = none).
    l4d_target_override_modes_off ""

    // Turn on the plugin in these game modes. 0=All, 1=Coop, 2=Survival, 4=Versus, 8=Scavenge. Add numbers together.
    l4d_target_override_modes_tog "0"

    // L4D1: Override these Specials target function: 1=Smoker, 2=Boomer, 4=Hunter, 8=Tank. 15=All. Add numbers together.
    l4d_target_override_specials "15"

    // L4D2: Override these Specials target function: 1=Smoker, 2=Boomer, 4=Hunter, 8=Spitter, 16=Jockey, 32=Charger, 64=Tank. 127=All. Add numbers together.
    l4d_target_override_specials "127"

    // Target Override plugin version.
    l4d_target_override_version 


    Changes:
    Code:
    2.3 (26-Mar-2020)
        - Added option "last" to the config to enable targeting the last attacker using order value 7.
        - Added option "7" to "order" to choose targeting the last attacker.
        - This option won't change target if one is already very close (250 units).
        - Thanks to "xZk" for requesting.
    
    2.2 (24-Mar-2020)
        - Fixed memory leak. Thanks to "sorallll" for reporting. Thanks to "Lux" for adding the fix.
    
    2.1 (23-Mar-2020)
        - Fixed only using the first 5 priority order values and never checking the 6th when the first 5 fail.
    
    2.0 (23-Mar-2020)
        - Initial Release.
    
        - Combined L4D1 and L4D2 versions into 1 plugin.
        - Major changes to how the plugin works. 
        - Now has a data config to choose preferences for each Special Infected.
    
        - Renamed plugin (delete the old .smx - added check to prevent duplicate plugins).
        - Removed cvar "l4d2_target_patch_special", now part part of data config settings.
        - Removed cvar "l4d2_target_patch_targets", now part part of data config settings.
        - Removed cvar "l4d2_target_patch_wait", now part part of data config settings.
        - Removed cvar "l4d2_target_patch_incap", now part part of data config settings.
        - Removed cvar "l4d_target_patch_incap", now part part of data config settings.


    Requirements:

    Installation:
    • Download the .zip and extract the files to their respective folders in your servers \addons\sourcemod\ folder.
    Attached Files
    File Type: zip l4d_target_override.zip (22.7 KB, 42 views)
    __________________

    Last edited by Silvers; 03-26-2020 at 01:00.
    Silvers is offline
    sorallll
    New Member
    Join Date: Oct 2018
    Old 03-24-2020 , 01:14   Re: [L4D & L4D2] Target Override (2.1) [23-Mar-2020]
    Reply With Quote #2

    L 03/24/2020 - 078:14: [SM] MEMORY LEAK DETECTED IN PLUGIN (file "optional/coop/l4d_target_override.smx")
    L 03/24/2020 - 078:14: [SM] Unloading plugin to free 31530 handles.
    L 03/24/2020 - 078:14: [SM] Contact the author(s) of this plugin to correct this error.
    L 03/24/2020 - 078:14: --------------------------------------------------------------------------
    L 03/24/2020 - 078:14: Type CellArray | Count 31527
    L 03/24/2020 - 078:14: Type HookSetup | Count 1
    L 03/24/2020 - 078:14: Type HookParams | Count 1
    L 03/24/2020 - 078:14: Type HookReturn | Count 1
    L 03/24/2020 - 078:14: -- Approximately 3652812 bytes of memory are in use by (31530) Handles.

    L 03/24/2020 - 078:14: [SM] Exception reported: Memory leak
    L 03/24/2020 - 078:14: [SM] Blaming: optional/coop/l4d_target_override.smx
    L 03/24/2020 - 078:14: [SM] Call stack trace:
    L 03/24/2020 - 078:14: [SM] [0] ArrayList.ArrayList
    L 03/24/2020 - 078:14: [SM] [1] Line 699, l4d_target_override.sp::ChooseVictim
    L 03/24/2020 - 07:45:07: Error log file session closed.
    sorallll is offline
    Lux
    Veteran Member
    Join Date: Jan 2015
    Location: Brexit
    Old 03-24-2020 , 02:18   Re: [L4D & L4D2] Target Override (2.1) [23-Mar-2020]
    Reply With Quote #3

    Quote:
    Originally Posted by sorallll View Post
    L 03/24/2020 - 078:14: [SM] MEMORY LEAK DETECTED IN PLUGIN (file "optional/coop/l4d_target_override.smx")
    L 03/24/2020 - 078:14: [SM] Unloading plugin to free 31530 handles.
    L 03/24/2020 - 078:14: [SM] Contact the author(s) of this plugin to correct this error.
    L 03/24/2020 - 078:14: --------------------------------------------------------------------------
    L 03/24/2020 - 078:14: Type CellArray | Count 31527
    L 03/24/2020 - 078:14: Type HookSetup | Count 1
    L 03/24/2020 - 078:14: Type HookParams | Count 1
    L 03/24/2020 - 078:14: Type HookReturn | Count 1
    L 03/24/2020 - 078:14: -- Approximately 3652812 bytes of memory are in use by (31530) Handles.

    L 03/24/2020 - 078:14: [SM] Exception reported: Memory leak
    L 03/24/2020 - 078:14: [SM] Blaming: optional/coop/l4d_target_override.smx
    L 03/24/2020 - 078:14: [SM] Call stack trace:
    L 03/24/2020 - 078:14: [SM] [0] ArrayList.ArrayList
    L 03/24/2020 - 078:14: [SM] [1] Line 699, l4d_target_override.sp::ChooseVictim
    L 03/24/2020 - 07:45:07: Error log file session closed.
    From quick skim don't really understand the code much but the error should fix after you put
    PHP Code:
    delete aTargets 
    Just before the function returns.


    Here did it below replace the whole function with this one.
    PHP Code:
    public MRESReturn ChooseVictim(int attackerHandle hReturn)
    {
        
    #if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
        
    StartProfiling(g_Prof);
        
    #endif

        #if DEBUG_BENCHMARK == 3
        
    PrintToServer("");
        
    PrintToServer("");
        
    PrintToServer("ENTRY %d (%N)"attackerattacker);
        
    #endif



        // =========================
        // VALIDATE SPECIAL ALLOWED CHANGE TARGET
        // =========================
        // 1=Smoker, 2=Boomer, 3=Hunter, 4=Spitter, 5=Jockey, 6=Charger, 5 (L4D1) / 8 (L4D2)=Tank
        
    int class = GetEntProp(attackerProp_Send"m_zombieClass");
        if( class == (
    g_bLeft4Dead2 5) ) class -= 1;
        if( 
    g_iCvarSpecials & (<< class - 1) == )
        {
            
    #if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
            
    StopProfiling(g_Prof);
            
    float speed GetProfilerTime(g_Prof);
            if( 
    speed g_fBenchMin g_fBenchMin speed;
            if( 
    speed g_fBenchMax g_fBenchMax speed;
            
    g_fBenchAvg += speed;
            
    g_iBenchTicks++;
            
    #endif

            #if DEBUG_BENCHMARK == 2
            
    PrintToServer("ChooseVictim End 1 in %f (Min %f. Avg %f. Max %f)"speedg_fBenchMing_fBenchAvg g_iBenchTicksg_fBenchMax);
            
    #endif

            
    return MRES_Ignored;
        }

        
    // Change tank class for use as index
        
    if( class == (g_bLeft4Dead2 4) )
        {
            class = 
    0;
        }



        
    // =========================
        // VALIDATE OLD TARGET, WAIT
        // =========================
        
    int newVictim;
        
    int lastVictim g_iLastVictim[attacker];
        if( 
    lastVictim )
        {
            
    // Player disconnected or player dead, otherwise validate last selected order still applies
            
    if( IsClientInGame(lastVictim) == true && IsPlayerAlive(lastVictim) )
            {
                
    #if DEBUG_BENCHMARK == 3
                
    PrintToServer("=== Test Last: Order: %d. newVictim %d (%N)"g_iLastOrders[attacker], lastVictimlastVictim);
                
    #endif

                
    newVictim OrderTest(attackerlastVictimGetClientTeam(lastVictim), g_iLastOrders[attacker]);

                
    #if DEBUG_BENCHMARK == 3
                
    PrintToServer("=== Test Last: newVictim %d (%N)"lastVictimlastVictim);
                
    #endif
            
    }

            
    // Not reached delay time
            
    if( newVictim && GetGameTime() <= g_fLastSwitch[attacker] )
            {
                
    #if DEBUG_BENCHMARK == 3
                
    PrintToServer("=== Test Last: wait delay.");
                
    #endif

                // CONTINUE OVERRIDE LAST
                
    DHookSetReturn(hReturnnewVictim);
                return 
    MRES_Supercede;
            }
            else
            {
                
    #if DEBUG_BENCHMARK == 3
                
    PrintToServer("=== Test Last: wait reset.");
                
    #endif

                
    g_iLastOrders[attacker] = 0;
                
    g_iLastVictim[attacker] = 0;
                
    g_fLastSwitch[attacker] = 0.0;
            }
        }



        
    // =========================
        // FIND NEAREST SURVIVORS
        // =========================
        // Visible near
        
    float vPos[3];
        
    int targets[MAXPLAYERS+1];
        
    ArrayList aTargets = new ArrayList(3);

        
    GetClientEyePosition(attackervPos);
        
    int numClients GetClientsInRange(vPosRangeType_VisibilitytargetsMAXPLAYERS);
        if( 
    numClients == )
        {
            
    #if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
            
    StopProfiling(g_Prof);
            
    float speed GetProfilerTime(g_Prof);
            if( 
    speed g_fBenchMin g_fBenchMin speed;
            if( 
    speed g_fBenchMax g_fBenchMax speed;
            
    g_fBenchAvg += speed;
            
    g_iBenchTicks++;
            
    #endif

            #if DEBUG_BENCHMARK == 2
            
    PrintToServer("ChooseVictim End 2 in %f (Min %f. Avg %f. Max %f)"speedg_fBenchMing_fBenchAvg g_iBenchTicksg_fBenchMax);
            
    #endif
            
            
    delete aTargets;
            return 
    MRES_Ignored;
        }



        
    // =========================
        // GET DISTANCE
        // =========================
        
    float vTarg[3];
        
    float dist;
        
    int team;
        
    int index;
        
    int victim;

        for( 
    int i 0numClientsi++ )
        {
            
    victim targets[i];

            if( 
    victim && IsPlayerAlive(victim) )
            {
                
    // Option "voms" then allow choosing team 3
                
    team GetClientTeam(victim);
                if( 
    team == || (team == && g_iVomsOption[class] == 1) )
                {
                    
    GetClientAbsOrigin(victimvTarg);
                    
    dist GetVectorDistance(vPosvTarg);

                    
    index aTargets.Push(dist);
                    
    aTargets.Set(indexvictim1);
                    
    aTargets.Set(indexteam2);
                }
            }
        }

        
    // Sort by nearest
        
    SortADTArray(aTargetsSort_AscendingSort_Float);



        
    // =========================
        // ALL INCAPPED CHECK
        // OPTION: "incap" "3"
        // =========================
        // 3=Only attack incapacitated when everyones incapacitated.
        
    bool allIncap;
        if( 
    g_iIncapOption[class] == )
        {
            
    allIncap true;

            for( 
    int i 1<= MaxClientsi++ )
            {
                if( 
    IsClientInGame(i) && GetClientTeam(i) == && IsPlayerAlive(i) )
                {
                    if( 
    g_bIncapped[i] == false )
                    {
                        
    allIncap false;
                        break;
                    }
                }
            }
        }



        
    // =========================
        // ORDER VALIDATION
        // =========================
        // Loop through all orders progressing to the next on fail, and each time loop through all survivors from nearest to test the order preference
        
    bool allPinned true;
        
    int order;

        
    int len aTargets.Length;
        
    int orders;
        for( ; 
    orders MAX_ORDERSorders++ )
        {
            
    // Found someone, exit loop
            #if DEBUG_BENCHMARK == 3
            
    PrintToServer("=== ORDER LOOP %d. newVictim %d (%N)"ordersnewVictimnewVictim);
            
    #endif

            
    if( newVictim ) break;



            
    // =========================
            // OPTION: "order"
            // =========================
            
    switch( class )
            {
                case 
    INDEX_TANK:        order g_iOrderTank[orders];
                case 
    INDEX_SMOKER:        order g_iOrderSmoker[orders];
                case 
    INDEX_BOOMER:        order g_iOrderBoomer[orders];
                case 
    INDEX_HUNTER:        order g_iOrderHunter[orders];
                case 
    INDEX_SPITTER:        order g_iOrderSpitter[orders];
                case 
    INDEX_JOCKEY:        order g_iOrderJockeys[orders];
                case 
    INDEX_CHARGER:        order g_iOrderCharger[orders];
            }



            
    // =========================
            // LOOP SURVIVORS
            // =========================
            
    for( int i 0leni++ )
            {
                
    victim aTargets.Get(i1);



                
    // All incapped, target nearest
                
    if( allIncap )
                {
                    
    #if DEBUG_BENCHMARK == 3
                    
    PrintToServer("Break allIncap");
                    
    #endif

                    
    newVictim victim;
                    break;
                }



                
    team aTargets.Get(i2);
                
    // dist = aTargets.Get(i, 0);



                // =========================
                // OPTION: "incap"
                // =========================
                // 0=Ignore incapacitated players.
                // 1=Allow attacking incapacitated players.
                // 2=Only attack incapacitated players when they are vomited.
                // 3=Only attack incapacitated when everyones incapacitated.
                // 3 is already checked above.
                
    if( team == &&
                    
    g_bIncapped[victim] == true &&
                    
    g_bIncapped[victim] == false
                
    )
                {
                    switch( 
    g_iIncapOption[class] )
                    {
                        case 
    0: continue;
                        case 
    2: if( g_bPinBoomer[victim] == false ) continue;
                    }
                }



                
    // =========================
                // OPTION: "pinned"
                // =========================
                // Validate pinned and allowed
                // 1=Smoker. 2=Hunter. 4=Jockey. 8=Charger.
                
    if( team == )
                {
                    if( 
    g_iPinnedOption[class] & && g_bPinSmoker[victim] ) continue;
                    if( 
    g_iPinnedOption[class] & && g_bPinHunter[victim] ) continue;
                    if( 
    g_bLeft4Dead2 )
                    {
                        if( 
    g_iPinnedOption[class] & && g_bPinJockey[victim] ) continue;
                        if( 
    g_iPinnedOption[class] & && g_bPinCharger[victim] ) continue;
                    }

                    
    allPinned false;
                }



                
    // =========================
                // OPTION: "order"
                // =========================
                
    newVictim OrderTest(attackervictimteamorder);

                
    #if DEBUG_BENCHMARK == 3
                
    PrintToServer("Order %d newVictim %d (%N)"ordernewVictimnewVictim);
                
    #endif

                
    if( newVictim ) break;
            }
        }



        
    // All pinned and not allowed to target, target self to avoid attacking pinned.
        
    if( allPinned && g_iPinnedOption[class] == )
        {
            
    newVictim attacker;
        }



        
    // =========================
        // NEW TARGET
        // =========================
        
    if( newVictim != g_iLastVictim[attacker] )
        {
            
    g_iLastOrders[attacker] = orders;
            
    g_iLastVictim[attacker] = newVictim;
            
    g_fLastSwitch[attacker] = GetGameTime() + g_fWaitOption[class];
        }



        
    // =========================
        // OVERRIDE VICTIM
        // =========================
        
    if( newVictim )
        {
            
    DHookSetReturn(hReturnnewVictim);

            
    #if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
            
    StopProfiling(g_Prof);
            
    float speed GetProfilerTime(g_Prof);
            if( 
    speed g_fBenchMin g_fBenchMin speed;
            if( 
    speed g_fBenchMax g_fBenchMax speed;
            
    g_fBenchAvg += speed;
            
    g_iBenchTicks++;
            
    #endif

            #if DEBUG_BENCHMARK == 2
            
    PrintToServer("ChooseVictim End 3 in %f (Min %f. Avg %f. Max %f)"speedg_fBenchMing_fBenchAvg g_iBenchTicksg_fBenchMax);
            
    #endif
            
            
    delete aTargets;
            return 
    MRES_Supercede;
        }

        
    #if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
        
    StopProfiling(g_Prof);
        
    float speed GetProfilerTime(g_Prof);
        if( 
    speed g_fBenchMin g_fBenchMin speed;
        if( 
    speed g_fBenchMax g_fBenchMax speed;
        
    g_fBenchAvg += speed;
        
    g_iBenchTicks++;
        
    #endif

        #if DEBUG_BENCHMARK == 2
        
    PrintToServer("ChooseVictim End 4 in %f (Min %f. Avg %f. Max %f)"speedg_fBenchMing_fBenchAvg g_iBenchTicksg_fBenchMax);
        
    #endif
        
        
    delete aTargets;
        return 
    MRES_Ignored;

    Also it looks like you edited the code somewhat line 699 has nothing but a comment.
    __________________
    Lux is offline
    sorallll
    New Member
    Join Date: Oct 2018
    Old 03-24-2020 , 04:40   Re: [L4D & L4D2] Target Override (2.1) [23-Mar-2020]
    Reply With Quote #4

    Quote:
    Originally Posted by Lux View Post
    From quick skim don't really understand the code much but the error should fix after you put
    PHP Code:
    delete aTargets 
    Just before the function returns.


    Here did it below replace the whole function with this one.
    PHP Code:
    public MRESReturn ChooseVictim(int attackerHandle hReturn)
    {
        
    #if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
        
    StartProfiling(g_Prof);
        
    #endif

        #if DEBUG_BENCHMARK == 3
        
    PrintToServer("");
        
    PrintToServer("");
        
    PrintToServer("ENTRY %d (%N)"attackerattacker);
        
    #endif



        // =========================
        // VALIDATE SPECIAL ALLOWED CHANGE TARGET
        // =========================
        // 1=Smoker, 2=Boomer, 3=Hunter, 4=Spitter, 5=Jockey, 6=Charger, 5 (L4D1) / 8 (L4D2)=Tank
        
    int class = GetEntProp(attackerProp_Send"m_zombieClass");
        if( class == (
    g_bLeft4Dead2 5) ) class -= 1;
        if( 
    g_iCvarSpecials & (<< class - 1) == )
        {
            
    #if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
            
    StopProfiling(g_Prof);
            
    float speed GetProfilerTime(g_Prof);
            if( 
    speed g_fBenchMin g_fBenchMin speed;
            if( 
    speed g_fBenchMax g_fBenchMax speed;
            
    g_fBenchAvg += speed;
            
    g_iBenchTicks++;
            
    #endif

            #if DEBUG_BENCHMARK == 2
            
    PrintToServer("ChooseVictim End 1 in %f (Min %f. Avg %f. Max %f)"speedg_fBenchMing_fBenchAvg g_iBenchTicksg_fBenchMax);
            
    #endif

            
    return MRES_Ignored;
        }

        
    // Change tank class for use as index
        
    if( class == (g_bLeft4Dead2 4) )
        {
            class = 
    0;
        }



        
    // =========================
        // VALIDATE OLD TARGET, WAIT
        // =========================
        
    int newVictim;
        
    int lastVictim g_iLastVictim[attacker];
        if( 
    lastVictim )
        {
            
    // Player disconnected or player dead, otherwise validate last selected order still applies
            
    if( IsClientInGame(lastVictim) == true && IsPlayerAlive(lastVictim) )
            {
                
    #if DEBUG_BENCHMARK == 3
                
    PrintToServer("=== Test Last: Order: %d. newVictim %d (%N)"g_iLastOrders[attacker], lastVictimlastVictim);
                
    #endif

                
    newVictim OrderTest(attackerlastVictimGetClientTeam(lastVictim), g_iLastOrders[attacker]);

                
    #if DEBUG_BENCHMARK == 3
                
    PrintToServer("=== Test Last: newVictim %d (%N)"lastVictimlastVictim);
                
    #endif
            
    }

            
    // Not reached delay time
            
    if( newVictim && GetGameTime() <= g_fLastSwitch[attacker] )
            {
                
    #if DEBUG_BENCHMARK == 3
                
    PrintToServer("=== Test Last: wait delay.");
                
    #endif

                // CONTINUE OVERRIDE LAST
                
    DHookSetReturn(hReturnnewVictim);
                return 
    MRES_Supercede;
            }
            else
            {
                
    #if DEBUG_BENCHMARK == 3
                
    PrintToServer("=== Test Last: wait reset.");
                
    #endif

                
    g_iLastOrders[attacker] = 0;
                
    g_iLastVictim[attacker] = 0;
                
    g_fLastSwitch[attacker] = 0.0;
            }
        }



        
    // =========================
        // FIND NEAREST SURVIVORS
        // =========================
        // Visible near
        
    float vPos[3];
        
    int targets[MAXPLAYERS+1];
        
    ArrayList aTargets = new ArrayList(3);

        
    GetClientEyePosition(attackervPos);
        
    int numClients GetClientsInRange(vPosRangeType_VisibilitytargetsMAXPLAYERS);
        if( 
    numClients == )
        {
            
    #if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
            
    StopProfiling(g_Prof);
            
    float speed GetProfilerTime(g_Prof);
            if( 
    speed g_fBenchMin g_fBenchMin speed;
            if( 
    speed g_fBenchMax g_fBenchMax speed;
            
    g_fBenchAvg += speed;
            
    g_iBenchTicks++;
            
    #endif

            #if DEBUG_BENCHMARK == 2
            
    PrintToServer("ChooseVictim End 2 in %f (Min %f. Avg %f. Max %f)"speedg_fBenchMing_fBenchAvg g_iBenchTicksg_fBenchMax);
            
    #endif
            
            
    delete aTargets;
            return 
    MRES_Ignored;
        }



        
    // =========================
        // GET DISTANCE
        // =========================
        
    float vTarg[3];
        
    float dist;
        
    int team;
        
    int index;
        
    int victim;

        for( 
    int i 0numClientsi++ )
        {
            
    victim targets[i];

            if( 
    victim && IsPlayerAlive(victim) )
            {
                
    // Option "voms" then allow choosing team 3
                
    team GetClientTeam(victim);
                if( 
    team == || (team == && g_iVomsOption[class] == 1) )
                {
                    
    GetClientAbsOrigin(victimvTarg);
                    
    dist GetVectorDistance(vPosvTarg);

                    
    index aTargets.Push(dist);
                    
    aTargets.Set(indexvictim1);
                    
    aTargets.Set(indexteam2);
                }
            }
        }

        
    // Sort by nearest
        
    SortADTArray(aTargetsSort_AscendingSort_Float);



        
    // =========================
        // ALL INCAPPED CHECK
        // OPTION: "incap" "3"
        // =========================
        // 3=Only attack incapacitated when everyones incapacitated.
        
    bool allIncap;
        if( 
    g_iIncapOption[class] == )
        {
            
    allIncap true;

            for( 
    int i 1<= MaxClientsi++ )
            {
                if( 
    IsClientInGame(i) && GetClientTeam(i) == && IsPlayerAlive(i) )
                {
                    if( 
    g_bIncapped[i] == false )
                    {
                        
    allIncap false;
                        break;
                    }
                }
            }
        }



        
    // =========================
        // ORDER VALIDATION
        // =========================
        // Loop through all orders progressing to the next on fail, and each time loop through all survivors from nearest to test the order preference
        
    bool allPinned true;
        
    int order;

        
    int len aTargets.Length;
        
    int orders;
        for( ; 
    orders MAX_ORDERSorders++ )
        {
            
    // Found someone, exit loop
            #if DEBUG_BENCHMARK == 3
            
    PrintToServer("=== ORDER LOOP %d. newVictim %d (%N)"ordersnewVictimnewVictim);
            
    #endif

            
    if( newVictim ) break;



            
    // =========================
            // OPTION: "order"
            // =========================
            
    switch( class )
            {
                case 
    INDEX_TANK:        order g_iOrderTank[orders];
                case 
    INDEX_SMOKER:        order g_iOrderSmoker[orders];
                case 
    INDEX_BOOMER:        order g_iOrderBoomer[orders];
                case 
    INDEX_HUNTER:        order g_iOrderHunter[orders];
                case 
    INDEX_SPITTER:        order g_iOrderSpitter[orders];
                case 
    INDEX_JOCKEY:        order g_iOrderJockeys[orders];
                case 
    INDEX_CHARGER:        order g_iOrderCharger[orders];
            }



            
    // =========================
            // LOOP SURVIVORS
            // =========================
            
    for( int i 0leni++ )
            {
                
    victim aTargets.Get(i1);



                
    // All incapped, target nearest
                
    if( allIncap )
                {
                    
    #if DEBUG_BENCHMARK == 3
                    
    PrintToServer("Break allIncap");
                    
    #endif

                    
    newVictim victim;
                    break;
                }



                
    team aTargets.Get(i2);
                
    // dist = aTargets.Get(i, 0);



                // =========================
                // OPTION: "incap"
                // =========================
                // 0=Ignore incapacitated players.
                // 1=Allow attacking incapacitated players.
                // 2=Only attack incapacitated players when they are vomited.
                // 3=Only attack incapacitated when everyones incapacitated.
                // 3 is already checked above.
                
    if( team == &&
                    
    g_bIncapped[victim] == true &&
                    
    g_bIncapped[victim] == false
                
    )
                {
                    switch( 
    g_iIncapOption[class] )
                    {
                        case 
    0: continue;
                        case 
    2: if( g_bPinBoomer[victim] == false ) continue;
                    }
                }



                
    // =========================
                // OPTION: "pinned"
                // =========================
                // Validate pinned and allowed
                // 1=Smoker. 2=Hunter. 4=Jockey. 8=Charger.
                
    if( team == )
                {
                    if( 
    g_iPinnedOption[class] & && g_bPinSmoker[victim] ) continue;
                    if( 
    g_iPinnedOption[class] & && g_bPinHunter[victim] ) continue;
                    if( 
    g_bLeft4Dead2 )
                    {
                        if( 
    g_iPinnedOption[class] & && g_bPinJockey[victim] ) continue;
                        if( 
    g_iPinnedOption[class] & && g_bPinCharger[victim] ) continue;
                    }

                    
    allPinned false;
                }



                
    // =========================
                // OPTION: "order"
                // =========================
                
    newVictim OrderTest(attackervictimteamorder);

                
    #if DEBUG_BENCHMARK == 3
                
    PrintToServer("Order %d newVictim %d (%N)"ordernewVictimnewVictim);
                
    #endif

                
    if( newVictim ) break;
            }
        }



        
    // All pinned and not allowed to target, target self to avoid attacking pinned.
        
    if( allPinned && g_iPinnedOption[class] == )
        {
            
    newVictim attacker;
        }



        
    // =========================
        // NEW TARGET
        // =========================
        
    if( newVictim != g_iLastVictim[attacker] )
        {
            
    g_iLastOrders[attacker] = orders;
            
    g_iLastVictim[attacker] = newVictim;
            
    g_fLastSwitch[attacker] = GetGameTime() + g_fWaitOption[class];
        }



        
    // =========================
        // OVERRIDE VICTIM
        // =========================
        
    if( newVictim )
        {
            
    DHookSetReturn(hReturnnewVictim);

            
    #if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
            
    StopProfiling(g_Prof);
            
    float speed GetProfilerTime(g_Prof);
            if( 
    speed g_fBenchMin g_fBenchMin speed;
            if( 
    speed g_fBenchMax g_fBenchMax speed;
            
    g_fBenchAvg += speed;
            
    g_iBenchTicks++;
            
    #endif

            #if DEBUG_BENCHMARK == 2
            
    PrintToServer("ChooseVictim End 3 in %f (Min %f. Avg %f. Max %f)"speedg_fBenchMing_fBenchAvg g_iBenchTicksg_fBenchMax);
            
    #endif
            
            
    delete aTargets;
            return 
    MRES_Supercede;
        }

        
    #if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
        
    StopProfiling(g_Prof);
        
    float speed GetProfilerTime(g_Prof);
        if( 
    speed g_fBenchMin g_fBenchMin speed;
        if( 
    speed g_fBenchMax g_fBenchMax speed;
        
    g_fBenchAvg += speed;
        
    g_iBenchTicks++;
        
    #endif

        #if DEBUG_BENCHMARK == 2
        
    PrintToServer("ChooseVictim End 4 in %f (Min %f. Avg %f. Max %f)"speedg_fBenchMing_fBenchAvg g_iBenchTicksg_fBenchMax);
        
    #endif
        
        
    delete aTargets;
        return 
    MRES_Ignored;

    Also it looks like you edited the code somewhat line 699 has nothing but a comment.
    Thanks,lux:眨眼:
    sorallll is offline
    Silvers
    AlliedModders Donor
    Join Date: Aug 2010
    Location: SpaceX
    Old 03-24-2020 , 09:56   Re: [L4D & L4D2] Target Override (2.2) [24-Mar-2020]
    Reply With Quote #5

    Oversight, didn't review close enough before posting. Thanks. Updated 1st post.
    __________________
    Silvers is offline
    Silvers
    AlliedModders Donor
    Join Date: Aug 2010
    Location: SpaceX
    Old 03-26-2020 , 01:01   Re: [L4D & L4D2] Target Override (2.3) [26-Mar-2020]
    Reply With Quote #6

    Code:
    2.3 (26-Mar-2020)
        - Added option "last" to the config to enable targeting the last attacker using order value 7.
        - Added option "7" to "order" to choose targeting the last attacker.
        - This option won't change target if one is already very close (250 units).
        - Thanks to "xZk" for requesting.
    __________________
    Silvers 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 11:31.


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