Serious-Engine/Sources/Entities/Pipebomb.es
2016-04-08 00:11:36 +02:00

259 lines
7.1 KiB
C++

503
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/BasicEffects";
uses "Entities/Light";
uses "Entities/AmmoItem";
// input parameter for launching the projectile
event EDropPipebomb {
CEntityPointer penLauncher, // who launched it
FLOAT fSpeed, // launch speed
};
%{
#define ECF_PIPEBOMB ( \
((ECBI_MODEL|ECBI_BRUSH|ECBI_PROJECTILE_SOLID|ECBI_MODEL_HOLDER)<<ECB_TEST) |\
((ECBI_PROJECTILE_SOLID)<<ECB_IS) )
void CPipebomb_OnPrecache(CDLLEntityClass *pdec, INDEX iUser)
{
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_GRENADE);
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_EXPLOSIONSTAIN);
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_SHOCKWAVE);
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_GRENADE_PLANE);
pdec->PrecacheModel(MODEL_PIPEBOMB);
pdec->PrecacheTexture(TEXTURE_PIPEBOMB);
pdec->PrecacheSound(SOUND_LAUNCH);
}
%}
class CPipebomb : CMovableModelEntity {
name "Pipebomb";
thumbnail "";
features "ImplementsOnPrecache", "CanBePredictable";
properties:
1 CEntityPointer m_penLauncher, // who lanuched it
2 FLOAT m_fIgnoreTime = 0.0f, // time when laucher will be ignored
3 FLOAT m_fSpeed = 0.0f, // launch speed
4 BOOL m_bCollected = FALSE, // collect -> do not explode
{
CLightSource m_lsLightSource;
}
components:
1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
2 class CLASS_LIGHT "Classes\\Light.ecl",
// ********* PIPEBOMB (GRENADE) *********
10 model MODEL_PIPEBOMB "Models\\Weapons\\Pipebomb\\Grenade\\Grenade.mdl",
11 texture TEXTURE_PIPEBOMB "Models\\Weapons\\Pipebomb\\Grenade\\Grenade.tex",
12 sound SOUND_LAUNCH "Sounds\\Weapons\\RocketFired.wav",
functions:
/* Read from stream. */
void Read_t( CTStream *istr) // throw char *
{
CMovableModelEntity::Read_t(istr);
SetupLightSource();
}
/* Get static light source information. */
CLightSource *GetLightSource(void)
{
if (!IsPredictor()) {
return &m_lsLightSource;
} else {
return NULL;
}
}
// Setup light source
void SetupLightSource(void)
{
// setup light source
CLightSource lsNew;
lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DYNAMIC;
lsNew.ls_colColor = C_vdRED;
lsNew.ls_rFallOff = 1.0f;
lsNew.ls_rHotSpot = 0.1f;
lsNew.ls_plftLensFlare = &_lftYellowStarRedRingFar;
lsNew.ls_ubPolygonalMask = 0;
lsNew.ls_paoLightAnimation = NULL;
m_lsLightSource.ls_penEntity = this;
m_lsLightSource.SetLightSource(lsNew);
}
// render particles
void RenderParticles(void) {
Particles_GrenadeTrail(this);
}
/************************************************************
* PIPEBOMB *
************************************************************/
void Pipebomb(void) {
// set appearance
InitAsModel();
SetPhysicsFlags(EPF_MODEL_BOUNCING);
SetCollisionFlags(ECF_PIPEBOMB);
//GetModelObject()->StretchModel(FLOAT3D(2.5f, 2.5f, 2.5f));
//ModelChangeNotify();
SetModel(MODEL_PIPEBOMB);
SetModelMainTexture(TEXTURE_PIPEBOMB);
// start moving
LaunchAsFreeProjectile(FLOAT3D(0.0f, 0.0f, -m_fSpeed), (CMovableEntity*)&*m_penLauncher);
SetDesiredRotation(ANGLE3D(0, FRnd()*120.0f+120.0f, FRnd()*250.0f-125.0f));
en_fBounceDampNormal = 0.7f;
en_fBounceDampParallel = 0.7f;
en_fJumpControlMultiplier = 0.0f;
en_fCollisionSpeedLimit = 45.0f;
en_fCollisionDamageFactor = 10.0f;
SetHealth(20.0f);
};
void PipebombExplosion(void) {
ESpawnEffect ese;
FLOAT3D vPoint;
FLOATplane3D vPlaneNormal;
FLOAT fDistanceToEdge;
// explosion
ese.colMuliplier = C_WHITE|CT_OPAQUE;
ese.betType = BET_GRENADE;
ese.vStretch = FLOAT3D(1,1,1);
SpawnEffect(GetPlacement(), ese);
// spawn sound event in range
if( IsDerivedFromClass( m_penLauncher, "Player")) {
SpawnRangeSound( m_penLauncher, this, SNDT_PLAYER, 50.0f);
}
// on plane
if (GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) {
if ((vPoint-GetPlacement().pl_PositionVector).Length() < 3.5f) {
// wall stain
ese.betType = BET_EXPLOSIONSTAIN;
ese.vNormal = FLOAT3D(vPlaneNormal);
SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese);
// shock wave
ese.betType = BET_SHOCKWAVE;
ese.vNormal = FLOAT3D(vPlaneNormal);
SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese);
// second explosion on plane
ese.betType = BET_GRENADE_PLANE;
ese.vNormal = FLOAT3D(vPlaneNormal);
SpawnEffect(CPlacement3D(vPoint+ese.vNormal/50.0f, ANGLE3D(0, 0, 0)), ese);
}
}
};
/************************************************************
* C O M M O N F U N C T I O N S *
************************************************************/
// projectile hitted (or time expired or can't move any more)
void ProjectileHitted(void) {
// explode ...
InflictRangeDamage(m_penLauncher, DMT_EXPLOSION, 100.0f,
GetPlacement().pl_PositionVector, 4.0f, 8.0f);
// sound event
ESound eSound;
eSound.EsndtSound = SNDT_EXPLOSION;
eSound.penTarget = m_penLauncher;
SendEventInRange(eSound, FLOATaabbox3D(GetPlacement().pl_PositionVector, 50.0f));
};
// spawn effect
void SpawnEffect(const CPlacement3D &plEffect, const ESpawnEffect &eSpawnEffect) {
CEntityPointer penEffect = CreateEntity(plEffect, CLASS_BASIC_EFFECT);
penEffect->Initialize(eSpawnEffect);
};
/************************************************************
* P R O C E D U R E S *
************************************************************/
procedures:
// --->>> PROJECTILE SLIDE ON BRUSH
ProjectileSlide(EVoid) {
m_bCollected = FALSE;
// fly loop
wait() {
on (EBegin) : { resume; }
// collected
on (ETouch etouch) : {
// clear time limit for launcher
if (etouch.penOther->GetRenderType() & RT_BRUSH) {
m_fIgnoreTime = 0.0f;
resume;
}
BOOL bCollect;
// ignore launcher within 0.5 second
bCollect = etouch.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime;
// speed must be almost zero
bCollect &= (en_vCurrentTranslationAbsolute.Length() < 0.25f);
// only if can be collected
EAmmoItem eai;
eai.EaitType = AIT_GRENADES;
eai.iQuantity = 1;
if (bCollect && etouch.penOther->ReceiveItem(eai)) {
m_bCollected = TRUE;
stop;
}
resume;
}
// killed
on (EDeath) : {
ProjectileHitted();
stop;
}
// activated
on (EStart) : {
ProjectileHitted();
stop;
}
}
return EEnd();
};
// --->>> MAIN
Main(EDropPipebomb edrop) {
// remember the initial parameters
ASSERT(edrop.penLauncher!=NULL);
m_penLauncher = edrop.penLauncher;
m_fSpeed = edrop.fSpeed;
// projectile initialization
Pipebomb();
// setup light source
SetupLightSource();
// remember lauching time
m_fIgnoreTime = _pTimer->CurrentTick() + 0.5f;
// slide
autocall ProjectileSlide() EEnd;
// pipebomb explosion if not collected
if (!m_bCollected) {
PipebombExplosion();
}
Destroy();
return;
}
};