Serious-Engine/Sources/EntitiesMP/Debris.es

372 lines
12 KiB
Erlang
Raw Normal View History

2016-03-11 14:57:17 +01:00
/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
602
%{
#include "StdH.h"
%}
uses "EntitiesMP/BasicEffects";
enum DebrisParticlesType {
0 DPT_NONE "", // no particles
1 DPT_BLOODTRAIL "", // blood
2 DPR_SMOKETRAIL "", // smoke
3 DPR_SPARKS "", // sparks (for robots)
4 DPR_FLYINGTRAIL "", // just flying object
5 DPT_AFTERBURNER "", // afterburner trail
};
// input parameter for spawning a debris
event ESpawnDebris {
EntityInfoBodyType Eeibt, // body type
CModelData *pmd, // model for this debris
FLOAT fSize, // stretch factor
CTextureData *ptd, // texture for this debris
CTextureData *ptdRefl, // reflection texture
CTextureData *ptdSpec, // specular texture
CTextureData *ptdBump, // bump texture
INDEX iModelAnim, // animation for debris model
enum DebrisParticlesType dptParticles, // particles type
enum BasicEffectType betStain, // stain left when touching brushes
COLOR colDebris, // multiply color for debris
BOOL bCustomShading, // if debris uses custom shading
ANGLE3D aShadingDirection, // custom shading direction
COLOR colCustomAmbient, // custom shading ambient
COLOR colCustomDiffuse, // custom shading diffuse
BOOL bImmaterialASAP, // if should stop colliding as soon as it hits the ground
FLOAT fDustStretch, // if should spawn dust when it hits the ground and size
FLOAT3D vStretch, // stretch for spawned model template
CEntityPointer penFallFXPapa, // parent of all spawned child effects
};
%{
%}
class CDebris: CMovableModelEntity {
name "Debris";
thumbnail "";
properties:
1 enum DebrisParticlesType m_dptParticles = DPT_NONE, // type of particles
2 INDEX m_iBodyType = 0, // body type of this debris
3 BOOL m_bFade = FALSE, // fade debris
4 FLOAT m_fFadeStartTime = 0.0f, // fade start time
5 FLOAT m_fFadeTime = 0.0f, // fade time
6 FLOAT3D m_fLastStainHitPoint = FLOAT3D(0,0,0), // last stain hit point
7 enum BasicEffectType m_betStain = BET_NONE, // type of stain left
8 INDEX m_ctLeftStains = 0, // count of stains already left
9 FLOAT m_tmStarted = 0.0f, // time when spawned
10 FLOAT m_fStretch = 1.0f, // stretch
11 ANGLE3D m_aShadingDirection = ANGLE3D(0,0,0),
12 BOOL m_bCustomShading = FALSE,
13 COLOR m_colCustomAmbient = COLOR(C_WHITE|CT_OPAQUE),
14 COLOR m_colCustomDiffuse = COLOR(C_WHITE|CT_OPAQUE),
15 BOOL m_bImmaterialASAP = FALSE,
16 FLOAT m_fDustStretch = 0.0f,
17 BOOL m_bTouchedGround=FALSE,
18 CEntityPointer m_penFallFXPapa,
components:
1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
functions:
/* Entity info */
void *GetEntityInfo(void) {
return GetStdEntityInfo((EntityInfoBodyType)m_iBodyType);
};
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
// cannot be damaged immediately after spawning
if ((_pTimer->CurrentTick()-m_tmStarted<1.0f)
||(dmtType==DMT_CANNONBALL_EXPLOSION) && (_pTimer->CurrentTick()-m_tmStarted<5.0f)) {
return;
}
CMovableModelEntity::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
};
/************************************************************
* FADE OUT *
************************************************************/
BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient)
{
if(m_bCustomShading)
{
colLight = m_colCustomDiffuse;
colAmbient = m_colCustomAmbient;
AnglesToDirectionVector(m_aShadingDirection, vLightDirection);
vLightDirection = -vLightDirection;
}
if (m_bFade) {
FLOAT fTimeRemain = m_fFadeStartTime + m_fFadeTime - _pTimer->CurrentTick();
if (fTimeRemain < 0.0f) { fTimeRemain = 0.0f; }
COLOR colAlpha = GetModelObject()->mo_colBlendColor;
colAlpha = (colAlpha&0xffffff00) + (COLOR(fTimeRemain/m_fFadeTime*0xff)&0xff);
GetModelObject()->mo_colBlendColor = colAlpha;
}
return FALSE;
};
/************************************************************
* EFFECTS *
************************************************************/
// leave a stain where hit
void LeaveStain(void)
{
// if no stains
if (m_betStain==BET_NONE) {
// do nothing
return;
}
// don't allow too many stains to be left
if (m_ctLeftStains>5) {
return;
}
ESpawnEffect ese;
FLOAT3D vPoint;
FLOATplane3D plPlaneNormal;
FLOAT fDistanceToEdge;
// on plane
if (GetNearestPolygon(vPoint, plPlaneNormal, fDistanceToEdge)) {
// away from last hit point and near to polygon
if ((m_fLastStainHitPoint-vPoint).Length()>3.0f &&
(vPoint-GetPlacement().pl_PositionVector).Length()<3.5f) {
m_fLastStainHitPoint = vPoint;
// stain
ese.colMuliplier = C_WHITE|CT_OPAQUE;
ese.betType = m_betStain;
ese.vNormal = FLOAT3D(plPlaneNormal);
GetNormalComponent( en_vCurrentTranslationAbsolute, plPlaneNormal, ese.vDirection);
FLOAT fLength = ese.vDirection.Length() / 7.5f;
fLength = Clamp( fLength, 1.0f, 15.0f);
ese.vStretch = FLOAT3D( 1.0f, fLength*1.0f, 1.0f);
SpawnEffect(CPlacement3D(vPoint+ese.vNormal/50.0f*(FRnd()+0.5f), ANGLE3D(0, 0, 0)), ese);
m_ctLeftStains++;
}
}
};
// spawn effect
void SpawnEffect(const CPlacement3D &plEffect, const class ESpawnEffect &eSpawnEffect)
{
CEntityPointer penEffect = CreateEntity(plEffect, CLASS_BASIC_EFFECT);
penEffect->Initialize(eSpawnEffect);
};
// particles
void RenderParticles(void)
{
// if going too slow
if (en_vCurrentTranslationAbsolute.Length()<0.1f) {
// don't render particles
return;
}
switch(m_dptParticles) {
case DPT_BLOODTRAIL: {
Particles_BloodTrail( this);
} break;
case DPR_SMOKETRAIL: {
Particles_GrenadeTrail( this);
} break;
case DPR_SPARKS: {
Particles_ColoredStarsTrail( this);
} break;
case DPR_FLYINGTRAIL:{
//Particles_WhiteLineTrail( this);
Particles_BombTrail( this);
} break;
case DPT_AFTERBURNER:{
Particles_AfterBurner( this, m_tmStarted, 0.5f);
} break;
default: ASSERT(FALSE);
case DPT_NONE:
return;
}
};
// explode
void Explode(void)
{
// spawn explosion
CPlacement3D plExplosion = GetPlacement();
CEntityPointer penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT);
ESpawnEffect eSpawnEffect;
eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE;
eSpawnEffect.betType = BET_BOMB;
eSpawnEffect.vStretch = FLOAT3D(0.3f,0.3f,0.3f);
penExplosion->Initialize(eSpawnEffect);
}
/************************************************************
* MAIN *
************************************************************/
procedures:
Main(ESpawnDebris eSpawn)
{
InitAsModel();
SetPhysicsFlags(EPF_MODEL_BOUNCING|EPF_CANFADESPINNING);
SetCollisionFlags(ECF_DEBRIS);
SetFlags(GetFlags() | ENF_SEETHROUGH);
SetHealth(25.0f);
en_fBounceDampNormal = 0.15f;
en_fBounceDampParallel = 0.5f;
en_fJumpControlMultiplier = 0.0f;
// set density
if (eSpawn.Eeibt==EIBT_ICE) {
en_fDensity = 500.0f;
} else if (eSpawn.Eeibt==EIBT_WOOD) {
en_fDensity = 500.0f;
} else if (eSpawn.Eeibt==EIBT_FLESH) {
en_fDensity = 5000.0f;
en_fBounceDampNormal = 0.25f;
en_fBounceDampParallel = 0.75f;
} else if (TRUE) {
en_fDensity = 5000.0f;
}
// set appearance
m_dptParticles = eSpawn.dptParticles;
if(m_dptParticles==DPT_AFTERBURNER)
{
Particles_AfterBurner_Prepare(this);
}
m_betStain = eSpawn.betStain;
m_iBodyType = (INDEX)eSpawn.Eeibt;
GetModelObject()->SetData(eSpawn.pmd);
GetModelObject()->mo_toTexture.SetData(eSpawn.ptd);
GetModelObject()->mo_toReflection.SetData(eSpawn.ptdRefl);
GetModelObject()->mo_toSpecular.SetData(eSpawn.ptdSpec);
GetModelObject()->mo_toBump.SetData(eSpawn.ptdBump);
GetModelObject()->PlayAnim(eSpawn.iModelAnim, AOF_LOOPING);
GetModelObject()->mo_Stretch = FLOAT3D( eSpawn.fSize, eSpawn.fSize, eSpawn.fSize);
GetModelObject()->mo_Stretch(1)*=eSpawn.vStretch(1);
GetModelObject()->mo_Stretch(2)*=eSpawn.vStretch(2);
GetModelObject()->mo_Stretch(3)*=eSpawn.vStretch(3);
// adjust color
GetModelObject()->mo_colBlendColor = eSpawn.colDebris|CT_OPAQUE;
m_bCustomShading = eSpawn.bCustomShading;
if( m_bCustomShading)
{
en_ulFlags|=ENF_NOSHADINGINFO;
}
m_aShadingDirection = eSpawn.aShadingDirection;
m_colCustomAmbient = eSpawn.colCustomAmbient;
m_colCustomDiffuse = eSpawn.colCustomDiffuse;
m_bImmaterialASAP = eSpawn.bImmaterialASAP;
m_fDustStretch = eSpawn.fDustStretch;
m_penFallFXPapa=eSpawn.penFallFXPapa;
ModelChangeNotify();
FLOATaabbox3D box;
GetBoundingBox(box);
FLOAT fEntitySize = box.Size().MaxNorm();
if (fEntitySize>0.5f) {
SetCollisionFlags(ECF_MODEL);
}
en_fCollisionSpeedLimit+=ClampDn(0.0f, fEntitySize*10.0f);
m_bFade = FALSE;
m_fLastStainHitPoint = FLOAT3D(32000.0f, 32000.0f, 32000.0f);
m_ctLeftStains = 0;
m_tmStarted = _pTimer->CurrentTick();
m_bTouchedGround=FALSE;
// wait some time
FLOAT fWaitBeforeFade=FRnd()*2.0f + 3.0f;
wait(fWaitBeforeFade)
{
on (EBegin) : { resume; }
// if touched something
on (ETouch etouch) : {
// if it is brush
if (etouch.penOther->GetRenderType()==RT_BRUSH)
{
// shake or some other effect
if( m_penFallFXPapa!=NULL && !m_bTouchedGround)
{
// loop all children of FX papa
FOREACHINLIST( CEntity, en_lnInParent, m_penFallFXPapa->en_lhChildren, iten)
{
// start it
CEntity *penNew = GetWorld()->CopyEntityInWorld( *iten, GetPlacement());
penNew->SetParent(NULL);
if( IsOfClass(&*penNew, "SoundHolder"))
{
penNew->SendEvent( EStart());
}
else
{
penNew->SendEvent( ETrigger());
}
}
}
if( m_fDustStretch>0 && !m_bTouchedGround)
{
// spawn dust
CPlacement3D plDust=GetPlacement();
plDust.pl_PositionVector=plDust.pl_PositionVector+FLOAT3D(0,m_fDustStretch*0.25f,0);
// spawn dust effect
ESpawnEffect ese;
ese.colMuliplier = C_WHITE|CT_OPAQUE;
ese.vStretch = FLOAT3D(m_fDustStretch,m_fDustStretch,m_fDustStretch);
ese.vNormal = FLOAT3D(0,1,0);
ese.betType = BET_DUST_FALL;
CEntityPointer penFX = CreateEntity(plDust, CLASS_BASIC_EFFECT);
penFX->Initialize(ese);
}
m_bTouchedGround=TRUE;
// maybe leave stain
LeaveStain();
// if robot
if (m_iBodyType==EIBT_ROBOT)
{
// explode
Explode();
SendEvent(EDeath());
resume;
}
}
if( m_bImmaterialASAP)
{
SetCollisionFlags(ECF_DEBRIS);
}
resume;
}
on (EDeath) : { Destroy(); return; }
on (ETimer) : { stop; }
}
// fade away
SetCollisionFlags(ECF_DEBRIS);
m_fFadeStartTime = _pTimer->CurrentTick();
m_fFadeTime = 5.0f;
m_bFade = TRUE;
autowait(m_fFadeTime);
// cease to exist
Destroy();
return;
}
};