Adding a Weapon into C4
From C4 Engine Wiki
Contents |
Preface
This is a beginner's guide to adding your own weapon to the C4 Demo game module. In this tutorial we will be adding a basic sniper rifle.
Download
For your convenience I have included the resources used by this tutorial here. Please download and place all files into their respective directories within your C4 folder. SniperRifle.zip
The Code
These are the files we will be working with:
- MGControllers.cpp
- MGFighter.cpp
- MGFighter.h
- MGGame.cpp
- MGGame.h
- MGInput.cpp
- MGInput.h
- MGMultiplayer.cpp
- MGMultiplayer.h
- MGWeapons.h
We will also be adding two new files:
- MGSniperRifle.cpp
- MGSniperRifle.h
And making some minor additions to:
- Input.txt
- Engine.cfg
Adding the source code for our new weapon
All coding additions have been encased with:
// New weapon start // New weapon end
MGSniperRifle.cpp & MGSniperRifle.h
- Add
MGSniperRIfle.cppandMGSniperRifle.h(found within the zip file) to your project.
MGInput.cpp
- Find void WeaponAction::Begin(void)
- Add the following code to that function.
case kActionProtonCannon: weaponType = kWeaponProtonCannon; break; // New weapon start case kActionSniperRifle: weaponType = kWeaponSniperRifle; break; // New weapon end
MGInput.h
- Add the following code to the action types near the top of the file.
kActionProtonCannon = 'cann', // New weapon start kActionSniperRifle = 'snip', // New weapon end kActionNextWeapon = 'next',
MGWeapons.h
- Add the following code to the controller types near the top of the file.
kControllerPlasma = 'plas', // New weapon start kControllerBullet = 'blet' // New weapon end
- Add the following code to the entity types near the top of the file.
kEntityProtonCannon = 'pcan', // New weapon start kEntitySniperRifle = 'snip', kEntityBullet = 'blet', // New weapon end kEntityRocketAmmo = 'rkam',
- At approx line 48 change the enum to:
enum
{
kWeaponNone,
kWeaponBlaster,
kWeaponSpikeShooter,
kWeaponQuantumCharger,
kWeaponGrenadeLauncher,
kWeaponRocketLauncher,
kWeaponPlasmaGun,
kWeaponProtonCannon,
// New weapon start
kWeaponSniperRifle,
// New weapon end
kWeaponCount
};
MGContollers.cpp
- Find void CollectableController::Preprocess(void)
- Add the following code to that function.
// This is a temporary piece of code to add a SpiralHelix effect to the weapons
switch (GetTargetNode()->GetEntityType())
{
case kEntityGrenadeLauncher:
case kEntityRocketLauncher:
case kEntityPlasmaGun:
case kEntityProtonCannon:
// New weapon start
case kEntitySniperRifle:
// New weapon end
- Find void CollectableController::Activate(Node *trigger, Node *activator)
- Add the following code to that function.
case kEntityProtonCannon:
{
player->AcquireWeapon(kWeaponProtonCannon);
break;
}
// New weapon start
case kEntitySniperRifle:
{
player->AcquireWeapon(kWeaponSniperRifle);
break;
}
// New weapon end
MGFighter.cpp
- Find void FighterController::SetWeapon(WeaponType weaponType)
- Add our sniper rifle entity to the end of the constructor.
// New weapon start
static const EntityType entityType[kWeaponCount] =
{
0, kEntityBlaster, 0, 0, kEntityGrenadeLauncher, kEntityRocketLauncher, kEntityPlasmaGun, kEntityProtonCannon,
kEntitySniperRifle
};
// New weapon end
- Find void FighterController::UpdateWeapon(WorldCallback *callback, void *data)
- Add the following case to the end of the switch statement.
// New weapon start
case kWeaponSniperRifle:
{
time = MaxZero(time + 2000);
shotIndex = fighter->GetWorld()->NewControllerIndex();
TheMessageMgr->SendMessageAll(CreateBulletMessage(shotIndex, position, direction * 0.1F, player->GetPlayerKey()));
break;
}
// New weapon end
MGFighter.h
- Add the following include at the top of the file.
// New weapon start #include "MGSniperRifle.h" // New weapon end
MGGame.cpp
- At approx line 268 register the sniper rifle entity,
protonCannonEntityReg(kEntityProtonCannon, "model/ProtonCannon/ProtonCannon", kEntityPrecache, kControllerCollectable), // New weapon start sniperRifleEntityReg(kEntitySniperRifle, "SniperRifle", kEntityPrecache, kControllerCollectable), // New weapon end
- A little further down do the same for the bullet entity,
rocketEntityReg(kEntityRocket, "model/RocketLauncher/Rocket", kEntityPrecache | kEntityPrivate), // New weapon start bulletEntityReg(kEntityBullet, "Bullet", kEntityPrecache | kEntityPrivate), // New weapon end
- At approx line 315 register the sniper rifle action,
protonCannonAction(kActionProtonCannon), // New weapon start sniperRifleAction(kActionSniperRifle), // New weapon end
- At approx line 334 register the sniper rifle entity size,
protonCannonEntityReg.SetEntitySize(0.6F, 0.25F, 0.25F); // New weapon start sniperRifleEntityReg.SetEntitySize(0.7F, 0.25F, 0.25F); // New weapon end
- Finally register our input action,
TheInputMgr->AddAction(&protonCannonAction); // New weapon start TheInputMgr->AddAction(&sniperRifleAction); // New weapon end
MGGame.h
- Find class Game : public Singleton<Game>, public Application
- Register the sniper rifle entity.
EntityRegistration plasmaAmmoEntityReg; // New weapon start EntityRegistration sniperRifleEntityReg; // New weapon end
- A little further down do the same for the bullet entity,
EntityRegistration rocketEntityReg; // New weapon start EntityRegistration bulletEntityReg; // New weapon end
- A little further down do the same for the weapon action,
WeaponAction protonCannonAction; // New weapon start WeaponAction sniperRifleAction; // New weapon end
MGMultiplayer.cpp
- Find CreateEntityMessage *CreateEntityMessage::ConstructMessage(EntityMessageType type)
- Add the following case to the switch statement.
case kEntityMessagePlasma: return (new CreatePlasmaMessage); // New weapon start case kEntityMessageBullet: return (new CreateBulletMessage); // New weapon end
- Find void Game::CreateEntity(const CreateEntityMessage *message)
- Add the following case to the switch statement.
case kEntityMessagePlasma:
{
const CreatePlasmaMessage *m = static_cast<const CreatePlasmaMessage *>(message);
controller = new PlasmaController(m->GetInitialPosition(), m->GetInitialVelocity(), m->GetShooterKey());
entity = Entity::Get(kEntityPlasma);
break;
}
// New weapon start
case kEntityMessageBullet:
{
const CreateBulletMessage *m = static_cast<const CreateBulletMessage *>(message);
controller = new BulletController(m->GetInitialPosition(), m->GetInitialVelocity(), m->GetShooterKey());
entity = Entity::Get(kEntityBullet);
break;
}
// New weapon end
MGMultiplayer.h
- At approx line 64 change the weapon message enum to:
enum
{
kEntityMessageBlast = 0,
kEntityMessageBlast2 = 1,
kEntityMessageGrenade = 2,
kEntityMessageRocket = 3,
kEntityMessagePlasma = 4,
kEntityMessageFireball = 5,
// New weapon start
kEntityMessageBullet = 6,
// New weapon end
kEntityMessageSoldier = 7
};
That takes care of all the source code. Recompile now.
Keyboard Input
Now we have to bind a keyboard input for our weapon so that we may select it in game.
- Open
C4/Data/cfg/Engine.cfg. - Add the following under the key binding for the proton cannon.
bind "6" %snip;
- Open
C4/Import/Demo/game/Input.txt - Add the following under the input for the proton cannon.
'snip' "Sniper Rifle"
- Now run C4 and type "istring" into the console. Select the Input.txt file from the String Import Dialog. You will need to close and restart C4 for the string to be imported.
Test out the new weapon
Please make sure you have compiled all source code without error, included all the files within the zip file at the top of this tutorial, added the key binding and imported the Input.txt string before commencing with this step.
- Open up any map of your choice in the World Editor.
- From the Entity page select SniperRifle.
- Make sure the zone where you want to place the gun is the active target zone. (Use Set Target Zone in the Node menu.)
- Click within the active target zone to place the machine gun. (Check the Z-axis position in the side view.)
Now all you have to do is run your map, collect the sniper rifle, press 6 to select it, and SHOOT!
For you to do
- Create your own weapon model.
- Add in your own sounds, particle effects, decals, and whatever else you can think of to make your gun exciting.
- Register some ammo for the sniper rifle.

