Jump to content

[L4D2] Party Boxes


Christian
 Share

Recommended Posts

  • Superuser

I just wanted to share an open source project I started working on recently for Left 4 Dead 2 and SourceMod!

 

Please view this GitHub repository for up-to-date details and source code!

 

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

dmg-box.gif

 

test-box (1).gif

 

My Motives
I've been occasionally 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.

 

// This file was auto-generated by SourceMod (v1.11.0.6969)
// 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.35"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_chance_bad "0.35"

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

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

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

// 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_).

 

 

  • l4d2pb_stats - Displays stats in chat.
  • l4d2pb_open [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.
 * @param weight    The boxes weight when being picked (the higher this value is, the more of a chance of the box being picked).
 *
 * @return 0 on success or 1 on error.
 */
native int L4D2PB_RegisterBox(BoxType type, const char[] name, const char[] display, float weight = 50.0);

/**
 * 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.

 

Damage
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.

 

// This file was auto-generated by SourceMod (v1.11.0.6969)
// 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"

// The box's weight when being picked.
// -
// Default: "50.0"
l4d2pb_box_dmg_weight "50.0"

 

Freeze
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.

 

// This file was auto-generated by SourceMod (v1.11.0.6969)
// 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"

// The box's weight when being picked.
// -
// Default: "50.0"
l4d2pb_box_freeze_weight "50.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);

 

Vomit
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.

 

// This file was auto-generated by SourceMod (v1.11.0.6969)
// 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 ""

// The vomit box's weight on getting picked.
// -
// Default: "50.0"
l4d2pb_box_vomit_weight "50.0"

 

Items
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.

 

 

  • weight (float, default 1.0) - The chance of the item being spawned. The higher the value this is, the better chance of it being spawned.
  • melee (int, default 0) - If 1, the item will be treated as a melee weapon.
  • model (string, default "") -  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, default 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.

 

// This file was auto-generated by SourceMod (v1.11.0.6969)
// 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"

// The box's weight when being picked.
// -
// Default: "50.0"
l4d2pb_box_items_weight "50.0"

 

Heal
This is a heal box registered under the Good category. When opened, the box opener and potentially users around them will be healed in round(s).

 

ConVars & Configuration
The configuration file may be found at cfg/sourcemod/plugin.l4d2pb-box-heal.cfg.

 

// This file was auto-generated by SourceMod (v1.11.0.6969)
// ConVars for plugin "l4d2pb-box-heal.smx"


// Whether to announce to players how much HP they've been healed with.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_heal_announce "1"

// Enables the heal box
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_heal_enabled "1"

// The maximum amount of heal amount to add.
// -
// Default: "100"
// Minimum: "1.000000"
l4d2pb_box_heal_heal_amount_max "100"

// The minimum amount of heal amount to add.
// -
// Default: "5"
// Minimum: "1.000000"
l4d2pb_box_heal_heal_amount_min "5"

// Whether to apply a random amount of health to each player.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_heal_heal_amount_rand_per_player "1"

// The maximum interval between heals.
// -
// Default: "3.0"
// Minimum: "0.000000"
l4d2pb_box_heal_heal_interval_max "3.0"

// The minimum interval between heals.
// -
// Default: "1.0"
// Minimum: "0.000000"
l4d2pb_box_heal_heal_interval_min "1.0"

// If 1, will revive incapped players and set HP.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_heal_heal_revive "1"

// The sound to play when a player is healed.
// -
// Default: "items/suitchargeok1.wav"
l4d2pb_box_heal_heal_sound "items/suitchargeok1.wav"

// The maximum amount of heals to perform.
// -
// Default: "3"
// Minimum: "1.000000"
l4d2pb_box_heal_heals_max "3"

// The minimum amount of heals to perform.
// -
// Default: "1"
// Minimum: "1.000000"
l4d2pb_box_heal_heals_min "1"

// The maximum HP the user can have.
// -
// Default: "100"
// Minimum: "1.000000"
l4d2pb_box_heal_max_hp "100"

// The maximum radius to heal players in.
// -
// Default: "200.0"
l4d2pb_box_heal_radius_max "200.0"

// The minimum radius to heals players in.
// -
// Default: "100.0"
l4d2pb_box_heal_radius_min "100.0"

// The heal box's version.
// -
// Default: "1.0.0"
l4d2pb_box_heal_version "1.0.0"

// The box's weight when being picked.
// -
// Default: "50.0"
l4d2pb_box_heal_weight "50.0"

 

Acid
This is an acid box registered under the Bad category. When opened, a Spitter acid projectile is spawned at the opener's location.

 

ConVars & Configuration
The configuration file may be found at cfg/sourcemod/plugin.l4d2pb-box-acid.cfg.

 

// This file was auto-generated by SourceMod (v1.11.0.6969)
// ConVars for plugin "l4d2pb-box-acid.smx"


// If non-empty, sets the angle for the spitter projectile (empty = uses client's angles). Separate each float by a space.
// -
// Default: ""
l4d2pb_box_acid_ang ""

// Enables the acid box
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2pb_box_acid_enabled "1"

// If non-empty, sets the rotation of the spitter projectile (empty = uses angles result). Separate each float by a space.
// -
// Default: ""
l4d2pb_box_acid_rot ""

// If non-empty, sets the velocity of the spitter projectile (empty = uses angles result). Separate each float by a space.
// -
// Default: ""
l4d2pb_box_acid_vel ""

// The acid box's version.
// -
// Default: "1.0.0"
l4d2pb_box_acid_version "1.0.0"

// The box's weight when being picked.
// -
// Default: "50.0"
l4d2pb_box_acid_weight "50.0"

 

Test
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.

 

// 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.

 

Using Multi Colors
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

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

By using this site you agree to the Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.