Merge branch 'master' of github.com:Jackzmc/sourcemod-plugins

This commit is contained in:
Jackz 2023-07-20 20:15:48 -05:00
commit 2c99586be1
No known key found for this signature in database
GPG key ID: E0BBD94CF657F603
6 changed files with 116 additions and 253 deletions

View file

@ -1,7 +1,8 @@
# sourcemod-plugins
This is a collection of all the sourcemod plugins I've created, most are just used for my own servers and some for very specific needs.
This is a collection of sourcemod plugins, most are used on my servers. The majority of the plugins are created by me, but some are modifications of other plugins.
Some of the plugins / changes are very specific, but may be useful to someone.
Not always the latest versions, if you have any interest with plugins I can make sure to upload the latest.
Not always the latest versions. If you have any interest with a plugin, I can make sure to upload the latest.
Useful things:
1. Netprop viewer https://jackz.me/netprops/l4d2
@ -16,33 +17,34 @@ Useful things:
* [l4d2-manual-director](#l4d2-manual-director) - Spawn specials on demand via director or at your cursor
* [l4d2-info-cmd](#l4d2-info-cmd) - Prints a full state of all survivors, useful for external information
* [AutoWarpBot](#autowarpbot) - Abandoned
* [L4D2FFKickProtection](#l4d2ffkickprotection) - Prevents friendly firing from players being voted off and admins from being kicked
* [l4d2_avoid_minigun](#l4d2_avoid_minigun) - Makes bots avoid being infront of any in use miniguns. Useful for spawned miniguns
* [L4D2FFKickProtection](#l4d2ffkickprotection) - Prevents players being voted off from friendly firing and prevents admins from being kicked
* [l4d2_avoid_minigun](#l4d2_avoid_minigun) - Makes bots avoid being infront of any in-use miniguns. Useful for spawned miniguns
* [l4d2_ai_minigun](#l4d2_ai_minigun) - Based off [Silver's Survivor Bot Holdout plugin](https://forums.alliedmods.net/showthread.php?p=1741099), allows you to spawn survivor bots but with no limit.
* [L4D2Tools](#l4d2tools) - A collection of utilities, mostly just used with [l4d_survivor_identity_fix](#l4d_survivor_identity_fix) and the /model command
* [l4d2_swarm](#l4d2_swarm) - Uses vscript RushVictim to make all zombies target a player, like a more subtle vomitplayer
* [l4d2_feedthetrolls](#l4d2_feedthetrolls) - Full collection of tools to troll your friends or troll the trolls
* [l4d2_autobotcrown](#l4d2_autobotcrown) - Bots will auto crown
* [l4d2_extraplayeritems](#l4d2_extraplayeritems) - Includes tons of utilities for 5+ games, such as 5+ player hud, extra kit spawning, and more
* [l4d2_autobotcrown](#l4d2_autobotcrown) - Bots will auto crown
* [l4d2_extraplayeritems](#l4d2_extraplayeritems) - Includes tons of utilities for 5+ games, such as 5+ player hud, extra kit / item spawning, and more
* [l4d2_population_control](#l4d2_population_control) - Allows you to custom the type of zombies that spawn (% of clowns, mud men, etc..)
* [globalbans](#globalbans) - Bans synced via mysql, way lighter than the sourcebans cesspool.
* [l4d2_rollback](#l4d2_rollback) - Abandoned but makes periodic backup of all player's items
* [l4d2_autorestart](#l4d2_autorestart) - Restarts server if it's been on for a certain uptime or when empty with just bots
* [l4d2_TKStopper](#l4d2_tkstopper) - All the teamkiller and shitty aim player punishments. Auto increasing reverse ff and teamkill detection
* [l4d2_crescendo_control](#l4d2_crescendo_control) - Prevents players from running far ahead and starting events & logs button presses
* [l4d2_rollback](#l4d2_rollback) - Abandoned and broken, but makes periodic backup of all player's items
* [l4d2_autorestart](#l4d2_autorestart) - Restarts server if it's been on for a certain uptime or when empty with just bots.
* [l4d2_TKStopper](#l4d2_tkstopper) - All the teamkiller and shitty-aim player punishments. Auto increasing reverse ff and teamkill detection
* [l4d2_crescendo_control](#l4d2_crescendo_control) - Prevents players from running far ahead and starting events, and logs button presses
* [l4d2_vocalize_control](#l4d2_vocalize_control) - Allows you to locally mute someone from vocalizing
* [l4d2_guesswho](#l4d2_guesswho) - Garrys mod's guess who in l4d2, inspired by hide and seek
* [l4d2_guesswho](#l4d2_guesswho) - Garry's Mod's Guess Who in l4d2, inspired by hide and seek
* [l4d2_hideandseek](#l4d2_hideandseek) - An enhancement to the base hide and seek mutation
* [l4d2_hats](#l4d2_hats) - Entity Hats & Entity editing
* [l4d2_prophunt](#l4d2_prophunt) - Garry's mod inspired prop hunt, inspired by hide and seek
* [l4d2_prophunt](#l4d2_prophunt) - Garry's Mod inspired prop hunt, inspired by hide and seek
* [sm_namespamblock](#sm_namespamblock) - Basic plugin that bans players if they change their name in rapid succession
* [l4d2-stats-plugin](https://github.com/jackzmc/l4d2-stats-plugin) - Custom stats recorder, see https://stats.jackz.me
* [l4d2-ai-tweaks](#l4d2_ai_tweaks) - Very minor tweaks to survivor bots' behavior
### Modified Others
* [200IQBots_FlyYouFools](#200iqbots_flyyoufools) - Improved code to make it support multiple tanks and work better
* [l4d_survivor_identity_fix](#l4d_survivor_identity_fix) - Use with [L4D2Tools](#l4d2tools) to change models, some fixes
* [BetterWitchAvoidance](#betterwitchavoidance)
* l4d_anti_rush - Modified plugin to add a forward, so other plugins (like feedthetrolls) can do something and use highest flow value achieved for players (fixes issue when admins go back and players who haven't moved suddenly get punished)
* l4d_anti_rush - Modified plugin to add a forward, so other plugins (like feedthetrolls) can do something. In addition, use highest flow value achieved for players (fixes issue when admins go back and players who haven't moved suddenly get punished)
* [l4d2_sb_fix](#l4d2_sb_fix) - Updated to 1.11 & latest sourcepawn syntax & removed the FCVAR_NOTIFY from all cvars (why is that added?)
* GrabEnt - Improved version that prevents moving certain entities (such as invisual walls, ragdolls, etc) and improved some code
@ -55,7 +57,7 @@ Check the plugin info for an exact list.
### Development Dependencies
Most L4D2 plugins use my own include: jutils.inc, it's provided in this repo.
Some do require newer includes by modified plugins (such as my improved survivor identity fix)
Some do require newer includes for my modified plugins (such as my improved survivor identity fix)
## Descriptions
@ -68,7 +70,7 @@ On knife kill, gives the player 100 HP (configurable)
### l4d2-manual-director
Probably going to be posted publicly sometime. allows you to spawn specials on cursor, or via director, forcefully, bypassing limits
~~Probably going to be posted publicly sometime.~~ Allows you to spawn specials on cursor, or via director, forcefully, bypassing limits
* **Convars:**
* `manual_director_version|mandirector_version` - ... gets version
* `mandirector_notify_spawn <1/0>` - Should spawning specials notify on use?
@ -102,7 +104,7 @@ Technically 'l4d2 game info', haven't changed name. Just prints general informat
### AutoWarpBot
Simple l4d2 plugin that will auto teleport everyone to checkpoint once all real players have reached the saferoom.
Simple l4d2 plugin that will auto teleport bots to checkpoint once all real players have reached the saferoom.
Doesn't really work well. Abandoned.
@ -119,7 +121,8 @@ Inspired by the 200IQBots_FlyYouFools. Bots avoid witch if its over 40% anger wh
### L4D2FFKickProtection
Simple plugin that prevents a player that is being vote-kicked from doing any ff damage to teammates.
It also prevents vote kicking of admins, instead will kick the player and notify admins.
It also prevents vote kicking of admins, instead will notify admins.
It also makes any vote kicks created by an admin to instantly be accepted by all players
* **Convars:**
* `sm_votekick_force_threshold <#>` - The threshold of damage where the offending player is just immediately kicked. 0 -> Any attempted damage, -1 -> No auto kick.
@ -165,10 +168,10 @@ A collection of small tools:
* Notification of when someone picks up laser sights (only the first user, includes bots),
* Record time it takes for a finale or gauntlet run to be completed.
* Record the amount of friendly fire damage done
* Set the survivor models of any survivor with updating [l4d_survivor_identity_fix](#l4d_survivor_identity_fix)
* Automatically gives melee weapons that an idle bot dropped once no longer idle
* Set the survivor models of any survivor with updated [l4d_survivor_identity_fix](#l4d_survivor_identity_fix)
* Automatically returns melee weapons that an idle bot dropped once no longer idle
* Automatically make players go idle when ping spikes
* Slowly kill any zombies attacking survivor bot's blind spots (Fixes bots stuck taking damage and brain dead)
* Slowly kill any zombies attacking survivor bot's blind spots (Fixes brain dead bots stuck taking damage and not killing them)
* **Convars:**
* `sm_laser_use_notice <0/1>` - Enable notification of when a laser box was used first
@ -202,7 +205,7 @@ This really only affects wandering zombies, mobs and panic events, but it may wo
Requires:
* [Left4Dhooks](https://forums.alliedmods.net/showthread.php?t=321696)
* (Optional) [Scene Processor](https://forums.alliedmods.net/showthread.php?p=2147410)
* (Optional) [L4D2 Behavior](https://forums.alliedmods.net/showthread.php?p=2752139) - To be replaced with [Actions](https://forums.alliedmods.net/showthread.php?t=336374)
* (Optional) [Actions](https://forums.alliedmods.net/showthread.php?t=336374)
* (Optional) [Modified L4D Antirush](#l4d_anti_rush)
This plugin allows you to enact certain troll modes on any player, some are subtle some are less so. Either way, it works great to deal with a rusher, an asshole or even your friends.
@ -218,23 +221,25 @@ https://admin.jackz.me/docs/ftt
* `sm_ftt_magnet_chance <0.0 - 1.0>` - % of the time that the magnet will work on a player."
* `sm_ftt_shove_fail_chance <0.0 - 1.0>` - The % chance that a shove fails
* **Commands:**
* `sm_fta [player]` - Opens a menu to select a troll to apply, with modifiers and flags
* `sm_fta [player]` - The main command, opens a menu to select a troll to apply, with modifiers and flags
* `sm_ftr [player]` - Removes all active trolls from a player
* `sm_ftc [player]` - Opens a menu to select a combo of trolls
* `sm_ftl` - Lists all players that have a mode applied.
* `sm_ftm` - Lists all troll options & their descriptions
* `sm_mark` - Toggles marking a player to be banned when they fully disconnect
* `sm_insta [player] [special]` - (No arguments opens menu) - Spawns a special via director that will only target the victim
* `sm_inface [player] [special]` - Identical to above, but special will be spawned as close as possible to survivor. Boomers auto explode.
* `sm_bots_attack <player> [target health]` - Slightly broken, but makes all bots shoot at player until they hit X health or a timeout is reached.
* `sm_insta [player] [special]` - (No arguments opens menu) - Spawns a special via the director that will only target the victim
* `sm_inface [player] [special]` - Identical to above, but special will be spawned as close as possible to survivor. Boomers auto explode, jockeys on their head, etc.
* `sm_bots_attack <player> [target health]` - Slightly broken, but makes all bots shoot at player until they hit X health or a timeout is reached. Turn on `sb_friendlyfire` for it to be effective.
* `sm_stagger <player>` - Makes a player stagger, shortcut to the Stagger troll
* `sm_witch_attack <player>` - Makes all witches agro on the player
* `sm_scharge <player> [timeout seconds]` - Will wait till there's no obstructions and players in the way and then spawns a charger to charge them.
* `sm_healbots <player> [# bots or 0 default]` - Makes n amount of bots chase a player down to heal them. Won't stop until they are healed or die.
* `sm_scharge <player> [timeout seconds]` - Will wait till there's no obstructions and players in the way, then spawns a charger behind them to charge them.
* `sm_healbots <player> [# bots or 0 default]` - Makes n amount of bots chase a player down to heal them. Won't stop until they are healed, they die, or you run command again.
### l4d2_autobotcrown
Makes any suitable bot (> 40 hp, has shotgun) automatically crown a witch. Supports multiple bots and witches, but only one bot can crown one witch at a time. Plugin is obviously disabled in realism, and is really on suitable for coop or versus. Even works with idle players.
Makes any suitable bot (> 40 hp, has shotgun) automatically crown a witch. Supports multiple bots and witches, but only one bot can crown one witch at a time. Plugin is disabled in realism, and is really on suitable for coop or versus. Even works with idle players.
Bots do sometimes miss, but sometimes still manage to kill witch. They also don't care if there is danger in the way (fire, acid, angry witch).
* **Convars:**
* `l4d2_autocrown_allowed_difficulty <default: 7>` - The difficulties the plugin is active on. 1=Easy, 2=Normal 4=Advanced 8=Expert. Add numbers together.
@ -253,7 +258,8 @@ Features:
* Automatically giving extra kits for each extra player in saferooms
* Increasing item count for items randomly depending on player count
* Fix same-models survivors having to fight over ammo pack usage
* Automatically lock the exit saferoom door until a threshold of players or time has passed
* Automatically lock the first saferoom door for every chapter, until a threshold of players or time has passed
* Includes a HUD that shows all the survivors and their items, and optionally their ping
* **Convars:**
* `l4d2_extraitem_chance` - The base chance (multiplied by player count) of an extra item being spawned. Default: 0.056
@ -276,7 +282,7 @@ Requires:
A fork of [Survivor Identity Fix plugin](https://forums.alliedmods.net/showthread.php?t=280539) that adds support for other plugins to update the model cache. This is used by [L4D2Tools](#L4D2Tools) to update the identity when someone changes their model with `sm_model`. It also will clear the memory of model when a player disconnects entirely or on a new map.
In addition, has a fix for the passing finale, and will automatically move L4D characters to L4D2 until finale starts preventing game messing up their characters.
In addition, has a fix for the passing finale, and will automatically temporarily change L4D characters to L4D2 until finale starts preventing game messing up their characters.
### l4d2_population_control
@ -328,7 +334,7 @@ Currently auto triggers:
### l4d2_autorestart
Plugin that automatically restarts server when the server is NOT hibernating, with bots around and no players.
This fixes an issue with (shitty) custom maps that force sb_all_bot_game to 1 and disable hibernation
This fixes an issue with custom maps that force sb_all_bot_game to 1 and disable hibernation.
### l4d2_TKStopper
Requires:
@ -345,7 +351,7 @@ Any survivor that attacks another survivor
See https://admin.jackz.me/docs/plugins#tkstopper for some more implementation information
During any of the above three conditions, if they deal (or attempt to deal) over 75 HP in 15 seconds they will be instantly banned for a set period of time (60 minutes). If they are for sure a team killer, it can be extended to a permanent ban.
During any of the above three conditions, if they deal (or attempt to deal) over 75 HP in 15 seconds (configurable) they will be instantly banned for a set period of time (60 minutes). If they are for sure a team killer, it can be extended to a permanent ban.
* **Cvars:**
* `l4d2_tk_forgiveness_time <#>` - The minimum amount of seconds to pass (in seconds) where a player's previous accumulated FF is forgive. Default is 15s
@ -361,7 +367,7 @@ Requires:
This plugin prevents the activation of buttons ahead of the team. It will prevent players from starting crescendos (and some small other activities as a side effect) until a certain threshold of the team has reached the area.
_This plugin is currently in **development.**_ Current implementation may be lacking.
_This plugin is not perfect, sometimes it may trigger early, or not trigger at all depending on the map. Sometimes you need to as admins, move forward to allow non-admins to activate events._
* **Cvars:**
@ -373,7 +379,7 @@ _This plugin is currently in **development.**_ Current implementation may be lac
A very small plugin that simply allows a player to mute another player's vocalizations only for them.
* **Commands:**
* `sm_vgag <player(s)>` - Vocalize gag or ungags selected player(s)
* `sm_vgag <player(s)>` - Vocalize gag or ungags selected player(s) for the command activator only
### l4d2_sb_fix
A fork of https://forums.alliedmods.net/showthread.php?p=2757330
@ -388,6 +394,7 @@ Requires:
A sourcemod extenstion of the vscript gamemode (https://steamcommunity.com/sharedfiles/filedetails/?id=2467133506)
- Player blockers, portals, and props to change and control the maps
- Optional climbable infected ladders, and heart beat when seeker nearby
- Some quality of life (winner messages, change seeker mid game, change map time)
- and a lot more
@ -403,7 +410,7 @@ Vscript required for hud & mutation
Gamemode: https://steamcommunity.com/sharedfiles/filedetails/?id=2823719841
Requires l4dtoolz and left4dhooks, and optioanlly skip intro cutscene
Requires l4dtoolz and left4dhooks, and optionally skip intro cutscene
### l4d2_prophunt
Requires:
@ -418,7 +425,7 @@ Vscript required for hud & mutation
* Demo Map: https://steamcommunity.com/sharedfiles/filedetails/?id=2855027013 (makes most prop_static -> prop_dynamic)
Requires l4dtoolz and left4dhooks, and optioanlly skip intro cutscene
Requires l4dtoolz and left4dhooks, and optionally skip intro cutscene
### l4d2_hats
@ -436,3 +443,11 @@ Requires recompile to change.
* **Commands:**
* `status2` - Shitty name, but shows all non-admin players, sorted by last joined ascending (up top). Shows steamid and the first name they joined the server as
* `sm_status2` - Same command, but allows /status2 in chat
### l4d2_ai_tweaks
Simply, prevents an idle bot (that is a bot for an idle player) from healing another player unless:
1. The target is black and white
2. The player has been idle for over **ALLOW_HEALING_MIN_IDLE_TIME** (a \#define) seconds (default is 3 minutes)
Requires recompile to change.

View file

@ -158,8 +158,9 @@ public Action Timer_PushLogs(Handle h) {
static char query[1024];
static Log log;
int length = logs.Length;
Transaction transaction = new Transaction();
if(length > 0) {
Transaction transaction = new Transaction();
for(int i = 0; i < length; i++) {
logs.GetArray(i, log, sizeof(log));
g_db.Format(query, sizeof(query), "INSERT INTO `activity_log` (`timestamp`, `server`, `type`, `client`, `target`, `message`) VALUES (%d, NULLIF('%s', ''), '%s', NULLIF('%s', ''), NULLIF('%s', ''), NULLIF('%s', ''))",
@ -173,11 +174,11 @@ public Action Timer_PushLogs(Handle h) {
transaction.AddQuery(query);
}
logs.Resize(logs.Length - length);
g_db.Execute(transaction, _, SQL_TransactionFailed, length, DBPrio_Low);
}
g_db.Execute(transaction, _, SQL_TransactionFailed, length, DBPrio_Low);
return Plugin_Continue;
}
public void SQL_TransactionFailed(Database db, any data, int numQueries, const char[] error, int failIndex, any[] queryData) {
void SQL_TransactionFailed(Database db, any data, int numQueries, const char[] error, int failIndex, any[] queryData) {
LogError("Push transaction failed: %s at query %d/%d", error, failIndex, numQueries);
}
@ -301,4 +302,4 @@ public any Native_AddLog(Handle plugin, int numParams) {
if(GetNativeString(4, message, sizeof(message)) != SP_ERROR_NONE) return false;
AddLog(type, clientName, targetName, message);
return true;
}
}

View file

@ -347,6 +347,8 @@ public Action Event_OnTakeDamage(int victim, int& attacker, int& inflictor, flo
float pos[3];
GetNearestPlayerPosition(victim, pos);
PrintToConsoleAdmins("%N within join time (%d min), attempted to fall");
TeleportEntity(victim, pos, NULL_VECTOR, NULL_VECTOR);
damage = 0.0;
if(pData[victim].jumpAttempts > hSuicideLimit.IntValue) {
if(hSuicideAction.IntValue == 1) {
LogMessage("[NOTICE] Kicking %N for suicide attempts", victim, hBanTime.IntValue);
@ -362,50 +364,52 @@ public Action Event_OnTakeDamage(int victim, int& attacker, int& inflictor, flo
pData[victim].isTroll = true;
}
}
return Plugin_Stop;
}
if(attacker == victim) return Plugin_Continue;
// Forgive player based on threshold, resetting accumlated damage
// Forgive player teamkill based on threshold, resetting accumlated damage
if(time - pData[attacker].lastFFTime > hForgivenessTime.IntValue) {
pData[attacker].TKDamageBuffer = 0.0;
}
pData[attacker].TKDamageBuffer += damage;
pData[attacker].totalDamageFF += damage;
pData[attacker].totalFFCount++;
pData[attacker].ffCount++;
// Auto reverse ff logic
// If not immune to RFF, damage is direct, _or admin shit_
if(~pData[attacker].immunityFlags & Immune_RFF && isDamageDirect) {
if(isDamageDirect) {
// Decrease the RFF scale based on how long since their last FF and an amount
float minutesSinceiLastFFTime = (time - pData[attacker].lastFFTime) / 60.0;
pData[attacker].autoRFFScaleFactor -= minutesSinceiLastFFTime * hFFAutoScaleForgivenessAmount.FloatValue;
if(pData[attacker].autoRFFScaleFactor < 0.0) {
pData[attacker].autoRFFScaleFactor = 0.0;
}
// Decrement any accumlated ff 'counts'
int ffCountMinutes = RoundFloat(minutesSinceiLastFFTime / 10.0);
pData[attacker].ffCount -= (ffCountMinutes * 2);
if(pData[attacker].ffCount < 0) {
pData[attacker].ffCount = 0;
}
// Decrement any forgiven ratio (computed on demand)
if(pData[attacker].autoRFFScaleFactor < 0.0) {
pData[attacker].autoRFFScaleFactor = 0.0;
}
// Then calculate a new reverse ff ratio
// Calculate a new reverse ff ratio based on scale threshold + damage dealt + # of recent friendly fires events
pData[attacker].autoRFFScaleFactor += hFFAutoScaleAmount.FloatValue * damage * (pData[attacker].ffCount*0.25);
if(pData[attacker].isTroll) {
pData[attacker].autoRFFScaleFactor *= 2;
}
// Cap max damage only for non-trolls
if(!pData[attacker].isTroll && hFFAutoScaleMaxRatio.FloatValue > 0.0 && pData[attacker].autoRFFScaleFactor > hFFAutoScaleMaxRatio.FloatValue) {
} else if(hFFAutoScaleMaxRatio.FloatValue > 0.0 && pData[attacker].autoRFFScaleFactor > hFFAutoScaleMaxRatio.FloatValue) {
// Cap it to the max - if they aren't marked as troll
pData[attacker].autoRFFScaleFactor = hFFAutoScaleMaxRatio.FloatValue;
}
}
int prevFFTime = pData[attacker].lastFFTime;
pData[attacker].lastFFTime = time;
// Check for excessive friendly fire damage in short timespan
// If not immune to TK, if over TK threshold, not when escaping, and direct damage
if(~pData[attacker].immunityFlags & Immune_TK
if(~pData[attacker].immunityFlags & Immune_TK
&& pData[attacker].TKDamageBuffer > hThreshold.IntValue
&& !isFinaleEnding
&& isDamageDirect
@ -441,9 +445,9 @@ public Action Event_OnTakeDamage(int victim, int& attacker, int& inflictor, flo
}
// Modify damages based on criteria
if(pData[victim].jumpAttempts > 0
|| L4D_IsInFirstCheckpoint(victim) || L4D_IsInLastCheckpoint(victim)
|| time - pData[attacker].joinTime <= hJoinTime.IntValue * 60
if(pData[victim].jumpAttempts > 0 // If they've attempted suicide, we just incase, disable their ff damage
|| L4D_IsInFirstCheckpoint(victim) || L4D_IsInLastCheckpoint(victim) // No FF damage in saferooms
|| time - pData[attacker].joinTime <= hJoinTime.IntValue * 60 // No FF damage within first X minutes
) {
/*
If the amount of seconds since they joined is <= the minimum join time cvar (min) threshold
@ -456,14 +460,14 @@ public Action Event_OnTakeDamage(int victim, int& attacker, int& inflictor, flo
}else if(isFinaleEnding) {
// Keep admins immune if escape vehicle out, or if victim is a bot
if(isAdmin || IsFakeClient(victim)) return Plugin_Continue;
// We ignore FF for fire/molotovs, can be accidental / non-issue
if(isDamageDirect)
SDKHooks_TakeDamage(attacker, attacker, attacker, damage * 2.0);
damage = 0.0;
return Plugin_Changed;
}else if(isDamageDirect && pData[attacker].autoRFFScaleFactor > 0.3) { // Ignore fire and propane damage, mistakes can happen
}else if(isDamageDirect && pData[attacker].autoRFFScaleFactor > 0.18) { // 0.18 buffer to ignore fire and propane damage, mistakes can happen
// Apply their reverse ff damage, and have victim take a decreasing amount
if(pData[attacker].isTroll) return Plugin_Stop;
else if(pData[attacker].immunityFlags & Immune_RFF) return Plugin_Continue;
SDKHooks_TakeDamage(attacker, attacker, attacker, pData[attacker].autoRFFScaleFactor * damage);
if(pData[attacker].autoRFFScaleFactor > 1.0)

View file

@ -21,7 +21,7 @@ public Plugin myinfo = {
url = "https://github.com/Jackzmc/sourcemod-plugins"
};
ConVar noHibernate;
ConVar cvar_hibernateWhenEmpty;
public void OnPluginStart() {
startupTime = GetTime();
@ -31,7 +31,7 @@ public void OnPluginStart() {
SetFailState("This plugin is for L4D/L4D2 only.");
}
noHibernate = FindConVar("sv_hibernate_when_empty");
cvar_hibernateWhenEmpty = FindConVar("sv_hibernate_when_empty");
RegAdminCmd("sm_request_restart", Command_RequestRestart, ADMFLAG_GENERIC);
@ -60,7 +60,7 @@ public Action Timer_Check(Handle h) {
} else if(GetTime() - startupTime > MAX_TIME_ONLINE_SECONDS) {
LogAction(0, -1, "Server has passed max online time threshold, will restart if remains empty");
pendingRestart = true;
noHibernate.BoolValue = true;
cvar_hibernateWhenEmpty.BoolValue = false;
if(IsServerEmpty()) {
if(++triesEmpty > 4) {
LogAction(0, -1, "Server has passed max online time threshold and is empty after %d tries, restarting now", triesEmpty);
@ -78,7 +78,7 @@ public Action Timer_Check(Handle h) {
public void OnConfigsExecuted() {
// Reset no hibernate setting when level changes:
if(pendingRestart) {
noHibernate.BoolValue = true;
cvar_hibernateWhenEmpty.BoolValue = false;
}
}

View file

@ -1,171 +0,0 @@
#pragma semicolon 1
#pragma newdecls required
#include <sourcemod>
#include <sdktools>
#define HIT_1 "weapons/golf_club/wpn_golf_club_melee_01.wav"
#define HIT_2 "weapons/golf_club/wpn_golf_club_melee_02.wav"
ConVar sv_melee_force_projectile, sv_melee_radius_projectile, sv_melee_force_boost_projectile_up;
int g_iLaser, g_iGlow;
public Plugin myinfo =
{
name = "[L4D2] Baseball",
author = "BHaType",
description = "Melee weapons can now deflect projectile",
version = "0.0",
url = ""
}
public void OnPluginStart()
{
sv_melee_force_projectile = CreateConVar("sv_melee_force_projectile", "0.6");
sv_melee_force_boost_projectile_up = CreateConVar("sv_melee_force_boost_projectile_up", "250.0");
sv_melee_radius_projectile = CreateConVar("sv_melee_radius_projectile", "75.0");
AutoExecConfig(true, "l4d2_baseball");
HookEvent("weapon_fire", weapon_fire);
HookEvent("entity_shoved", entity_shoved);
}
public void OnMapStart()
{
PrecacheSound(HIT_1, true);
PrecacheSound(HIT_2, true);
g_iLaser = PrecacheModel("materials/sprites/laserbeam.vmt");
g_iGlow = PrecacheModel("materials/sprites/glow.vmt");
}
public void entity_shoved (Event event, const char[] name, bool dontbroadcast)
{
int entity = event.GetInt("entityid");
static char szName[36];
GetEntityClassname(entity, szName, sizeof szName);
if ( StrContains(szName, "_projectile") != -1 )
{
float vVelocity[3];
vVelocity = CalculateBaseForce(entity);
vVelocity[2] += sv_melee_force_boost_projectile_up.FloatValue;
TeleportEntity(entity, NULL_VECTOR, NULL_VECTOR, vVelocity);
}
}
public void weapon_fire (Event event, const char[] name, bool dontbroadcast)
{
static char szName[36];
event.GetString("weapon", szName, sizeof szName);
if ( strcmp(szName, "melee") != 0 )
return;
int client = event.GetInt("userid");
timer (CreateTimer(0.1, timer, client, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE), client);
}
public Action timer (Handle timer, int client)
{
client = GetClientOfUserId(client);
if ( !client )
return Plugin_Stop;
int weapon = GetPlayerWeaponSlot(client, 1);
if ( weapon == -1 || GetEntPropFloat(weapon, Prop_Send, "m_flNextPrimaryAttack") <= GetGameTime())
return Plugin_Stop;
float vAngles[3], vOrigin[3], vVector[3], vEnd[3];
GetClientEyePosition(client, vOrigin);
GetClientEyeAngles(client, vAngles);
GetAngleVectors(vAngles, vVector, NULL_VECTOR, NULL_VECTOR);
ScaleVector(vVector, sv_melee_radius_projectile.FloatValue);
AddVectors(vOrigin, vVector, vEnd);
GetClientEyePosition(client, vOrigin);
#define hull 10.0
static const float vMaxs[3] = { hull, hull, hull };
static const float vMins[3] = { -hull, -hull, -hull };
TR_TraceHullFilter(vOrigin, vEnd, vMins, vMaxs, MASK_SOLID, TraceFilter, client);
float vHit[3];
TR_GetEndPosition(vHit);
if ( TR_DidHit () )
{
int entity = TR_GetEntityIndex();
if ( entity != 0 )
{
static char szName[36];
GetEntityClassname(entity, szName, sizeof szName);
if ( StrContains(szName, "_projectile") != -1 )
{
float vVelocity[3], vVec[3];
vVelocity = CalculateBaseForce(entity, client);
GetEntPropVector(entity, Prop_Send, "m_vecOrigin", vOrigin);
MakeVectorFromPoints(vHit, vOrigin, vVec);
ScaleVector(vVec, 1.0 - sv_melee_force_projectile.FloatValue * sv_melee_radius_projectile.FloatValue);
AddVectors(vVec, vVector, vVec);
AddVectors(vVec, vVelocity, vVelocity);
TE_SetupSparks(vHit, vVelocity, 1, 1);
TE_SendToAll();
NegateVector(vVelocity);
vVelocity[2] += sv_melee_force_boost_projectile_up.FloatValue;
TeleportEntity(entity, NULL_VECTOR, NULL_VECTOR, vVelocity);
int color[4] = { 255, ... };
for (int i; i <= 2; i++)
color[i] = GetRandomInt(0, 255);
TE_SetupBeamFollow(entity, g_iLaser, g_iGlow, 4.6, 0.8, 0.8, 1, color);
TE_SendToAll();
EmitSoundToAll((GetRandomInt(0, 1) == 0 ? HIT_1 : HIT_2), SOUND_FROM_WORLD, .origin = vHit);
// PrintToChatAll("\x04%N \x03baseballed projectile for \x04%.2f \x03velocity!", client, GetVectorLength(vVelocity));
return Plugin_Stop;
}
}
}
return Plugin_Continue;
}
float[] CalculateBaseForce (int victim, int attacker = 0)
{
float m_vecBaseVelocity[3], m_vecVelocity[3], vAngles[3];
if ( attacker )
{
GetEntPropVector(attacker, Prop_Send, "m_vecBaseVelocity", m_vecBaseVelocity);
GetClientEyeAngles(attacker, vAngles);
}
GetEntPropVector(victim, Prop_Data, "m_vecVelocity", m_vecVelocity);
AddVectors(m_vecBaseVelocity, m_vecVelocity, m_vecVelocity);
ScaleVector(m_vecVelocity, sv_melee_force_projectile.FloatValue);
return m_vecVelocity;
}
public bool TraceFilter (int entity, int mask, int data)
{
return entity != data;
}

View file

@ -61,8 +61,8 @@ public void OnPluginStart() {
LoadTranslations("common.phrases");
HookEvent("player_entered_checkpoint", OnEnterSaferoom);
HookEvent("player_left_checkpoint", OnLeaveSaferoom);
HookEvent("player_bot_replace", Event_PlayerOutOfIdle );
HookEvent("bot_player_replace", Event_PlayerToIdle);
HookEvent("player_bot_replace", Event_PlayerToIdle);
HookEvent("bot_player_replace", Event_PlayerOutOfIdle);
RegConsoleCmd("sm_hat", Command_DoAHat, "Hats");
RegAdminCmd("sm_hatf", Command_DoAHat, ADMFLAG_ROOT, "Hats");
@ -470,28 +470,45 @@ void ChooseRandomPosition(float pos[3], int ignoreClient = 0) {
public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3], float angles[3], int& weapon, int& subtype, int& cmdnum, int& tickcount, int& seed, int mouse[2]) {
float tick = GetGameTime();
//////////////////////////////
// OnPlayerRunCmd :: HATS
/////////////////////////////
if(IsHatsEnabled(client)) {
int entity = GetHat(client);
int visibleEntity = EntRefToEntIndex(hatData[client].visibleEntity);
///#HAT PROCESS
if(entity > 0) {
// try to tp hat to itys own pos
// Crash prevention: Prevent hat from touching ladder as that can cause server crashes
if(!onLadder[client] && GetEntityMoveType(client) == MOVETYPE_LADDER) {
onLadder[client] = true;
ClearParent(entity);
// Hide hat temporarily in void:
// If hat is not a player, we teleport them to the void (0, 0, 0)
// Otherwise, we just simply dismount the player while hatter is on ladder
if(entity >= MaxClients)
TeleportEntity(entity, EMPTY_ANG, NULL_VECTOR, NULL_VECTOR);
if(visibleEntity > 0) {
hatData[client].visibleEntity = INVALID_ENT_REFERENCE;
RemoveEntity(visibleEntity);
}
} else if(onLadder[client] && GetEntityMoveType(client) != MOVETYPE_LADDER) {
}
// Player is no longer on ladder, restore hat:
else if(onLadder[client] && GetEntityMoveType(client) != MOVETYPE_LADDER) {
onLadder[client] = false;
EquipHat(client, entity);
}
// Do the same crash protection for the hat itself, just to be safe:
if(entity <= MaxClients) {
if(!onLadder[entity] && GetEntityMoveType(entity) == MOVETYPE_LADDER) {
onLadder[entity] = true;
ClearParent(entity);
} else if(onLadder[entity] && GetEntityMoveType(entity) != MOVETYPE_LADDER) {
onLadder[entity] = false;
EquipHat(client, entity);
}
}
// Rainbow hat processing
if(HasFlag(client, HAT_RAINBOW)) {
// Decrement and flip, possibly when rainbowticks
if(hatData[client].rainbowReverse) {
@ -515,24 +532,18 @@ public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3
EquipHat(client, entity);
}
if(entity <= MaxClients) {
if(!onLadder[entity] && GetEntityMoveType(entity) == MOVETYPE_LADDER) {
onLadder[entity] = true;
ClearParent(entity);
} else if(onLadder[entity] && GetEntityMoveType(entity) != MOVETYPE_LADDER) {
onLadder[entity] = false;
EquipHat(client, entity);
}
}
// If bot is commandable and reversed (player reverse-hat common/survivor), change position:
if(HasFlag(client, HAT_COMMANDABLE | HAT_REVERSED) && tickcount % 200 == 0) {
float pos[3];
ChooseRandomPosition(pos, client);
L4D2_CommandABot(entity, client, BOT_CMD_MOVE, pos);
}
}
// Detect E + R to offset hat or place down
if(buttons & IN_USE && buttons & IN_RELOAD) {
if(entity > 0) {
if(buttons & IN_ZOOM) {
// Offset controls:
if(buttons & IN_JUMP) hatData[client].offset[2] += 1.0;
if(buttons & IN_DUCK) hatData[client].offset[2] -= 1.0;
if(buttons & IN_FORWARD) hatData[client].offset[0] += 1.0;
@ -542,7 +553,7 @@ public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3
TeleportEntity(entity, hatData[client].offset, angles, vel);
return Plugin_Handled;
} else if(tick - cmdThrottle[client] > 0.25) {
if(buttons & IN_ATTACK) {
if(buttons & IN_ATTACK) { // doesn't work reliably for some reason
ClientCommand(client, "sm_hat y");
} else if(buttons & IN_DUCK) {
ClientCommand(client, "sm_hat p");
@ -558,7 +569,9 @@ public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3
}
}
///#WALL BUILDER PROCESS
//////////////////////////////
// OnPlayerRunCmd :: ENTITY EDITOR
/////////////////////////////
if(WallBuilder[client].IsActive() && WallBuilder[client].CheckEntity(client)) {
if(buttons & IN_USE && buttons & IN_RELOAD) {
ClientCommand(client, "sm_wall done");
@ -578,6 +591,7 @@ public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3
if(buttons & IN_ATTACK) WallBuilder[client].CycleAxis(client, tick);
else if(buttons & IN_ATTACK2) WallBuilder[client].CycleSnapAngle(client, tick);
// Rotation control:
if(tick - cmdThrottle[client] > 0.20) {
if(WallBuilder[client].axis == 0) {
if(mouse[1] > 10) WallBuilder[client].angles[0] += WallBuilder[client].snapAngle;
@ -876,4 +890,4 @@ stock bool GetCursorLimited2(int client, float distance, float endPos[3], TraceE
return true;
}
return false;
}
}