Skip to content

A SourceMod plugin for Left 4 Dead 2 that allows you to open upgrade boxes as party/fun boxes. A big work-in-progress!

Notifications You must be signed in to change notification settings

gamemann/l4d2-partyboxes

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

52 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A SourceMod plugin for Left 4 Dead 2 that turns upgrade boxes such as incendiary and explosive ammo boxes into random/fun boxes. There are three categories a box may be registered under which include Good, Mid, and Bad. Good boxes help the survivors, mid boxes are somewhere in-between (misc?), and bad boxes negatively impact the survivors.

You can configure the chance probability for each box category using SourceMod ConVars which is detailed below.

My main goal is to create a modular core plugin that handles things like picking the box and calculating stats, and then allow developers to create their own boxes as separate SourceMod plugins which register with the core via natives and global forwards.

NOTE - This project is a big work-in-progress and I'm also pretty rusty in SourcePawn since I haven't utilized it much in recent years so I'm sure there are many things that can be improved on (feel free to make a PR!).

Preview

Test Box

Damage Box

My Motives

I've been occassionally playing a custom mega (24 players) COOP game server in Left 4 Dead 2 for almost a year now (Core-SS) and I've had a lot of fun! The server runs a custom plugin very similar to this plugin and since I've been wanting to get back into SourcePawn, I figured I'd create my own open source plugin (to my knowledge, the plugin they use isn't open source, but even if it was, I really wanted to make my own to get back into SourcePawn again).

Additionally, I've been really wanting to get back into learning game development so I can create open source 3D games in the future and I really believe creating plugins like this and modding in general can really help with understanding game development further!

Core

Config & ConVars

A config file should be generated to cfg/sourcemod/plugin.l4d2pb.cfg. Additionally, box-specific configs should be located in the same directory.

Here's the output of the plugin.l4d2pb.cfg config file for more information on the current core ConVars.

Show Configuration
// This file was auto-generated by SourceMod (v1.11.0.6968)
// ConVars for plugin "l4d2pb-core.smx"


// The maximum amount of bad boxes that can be opened per round. 0 = disables bad boxes. -1 = no limit.
// -
// Default: "-1"
l4d2_max_bad_boxes "-1"

// Whether to announce who opens boxes.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_announce "1"

// What type of printing to do for announcing. 0 = chat. 1 = server console. 2 = client console. 3 = hint.
// -
// Default: "3"
// Minimum: "0.000000"
l4d2pb_announce_type "3"

// The chances of a bad box being opened.
// -
// Default: "0.25"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_chance_bad "0.25"

// The chances of a good box being opened.
// -
// Default: "0.15"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_chance_good "0.15"

// The chances of a mid box being opened.
// -
// Default: "0.50"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_chance_mid "0.50"

// The chances of getting no fun boxes when opened.
// -
// Default: "0.10"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_chance_none "0.10"

// Enables or disables L4D2 Party Boxes plugin.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_enabled "1"

// Whether to display stats in chat on round end.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_end_round_stats "1"

// The maximum amount of good boxes that can be opened per round. 0 = disables good boxes. -1 = no limit.
// -
// Default: "-1"
l4d2pb_max_good_boxes "-1"

// The maximum amount of mid boxes that can be opened per round. 0 = disables mid boxes. -1 = no limit.
// -
// Default: "-1"
l4d2pb_max_mid_boxes "-1"

// The type of max limits. 0 = round-based. 1 = map-based.
// -
// Default: "0"
// Minimum: "0.000000"
// Maximum: "2.000000"
l4d2pb_max_type "0"

// If 1, any boxes that are opened (and not none type) are removed immediately when opened.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_remove_opened "1"

// The plugin's verbose level.
// -
// Default: "0"
// Minimum: "0.000000"
l4d2pb_verbose "0"

// The type of verbose messages. 0 = prints to chat. 1 = prints to server console. 2 = prints to client's console.
// -
// Default: "0"
// Minimum: "0.000000"
l4d2pb_verbose_type "0"

// The plugin's version.
// -
// Default: "1.0.0"
l4d2pb_version "1.0.0"

Commands

Here are a list of commands you may run from chat (prefixed with ! or /) or console (prefixed with sm_).

Command Admin Only Arguments Description
l4d2pb_stats No - Displays stats in chat.
l4d2pb_open Yes (1) Box Name Manually opens a box determined by box name argument. Requires root admin flag.

Enums

Here are some useful enums you'll need when developing your own box types.

enum BoxType {
    BOXTYPE_NONE = 0,
    BOXTYPE_GOOD = 1,
    BOXTYPE_MID = 2,
    BOXTYPE_BAD = 3
}

Natives

Here are a list of core natives you may use when developing your own box types. Take a look at scripting/l4d2pb-box-test.sp for a basic example.

/**
 * Registers a box to core and adds it to the box rotation.
 *
 * @param type      The box type (BoxType enum).
 * @param name      A short/code name for the box.
 * @param display   The box display name.      
 *
 * @return 0 on success or 1 on error.
 */
native int L4D2PB_RegisterBox(BoxType type, const char[] name, const char[] display);

/**
 * Unloads a box from the core.
 *
 * @param name      A short/code name for the box.
 *
 * @return 0 on success or 1 on error.
 */
native int L4D2PB_UnloadBox(const char[] name);

/**
 * Prints a debug message from the core plugin.
 *
 * @param req      The required verbose level from the core plugin.
 * @param msg      The debug message to send.
 * @param ...      Formatted arguments for msg.
 *
 * @return void
 */
native void L4D2PB_DebugMsg(int req, const char[] msg, any...);

/**
 * Prints a message to a client's chat from the core plugin (recommended).
 *
 * @param client   The client's index to print to.
 * @param msg      The message to print.
 * @param ...      Formatted arguments for msg.
 *
 * @return void
 */
native void L4D2PB_PrintToChat(int client, const char[] msg, any...);

/**
 * Prints a message to all clients from the core plugin (recommended).
 *
 * @param msg      The message to print.
 * @param ...      Formatted arguments for msg.
 *
 * @return void
 */
native void L4D2PB_PrintToChatAll(const char[] msg, any...);

Forwards

Here are core (global) forwards you may call while developing your own box types. Take a look at scripting/l4d2pb-box-test.sp for a basic example.

/**
 * Called when the core plugin is initially loaded (in OnPluginStart()).
 * 
 */
public void L4D2PB_OnCoreLoaded();

/**
 * Called when the core plugin executes its config (in OnConfigsExecuted()).
 * 
 * @note This is where I recommend registering a box.
 * 
 */
public void L4D2PB_OnCoreCfgsLoaded();

/**
 * Called when the core plugin is unloaded (in OnPluginEnd()).
 * 
 */
public void L4D2PB_OnCoreUnloaded();

/**
 * Called when a box is opened.
 * 
 * @param type      The type of box opened.
 * @param boxName   The box short/code name that was opened.
 * @param userid    The user ID who opened the box.
 * 
 */
public void L4D2PB_BoxOpened(int type, const char[] boxName, int userId);

Provided Boxes

Here are a list of boxes provided in this repository. Boxes are developed as separate plugins that use forwards and natives from the core plugin to register the box and such.

This is a damage box registered under the Bad category. It is enabled by default and damages the user and potentially players around them depending on the ConVar values set when opened.

ConVars & Configuration

The configuration file may be found at cfg/sourcemod/plugin.l4d2pb-box-dmg.cfg.

Show Configuration
// This file was auto-generated by SourceMod (v1.11.0.6968)
// ConVars for plugin "l4d2pb-box-dmg.smx"


// Announces to damaged players who opened the box and the amount it damaged them for.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_dmg_announce "1"

// If 1, bypasses the SDKHooks_OnTakeDamage() hook when damaging users.
// -
// Default: "0"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_dmg_bypass_ontakedamage "0"

// Enables the damage box
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_dmg_enabled "1"

// The maximum damage to apply.
// -
// Default: "100.0"
// Minimum: "1.000000"
l4d2pb_box_dmg_max "100.0"

// The minimum damage to apply.
// -
// Default: "5.0"
// Minimum: "1.000000"
l4d2pb_box_dmg_min "5.0"

// The maximum radius to damage survivors in. 0 = disables damaging others.
// -
// Default: "500.0"
// Minimum: "0.000000"
l4d2pb_box_dmg_radius_max "500.0"

// The mimimum radius to damage survivors in.
// -
// Default: "200.0"
// Minimum: "0.000000"
l4d2pb_box_dmg_radius_min "200.0"

// If 1, when damage is applied, each player affected receives a random damage count.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_dmg_rand_per_player "1"

// If 1, the uesr who opened the damage box is used as the attacker when damaging players.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_dmg_use_user_as_attacker "1"

// If 1, the user who opened the damage box is used as the inflictor when damaging players.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_dmg_use_user_as_inflictor "1"

// If 1, uses the position of who opened the box as the damage position.
// -
// Default: "0"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_dmg_use_user_pos "0"

// The damage box's version.
// -
// Default: "1.0.0"
l4d2pb_box_dmg_version "1.0.0"

This is a freeze box registered under the Bad category. When a user opens this box, they are frozen along with players around the user depending on the radius ConVar values. The freeze time can also be random. This box also includes functionality for setting a player's RGBA value and playing a sound when a player is frozen/unfrozen.

ConVars & Configuration

The configuration file may be found at cfg/sourcemod/plugin.l4d2pb-box-freeze.cfg.

Show Configuration
// This file was auto-generated by SourceMod (v1.11.0.6968)
// ConVars for plugin "l4d2pb-box-freeze.smx"


// Announces to players affected by freeze.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_freeze_announce "1"

// Enables the freeze box
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_freeze_enabled "1"

// If non-empty, will play this sound file when a player is frozen (treated as a path).
// -
// Default: "physics/glass/glass_impact_bullet1.wav"
l4d2pb_box_freeze_freeze_sound "physics/glass/glass_impact_bullet1.wav"

// The maximum radius to freeze players in. 0 = Disables other players being impacted.
// -
// Default: "500"
// Minimum: "0.000000"
l4d2pb_box_freeze_radius_max "500"

// The minimum radius to freeze players in.
// -
// Default: "200"
// Minimum: "0.000000"
l4d2pb_box_freeze_radius_min "200"

// The RGBA color to set the player when frozen (red green blue alpha).
// -
// Default: "0 0 0 174"
l4d2pb_box_freeze_rgba "0 0 0 174"

// The maximum amount of time in seconds to freezep layers for.
// -
// Default: "15.0"
// Minimum: "0.000000"
l4d2pb_box_freeze_time_max "15.0"

// The minimum amount of time in seconds to freeze players for.
// -
// Default: "3.0"
// Minimum: "0.000000"
l4d2pb_box_freeze_time_min "3.0"

// Whether to pick a random freeze time for each person affected.
// -
// Default: "0.0"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_freeze_time_rand_per_player "0.0"

// The RGBA color to set the player when frozen (red green blue alpha)
// -
// Default: "255 255 255 255"
l4d2pb_box_freeze_unfreeze_rgba "255 255 255 255"

// If non-empty, will play this sound file when a player is unfrozen (treated as a path).
// -
// Default: "physics/glass/glass_largesheet_break1.wav"
l4d2pb_box_freeze_unfreeze_sound "physics/glass/glass_largesheet_break1.wav"

// The freeze box's version.
// -
// Default: "1.0.0"
l4d2pb_box_freeze_version "1.0.0"

Forwards

There is also a global forward included for when a player is unfrozen in the case you want to perform other actions such as setting a custom RGBA value on the player.

/**
 * Called when a player is unfrozen.
 * 
 * @param userId    The user ID that was unfrozen.
 * 
 */
public void L4D2PB_Freeze_OnUnfrozen(int userId);

This is a vomit box registered under the Bad category. It is enabled by default and vomits on the user who opens the box (similar to the Boomer) and potentially players around them depending on the ConVar values set when opened.

Unfortunately, I couldn't figure out how to adjust the vomit times dynamically. Therefore, you will need to set the z_vomit_fade_start and z_vomit_fade_duration game ConVars if you want different vomit durations.

ConVars & Configuration

The configuration file may be found at cfg/sourcemod/plugin.l4d2pb-box-vomit.cfg.

Show Configuration
// This file was auto-generated by SourceMod (v1.11.0.6968)
// ConVars for plugin "l4d2pb-box-vomit.smx"


// Enables the vomit box
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_vomit_enabled "1"

// The maximum radius to vomit players in. 0 = Disables other players being impacted.
// -
// Default: "500"
// Minimum: "0.000000"
l4d2pb_box_vomit_radius_max "500"

// The minimum radius to vomit players in.
// -
// Default: "200"
// Minimum: "0.000000"
l4d2pb_box_vomit_radius_min "200"

// The vomit box's version.
// -
// Default: "1.0.0"
l4d2pb_box_vomit_version "1.0.0"

// If non-empty, will play this sound file when a player is vomited on (treated as a path).
// -
// Default: ""
l4d2pb_box_vomit_vomit_sound ""

This is an items box registered under the Good category. It is enabled by default and spawns random item(s) at the box opener's position.

ConVars & Configuration

The ConVar configuration file may be found at cfg/sourcemod/plugin.l4d2pb-box-items.cfg.

Additionally, you may configure which items can be spawned along with the chance of their spawn + more in the l4d2pb-box-items.cfg configuration file which should be placed in your game server's addons/sourcemod/configs directory. This file is parsed using KeyValues. Additionally, the key is the item name and the following sub-keys and values are supported.

Key Type Default Description
weight float 1.0 The chance of the item being spawned. The higher the value this is, the better chance of it being spawned.
melee int 0 If 1, the item will be treated as a melee weapon.
model string "" If set and non-empty, this model is precached on every map start. Some items may need to be precached for certain maps.
preload int 1 If the model is being precached, this is the value passed as preload to PrecacheModel().

Additionally, here is a list of the plugin's general ConVars.

Show Configuration
// This file was auto-generated by SourceMod (v1.11.0.6968)
// ConVars for plugin "l4d2pb-box-items.smx"


// Announces each item found from the items box.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_items_announce "1"

// Enables the items box
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_items_enabled "1"

// The maximum amount of items to spawn.
// -
// Default: "5"
// Minimum: "1.000000"
l4d2pb_box_items_max "5"

// The maximum amount of force to apply to items when spawned
// -
// Default: "100.0"
// Minimum: "0.000000"
l4d2pb_box_items_max_force "100.0"

// The Minimum amount of items to spawn
// -
// Default: "1"
// Minimum: "0.000000"
l4d2pb_box_items_min "1"

// The mimimum amount of force to apply to items when spawned.
// -
// Default: "0.0"
// Minimum: "0.000000"
l4d2pb_box_items_min_force "0.0"

// Whether to apply random force per item.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_items_random_force_per_item "1"

// The items box's version.
// -
// Default: "1.0.0"
l4d2pb_box_items_version "1.0.0"

This is a test box registered under the Mid category. It is disabled by default and simply prints a message to chat.

ConVars & Configuration

The configuration file may be found at cfg/sourcemod/plugin.l4d2pb-box-test.cfg.

Show Configuration
// This file was auto-generated by SourceMod (v1.11.0.6968)
// ConVars for plugin "l4d2pb-box-test.smx"


// Enables the test box
// -
// Default: "0"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_test_enabled "0"

// The test box's version.
// -
// Default: "1.0.0"
l4d2pb_box_test_version "1.0.0"

More Boxes In Development!

I plan to keep adding boxes over time! If you would like to make your own boxes and release them here, feel free to make a pull request!

Building

Firstly, you'll want to download SourceMod from here.

Afterwards, extract the compressed file(s) and keep note of the path to the addons/sourcemod/scripting directory.

On Linux, you may use the build.sh Bash script included in this repository to build all plugins in scripting/. You'll want to set the SM_DIR environmental variable to the path to the addons/sourcemod/scripting directory mentioned above (by default, it's set to /opt/sourcemod/addons/sourcemod/scripting).

Additionally, you may set the SRC_DIR environment variable which is the path to the plugin's source code ($(pwd)/scripting by default) and BUILD_DIR which is the directory used to store the compiled plugins ($(pwd)/build by default).

On Windows, there isn't a Batch script created at the moment (to do...), but simply dragging the plugin's source code files inside of the addons/sourcemod/scripting/compile.exe should be fine. Just make sure to copy scripting/include/l4d2pb-core.inc into addons/sourcemod/scripting/include.

NOTE - I've included a tasks.json file for Visual Studio Code that builds the current file you're working on with a task! You can bind the task execution to a keyboard shortcut to make building very easy inside of VS Code.

If you want to utilize Multi Colors inside of chat messages and such, you will need to uncomment the #define USE_COLORS line in the scripting/l4d2pb-core.sp file and recompile.

Afterwards, you should be able to utilize colors such as {red}, {green}, etc. inside of translations files located in the translations/ directory.

Installing

After building the plugin's source code, copy the compiled plugin files (ending in .smx) to the game server's addons/sourcemod/plugins/ directory.

Also, copy all translation files from translations/ to the game server's addons/sourcemod/translations/ directory.

Afterwards, you may restart the server/map or load the plugins manually via sm plugins load <plugin name> (e.g. sm plugins load l4d2pb-core) to load the plugins.

Credits