Randomizer Gamemode: Difference between revisions
m (add a suggestion) |
GamerDude27 (talk | contribs) m (Syntax highlighting, QoL changes, links and corrections) |
||
Line 6: | Line 6: | ||
== Concept == | == Concept == | ||
What we'll be doing is a very basic implementation of a Randomizer gamemode, inspired by custom server-hosted gamemodes like Team Fortress 2 Randomizer. | What we'll be doing is a very basic implementation of a Randomizer gamemode, inspired by custom server-hosted gamemodes like [https://wiki.teamfortress.com/wiki/Randomizer Team Fortress 2 Randomizer]. | ||
What will happen is we will replace <code>GiveAllItems</code> with a more complicated function, <code>GiveItems</code>. This will allow us to update the weapon list for both the | What will happen is we will replace <code>GiveAllItems</code> with a more complicated function, <code>GiveItems</code>. This will allow us to update the weapon list for both the [[Impulse|impulse 101]] command and the randomizer gamemode. If the server host decides to enable the gamemode, we will replace the default items and weapons with a certain number of items from the list. This system will also provide ammo for those specific weapons. | ||
== Implementation == | == Implementation == | ||
Line 14: | Line 14: | ||
Scroll down to: | Scroll down to: | ||
< | <source lang=cpp> | ||
void GiveAllItems(void); | void GiveAllItems( void ); | ||
</ | </source> | ||
and replace that line of text with: | and replace that line of text with: | ||
< | <source lang=cpp> | ||
void GiveItems(bool bGiveAll = false); | void GiveItems( bool bGiveAll = false ); | ||
</ | </source> | ||
This will cause errors in hl2mp_player.cpp. Don't worry, we will fix these in a bit. | This will cause errors in '''hl2mp_player.cpp'''. Don't worry, we will fix these in a bit. | ||
=== hl2mp_player.cpp (or any mod-equivalent player.cpp file) === | === hl2mp_player.cpp (or any mod-equivalent player.cpp file) === | ||
Above < | Above <source lang=cpp>#define HL2MP_COMMAND_MAX_RATE 0.3</source> at the beginning of the file, add the following lines: | ||
< | <source lang=cpp> | ||
ConVar sv_randomizer("sv_randomizer", "0", FCVAR_NOTIFY, ""); | ConVar sv_randomizer( "sv_randomizer", "0", FCVAR_NOTIFY, "" ); | ||
ConVar sv_randomizer_weaponcount("sv_randomizer_weaponcount", "5", FCVAR_NOTIFY, ""); | ConVar sv_randomizer_weaponcount( "sv_randomizer_weaponcount", "5", FCVAR_NOTIFY, "" ); | ||
</ | </source> | ||
These | These [[ConVar|ConVars]] will allow us to turn on the gamemode and set the number of weapons we want given to our player. | ||
Next, scroll down to <code>void CHL2MP_Player::GiveAllItems(void)</code> and replace the entire function with: | Next, scroll down to <code>void CHL2MP_Player::GiveAllItems( void )</code> and replace the entire function with: | ||
< | <source lang=cpp> | ||
void CHL2MP_Player::GiveItems(bool bGiveAll) | void CHL2MP_Player::GiveItems( bool bGiveAll ) | ||
{ | { | ||
EquipSuit(); | EquipSuit(); | ||
static const char* | static const char *g_pszAllWeaponNames[] = | ||
{ | { | ||
"weapon_stunstick", | "weapon_stunstick", | ||
Line 57: | Line 57: | ||
}; | }; | ||
static const char* | static const char *g_pszAllAmmoNames[] = | ||
{ | { | ||
"AR2", | "AR2", | ||
Line 72: | Line 72: | ||
}; | }; | ||
if (bGiveAll) | if ( bGiveAll ) | ||
{ | { | ||
// | // Give us everything. | ||
int WeaponList = ARRAYSIZE( | int WeaponList = ARRAYSIZE( g_pszAllWeaponNames ); | ||
for (int i = 0; i < WeaponList; ++i) | for ( int i = 0; i < WeaponList; ++i ) | ||
{ | { | ||
GiveNamedItem( | GiveNamedItem( g_pszAllWeaponNames[i] ); | ||
} | } | ||
int AmmoList = ARRAYSIZE( | int AmmoList = ARRAYSIZE( g_pszAllAmmoNames ); | ||
for (int i = 0; i < AmmoList; ++i) | for ( int i = 0; i < AmmoList; ++i ) | ||
{ | { | ||
CBasePlayer::GiveAmmo(999, | CBasePlayer::GiveAmmo( 999, g_pszAllAmmoNames[i] ); | ||
} | } | ||
} | } | ||
else | else | ||
{ | { | ||
// | // Give us some weapons. | ||
int nWeapons = ARRAYSIZE( | int nWeapons = ARRAYSIZE( g_pszAllWeaponNames ); | ||
int weaponCount = Clamp(sv_randomizer_weaponcount.GetInt(), 1, nWeapons); | int weaponCount = Clamp( sv_randomizer_weaponcount.GetInt(), 1, nWeapons ); | ||
for (int i = 0; i < weaponCount; ++i) | for ( int i = 0; i < weaponCount; ++i ) | ||
{ | { | ||
int randomChoice = rand() % nWeapons; | int randomChoice = rand() % nWeapons; | ||
GiveNamedItem( | GiveNamedItem( g_pszAllWeaponNames[randomChoice] ); | ||
} | } | ||
// | // Give us ammo for our new weapons. | ||
int WeaponList = ARRAYSIZE( | int WeaponList = ARRAYSIZE( g_pszAllWeaponNames ); | ||
for (int i = 0; i < WeaponList; ++i) | for ( int i = 0; i < WeaponList; ++i ) | ||
{ | { | ||
CBaseCombatWeapon* pCheckWeapon = Weapon_OwnsThisType( | CBaseCombatWeapon *pCheckWeapon = Weapon_OwnsThisType( g_pszAllWeaponNames[i] ); | ||
if (pCheckWeapon) | if ( pCheckWeapon ) | ||
{ | { | ||
CBasePlayer::GiveAmmo(RandomInt(10, 999), pCheckWeapon->GetPrimaryAmmoType()); | CBasePlayer::GiveAmmo( RandomInt( 10, 999 ), pCheckWeapon->GetPrimaryAmmoType() ); | ||
CBasePlayer::GiveAmmo(RandomInt(10, 999), pCheckWeapon->GetSecondaryAmmoType()); | CBasePlayer::GiveAmmo( RandomInt( 10, 999 ), pCheckWeapon->GetSecondaryAmmoType() ); | ||
} | } | ||
} | } | ||
} | } | ||
} | } | ||
</ | </source> | ||
Let's go over this. | Let's go over this. | ||
Line 118: | Line 118: | ||
At the beginning, we call <code>EquipSuit();</code>, which gives us the HEV suit and enables the HUD. Simple enough. | At the beginning, we call <code>EquipSuit();</code>, which gives us the HEV suit and enables the HUD. Simple enough. | ||
Next, we make 2 lists: <code> | Next, we make 2 lists: <code>g_pszAllWeaponNames</code> and <code>g_pszAllAmmoNames</code>. These lists store every weapon and ammo type ever in the game. <code>g_pszAllAmmoNames</code> is not used in the randomizer gamemode, but rather to give us all ammo types when we execute the <code>impulse 101</code> command. When you add a new weapon or ammo type, make sure to add it to these lists! | ||
Now we get to the meat of the entire system. if the argument <code>bGiveAll</code> is true, it will give us every weapon and ammo type on the lists. If not, it will randomize every weapon listed in <code> | Now we get to the meat of the entire system. if the argument <code>bGiveAll</code> is true, it will give us every weapon and ammo type on the lists. If not, it will randomize every weapon listed in <code>g_pszAllWeaponNames</code>, and give a certain number of weapons to us. Afterwards, we give us a randomized amount of ammo for each weapon. | ||
Now, let's change a few things in order to get this system to work. Scroll down to <code>void CHL2MP_Player::Spawn(void)</code> and go to the code block at the beginning that looks like this: | Now, let's change a few things in order to get this system to work. Scroll down to <code>void CHL2MP_Player::Spawn(void)</code> and go to the code block at the beginning that looks like this: | ||
< | <source lang=cpp> | ||
if ( !IsObserver() ) | if ( !IsObserver() ) | ||
{ | { | ||
Line 133: | Line 133: | ||
GiveDefaultItems(); | GiveDefaultItems(); | ||
} | } | ||
</ | </source> | ||
and change it to: | and change it to: | ||
< | <source lang=cpp highlight=8-15> | ||
if ( !IsObserver() ) | if ( !IsObserver() ) | ||
{ | { | ||
Line 144: | Line 144: | ||
RemoveEffects( EF_NODRAW ); | RemoveEffects( EF_NODRAW ); | ||
if (sv_randomizer.GetBool()) | if ( sv_randomizer.GetBool() ) | ||
{ | { | ||
GiveItems(); | GiveItems(); | ||
Line 153: | Line 153: | ||
} | } | ||
} | } | ||
</ | </source> | ||
Whenever we spawn, it will check to see if <code>sv_randomizer</code> is enabled or not. If so, we will give the player random items. If not, we will give the player the normal HL2:DM loadout. | Whenever we spawn, it will check to see if <code>sv_randomizer</code> is enabled or not. If so, we will give the player random items. If not, we will give the player the normal HL2:DM loadout. | ||
Finally, let's fix the <code>impulse 101</code> command. Scroll down to <code>void CHL2MP_Player::CheatImpulseCommands( int iImpulse )</code> and you will see a code block that looks like this: | Finally, let's fix the <code>impulse 101</code> command. Scroll down to <code>void CHL2MP_Player::CheatImpulseCommands( int iImpulse )</code> and you will see a code block that looks like this: | ||
< | <source lang=cpp> | ||
switch ( iImpulse ) | switch ( iImpulse ) | ||
{ | { | ||
Line 173: | Line 173: | ||
BaseClass::CheatImpulseCommands( iImpulse ); | BaseClass::CheatImpulseCommands( iImpulse ); | ||
} | } | ||
</ | </source> | ||
Replace it with: | Replace it with: | ||
< | <source lang=cpp highlight=7> | ||
switch ( iImpulse ) | switch ( iImpulse ) | ||
{ | { | ||
Line 183: | Line 183: | ||
if( sv_cheats->GetBool() ) | if( sv_cheats->GetBool() ) | ||
{ | { | ||
GiveItems(true); | GiveItems( true ); | ||
} | } | ||
} | } | ||
Line 191: | Line 191: | ||
BaseClass::CheatImpulseCommands( iImpulse ); | BaseClass::CheatImpulseCommands( iImpulse ); | ||
} | } | ||
</ | </source> | ||
This will allow <code>impulse 101</code> to give us every weapon again, just like old times. | This will allow <code>impulse 101</code> to give us every weapon again, just like old times. |
Latest revision as of 05:11, 6 March 2021
This tutorial will showcase how to create a Randomizer gamemode.
The code listed in this tutorial has been tested in Source SDK 2013 Base Multiplayer, but it should work in other versions of the Source SDK without much hassle.
This is more of a copy/paste tutorial, so not a lot of programming knowledge is required. However, reading the tutorial fully will provide a lot of context to what we are doing here.
Concept
What we'll be doing is a very basic implementation of a Randomizer gamemode, inspired by custom server-hosted gamemodes like Team Fortress 2 Randomizer.
What will happen is we will replace GiveAllItems
with a more complicated function, GiveItems
. This will allow us to update the weapon list for both the impulse 101 command and the randomizer gamemode. If the server host decides to enable the gamemode, we will replace the default items and weapons with a certain number of items from the list. This system will also provide ammo for those specific weapons.
Implementation
hl2mp_player.h (or any mod-equivalent player.h file)
Scroll down to:
void GiveAllItems( void );
and replace that line of text with:
void GiveItems( bool bGiveAll = false );
This will cause errors in hl2mp_player.cpp. Don't worry, we will fix these in a bit.
hl2mp_player.cpp (or any mod-equivalent player.cpp file)
Above
#define HL2MP_COMMAND_MAX_RATE 0.3
at the beginning of the file, add the following lines:
ConVar sv_randomizer( "sv_randomizer", "0", FCVAR_NOTIFY, "" );
ConVar sv_randomizer_weaponcount( "sv_randomizer_weaponcount", "5", FCVAR_NOTIFY, "" );
These ConVars will allow us to turn on the gamemode and set the number of weapons we want given to our player.
Next, scroll down to void CHL2MP_Player::GiveAllItems( void )
and replace the entire function with:
void CHL2MP_Player::GiveItems( bool bGiveAll )
{
EquipSuit();
static const char *g_pszAllWeaponNames[] =
{
"weapon_stunstick",
"weapon_crowbar",
"weapon_pistol",
"weapon_357",
"weapon_smg1",
"weapon_ar2",
"weapon_shotgun",
"weapon_frag",
"weapon_crossbow",
"weapon_rpg",
"weapon_slam",
"weapon_physcannon"
};
static const char *g_pszAllAmmoNames[] =
{
"AR2",
"AR2AltFire",
"Pistol",
"SMG1",
"smg1_grenade",
"Buckshot",
"357",
"rpg_round",
"XBowBolt",
"grenade",
"slam"
};
if ( bGiveAll )
{
// Give us everything.
int WeaponList = ARRAYSIZE( g_pszAllWeaponNames );
for ( int i = 0; i < WeaponList; ++i )
{
GiveNamedItem( g_pszAllWeaponNames[i] );
}
int AmmoList = ARRAYSIZE( g_pszAllAmmoNames );
for ( int i = 0; i < AmmoList; ++i )
{
CBasePlayer::GiveAmmo( 999, g_pszAllAmmoNames[i] );
}
}
else
{
// Give us some weapons.
int nWeapons = ARRAYSIZE( g_pszAllWeaponNames );
int weaponCount = Clamp( sv_randomizer_weaponcount.GetInt(), 1, nWeapons );
for ( int i = 0; i < weaponCount; ++i )
{
int randomChoice = rand() % nWeapons;
GiveNamedItem( g_pszAllWeaponNames[randomChoice] );
}
// Give us ammo for our new weapons.
int WeaponList = ARRAYSIZE( g_pszAllWeaponNames );
for ( int i = 0; i < WeaponList; ++i )
{
CBaseCombatWeapon *pCheckWeapon = Weapon_OwnsThisType( g_pszAllWeaponNames[i] );
if ( pCheckWeapon )
{
CBasePlayer::GiveAmmo( RandomInt( 10, 999 ), pCheckWeapon->GetPrimaryAmmoType() );
CBasePlayer::GiveAmmo( RandomInt( 10, 999 ), pCheckWeapon->GetSecondaryAmmoType() );
}
}
}
}
Let's go over this.
At the beginning, we call EquipSuit();
, which gives us the HEV suit and enables the HUD. Simple enough.
Next, we make 2 lists: g_pszAllWeaponNames
and g_pszAllAmmoNames
. These lists store every weapon and ammo type ever in the game. g_pszAllAmmoNames
is not used in the randomizer gamemode, but rather to give us all ammo types when we execute the impulse 101
command. When you add a new weapon or ammo type, make sure to add it to these lists!
Now we get to the meat of the entire system. if the argument bGiveAll
is true, it will give us every weapon and ammo type on the lists. If not, it will randomize every weapon listed in g_pszAllWeaponNames
, and give a certain number of weapons to us. Afterwards, we give us a randomized amount of ammo for each weapon.
Now, let's change a few things in order to get this system to work. Scroll down to void CHL2MP_Player::Spawn(void)
and go to the code block at the beginning that looks like this:
if ( !IsObserver() )
{
pl.deadflag = false;
RemoveSolidFlags( FSOLID_NOT_SOLID );
RemoveEffects( EF_NODRAW );
GiveDefaultItems();
}
and change it to:
if ( !IsObserver() )
{
pl.deadflag = false;
RemoveSolidFlags( FSOLID_NOT_SOLID );
RemoveEffects( EF_NODRAW );
if ( sv_randomizer.GetBool() )
{
GiveItems();
}
else
{
GiveDefaultItems();
}
}
Whenever we spawn, it will check to see if sv_randomizer
is enabled or not. If so, we will give the player random items. If not, we will give the player the normal HL2:DM loadout.
Finally, let's fix the impulse 101
command. Scroll down to void CHL2MP_Player::CheatImpulseCommands( int iImpulse )
and you will see a code block that looks like this:
switch ( iImpulse )
{
case 101:
{
if( sv_cheats->GetBool() )
{
GiveAllItems();
}
}
break;
default:
BaseClass::CheatImpulseCommands( iImpulse );
}
Replace it with:
switch ( iImpulse )
{
case 101:
{
if( sv_cheats->GetBool() )
{
GiveItems( true );
}
}
break;
default:
BaseClass::CheatImpulseCommands( iImpulse );
}
This will allow impulse 101
to give us every weapon again, just like old times.
Conclusion
After compiling your code, check to see if it works in-game by starting a server and putting in the command sv_randomizer 1
. After you have done that, respawn your player. You should have a completely randomized loadout!
Feel free to mess around with the code to get different results. Maybe you could use a script file for the weapon/ammo names!