A weapon is an item which contains the four following components:
The core functionality is implemented in C++ , but these components read the data stored inside XML script files located in: <Game_Folder>/Scripts/Entities/Items/Weapons
.
A new weapon class can be added by implementing the CItem and IWeapon interfaces. A basic weapon implementation is supplied in the GameDLL project which provide the most commonly required weapon functionality:
class CMyWeapon : public CItem, public IWeapon
{
// IItem, IGameObjectExtension
virtual bool Init(IGameObject * pGameObject);
virtual void InitClient(int channelId) { CItem::InitClient(channelId); };
virtual void Release();
//...other IItem, IGameObjectExtension methods
// IWeapon
virtual void StartFire();
virtual void StartFire(const SProjectileLaunchParams& launchParams);
virtual void StopFire();
virtual bool CanFire() const;
virtual bool CanStopFire() const { return true; }
//... other IWeapon methods
}
When implementing a new weapon class, it's recommended to derive from the CWeapon class. The following functions from CWeapon are the most common ones overridden to provide new gameplay functionalities:
Functions | Description |
---|---|
CWeapon::OnAction() | CWeapon already implements the common weapon action possibles like attack, reload, zoom and changing the fire mode. A new weapon requiring new actions from the player should override this function. |
CWeapon::Select() | This function is called when the actor select/deselect the weapon as his current item. Any code which modifies the camera/rendering settings should be placed in this function. |
CItem::CanPickUp() | The CItem implementation will make sure that the action does not already carry this weapon. When overriding this function, it is possible to add conditions which rule if the actor is allowed to pickup the weapon. |
CItem::PickUp() | Should handle adding the weapon to the actor inventory. Please note that after CItem::PickUp has been called, it's no longer possible to refuse the actor from picking up the weapon. The appropriate code to validate the actor from taking the weapon should be placed in the CanPickUp() function. |
The final step for your custom weapon, to be useable in the weapon xml file, is to register it in the Game Factory (Code\Game\GameDll\GameFactory.cpp
), the central point to register new Game Objects:
#include "MyWeapon.h"
//...
void InitGameFactory(IGameFramework *pFramework)
{
//...
REGISTER_FACTORY(pFramework, "MyWeapon", CMyWeapon, false);
//...
}
The GameSDK example code already includes many unique fire modes:
In case these fire modes aren't sufficient, it's possible to implement a new fire mode by deriving from the IFireMode interface:
class CMyFiremode : public IFireMode
{
virtual void Init(IWeapon *pWeapon, const struct IItemParamsNode *params, uint32 id);
virtual void PostInit();
virtual void Update(float frameTime, uint32 frameId);
virtual void PostUpdate(float frameTime);
virtual void Reload(int zoomed);
//...other IFireMode methods
}
In most of the cases, deriving from the existing CSingle class should simplify this process. If this approach is followed, the following functions are usually the only ones needed to override:
Function | Description of the functionalities already provided by CSingle |
---|---|
IFireMode::Activate() | Triggers the appropriates effects and sounds, resets state variables. |
IFireMode::CanFire() | Performs various tests to be sure ammunition are still available and that the weapon isn't overheating. |
IFireMode::CanReload() | Search the in inventory to be sure the actor carries the clips for ammunition required. |
IFireMode::StartFire() | Triggers the appropriates effects and sounds, performs hit computations. |
IFireMode::Update() | Performs various frame dependent computations for different weapon features including auto-aim, zoom, recoil and heat accumulation. |
The final step for your custom fire mode, to be useable in the weapon xml file, is to register it in the Weapon System implementation (Code\Game\GameDll\WeaponSystem.cpp
):
CWeaponSystem::CWeaponSystem(CGame *pGame, ISystem *pSystem)
: m_pGame(pGame),
m_pSystem(pSystem),
m_pItemSystem(pGame->GetIGameFramework()->GetIItemSystem()),
m_pPrecache(0),
m_reloading(false),
m_recursing(false),
m_frozenEnvironment(false),
m_wetEnvironment(false),
m_tokensUpdated(false)
{
//...
RegisterFireMode("MyFireMode", &CreateIt<CMyFireMode, IFireMode>);
//...
}
The CProjectile class implemented in the GameDLL project provides most of the functionality needed. It is possible to extend this class by deriving from it, for example to implement new functionality for homing missiles or to have a new class of explosives.
When deriving from CProjectile, the following functions should be able to give enough flexibility to expand its gameplay features.
Functions | Descriptions |
---|---|
IGameObjectExtension::HandleEvent() | Function used to handle game events, the ideal location to deal with collisions. |
CProjectile::Launch() | Provides a way to adjust or setup any functionality before the projectile is shot by the weapon. |
CProjectile::Update() | After the projectile was launched, this function is called at every frame until the projectile reaches its destination. |
CProjectile::SetDestination() | If the weapon has any auto-aiming capabilities, this function will be called with the world position of the target. |
CProjectile::SetDestination(targetId) | If the weapon has any auto-aiming capabilities, this function will be called with entity id of the locked target. |
The final step for your custom projectile is to register it in the Weapon System implementation (Code\Game\GameDll\WeaponSystem.cpp
):
CWeaponSystem::CWeaponSystem(CGame *pGame, ISystem *pSystem)
: m_pGame(pGame),
m_pSystem(pSystem),
m_pItemSystem(pGame->GetIGameFramework()->GetIItemSystem()),
m_pPrecache(0),
m_reloading(false),
m_recursing(false),
m_frozenEnvironment(false),
m_wetEnvironment(false),
m_tokensUpdated(false)
{
//...
REGISTER_PROJECTILE(MyProjectile, CMyProjectile);
//...
}
The SDK example already includes the following zoom modes: IronSight and Scope. In case you need a customized zoom mode for your weapon it's possible to implement a new zoom mode by deriving from the IZoomMode interface:
class CMyZoomMode : public IZoomMode
{
virtual bool CanZoom() const;
virtual bool StartZoom(bool stayZoomed = false, bool fullZoomout = true, int zoomStep = 1);
virtual void StopZoom();
virtual void ExitZoom(bool force=false);
//...other IZoomMode methods
}
In most of the cases, deriving from the existing CIronSight class should simplify this process. If this approach is followed, the following functions are usually the only ones needed to override:
Function | Description of the functionalities already provided by CIronSight |
---|---|
CIronSight::OnEnterZoom() | Triggers when entering zoom mode. |
CIronSight::OnLeaveZoom() | Triggers when leaving zoom mode. |
CIronSight::OnZoomStep() | Triggers when switching the actual zoom step. |
IZoomMode::UpdateFPView() | Updating/Changing any first person view parameters should go here. |
The final step for your custom zoom mode is to register it in the Weapon System implementation (Code\Game\GameDll\WeaponSystem.cpp
):
CWeaponSystem::CWeaponSystem(CGame *pGame, ISystem *pSystem)
: m_pGame(pGame),
m_pSystem(pSystem),
m_pItemSystem(pGame->GetIGameFramework()->GetIItemSystem()),
m_pPrecache(0),
m_reloading(false),
m_recursing(false),
m_frozenEnvironment(false),
m_wetEnvironment(false),
m_tokensUpdated(false)
{
//...
RegisterZoomMode("MyZoomMode", &CreateIt<CMyZoomMode, IZoomMode>);
//...
}
Creating the final weapon is completely done in an easy to edit XML file, which should be stored in <Game_Folder>/Scripts/Entities/Items/Weapons/
.
A good starting point for creating your own weapon XML implementation is to use the shipped Rifle.xml script. It already includes everything you need to have a usable and realistic weapon. More details about the general structure of a weapon XML implementation can be found via comments inside the Rifle.xml weapon example.