602 %{ #include "Entities/StdH/StdH.h" %} uses "Entities/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 }; // 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 }; %{ %} 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 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_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; 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, 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); // adjust color GetModelObject()->mo_colBlendColor = eSpawn.colDebris|CT_OPAQUE; 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(); // wait some time wait(FRnd()*2.0f + 3.0f) { on (EBegin) : { resume; } // if touched something on (ETouch etouch) : { // if it is brush if (etouch.penOther->GetRenderType()==RT_BRUSH) { // maybe leave stain LeaveStain(); // if robot if (m_iBodyType==EIBT_ROBOT) { // explode Explode(); SendEvent(EDeath()); resume; } } 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; } };