Insane limits examples

Slawter

Support team
5 Сен 2014
22.475
877
Disable Vehicles Based on Player Count
This limit will check the number of players in the server at specific intervals of time, and depending on how many players are there in the server, it will enable/disable vehicle spawn by changing the value of "vars.vehicleSpawnAllowed". This change is in effect immediately, no need to wait for next round. However, this only applies to attack vehicles. Transport vehicles will still spawn.


Set limit to evaluate OnInterval, and set action to None

Set first_check to use this Code snippet:

Code:
if (server.PlayerCount < 8 )
plugin.ServerCommand("vars.vehicleSpawnAllowed", "false");
else
plugin.ServerCommand("vars.vehicleSpawnAllowed", "true");​

In this case, if number of players in the server falls below 8, vehicles are disabled. As soon as it goes to or over 8, vehicles are re-enabled. You may change this value as you see fit.

Also note that when you turn off vehicle spawn, your server may not be listed in Battlelog as Hard-core. Additionally, disabling vehicles can reportedly interfere with Battlelog's Quick Match option.​
 

Slawter

Support team
5 Сен 2014
22.475
877
Disable Vehicles Based On Current Map

Originally Posted by cpt
Is it possible to disable Vehicles on specific maps only (seine crossing, teheran highway)?
Yes you can. In that case, instead of checking for player count, you just check for what is the current map.

Set limit to evaluate OnInterval, and set action to None

Set first_check to use this Code snippet:

Code:
List<String> map_names = new List<String>();

map_names.Add("MP_003");
map_names.Add("MP_011");

if (map_names.Contains(server.MapFileName))
plugin.ServerCommand("vars.vehicleSpawnAllowed", "false");
else
plugin.ServerCommand("vars.vehicleSpawnAllowed", "true");

return false;​

For this example, vehicles will be disabled when map is "MP_003", or "MP_011", which are the files names for Tehran Highway, and Seine Crossing. For all other maps, the vehicles will be allowed.

This is the full list of map files names for BF3, (including Back to Karkand expansion)

  • MP_001 - Grand Bazaar
  • MP_003 - Teheran Highway
  • MP_007 - Caspian Border
  • MP_011 - Seine Crossing
  • MP_012 - Operation Firestorm
  • MP_013 - Damavand Peak
  • MP_017 -Noshahr Canals
  • MP_018 - Kharg Island
  • MP_Subway - Operation Metro
  • XP1_001 - Strike At Karkand
  • Xp1_002 - Gulf of Oman
  • XP1_003 - Sharqi Peninsula
  • XP1_004 - Wake Island

Note that since this only disables the vehicles after the map has loaded, the first set of vehicles might spawn. But, after that, they should not spawn anymore. I haven't tested it to verify, but I suspect that's what would happen.

Finally, this is just a very crude way of doing Per-Map settings. Sure it will work, but if there is already a plugin that specializes on that area, and already does the job well, you should use that.​
 

Slawter

Support team
5 Сен 2014
22.475
877
Simple Welcome Message
This limit will send a message (global) for the player when he spawns in the server for the first time.

Set limit to evaluate OnSpawn, and action to Say

Set first_check to this Expression:

Code:
(true)​

Set second_check to this Expression:

Code:
( limit.ActivationsTotal(player.Name) == 1 )
Set these action specific parameters

Code:
say_audience = All
say_message = Everyone, lets welcome %p_n%, from %p_cn%!​

If player leaves, and re-joins, welcome message should be displayed again.​
 

Slawter

Support team
5 Сен 2014
22.475
877
Welcome Message Based on Country
This limit sends a different welcome message to the players, depending on what country they are from.

Set limit to evaluate OnSpawn, and action to None,

Set first_check to this Expression:

Code:
(true)​

Set second_check to this Code:

Code:
double count = limit.ActivationsTotal(player.Name);

if (count > 1)
return false;

String CC = player.CountryCode;

if (CC.Equals("us"))
plugin.SendGlobalMessage(plugin.R("Welcome %p_n%"));
else if (CC.Equals("at"))
plugin.SendGlobalMessage(plugin.R("Willkommen %p_n%"));
else if(CC.Equals("fr"))
plugin.SendGlobalMessage(plugin.R("Bienvenue %p_n%"));
else if (CC.Equals("it"))
plugin.SendGlobalMessage(plugin.R("Benvenuto %p_n%"));
else
plugin.SendGlobalMessage(plugin.R("Everyone lets welcome %p_n% from %p_cn%!"));

return false;​
 

Slawter

Support team
5 Сен 2014
22.475
877
Admin Welcome Messages
Set use_custom_lists to True and create a new list with these parameters:

Code:
name = admin_list
data = player1, player2, player3, etc​

Create a new limit to evaluate OnSpawn and set action to Say

Set first_check to this Expression:

Code:
plugin.isInList(player.Name, "admin_list")
Set second_check to this Expression:

Code:
limit.ActivationsTotal(player.Name) == 1
Set these action specific parameters:
Code:
say_audience = All
say_message = Admin %p_n% has logged in, everyone behave!​
 

Slawter

Support team
5 Сен 2014
22.475
877
Warning/Kick for RPG/M320/SMAW Suicides

Originally Posted by Idanue
Is it possible to first give someone a warning with suicide when they use M320 RPG-7 or SMAW and kick/ban after second kill?
It's possible, only limitation is that if the M320 is attached to the weapon (underslug), it won't register as M320.

This limit will warn the player on first Suicide, and Kick him on second. It will also send a global message to server saying that he was kicked.

Set limit to evaluate OnSuicide, and set action to None

Set first_check to this Expression:

Code:
Regex.Match(kill.Weapon, @"(RPG|SMAW|M320)", RegexOptions.IgnoreCase).Success​

Set second_check to this Code:

Code:
double count = limit.Activations(player.Name);

if (count == 1)
plugin.SendGlobalMessage(plugin.R("%p_n%, do not suicide with %w_n%, next time kick!"));
else if (count == 2)
{
plugin.SendGlobalMessage(plugin.R("%p_n%, was kicked for suiciding with %w_n%!"));
plugin.KickPlayerWithMessage(player.Name, plugin.R("Kicked for suiciding with %w_n%!"));
}

return false;​


When you paste the Code part into the second_check field, make sure to click on the down-arrow, on the field, so that it expands and allows you to paste multi-line.​
 

Slawter

Support team
5 Сен 2014
22.475
877
Good Morning Messages (Time Dependent)
This limit will send a a Good Morning message to all players, between 7AM, and 8 AM ... after the first kill each round. The reason I did it, for OnKill is so that it guarantees that everyone has already loaded the map, and will see the message.

Set limit to evaluate OnKill, set action to Say

Set first_check to this Expression:

Code:
DateTime.Now.TimeOfDay.CompareTo(TimeSpan.FromHours(7)) > 0 && DateTime.Now.TimeOfDay.CompareTo(TimeSpan.FromHours(8)) < 0​


Set second_check to this Expression:

Code:
limit.Activations() == 1
Set these action specific parameters:

Code:
say_audience = All
say_message = Good morning everyone, the time is %time%!​

This example depends, on the Time-Zone of the computer (layer) where the plugin is running. If that turns to be a problem, you should adjust the 7 AM, and 8 AM values to account for Time-Zones.

Also, the hours should be put in military time. 1 PM = 13, 2 PM = 14, etc ...​
 

Slawter

Support team
5 Сен 2014
22.475
877
First Kill of the Year
This limit will activate on January 1st, of any year. Test this locally by changing your computer clock. Also note that since limit activations are reset every 10 rounds. It will say the same again after 10 rounds. Or, if the server empties out, (the stats are cleared) ... it will say it again.

Set limit to evaluate OnKill, set action to Say:

Set first_check to this Expression:

Code:
DateTime.Now.DayOfYear == 1​

Set first_check to this Expression:

Code:
limit.ActivationsTotal() == 1​

Set these action specific parameters:

Code:
say_audience = All
say_message = Congratulations to %p_n% for the first kill of the year!​
 

Slawter

Support team
5 Сен 2014
22.475
877
Nuke/Knife Cheat Catcher

As an admin you might have seen cheaters that kills with knife or nothing but "Death".

This should help catch those.


Set limit to evaluate OnKill, set action to PBBan

Set first_check to this Expression:
Code:
Regex.Match(kill.Weapon, @"(Death|Knife|Melee)", RegexOptions.IgnoreCase).Success​
Set second_check to this Expression:
Code:
( limit.Activations(player.Name, TimeSpan.FromSeconds(30)) > 13 )


Set these action specific parameters:
Code:
ban_duration = Permanent
ban_message = Knife\Nuke hack %w_n%​
 

Slawter

Support team
5 Сен 2014
22.475
877
Multi-Action Bad-Word Filter
It's possible to have a multi-action bad-word filter. This limit will warn on first violation, kill on second, and kick on third. The words in the bad_words list can also be regular epxressions if you want.

Set limit to evaluate OnAnyChat, set action to None

Set first_check to this Code:

Code:
List<String> bad_words = new List<String>();

bad_words.Add("word1");
bad_words.Add("word2");
bad_words.Add(@"f[eua]+c*k(i+n?g?)?");
bad_words.Add(@"a+ss+");
bad_words.Add(@"n[o0]{2,}b");

String[] chat_words = Regex.Split(player.LastChat, @"\s+");

foreach(String chat_word in chat_words)
foreach(String bad_word in bad_words)
if (Regex.Match(chat_word, "^"+bad_word+"$", RegexOptions.IgnoreCase).Success)
return true;

return false;​

Set second_check to this Code:

Code:
double count = limit.Activations(player.Name);

if (count == 1)
plugin.SendSquadMessage(player.TeamId, player.SquadId, plugin.R("%p_n%, please avoid using profanity"));
else if (count == 2)
{
plugin.KillPlayer(player.Name);
plugin.SendSquadMessage(player.TeamId, player.SquadId, plugin.R("%p_n%, this is your %p_x_th% profanity warning, next time you are out!"));
}
else if (count == 3)
{
plugin.KickPlayerWithMessage(player.Name, plugin.R("%p_n%, kicked you for excessive profanity!"));
plugin.SendGlobalMessage(plugin.R("%p_n% was kicked for excessive profanity"));
}

return false;​


You can modify this example to perform different actions depending on the count. But, once the player is kicked, and leaves the server, the count values are reset back to 0. It will not remember the player after he has left.

There is a plugin called Watchdog that works with BF3, which is able to remember a player if he comes back after being kicked.​
 

Slawter

Support team
5 Сен 2014
22.475
877
In-Game Per-Weapon Headshots Percentage Kicker
This limit will activate for players who get more than 90% headshots after 30 kills (with a specific weapon). This works across rounds. (Total stats are not reset at the end of the round).

Set limit to evaluate OnKill, set action to Kick,

Set first_check to this Code:

Code:
double kills = player[kill.Weapon].KillsTotal;
double headshots = player[kill.Weapon].HeadshotsTotal;
double headshots_percent = Math.Round((headshots / kills)*100.0, 2);

if (headshots_percent > 90 && kills > 30)
{
plugin.ConsoleWrite(plugin.R("%p_n% has " + headshots_percent + " headshots percent with "+ kill.Weapon + " after " + kills + " kills"));
return true;
}

return false;​

Set these action specific parameters:
Code:
kick_message = %p_n%, you were kicked for suspicious headshots percentage with %w_n%​

This feature (per-weapon stats) is not extensively tested. You should adjust the conditions to test, and see if it works as you expect it. If you are going to test it on a populated server, make sure it's on virtual so you can adjust the values until you feel comfortable that it will not kick everyone.​
 

Slawter

Support team
5 Сен 2014
22.475
877
Change Server Settings for Late-Night vs. Prime-Time Hours
NOTE: Compiles without error, but not tested for correct behavior.

This example shows how to change server settings for two periods of time, the prime-time hours and the late-night hours. As an example, this code uses vars.gameModeCounter to set double the number of tickets in a round during prime-time and sets it back to normal tickets late at night, but you can execute any code between the two time intervals that you want, for example, change the idle timeout, friendly fire, hardcore, etc.

Server settings are changed during the OnRoundOver event, to give maximum flexibility in what you can change and reducing the chance of confusing your players or the server.

Set limit to evaluate OnRoundOver, set action to None

Set first_check to this Code:

Code:
// Bracket the start and end times of the late-night settings
// startOClock must be between 20 (8pm) and 23 (11pm) inclusive, or 0 (midnight)
// endOClock must be between 1 (1am) and 5 (5:59am) inclusive

int startOClock = 22; // 22:00 at night (10pm)
int endOClock = 4; // 4:59 in the morning of the next day (4am)

// Assert(8pm >= startOClock <= midnight), sanity check
if ((startOClock != 0 && startOClock < 20) || startOClock > 23) {
plugin.ConsoleError("startOClock must be between 20 and 23 inclusive, or 0 for midnight!");
return false;
}

// Assert(1am <= endOClock <= 5am), sanity check
if (endOClock > 5 || endOClock < 1) {
plugin.ConsoleError("endOClock must be between 1 and 5 inclusive!");
return false;
}

int hour = DateTime.Now.Hour;

// Adjust for midnight transition
hour = (hour <= 5) ? hour + 24 : hour;
int adjustedEnd = endOClock + 24;
int adjustedStart = (startOClock == 0) ? 24 : startOClock;

if (hour >= adjustedStart && hour <= adjustedEnd) {
// Late-night settings
plugin.ServerCommand("vars.gameModeCounter", "100");
plugin.ConsoleWrite("Running late-night settings!");
} else {
// Prime-time hours settings
plugin.ServerCommand("vars.gameModeCounter", "200");
plugin.ConsoleWrite("Running prime-time settings!");
}
return true;​

Leave second_check Disabled


To set a different start and end hour for the late-night period, change the value of startOClock and/or endOClock and the comments that follow them. Only specify the hour -- the limit doesn't support minutes -- for example, instead of 10:30pm and 1:15am, use 10 and 1 respectively. Note that the example (arbitrarily) limits startOClock to between 8pm and midnight and endOClock to between 1am and 6am (5:59), in order to have a reasonable correspondence with "late-night" and to simplify the calculations.​
 

Slawter

Support team
5 Сен 2014
22.475
877
nsane Limits V0.8/R2: Player Count Tracker
Version V0.8/R2: R1 fully tested, but R2 update not yet compiled or tested.

This example shows how to track the number of players in the server over time. It's useful to determining if a particular map is very popular and good at attracting players, or unpopular and causes a lot of quitting.

At debug level 3, the plugin console will get posted with every change to map level/round or number of players. At level 2 or lower, only the change to map level/round is posted. Example output at level 3 (other Thread lines deleted for clarity):

[23:03:53] [Insane Limits] Thread(enforcer): [PCT]: Seine/CQ64/2/2, 32/32, +1 net change. Round (min-max) 21-32
[23:04:13] [Insane Limits] Thread(enforcer): Checking limits for 32 players in list
...
[23:09:20] [Insane Limits] Thread(enforcer): Checking limits for 32 players in list
[23:09:21] [Insane Limits] Thread(enforcer): [PCT]: Seine/CQ64/2/2, 30/32, -2 net change. Round (min-max) 30-30
[23:09:41] [Insane Limits] Thread(enforcer): Checking limits for 29 players in list
[23:09:43] [Insane Limits] Thread(enforcer): [PCT]: Seine/CQ64/2/2, 23/32, -7 net change. Round (min-max) 23-30
[23:10:03] [Insane Limits] Thread(enforcer): Checking limits for 22 players in list
[23:10:05] [Insane Limits] Thread(enforcer): [PCT]: Karkand/CQ64/1/2, 21/32, -2 net change. Round (min-max) 21-30
[23:10:13] [Insane Limits] round start detected
...
[23:10:25] [Insane Limits] Thread(enforcer): Checking limits for 18 players in list
[23:10:27] [Insane Limits] Thread(enforcer): [PCT]: Karkand/CQ64/1/2, 18/32, -3 net change. Round (min-max) 18-30
...
[23:10:47] [Insane Limits] Thread(enforcer): Checking limits for 20 players in list
[23:10:48] [Insane Limits] Thread(enforcer): [PCT]: Karkand/CQ64/1/2, 20/32, +2 net change. Round (min-max) 18-30
...
[23:11:52] [Insane Limits] Thread(enforcer): Checking limits for 21 players in list
[23:11:54] [Insane Limits] Thread(enforcer): [PCT]: Karkand/CQ64/1/2, 21/32, +1 net change. Round (min-max) 18-30

Optionally, the example will also log comma separated values (CSV) to a log file. The default location of the log file is procon/Logs/%ip%_%port%/YYYYMMDD_pct.csv, where %ip% and %port% are the IP address and port of your RCON connection, and YYYYMMDD are the year, month and date of the log file. For example, if your IP is 129.0.0.1 and your port is 47000 and the date was Feb 4, 2012, the path would be: procon/Logs/129.0.0.1_47000/20120204_pct.csv. The logging interval is approximately 1 minute if there is no change in the player count, or, every OnInterval period in which there is a change.

Sample CSV:

Code:
23:03:53,Seine,CQ64,2,2,32,32,1,21,32
23:04:58,Seine,CQ64,2,2,32,32,0,21,32
23:06:04,Seine,CQ64,2,2,32,32,0,21,32
23:07:09,Seine,CQ64,2,2,32,32,0,21,32
23:08:15,Seine,CQ64,2,2,32,32,0,21,32
23:09:21,Seine,CQ64,2,2,30,32,-2,30,30
23:09:43,Seine,CQ64,2,2,23,32,-7,23,30
23:10:05,Karkand,CQ64,1,2,21,32,-2,21,30
23:10:27,Karkand,CQ64,1,2,18,32,-3,18,30
23:10:48,Karkand,CQ64,1,2,20,32,2,18,30
23:11:54,Karkand,CQ64,1,2,21,32,1,18,30​

The columns are: Time, Map, Mode, Round, Of Rounds, Player Count, Max Players, Net Change, Min Players For Round, Max Players For Round.


Version 0.8p3: Set limit to evaluate OnIntervalServer, set the interval to 31, set Action to None

Set first_check to this Code:

Code:
/* Version: V0.8/R2 */

/* Track count of players by map/mode name */

bool logToFile = true; // Set to false to disable logging

String kMaxPlayers = "PCT_max"; // PCT = Player Count Tracker
String kMinPlayers = "PCT_min";
String kPlayers = "PCT_players";
String kTime = "PCT_time";
String kMapRound = "PCT_map_round";

if (!server.Data.issetInt(kPlayers)) {
server.Data.setInt(kPlayers, 0);
}
if (!server.RoundData.issetInt(kMaxPlayers)) {
server.RoundData.setInt(kMaxPlayers, 0);
}
if (!server.RoundData.issetInt(kMinPlayers)) {
server.RoundData.setInt(kMinPlayers, 64);
}
if (!server.RoundData.issetObject(kTime)) {
server.RoundData.setObject(kTime, DateTime.Now);
}
if (!server.RoundData.issetString(kMapRound)) {
server.RoundData.setString(kMapRound, server.MapFileName + server.CurrentRound.ToString());
}

int level = 2;

try {
level = Convert.ToInt32(plugin.getPluginVarValue("debug_level"));
} catch (Exception e) {}

/* Check for change */

int lastPlayers = server.Data.getInt(kPlayers);
int currentPlayers = server.PlayerCount;

if (lastPlayers == currentPlayers) {
// No change, skip update
if (level >= 6) plugin.ConsoleWrite("^b[PCT]^n: skipping " + lastPlayers + "->" + currentPlayers);
if (!logToFile) return false;
// Even if we are logging, skip if less than a minute has passed
DateTime lastTime = (DateTime)server.RoundData.getObject(kTime);
TimeSpan span = DateTime.Now.Subtract(lastTime);
if (span.TotalSeconds < 60) return false;
}

/* Calculate net change */

int maxPlayers = server.RoundData.getInt(kMaxPlayers);
int minPlayers = server.RoundData.getInt(kMinPlayers);

int netChange = currentPlayers - lastPlayers;

if (maxPlayers < currentPlayers) {
server.RoundData.setInt(kMaxPlayers, currentPlayers);
maxPlayers = currentPlayers;
}
if (minPlayers > currentPlayers) {
server.RoundData.setInt(kMinPlayers, currentPlayers);
minPlayers = currentPlayers;
}
server.Data.setInt(kPlayers, currentPlayers);
server.RoundData.setObject(kTime, DateTime.Now);

/* Log changes */

/* BF3 friendly map names, including B2K */
Dictionary<String, String> maps = new Dictionary<String, String>();
maps.Add("MP_001", "Bazaar");
maps.Add("MP_003", "Teheran");
maps.Add("MP_007", "Caspian");
maps.Add("MP_011", "Seine");
maps.Add("MP_012", "Firestorm");
maps.Add("MP_013", "Damavand");
maps.Add("MP_017", "Canals");
maps.Add("MP_018", "Kharg");
maps.Add("MP_Subway", "Metro");
maps.Add("XP1_001", "Karkand");
maps.Add("XP1_002", "Oman");
maps.Add("XP1_003", "Sharqi");
maps.Add("XP1_004", "Wake");
maps.Add("XP2_Factory", "Factory");
maps.Add("XP2_Office", "Office");
maps.Add("XP2_Palace", "Palace");
maps.Add("XP2_Skybar", "Skybar");

/* BF3 friendly game modes, including B2K */
Dictionary<String, String> modes = new Dictionary<String, String>();
modes.Add("ConquestLarge0", "CQ64");
modes.Add("ConquestSmall0", "CQ");
modes.Add("ConquestSmall1", "CQA");
modes.Add("RushLarge0", "Rush");
modes.Add("SquadRush0", "SQRush");
modes.Add("SquadDeathMatch0", "SQDM");
modes.Add("TeamDeathMatch0", "TDM");
modes.Add("Domination0", "CQD");
modes.Add("GunMaster0", "GM");
modes.Add("TeamDeathMatchC0", "TDMC");

String mapName = (maps.ContainsKey(server.MapFileName)) ? maps[server.MapFileName] : server.MapFileName;
String modeName = (modes.ContainsKey(server.Gamemode)) ? modes[server.Gamemode] : server.Gamemode;
String color = (netChange >= 0) ? "^2+" : "^8";
String time = DateTime.Now.ToString("HH:mm:ss");
String currMapRound = server.MapFileName + server.CurrentRound.ToString();

// Example console line:
// [PCT]: Metro/CQ64/1/2, 47/64, -3 net change. Round (min-max) 33-60

// Log to console if map/round changed, or if debugging and player count changed
if (!server.RoundData.getString(kMapRound).Equals(currMapRound) || (level >= 3 && lastPlayers != currentPlayers)) {
plugin.ConsoleWrite("^b[PCT]^n: ^4" + mapName + "/" + modeName + "/" + (server.CurrentRound+1) + "/" + server.TotalRounds + "^0, " + currentPlayers + "/" + server.MaxPlayers + ", ^b" + color + netChange + "^0^n net change. Round (min-max) " + minPlayers + "-" + maxPlayers);
server.RoundData.setString(kMapRound, currMapRound);
}

// Example log line:
// 23:11:54,Karkand,CQ64,1,2,21,32,1,18,30
if (logToFile) {
String logName = plugin.R("Logs/%server_host%_%server_port%/") + DateTime.Now.ToString("yyyyMMdd") + "_pct.csv";
String line = time + "," + mapName + "," + modeName + "," + (server.CurrentRound+1) + "," + server.TotalRounds + "," + currentPlayers + "," + server.MaxPlayers + "," + netChange + "," + minPlayers + "," + maxPlayers;
plugin.Log(logName, line);
}
return false;​

Leave second_check Disabled

To disable CSV logging, change the value of logToFile from true to false.

REVISIONS​
 

Slawter

Support team
5 Сен 2014
22.475
877
Insane Limits V0.8/R1: Bad Name Kicker
Version: V0.8/R1

In this case, let's define a "bad name" to be one that is all digits. You can use some other pattern, like bad words or unusual characters that are hard to type, but for clarity this example will just look for players with all digit names like 00010110100101. This example also shows a variety of action settings, which include the Kick action as well as conventional Say, PRoConEvent and Log actions.

Set limit to evaluate OnJoin, set action to Say | PRoConEvent | Log | Kick.

Set first_check to this Expression:

Code:
( Regex.Match(player.Name, @"^[0-9]+$").Success )​

Set the action specific settings to something like the following. This shows the settings for limit_1, but if your limit is a different number, for example "3", look for "limit_3_kick_message", etc.

Code:
limit_1_say_message %p_fn% kicked for bad player name, all digits!
limit_1_say_audience All
limit_1_say_delay 0
limit_1_procon_chat True

limit_1_procon_event_text Attempting to kick %p_fn% for bad player name, all digits
limit_1_procon_event_player Insane Limits

limit_1_log_destination Plugin
limit_1_log_message [%date% %time%] %p_fn% kicked for bad name: all digits

limit_1_kick_message bad player name: all digits​
 

Slawter

Support team
5 Сен 2014
22.475
877
Switch Hardcore/Softcore Mode Based on Player Count

Originally Posted by WaxMyCarrot
Can we add an admin.say string here to say something like "Server switching to Hardcore!"?
This limit will keep switching server between hard-core, and soft-core mode, depending on the number of players in the server. When the mode is switched, the limit sends a global message notifying players of the change.

Set limit to evaluate OnInterval, set action to None

Set first_check to this Code:

Code:
double switch_value = 16;

bool? hardcore = null;
if (server.Data.issetBool("hardcore"))
hardcore = server.Data.getBool("hardcore");

if (server.PlayerCount < switch_value && ( hardcore == true || hardcore == null) )
{
plugin.SendGlobalMessage("Switching server to soft-core mode");
plugin.ConsoleWrite("Switching server to soft-core mode");
server.Data.setBool("hardcore", false);

plugin.ServerCommand("vars.friendlyFire", "false");
plugin.ServerCommand("vars.killCam", "true");
plugin.ServerCommand("vars.nameTag", "true");
plugin.ServerCommand("vars.regenerateHealth", "true");
plugin.ServerCommand("vars.hud", "true");
plugin.ServerCommand("vars.onlySquadLeaderSpawn", "false");
plugin.ServerCommand("vars.3dSpotting", "true");
plugin.ServerCommand("vars.3pCam", "true");
plugin.ServerCommand("vars.idleTimeout", "0");
plugin.ServerCommand("vars.soldierHealth", "100");

}
else if ( server.PlayerCount > switch_value && (hardcore == false || hardcore == null))
{
plugin.SendGlobalMessage("Switching server to hard-core mode");
plugin.ConsoleWrite("Switching server to hard-core mode");

server.Data.setBool("hardcore", true);

plugin.ServerCommand("vars.friendlyFire", "true");
plugin.ServerCommand("vars.killCam", "false");
plugin.ServerCommand("vars.nameTag", "false");
plugin.ServerCommand("vars.regenerateHealth", "false");
plugin.ServerCommand("vars.hud", "false");
plugin.ServerCommand("vars.onlySquadLeaderSpawn", "true");
plugin.ServerCommand("vars.3dSpotting", "false");
plugin.ServerCommand("vars.3pCam", "false");
plugin.ServerCommand("vars.idleTimeout", "1800");
plugin.ServerCommand("vars.soldierHealth", "60");
}​

Note that this limit stores a flag "hardcore" in the server object. Depending on the value of the flag, it decides whether or not mode needs to be switched again. This is needed so that it would not keep spamming the switch message, as well well as not sending server commands unnecessarily if the mode is already the same.

This flag is only cleared if the plugin is enabled/disabled. The limit is not in any way aware of what the current mode is. It assumes that whatever mode it set last time ... is the one currently active. Because of this, if you manually change the mode, the limit will not know of the mode change.​