plasmarepulser.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 324 行
CPP
324 行
#include "StdAfx.h"
#include "creg/STL_List.h"
#include "creg/STL_Set.h"
#include "Game/Team.h"
#include "LogOutput.h"
#include "PlasmaRepulser.h"
#include "Rendering/UnitModels/3DOParser.h"
#include "Sim/Misc/InterceptHandler.h"
#include "Sim/Projectiles/Projectile.h"
#include "Sim/Projectiles/Unsynced/RepulseGfx.h"
#include "Sim/Projectiles/Unsynced/ShieldPartProjectile.h"
#include "Sim/Projectiles/WeaponProjectiles/WeaponProjectile.h"
#include "Sim/Units/COB/CobFile.h"
#include "Sim/Units/COB/CobInstance.h"
#include "Sim/Units/Unit.h"
#include "WeaponDefHandler.h"
#include "Weapon.h"
#include "mmgr.h"
CR_BIND_DERIVED(CPlasmaRepulser, CWeapon, (NULL));
CR_REG_METADATA(CPlasmaRepulser, (
CR_MEMBER(radius),
CR_MEMBER(sqRadius),
CR_MEMBER(curPower),
CR_MEMBER(hitFrames),
CR_MEMBER(isEnabled),
CR_MEMBER(wasDrawn),
CR_MEMBER(incoming),
CR_MEMBER(hasGfx),
CR_MEMBER(visibleShieldParts),
CR_RESERVED(8)
));
static void ShieldScriptCallback(int retCode, void* p1, void* p2)
{
((CPlasmaRepulser*)p1)->isEnabled = !!retCode;
}
CPlasmaRepulser::CPlasmaRepulser(CUnit* owner)
: CWeapon(owner),
radius(0),
sqRadius(0),
curPower(0),
hitFrames(0),
isEnabled(true),
wasDrawn(true),
startShowingShield(true)
{
interceptHandler.AddPlasmaRepulser(this);
}
CPlasmaRepulser::~CPlasmaRepulser(void)
{
interceptHandler.RemovePlasmaRepulser(this);
for(std::list<CShieldPartProjectile*>::iterator si=visibleShieldParts.begin();si!=visibleShieldParts.end();++si){
(*si)->deleteMe=true;
}
}
void CPlasmaRepulser::Init(void)
{
radius=weaponDef->shieldRadius;
sqRadius=radius*radius;
if(weaponDef->shieldPower==0)
curPower=99999999999.0f;
else
curPower=weaponDef->shieldStartingPower;
CWeapon::Init();
}
void CPlasmaRepulser::Update(void)
{
const int defHitFrames = weaponDef->visibleShieldHitFrames;
const bool couldBeVisible = (weaponDef->visibleShield || (defHitFrames > 0));
if (startShowingShield) {
startShowingShield = false;
if (couldBeVisible) {
// 32 parts
for (int y = 0; y < 16; y += 4) {
for (int x = 0; x < 32; x += 4) {
visibleShieldParts.push_back(
SAFE_NEW CShieldPartProjectile(owner->pos, x, y, radius,
weaponDef->shieldBadColor,
weaponDef->shieldAlpha,
weaponDef->visuals.texture1, owner)
);
}
}
}
}
if (isEnabled && (curPower < weaponDef->shieldPower)) {
if (owner->UseEnergy(weaponDef->shieldPowerRegenEnergy * (1.0f / 30.0f))) {
curPower += weaponDef->shieldPowerRegen * (1.0f / 30.0f);
}
}
weaponPos = owner->pos + (owner->frontdir * relWeaponPos.z)
+ (owner->updir * relWeaponPos.y)
+ (owner->rightdir * relWeaponPos.x);
if (couldBeVisible) {
float drawAlpha = 0.0f;
if (hitFrames > 0) {
drawAlpha += float(hitFrames) / float(defHitFrames);
hitFrames--;
}
if (weaponDef->visibleShield) {
drawAlpha += 1.0f;
}
drawAlpha = min(1.0f, drawAlpha * weaponDef->shieldAlpha);
const bool drawMe = (drawAlpha > 0.0f);
if (drawMe || wasDrawn) {
const float colorMix = min(1.0f, curPower / max(1.0f, weaponDef->shieldPower));
const float3 color = (weaponDef->shieldGoodColor * colorMix) +
(weaponDef->shieldBadColor * (1.0f - colorMix));
std::list<CShieldPartProjectile*>::iterator si;
for (si = visibleShieldParts.begin(); si != visibleShieldParts.end(); ++si) {
CShieldPartProjectile* part = *si;
part->centerPos = weaponPos;
part->color = color;
if (isEnabled) {
part->baseAlpha = drawAlpha;
} else {
part->baseAlpha = 0.0f;
}
}
}
wasDrawn = drawMe;
}
if (isEnabled) {
for (std::list<CWeaponProjectile*>::iterator pi=incoming.begin();pi!=incoming.end();++pi) {
const float3 dif = (*pi)->pos-owner->pos;
if ((*pi)->checkCol && dif.SqLength()<sqRadius && curPower > (*pi)->weaponDef->damages[0]) {
if (gs->Team(owner->team)->energy > weaponDef->shieldEnergyUse) {
if (weaponDef->shieldRepulser) {
// bounce the projectile
const int type = (*pi)->ShieldRepulse(this, weaponPos,
weaponDef->shieldForce,
weaponDef->shieldMaxSpeed);
if (type == 0) {
continue;
}
else if (type == 1) {
owner->UseEnergy(weaponDef->shieldEnergyUse);
if (weaponDef->shieldPower != 0) {
curPower -= (*pi)->weaponDef->damages[0];
}
}
else {
owner->UseEnergy(weaponDef->shieldEnergyUse / 30.0f);
if (weaponDef->shieldPower != 0) {
curPower -= (*pi)->weaponDef->damages[0] / 30.0f;
}
}
if (weaponDef->visibleShieldRepulse) {
std::list<CWeaponProjectile*>::iterator i;
for (i=hasGfx.begin();i!=hasGfx.end();i++)
if (*i==*pi) {
break;
}
if (i == hasGfx.end()) {
hasGfx.insert(hasGfx.end(),*pi);
const float colorMix = min(1.0f, curPower / max(1.0f, weaponDef->shieldPower));
const float3 color = (weaponDef->shieldGoodColor * colorMix) +
(weaponDef->shieldBadColor * (1.0f - colorMix));
SAFE_NEW CRepulseGfx(owner, *pi, radius, color);
}
}
if (defHitFrames > 0) {
hitFrames = defHitFrames;
}
}
else {
// kill the projectile
if (owner->UseEnergy(weaponDef->shieldEnergyUse)) {
if (weaponDef->shieldPower != 0) {
curPower -= (*pi)->weaponDef->damages[0];
}
(*pi)->Collision(owner);
if (defHitFrames > 0) {
hitFrames = defHitFrames;
}
}
}
} else {
// Calculate the amount of energy we wanted to pull
/*
Domipheus: TODO Commented out for now, ShieldRepulse has side effects, design needs altering.
if(weaponDef->shieldRepulser) { //bounce the projectile
int type=(*pi)->ShieldRepulse(this,weaponPos,weaponDef->shieldForce,weaponDef->shieldMaxSpeed);
if (type==1){
gs->Team(owner->team)->energyPullAmount += weaponDef->shieldEnergyUse;
} else {
gs->Team(owner->team)->energyPullAmount += weaponDef->shieldEnergyUse/30.0f;
}
} else { //kill the projectile
gs->Team(owner->team)->energyPullAmount += weaponDef->shieldEnergyUse;
}*/
}
}
}
}
}
void CPlasmaRepulser::SlowUpdate(void)
{
std::vector<int> args;
args.push_back(0);
owner->cob->Call(COBFN_QueryPrimary+weaponNum,args);
relWeaponPos=owner->localmodel->GetPiecePos(args[0]);
weaponPos = owner->pos + (owner->frontdir * relWeaponPos.z)
+ (owner->updir * relWeaponPos.y)
+ (owner->rightdir * relWeaponPos.x);
std::vector<int> args2;
args2.push_back(0);
args2.push_back(0);
owner->cob->Call(COBFN_AimPrimary + weaponNum, args2, ShieldScriptCallback, this, 0);
}
void CPlasmaRepulser::NewProjectile(CWeaponProjectile* p)
{
if (weaponDef->smartShield && gs->AlliedTeams(p->owner->team, owner->team)) {
return;
}
float3 dir;
if (p->targetPos!=ZeroVector) {
dir = p->targetPos-p->pos; // assume that it will travel roughly in the direction of the targetpos if it have one
} else {
dir = p->speed; // otherwise assume speed will hold constant
}
dir.y = 0;
dir.Normalize();
float3 dif = owner->pos-p->pos;
if (weaponDef->exteriorShield && (dif.SqLength() < sqRadius)) {
return;
}
float closeLength=dif.dot(dir);
if (closeLength < 0) {
closeLength = 0;
}
float3 closeVect=dif-dir*closeLength;
if (closeVect.Length2D() < (radius * 1.5f + 400)) {
incoming.push_back(p);
AddDeathDependence(p);
}
}
float CPlasmaRepulser::NewBeam(CWeapon* emitter, float3 start, float3 dir, float length, float3& newDir)
{
if (!isEnabled) {
return -1;
}
if (emitter->weaponDef->damages[0] > curPower) {
return -1;
}
if (weaponDef->smartShield && gs->AlliedTeams(emitter->owner->team,owner->team)) {
return -1;
}
const float3 dif = weaponPos - start;
if (weaponDef->exteriorShield && dif.SqLength() < sqRadius) {
return -1;
}
const float closeLength = dif.dot(dir);
if (closeLength < 0) {
return -1;
}
const float3 closeVect = dif-dir*closeLength;
const float tmp = sqRadius - closeVect.SqLength();
if ((tmp > 0) && (length > (closeLength - sqrt(tmp)))) {
float colLength = closeLength - sqrt(tmp);
float3 colPoint = start + dir * colLength;
float3 normal = colPoint - weaponPos;
normal.Normalize();
newDir = dir-normal*normal.dot(dir) * 2;
return colLength;
}
return -1;
}
void CPlasmaRepulser::DependentDied(CObject* o)
{
incoming.remove((CWeaponProjectile*)o);
ListErase<CWeaponProjectile*>(hasGfx, (CWeaponProjectile*)o);
CWeapon::DependentDied(o);
}
bool CPlasmaRepulser::BeamIntercepted(CWeapon* emitter)
{
if (weaponDef->shieldPower > 0) {
curPower -= emitter->weaponDef->damages[0];
}
return weaponDef->shieldRepulser;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?