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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "LightningCannon.h"
#include "PlasmaRepulser.h"
#include "WeaponDef.h"
#include "WeaponDefHandler.h"
#include "Game/GameHelper.h"
#include "Game/TraceRay.h"
#include "Rendering/Models/3DModel.h"
#include "Sim/Misc/CollisionHandler.h"
#include "Sim/Misc/GlobalSynced.h"
#include "Sim/Misc/InterceptHandler.h"
#include "Sim/Projectiles/WeaponProjectiles/WeaponProjectileFactory.h"
#include "Sim/Units/Unit.h"
CR_BIND_DERIVED(CLightningCannon, CWeapon, (NULL, NULL))
CR_REG_METADATA(CLightningCannon,(
CR_MEMBER(color),
CR_RESERVED(8)
))
CLightningCannon::CLightningCannon(CUnit* owner, const WeaponDef* def)
: CWeapon(owner, def)
, color(def->visuals.color)
{
}
void CLightningCannon::Update()
{
if (targetType != Target_None) {
weaponPos = owner->GetObjectSpacePos(relWeaponPos);
weaponMuzzlePos = owner->GetObjectSpacePos(relWeaponMuzzlePos);
if (!onlyForward) {
wantedDir = (targetPos - weaponPos).Normalize();
}
}
CWeapon::Update();
}
void CLightningCannon::FireImpl(bool scriptCall)
{
float3 curPos = weaponMuzzlePos;
float3 curDir = (targetPos - curPos).Normalize();
float3 newDir = curDir;
curDir +=
(gs->randVector() * SprayAngleExperience() + SalvoErrorExperience());
curDir.Normalize();
CUnit* hitUnit = NULL;
CFeature* hitFeature = NULL;
CPlasmaRepulser* hitShield = NULL;
CollisionQuery hitColQuery;
float boltLength = TraceRay::TraceRay(curPos, curDir, range, collisionFlags, owner, hitUnit, hitFeature, &hitColQuery);
if (!weaponDef->waterweapon) {
// terminate bolt at water surface if necessary
if ((curDir.y < 0.0f) && ((curPos.y + curDir.y * boltLength) <= 0.0f)) {
boltLength = curPos.y / -curDir.y;
}
}
const float shieldLength = interceptHandler.AddShieldInterceptableBeam(this, curPos, curDir, range, newDir, hitShield);
if (shieldLength < boltLength) {
boltLength = shieldLength;
hitShield->BeamIntercepted(this, curPos);
}
if (hitUnit != NULL) {
hitUnit->SetLastAttackedPiece(hitColQuery.GetHitPiece(), gs->frameNum);
}
const DamageArray& damageArray = CWeaponDefHandler::DynamicDamages(weaponDef, weaponMuzzlePos, targetPos);
const CGameHelper::ExplosionParams params = {
curPos + curDir * boltLength, // hitPos (same as hitColQuery.GetHitPos() if no water or shield in way)
curDir,
damageArray,
weaponDef,
owner,
hitUnit,
hitFeature,
craterAreaOfEffect,
damageAreaOfEffect,
weaponDef->edgeEffectiveness,
weaponDef->explosionSpeed,
0.5f, // gfxMod
weaponDef->impactOnly,
weaponDef->noExplode || weaponDef->noSelfDamage, // ignoreOwner
false, // damageGround
-1u // projectileID
};
helper->Explosion(params);
ProjectileParams pparams = GetProjectileParams();
pparams.pos = curPos;
pparams.end = curPos + curDir * (boltLength + 10.0f);
pparams.ttl = weaponDef->beamLaserTTL;
WeaponProjectileFactory::LoadProjectile(pparams);
}
void CLightningCannon::SlowUpdate()
{
CWeapon::SlowUpdate();
}
|