8:《地牢守卫者》代码分析:AntInventoryManager,AntWeapon,AntProjectile

  AntInventoryManager是装备管理栏,在这里管理武器创建工作。

  先处理一个函数OwnerDied(),这是处理玩家死亡时,手上的武器是否存在。将他写空将不会让手上的武器消失。

  

  记着在AntPlayerController中的possess处调用了AntPlayer(pawn).CreateInventoryManagerFromTemplate();来将武器栏创建给pawn

  这里将声明其函数该函数的返回类型为Inventory

  

function Inventory CreateInventoryFromTemplate(Actor InventoryActorTemplate,bool bDoNotActive)

{

  local Inventory Inv;

  if(InventoryActorTemplate!=none)

  {

  Inv=Inventory(spawn(InventoryActorTemplate.class,Owner,,,,InventoryActorTemplate,true));

  if(Inv!=none)

  {

    if(!Inv.AddInventory(InventoryActorTemplate,bDoNotActive))

    {

      Inv.Destory();

      Inv=none;

    }      
  }

  else

    `log('Can't spawn Inv');

  }

  return Inv; //没有太多复杂的地方,就是将代码写的更健壮
}
defaultProperties

{

  PendingFire(0)=0

  PendingFire(1)=0
}

接下来创建武器类Weapon,武器类有一个连接函数,将武器和pawn及相应的骨骼插槽进行连接

首先生成一些变量

var name AttachWeaponSocket;

var AntProjectile Projectile;

var vector ProjectileSpawnLocation;

var name MuzzleFlashSocket;


以上变量都能见名知意。

simulated function AttachWeaponTo(SkeletalMeshComponent SkelComp,optional name SocketName)

{

  local AntPawn P;

  p=AntPawn(Instigator); //武器所属的一个引用

    

  Mesh.SetLightEnvironment(p.LightEnvironment);

  Mesh.SetShadowParent(P.Mesh); //Mesh是枪的骨骼,他将以角色的光照和阴影为父系

  if(Socket!='none')

  {

    SetBase(P,,P.Mesh,SocketName);

    P.Mesh.AttachComponentToSocket(Mesh,SocketName); //参数Mesh是枪的,将其连接到插槽上

  }

  SetBase(P);

  SetHidden(false); //如果没有激活,不将其弄消失    

}

同样有链接就有取消连接

simulated function DetachWeapon()

{

  super.DetachWeapon();

  SetHidden(true);

  Mesh.SetShadowParent(none);

  Insitgator.Mesh.DetachComponent(Mesh);
}

前面的连接函数是在Activate中被进行调用的,该函数可以初始化枪的底层系统。

function Acitvate()

{

  super.Activate();

  AttachWeaponTo(instigator.Mesh,AttachWeaponSocket);
}

和Activate对应的是PutDownWeapon

function PutDownWeapon()

{

  super.PutDownWeapon();

  DetachWeapon();
}

以下是最为关键的内容,定义发射。

有两种标准的函数可以控制发出射弹,其中之一是

simulated function projectile projectilefire()

simulated function CustomFire()

这里使用customFire

simulated function CusomFire()

{

  local AntProjectile theProjectile;

  local rotator SpawnRotation;

  loca vector SpawnLocation;

  SpawnLocation+=vector(ProjectileSpawnLocation>>spawnRotation); //将生成的射弹位置以SpawnRotation为参考系

  SpawnRotation=AntPawn(instigator).Rotation; //获取玩家的转向

            //变量的引用类,自己的actor

  theProjectile=Spawn(ProjectileTemplate.class,self,spawnLocation,SpawnRotation,ProjectileTemplate,true);

  theProjectile.Init(vector(SpawnRotation)); //还记着怎么找初始化吗 spawn(enemy.location,location); 
   
}

weapon类中有以下几个重要属性

WeaponFireTypes[0]=EWFT_Custom
FiringStatesArray[0]=WeaponFiring

FireInterval[0]=0.25


 最后一个类是Projectile,该类描述了射弹。

Weapon中调用了Projectile的Init函数,该函数生成了射弹,同时内不能定义DamageRadius,DamageType,Damage,MomentumTransfer,Inistigator能一些变量

var float ProjDamage;

var float ProjDamageRadius;

var float ProjMomentumTransfer;

var class<DamageType> ProjDamageType;

可以利用自定义的变量在这里覆盖

function Init(vector Direction)

{

  Damage=ProjDamage;

  DamageRadius=ProjDamageRadius;

  MomentumTransfer=ProjMomentumTransfer;

  DamageType=ProjDamageType;

    

  super.Init(Direction0);
}

还有两个变量可以重载Speed,MaxSpeed这两个变量在PostBeginPlay中进行重载

var float Projspeed;

var float ProjMaxSpeed;
var float LifeSpan;    //当然是一个重要的参数
simulated event PostBeginPlay()

{

  speed=projSpeed;

  MaxSpeed=ProjMaxSpeed;

  super.PostBeginPlay();

  ///以下内容在将Emitter综合之后再添加
}

一下是处理伤害和可以生成贴花的地方

simulated function ProcessTouch(actor other,vector Hitlocation,vector hitnormal)

{

  if(other!=instigator)

  Explode(Hitlocation,hitnormal);
}



simulated function Explode(vector HitLocation,vector HitNormal)

{

  local vector DownHitLocation,DownHitNormal;

  super.Explode(HitLocation,HitNormal);

  //可以再次创建贴花
}

至此,武器系统告一段落。下一节我将进行ManaToken的研究。 


 

原文地址:https://www.cnblogs.com/NEOCSL/p/2371822.html