Raised This Month: $32 Target: $400
 8% 

[L4D2]Update Difficulty Control(ASDC) V1.2


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
rtokuda
Senior Member
Join Date: Dec 2019
Old 08-01-2020 , 09:46   [L4D2]Update Difficulty Control(ASDC) V1.2
Reply With Quote #1

There could be an update of this plugin to sourcemod 1.10, the author seems to no longer participate in the forum.

https://forums.alliedmods.net/showthread.php?t=221016

PHP Code:
#pragma semicolon 1
#include <sourcemod>
#define PLUGIN_VERSION "1.2"



public Plugin:myinfo =
{
    
name "L4D2 Automatic Scaling Difficulty Controller(ASDC)",
    
author "Fwoosh/harryhecanada",
    
description "Difficulty Controller for the L4D2 AI director, automatically spawns extra zombies to increase difficulty.",
    
version PLUGIN_VERSION,
    
url "www.AlliedMods.net"
};

//Default limits for maximum tanks and witches, with seperate counters for each
#define MAX_WITCHES 4
#define MAX_TANKS 4

//Counting Variables
new nummonsters;
new 
witchcount=0;
new 
tankcount=0;

//Max amount of bots
new Handle:ASDCbots=INVALID_HANDLE;

//Handles for type selection
new Handle:ASDCtype0=INVALID_HANDLE;
new 
Handle:ASDCtype1=INVALID_HANDLE;
new 
Handle:ASDCtype2=INVALID_HANDLE;
new 
Handle:ASDCtype3=INVALID_HANDLE;
new 
Handle:ASDCtypeMOB=INVALID_HANDLE;
new 
Handle:ASDCtypetank=INVALID_HANDLE;
new 
Handle:ASDCtypewitch=INVALID_HANDLE;

//Tick per Time base and multiplier
new Handle:ASDCbase=INVALID_HANDLE;
new 
Handle:ASDCmult=INVALID_HANDLE;
new 
Handle:ASDCCImult=INVALID_HANDLE;

//Common infected amount handlers
new Handle:ASDCcommons INVALID_HANDLE;
new 
Handle:ASDCcommonsbackground INVALID_HANDLE;
new 
Handle:ASDCmob INVALID_HANDLE;

//Intervals
new Handle:ASDCMOBinterval=INVALID_HANDLE;
new 
Handle:ASDCSIinterval=INVALID_HANDLE;
new 
Handle:ASDCTankinterval=INVALID_HANDLE;
new 
Handle:ASDCWitchinterval=INVALID_HANDLE;

//base Tick timer
new Handle:mTimer=INVALID_HANDLE;

//Ticks for each type of spawn
new Float:SItick=0.0;
new 
Float:MOBtick=0.0;
new 
Float:Tanktick=0.0;
new 
Float:Witchtick=0.0;

//Array to store monster type spawned
new monster[4];

new 
l4d2flag=0;


public 
OnPluginStart()
{
    
CreateConVar("ASDCversion"PLUGIN_VERSION"L4D2 Monster Bots Version"FCVAR_PLUGIN|FCVAR_DONTRECORD);
    
//Get control variables
    
ASDCbots CreateConVar("ASDCmaxbots""8""The maximum amount of monster bots"FCVAR_PLUGINtrue0.0);
    
    
//Type Enables
    
ASDCtype0 CreateConVar("ASDCtype0""0""The first kind of special infected to spawn. Set to 9 to disable."FCVAR_PLUGINtrue0.0true9.0);
    
ASDCtype1 CreateConVar("ASDCtype1""0""The second kind of special infected to spawn. Set to 9 to disable."FCVAR_PLUGINtrue0.0true9.0);
    
ASDCtype2 CreateConVar("ASDCtype2""0""The third kind of special infected to spawn. Set to 9 to disable."FCVAR_PLUGINtrue0.0true9.0);
    
ASDCtype3 CreateConVar("ASDCtype3""0""The fourth kind of special infected to spawn. Set to 9 to disable."FCVAR_PLUGINtrue0.0true9.0);
    
ASDCtypeMOB CreateConVar("ASDCtypeMOB""1""Is Mobs of Common Infected wave spawn on (1/0). Set to 0 to disable."FCVAR_PLUGINtrue0.0);
    
ASDCtypetank CreateConVar("ASDCtypetank""1""Is tank spawn on (1/0). Set to 0 to disable."FCVAR_PLUGINtrue0.0);
    
ASDCtypewitch CreateConVar("ASDCtypewitch""1""Is tank spawn on (1/0). Set to 0 to disable."FCVAR_PLUGINtrue0.0);
    
    
//Math
    
ASDCbase CreateConVar("ASDCbase""1""Base time scale for difficulty controller. Set base and mult to 0 to turn off ASDC."FCVAR_PLUGINtrue0.0);
    
ASDCmult CreateConVar("ASDCmult""1""Multiplication tuning for difficulty controller. Set base and mult to 0 to turn off ASDC."FCVAR_PLUGINtrue0.0);
    
ASDCCImult CreateConVar("ASDCCImult""1""Multiplication tuning for CI difficulty controller. Set base and mult to 0 to turn off CI part of ASDC."FCVAR_PLUGINtrue0.0);
    
    
//Base Intervals
    
ASDCSIinterval CreateConVar("ASDCSIinterval","30""How many ticks(unmodified seconds) till another SI spawns"FCVAR_PLUGINtrue0.0);
    
ASDCMOBinterval CreateConVar("ASDCMOBinterval","200""How many ticks(unmodified seconds) till another Mob of CI spawns"FCVAR_PLUGINtrue0.0);
    
ASDCTankinterval CreateConVar("ASDCtankinterval","180""How many ticks(unmodified seconds) till another tank spawns"FCVAR_PLUGINtrue0.0);
    
ASDCWitchinterval CreateConVar("ASDCwitchinterval","120""How many ticks(unmodified seconds) till another witch spawns"FCVAR_PLUGINtrue0.0);
    
    
//CI Controls
    
ASDCcommons CreateConVar("ASDCcommons""10""Number of CI per person in a CI zombie wave."FCVAR_PLUGINtrue0.0);
    
ASDCcommonsbackground CreateConVar("ASDCcommonsbackground""15""Number of CI per person in a CI zombie wave."FCVAR_PLUGINtrue0.0);
    
ASDCmob CreateConVar("ASDCmob""15""Number of CI per person in a Mega CI zombie wave."FCVAR_PLUGINtrue0.0);
    
    
HookEvent("round_start"Event_RoundStart);
    
HookEvent("round_end"Event_RoundEnd);
    
HookEvent("map_transition"Event_RoundEnd);
    
HookEvent("round_start_pre_entity"Event_RoundEnd);
    
HookEvent("round_start_post_nav"Event_RoundEnd);
    
HookEvent("infected_death"Game_Start);
    
    
AutoExecConfig(true"l4d2_ASDCconfig");
}

public 
Action:Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast)
{
    
//Set amount of SI that can be spawned. By machine from monsterbots.
    
new flags GetConVarFlags(FindConVar("z_max_player_zombies"));
        
    new 
String:mapname[30];
    
    
SetConVarBounds(FindConVar("z_max_player_zombies"), ConVarBound_Upperfalse);
    
SetConVarFlags(FindConVar("z_max_player_zombies"), flags & ~FCVAR_NOTIFY);
    
SetConVarInt(FindConVar("z_max_player_zombies"), 32);
    
    
//Increase default limits to match spawns
    
SetConVarInt(FindConVar("z_mob_min_notify_count"), GetConVarInt(ASDCcommons));
    
    
//Get map name
    
GetCurrentMap(mapnamesizeof(mapname));

    
//Due to buggy nature of l4d1, we disable the mob spawn feature entirely.
    
if (StrEqual(mapname,"c1m1_hotel")==true||
    
StrEqual(mapname,"c7m1_docks")||
    
StrEqual(mapname,"c6m1_riverbank")||
    
StrEqual(mapname,"c2m1_highway")||
    
StrEqual(mapname,"c3m1_plankcountry")||
    
StrEqual(mapname,"c4m1_milltown_a")||
    
StrEqual(mapname,"c5m1_waterfront")||
    
StrEqual(mapname,"c13m1_alpinecreek"))
    {
        
l4d2flag=1;
    }
    else if (
StrEqual(mapname,"c7m1_docks.bsp")||
    
StrEqual(mapname,"c8m1_apartment.bsp")||
    
StrEqual(mapname,"c9m1_alleys.bsp")||
    
StrEqual(mapname,"c10m1_caves.bsp")||
    
StrEqual(mapname,"c11m1_greenhouse.bsp")||
    
StrEqual(mapname,"c12m1_hilltop.bsp")
    )
    {
        
l4d2flag=0;
    }
    
    if(
l4d2flag==1)
    {
        
SetConVarInt(FindConVar("z_mob_spawn_min_size"), GetConVarInt(ASDCcommons));
        
SetConVarInt(FindConVar("z_mob_spawn_max_size"), GetConVarInt(ASDCmob)*5);
        
SetConVarInt(FindConVar("z_mob_spawn_finale_size"), GetConVarInt(ASDCmob)*5);
    }
    else
    {
        
//Close to default l4d2 values. stop spawning witches and tanks.
        
SetConVarInt(ASDCcommons,8);
        
SetConVarInt(ASDCmob,8);
        
SetConVarInt(ASDCtypeMOB,0);
        
SetConVarInt(ASDCtypewitch,0);
        
SetConVarInt(ASDCtypetank,0);
        
//SetConVarInt(FindConVar("director_force_tank"), 1);
        //SetConVarInt(FindConVar("director_force_witch"), 1);    
    
}
    
    
//Not sure about ASDCing background limit, seemed to crash client game in certain situations.
    
SetConVarInt(FindConVar("z_background_limit"), GetConVarInt(ASDCcommonsbackground)*4);
}

public 
Action:Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{
    
//Kill timer to prevent spawn during load screen
    
if(mTimer)
    {
        
KillTimer(mTimer);
        
mTimer=INVALID_HANDLE;
    }
    if(
GetConVarFloat(ASDCmult)>&& GetConVarInt(ASDCbase)>0
    {
        for(new 
i=1i<=MaxClientsi++)
        {
            if(
IsClientInGame(i) && IsFakeClient(i) && GetClientTeam(i) == && !IsTank(i))
            {
                
KickClient(i);
            }
        }
    }
}

public 
Action:Game_Start(Handle:event, const String:name[], bool:dontBroadcast)
{
    
//create tick timer when a zombie dies, had to be this way because other event hooks not reliable.
    
if(!mTimer)
    {
        
mTimer=CreateTimer(3.0,TimerUpdate_TIMER_REPEAT);
    }
}

public 
Action:TimerUpdate(Handle:timer)
{
    
//put control vars in array for easier spawning
    
monster[0]=GetConVarInt(ASDCtype0);
    
monster[1]=GetConVarInt(ASDCtype1);
    
monster[2]=GetConVarInt(ASDCtype2);
    
monster[3]=GetConVarInt(ASDCtype3);

    if (!
IsServerProcessing()) return;
    
    
//Calculate tick/sec based on player health
    
new Float:temp=3*(GetConVarFloat(ASDCbase)+ASDC(2)*GetConVarFloat(ASDCmult));
    
    
//Increment ticks
    
SItick += temp;
    if(
ASDCtypetank)
    {
        
Tanktick += temp;
    }
    if(
ASDCtypewitch)
    {
        
Witchtick += temp;
    }
    if(
ASDCtypeMOB)
    {
        
MOBtick += temp;
    }
    
//Spawn SI
    
if (Tanktick >= GetConVarFloat(ASDCTankinterval))
    {
        
CountMonsters();
        if(
tankcount<MAX_TANKS)
        {
            new 
tankbot CreateFakeClient("Tank");
            if (
tankbot 0)
            {
                
//PrintToServer("Spawning Tank.");
                
SpawnCommand(tankbot"z_spawn_old""tank auto");
                
tankcount++;
            }
        }
        
Tanktick 0.0;
    }
    if (
Witchtick >= GetConVarFloat(ASDCWitchinterval))
    {
        
CountMonsters();
        if(
witchcount<MAX_WITCHES)
        {
            new 
witchbot CreateFakeClient("Witch");
            if (
witchbot 0)
            {
                
//PrintToServer("Spawning Witch.");
                
SpawnCommand(witchbot"z_spawn_old""witch auto");
                
witchcount++;
            }
        }
        
Witchtick 0.0;
    }
    
    if (
MOBtick >= GetConVarFloat(ASDCMOBinterval))
    {
        new 
spawnbot=CreateFakeClient("Mob");
        
SpawnCommand(spawnbot"z_spawn""mob");
        
MOBtick=0.0;
    }
    
    if (
SItick >= GetConVarFloat(ASDCSIinterval))
    {
        
CountMonsters();
        new 
i=4;
        while(
i)
        {
            if (
nummonsters GetConVarInt(ASDCbots) && monster[i-1]<7)
            {    
                new 
bot CreateFakeClient("Monster");
                
//PrintToServer("New Monster.");
                
if (bot 0)
                {
                    switch(
monster[i-1])
                    {
                        case 
0:
                        {
                            new 
random GetRandomInt(1,6);
                            switch(
random)
                            {
                                case 
1:
                                
SpawnCommand(bot"z_spawn_old""smoker auto");
                                case 
2:
                                
SpawnCommand(bot"z_spawn_old""boomer auto");
                                case 
3:
                                
SpawnCommand(bot"z_spawn_old""hunter auto");
                                case 
4:
                                
SpawnCommand(bot"z_spawn_old""spitter auto");
                                case 
5:
                                
SpawnCommand(bot"z_spawn_old""jockey auto");
                                case 
6:
                                
SpawnCommand(bot"z_spawn_old""charger auto");
                            }
                        }
                        case 
1:
                        
SpawnCommand(bot"z_spawn_old""smoker auto");
                        case 
2:
                        
SpawnCommand(bot"z_spawn_old""boomer auto");
                        case 
3:
                        
SpawnCommand(bot"z_spawn_old""hunter auto");
                        case 
4:
                        
SpawnCommand(bot"z_spawn_old""spitter auto");
                        case 
5:
                        
SpawnCommand(bot"z_spawn_old""jockey auto");
                        case 
6:
                        
SpawnCommand(bot"z_spawn_old""charger auto");
                    }
                }
                
bot=0;
            }
            
i--;
        }
        
SItick 0.0;
    }
}

public 
Action:Kickbot(Handle:timerany:client)
{
    if (
IsFakeClient(client)) 
        
KickClientEx(client);
}

CountMonsters()
{
    
nummonsters 0;
    
witchcount 0;
    
tankcount 0;
    
decl Stringclassname[32];
    new 
n=4;
    while(
n)
    {
        for (new 
i=1i<=MaxClientsi++)
        {
            if (
IsClientInGame(i) && IsFakeClient(i) && GetClientTeam(i) == 3)
            {
                
GetClientModel(iclassnamesizeof(classname));
                switch(
monster[n-1])
                {
                    case 
0:
                    {
                        if (
StrContains(classname"smoker") || StrContains(classname"boomer") || StrContains(classname"hunter") || StrContains(classname"spitter") || StrContains(classname"jockey") || StrContains(classname"charger"))
                        {
                            
nummonsters++;
                        }
                    }
                    case 
1:
                    {
                        if (
StrContains(classname"smoker"))
                        {
                            
nummonsters++;
                        }
                    }
                    case 
2:
                    {
                        if (
StrContains(classname"boomer"))
                        {
                            
nummonsters++;
                        }
                    }
                    case 
3:
                    {
                        if (
StrContains(classname"hunter"))
                        {
                            
nummonsters++;
                        }
                    }
                    case 
4:
                    {
                        if (
StrContains(classname"spitter"))
                        {
                            
nummonsters++;
                        }
                    }
                    case 
5:
                    {
                        if (
StrContains(classname"jockey"))
                        {
                            
nummonsters++;
                        }
                    }
                    case 
6:
                    {
                        if (
StrContains(classname"charger"))
                        {
                            
nummonsters++;
                        }
                    }
                    
                }
                
//Special cases for counting tank and witch
                
if (StrContains(classname"witch") && ASDCtypetank)
                {
                    
witchcount++;
                }
                if (
StrContains(classname"hulk") && ASDCtypewitch)
                {
                    
tankcount++;
                }
            }
        }
        
n--;
    }
}

Float:ASDC(TeamValue)
{
    new 
Float:health=0.0;
    new 
temp=0;
    new 
Float:ASDCout=0.0;
    
    for (new 
i=1i<=MaxClientsi++)
    {
        if (
IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == TeamValue)
        {
            
health += GetClientHealth(i);
            
temp++;
        }
    }
    
    
ASDCout=health/(100.0*float(temp));
    
    
//Sets CI density to 1% of ASDC output.
    
temp=RoundToCeil(0.01*2*(GetConVarFloat(ASDCcommons)*ASDCout*GetConVarFloat(ASDCCImult)+GetConVarFloat(ASDCcommons)));
    
SetConVarInt(FindConVar("z_wandering_density"), temp);
    
SetConVarInt(FindConVar("z_mob_population_density"), temp);
    
    
//Set Amount of zombies to spawn in a waves
    
temp=temp*100;
    
SetConVarInt(FindConVar("z_common_limit"), temp);
    
SetConVarInt(FindConVar("z_background_limit"), temp);
    
temp=RoundToCeil(2*(GetConVarFloat(ASDCmob)*ASDCout*GetConVarFloat(ASDCCImult)+GetConVarFloat(ASDCmob)));
    
SetConVarInt(FindConVar("z_mega_mob_size"), temp);
    
    
    return 
ASDCout;
}

bool:IsTank(i)
{
    
decl Stringclassname[32];
    
GetClientModel(iclassnamesizeof(classname));
    if (
StrContains(classname"hulk"false) != -1)
        return 
true;
    return 
false;
}

stock SpawnCommand(clientString:command[], String:arguments[] = "")
{
    if (
client)
    {
        
ChangeClientTeam(client,3);
        new 
flags GetCommandFlags(command);
        
SetCommandFlags(commandflags & ~FCVAR_CHEAT);
        
FakeClientCommand(client"%s %s"commandarguments);
        
SetCommandFlags(commandflags FCVAR_CHEAT);
        
CreateTimer(0.1,Kickbot,client);
    }

rtokuda is offline
HarryPotter
Veteran Member
Join Date: Sep 2017
Location: Taiwan, Asia
Old 08-01-2020 , 13:14   Re: [L4D2]Update Difficulty Control(ASDC) V1.2
Reply With Quote #2

Wasn't there an updated version ??

https://forums.alliedmods.net/showpo...9&postcount=22
__________________

Last edited by HarryPotter; 08-01-2020 at 13:15.
HarryPotter is offline
Alex101192
Senior Member
Join Date: Aug 2018
Old 08-02-2020 , 12:08   Re: [L4D2]Update Difficulty Control(ASDC) V1.2
Reply With Quote #3

Quote:
Originally Posted by fbef0102 View Post
No offence but how do you expect anyone to find that hidden little post on this forum? That code is also 3 years old, still using downtown and probably not working with silver's dhooks.

Last edited by Alex101192; 08-02-2020 at 12:09.
Alex101192 is offline
HarryPotter
Veteran Member
Join Date: Sep 2017
Location: Taiwan, Asia
Old 08-02-2020 , 12:58   Re: [L4D2]Update Difficulty Control(ASDC) V1.2
Reply With Quote #4

Quote:
Originally Posted by Alex101192 View Post
No offence but how do you expect anyone to find that hidden little post on this forum? That code is also 3 years old, still using downtown and probably not working with silver's dhooks.

1. That is not the hidden little post. Updated plugin is on #22, and rtokuda leaves the comment on #23, #24. How do people just ignore the obvious post ???? obvious same page 3???

2. That updated plugin is 3 years old, but it is using new syntax and can be compiled with sm 1.10.
He can make a request of that updated plugin, remove old downtown and add silver's new left4dooks.
__________________

Last edited by HarryPotter; 08-02-2020 at 13:01.
HarryPotter is offline
rtokuda
Senior Member
Join Date: Dec 2019
Old 08-05-2020 , 11:52   Re: [L4D2]Update Difficulty Control(ASDC) V1.2
Reply With Quote #5

Quote:
Originally Posted by fbef0102 View Post
1. That is not the hidden little post. Updated plugin is on #22, and rtokuda leaves the comment on #23, #24. How do people just ignore the obvious post ???? obvious same page 3???

2. That updated plugin is 3 years old, but it is using new syntax and can be compiled with sm 1.10.
He can make a request of that updated plugin, remove old downtown and add silver's new left4dooks.

I saw the jhee plugin, but I thought that the end of the campaign takes too long with so much spawning of infected. Not to mention that the old plugin already regulated the number of common and special infected.
rtokuda is offline
HarryPotter
Veteran Member
Join Date: Sep 2017
Location: Taiwan, Asia
Old 08-06-2020 , 06:58   Re: [L4D2]Update Difficulty Control(ASDC) V1.2
Reply With Quote #6

Quote:
Originally Posted by rtokuda View Post
I saw the jhee plugin, but I thought that the end of the campaign takes too long with so much spawning of infected. Not to mention that the old plugin already regulated the number of common and special infected.
update.
Attached Files
File Type: sp Get Plugin or Get Source (l4d2_ASDC.sp - 179 views - 13.5 KB)
__________________

Last edited by HarryPotter; 08-06-2020 at 06:59.
HarryPotter 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 17:35.


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