CE3备忘录1--弹头创建

关于备忘录:
这里主要是自己记录一些CE3(Cryengine3)的常用方法,包括代码编写以及API功能,如果有什么问题感谢指出,这是我的邮箱albstein2@gmail.com


这里介绍在CE3中子弹弹头的创建及使用。

首先CE3中的弹头的创建一般基于抛射物,即继承自CProjectile,当然根据需要有时会用到多重继承调用其他的资源,不过这里作为基本的介绍所以不予考虑。

这里的环境为windows7 x64下的VS2012

这里我们以一个可以为目标物体造成固定伤害的弹头为例子介绍:

首先在VS的资源管理器中的/CryGameSDK/Item Files/Weapon Files/Projectiles目录下创建文件HitBullet.h和HitBullet.cpp

###打开HitBullet.h编辑如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef _HITBULLET_H_
#define _HITBULLET_H_
//保证文件只编译一次这里很重要希望大家注意,之后我就不再说明了
#include "StdAfx.h"
#include "Projectile.h"
class CHitBullet : public CProjectile
{
typedef CProjectile BaseClass;//方便使用基类资源,不过这里我们用不到实际操作时可以删掉这行
public:
CHitBullet();
~CHitBullet();
virtual void HandleEvent(const SGameObjectEvent &);
//事件处理函数,继承自CProjectile,由于该类可能被作为基类调用故声明为虚函数
//在这里我们通过重写这一函数来实现效果
private:
float damage;
//手动设置伤害值,这里通过函数调用伤害其实可以从武器的xml中获得
//这里为了方便直接设置
};
#endif

###保存后打开HitBullet.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include "StdAfx.h"
#include "HitBullet.h"
#include "Game.h"
#include "GameRules.h"
#include "Actor.h"
CHitBullet::CHitBullet()
:damage(100) //将伤害初始化
{
}
CHitBullet::~CHitBullet()
{
}
void CHitBullet::HandleEvent(const SGameObjectEvent &event)
{
CProjectile::HandleEvent(event); //先调用父类的HandleEvent完成必要操作
if(event.event == eGFE_OnCollision) //判断实体事件是否为碰撞事件,若不是则不进行操作
{
EventPhysCollision *pCollision = (EventPhysCollision*)(event.ptr); //强制转换类型,在CE里很常见
if(!pCollision) //如果指针为空则不进行操作
return;
IEntity *pTarget=pCollision->iForeignData[1] ==PHYS_FOREIGN_ID_ENTITY ? (IEntity*)pCollision->pForeignData[1] : 0; //获取与弹头发生碰撞的实体.(PHYS_FOREIGN_ID_ENTITY表明是实体)
if(pTarget) //如果实体获取成功进行如下操作
{
CActor *pActor=(CActor*)g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pTarget->GetId()); //获取角色
EntityId targetId=pTarget->GetId();
CryLogAlways(pTarget->GetClass()->GetName()); //CryLogAlwasy是用的非常多的Debug函数,用法跟printf一样.默认类型为string,%d,%f啥的你都懂的
HitInfo hitInfo(m_ownerId ? m_ownerId : m_hostId, targetId, m_weaponId,
damage, 0.0f, 0, pCollision->partid[1],
m_hitTypeId, pCollision->pt, Vec3(0,0,1), pCollision->n); //Hitinfo是个结构体,定义了子弹(或别的什么)造成的伤害的各种参数
hitInfo.knocksDown=false;
hitInfo.knocksDownLeg=false;
hitInfo.remote = IsRemote();
hitInfo.projectileId = GetEntityId();
hitInfo.bulletType = m_pAmmoParams->bulletType;
hitInfo.knocksDown = CheckAnyProjectileFlags(ePFlag_knocksTarget) && ( damage > m_minDamageForKnockDown );
hitInfo.knocksDownLeg = m_chanceToKnockDownLeg>0 && damage>m_minDamageForKnockDownLeg && m_chanceToKnockDownLeg>(int)Random(100);
hitInfo.penetrationCount = 0;
hitInfo.hitViaProxy = CheckAnyProjectileFlags(ePFlag_firedViaProxy);
hitInfo.aimed = CheckAnyProjectileFlags(ePFlag_aimedShot); //上面一长串都是初始化hitinfo里的玩意,这些记住就好,记不住就直接复制粘贴...
g_pGame->GetGameRules()->ClientHit(hitInfo); //处理这个伤害事件
}
Destroy(); //销毁弹头.
}
}

上述内容完成后,我们武器本体代码就完成了,接下来我们将新建的弹头加入到武器系统中

打开/CryGameSDK/Item Files/Weapon Files下的WeaponSystem.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include "StdAfx.h"
#include "Game.h"
#include <IEntitySystem.h>
#include "Rocket.h"
...//省略一部分
#include "HitBullet.h"//包含武器的头文件
...//省略一部分
CWeaponSystem::CWeaponSystem(CGame *pGame, ISystem *pSystem)
...//省略初始化
{
...//省略一部分
// register projectile classes here
REGISTER_PROJECTILE(Projectile, CProjectile);
REGISTER_PROJECTILE(Bullet, CBullet);
REGISTER_PROJECTILE(KVoltBullet, CKVoltBullet);
REGISTER_PROJECTILE(Rocket, CRocket);
REGISTER_PROJECTILE(HomingMissile, CHomingMissile);
REGISTER_PROJECTILE(C4Projectile, CC4Projectile);
REGISTER_PROJECTILE(Chaff, CChaff);
...//省略一部分
REGISTER_PROJECTILE(HitBullet, CHitBullet);//将刚才写好的弹头类在这里注册,其他的地方不用管,这样就将写好的弹头注册进了武器系统
m_pPrecache = gEnv->pConsole->GetCVar("i_precache");
CBullet::EntityClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("Bullet");
m_pGame->GetIGameFramework()->GetILevelSystem()->AddListener(this);
m_linkedProjectiles.reserve(LINKED_PROJ_MAP_RESERVE);
m_freePoolHandlers.insert(TWeaponComponentPoolFreeFunctions::value_type(CMelee::GetWeaponComponentType(), &FreeWeaponComponentPool<CMelee, CMelee>));
m_listenersLock = 0;
}
...//省略其它成员函数

之后在CE3目录下的GameSDK\Scripts\Entities\Items\XML\Ammo中新建文件HitBullet.xml
打开后拷贝该目录下的RifleBullet.xml中的内容

    
        <ammo name="HitBullet" class="HitBullet">
        <!--将第一行改为这样-->
        ...<!--略-->
    

接着新建一种使用该弹头的武器,我们一Rifle为模板改动
在GameSDK\Scripts\Entities\Items\XML\Weapons中新建文件HitBullet.xml
打开后拷贝该目录下的Rifle.xml中的内容

    
    <item name="HitBullet" class="HitBullet" category="secondary" priority="13" weaponParams="1">
      <params>
        <param name="display_name" value="@mp_eHitBullet" />
           ...<!--略-->
      </params>
        ...<!--略-->  
      <ammos>
        <ammo name="HitBullet" extra="1" amount="1" minAmmo="1" capacity="0" GAME="SP" /><!--改动-->
        <ammo name="HitBullet" extra="45" amount="9" capacity="45" GAME="MP" /><!--改动-->
      
      <firemodes>
        <firemode type="default">
          <fire>
            <param name="hit_type" value="RifleBullet" />
            <param name="ammo_type" value="HitBullet" /><!--改动-->
            ...<!--略-->
          </fire>
          ...<!--略-->
    

之后编译运行就可以在边栏看到武器了,添加后即可使用。