Adding New Ammotypes
Introduction
This tutorial will teach you on how to create your own ammunition types for your weapons.
What you need:
- A basic knowledge of C++
- Microsoft Visual C++ 2003/2005
Important Note
If you plan on adding multiple new ammo types, you can reach a limit which will cause your ammo to fail to be picked up. This can be solved by changing the following values in shareddefs.h to be higher than in stock HL2:
Unedited:
#define MAX_AMMO_TYPES 32 // ??? #define MAX_AMMO_SLOTS 32 // not really slots
Edited:
#define MAX_AMMO_TYPES 128 // ??? #define MAX_AMMO_SLOTS 128 // not really slots
Defining the Ammunition
First you will need to define the Ammunition in the Game Rules
To do this, first navigate to hl2mp_gamerules.cpp/hl2_gamerules.cpp in the server project, (Under Source Files/HL2 DLL) and navigate to the function CAmmoDef *GetAmmoDef().
In this function, the necessary ammo types are defined in the table like structure, beginning with def.AddAmmoTypes.
At the bottom of these defines, add a new row and add your own, following the same structure (Copy, paste and edit will work). As an example, the following line will be used:
def.AddAmmoType("SMG2", DMG_BULLET, TRACER_LINE_AND_WHIZ, "sk_plr_dmg_smg2", "sk_npc_dmg_smg2", "sk_max_smg2", BULLET_IMPULSE(200, 1225), 0 );
With this line, a new ammo type 'SMG2' is defined.
Explanation of def.AddAmmoType:
def.AddAmmoType( const char *name //The name of the new ammo type (For use in weapon script). e.g "SMG2" int damageType //The damage type(s) this ammo will have. e.g "DMG_BULLET . For more than one damage type, use a | seperator ( DMG_BULLET | DMG_SNIPER ) int tracerType //The trace type to use. Possible of TRACER_NONE, TRACER_LINE and TRACER_LINE_AND_WIZZ int plr_dmg //An skill (sk_) convar to allow for dynamic modification of the damage this ammo will do if fired from the player. Define all necessary sk_ variables in the ConVar listing around line 100, or type a number here. e.g. sk_plr_dmg_smg2 int npc_dmg //The same as above except the damage dealt when an NPC uses this ammo int carry //The max ammount of ammo allowed. Can be a number or a sk_ convar. e.g. sk_max_smg2 float physicsForceImpulse //The force of the ammunition. Can be a number, calculation or you can use the function BULLET_IMPULSE(grain, ftpersec) to convert real world units to ingame units easily. int nFlags //Specific flags. Possible being AMMO_FORCE_DROP_IF_CARRIED (If the player is hit, he drops whatever physics prop he was holding) and AMMO_INTERPRET_PLRDAMAGE_AS_DAMAGE_TO_PLAYER (Makes the plr_dmg varable damage to player instead of from). Both of these can be used using a | seperator )
They are all you should need.
Adding an ammobox entity
Now a Item (Entity) must be provided, be waived thus one the ammunition (new type of ammunition) can.
In the File Item_Ammo.cpp the classes and the implementations are defined.
Also there the Item (Entity) is defined and implemented.
For our example, this is the code SMG1 copied and renamed
// ======================================================================== // >> BoxMRounds // ======================================================================== class CItem_BoxMRounds : public CItem { public: DECLARE_CLASS( CItem_BoxMRounds, CItem ); void Spawn( void ) { Precache( ); SetModel( "models/items/boxmrounds.mdl"); BaseClass::Spawn( ); } void Precache( void ) { PrecacheModel ("models/items/boxmrounds.mdl"); } bool MyTouch( CBasePlayer *pPlayer ) { if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_SMG1, "SMG1")) { if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) { UTIL_Remove(this); } return true; } return false; } }; LINK_ENTITY_TO_CLASS(item_box_mrounds, CItem_BoxMRounds); LINK_ENTITY_TO_CLASS(item_ammo_smg1, CItem_BoxMRounds); // ======================================================================== // >> LargeBoxMRounds // ======================================================================== class CItem_LargeBoxMRounds : public CItem { public: DECLARE_CLASS( CItem_LargeBoxMRounds, CItem ); void Spawn( void ) { Precache( ); SetModel( "models/items/boxmrounds.mdl"); BaseClass::Spawn( ); } void Precache( void ) { PrecacheModel ("models/items/boxmrounds.mdl"); } bool MyTouch( CBasePlayer *pPlayer ) { if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_SMG1_LARGE, "SMG1")) { if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) { UTIL_Remove(this); } return true; } return false; } }; LINK_ENTITY_TO_CLASS(item_large_box_mrounds, CItem_LargeBoxMRounds); LINK_ENTITY_TO_CLASS(item_ammo_smg1_large, CItem_LargeBoxMRounds);
Our classes are called instead of:
- CItem_SmallBoxSMG1
- CItem_BigBoxSMG1
now:
- CItem_SmallBoxSMG2
- CItem_BigBoxSMG2
When everything is installed you have to change 2 more things. These changes affect both classes in the CSMG2 bool MyTouch( CBasePlayer *pPlayer ) method.
There we must change the query if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_SMG1_LARGE, "SMG1")) Two things to change.
And although we must define SIZE_AMMO_SMG1_ either new, for the SMG2, or can directly define the size of recordable ammunition.
If one wishes to define itself, it only needs to insert the relevant number of balls that should be add to the touch. If you want to define it but then you have to open the items.h. There, you just have to install two new defines.
The second is just the name be changed from SMG1 to SMG2 (your ammo types) must be.
Now still the Spawn and the Prechace methods must be changed.
There must be the name of the Model( With path) Enter. If you want to change the models nich then let these methods.
Thus we have the classes and methods. Now the code for the entity itself follows
For this you have with theLINK TO ENTITYfunctions to link the class name with the name of the entity.
Now the Entity must be merged still into the FGD of the Mod.
For this you have to open the FGD and write in the following:
@PointClass base(Item) studio("models/items/boxmrounds.mdl")= item_ammo_smg2 : "Box of SMG2 ammo" []
For an entity is of type item with the Model models/items/boxmrounds.mdl for the hammer editor provided.
The item is then called item_ammo_smg2 and contains the description Box of SMG2 ammo.
Implementing ammunition into a weapon
Problem:
- Valve has txt files of the weapons coded
We must therefore create yourself a gun.
If you already have coded your own weapon, then you must open the weapon Weapons_Name.txt.
If not open the weapon_smg1.txt
There must be only the line
"primary_ammo" "SMG1"
through
"primary_ammo" "SMG2"
Replace