/* Copyright (c) 2002-2012 Croteam Ltd. This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 242 %{ #include "StdH.h" #include "EntitiesMP/WorldSettingsController.h" %} uses "EntitiesMP/ModelDestruction"; uses "EntitiesMP/AnimationChanger"; uses "EntitiesMP/BloodSpray"; enum SkaCustomShadingType { 0 SCST_NONE "Automatic shading", 1 SCST_CONSTANT_SHADING "Constant shading", 2 SCST_FULL_CUSTOMIZED "Customized shading" }; enum SkaShadowType { 0 SST_NONE "None", 1 SST_CLUSTER "Cluster shadows", 2 SST_POLYGONAL "Polygonal" }; %{ // #define MIPRATIO 0.003125f //(2*tan(90/2))/640 %} class CModelHolder3 : CRationalEntity { name "ModelHolder3"; thumbnail "Thumbnails\\ModelHolder3.tbn"; features "HasName", "HasDescription"; properties: 1 CTFileName m_fnModel "Model file (.smc)" 'M' = CTFILENAME(""), //("Models\\Editor\\Axis.mdl"), // 2 CTFileName m_fnTexture "Texture" 'T' =CTFILENAME("Models\\Editor\\Vector.tex"), // 22 CTFileName m_fnReflection "Reflection" =CTString(""), // 23 CTFileName m_fnSpecular "Specular" =CTString(""), // 24 CTFileName m_fnBump "Bump" =CTString(""), 3 FLOAT m_fStretchAll "StretchAll" 'S' = 1.0f, 4 ANGLE3D m_vStretchXYZ "StretchXYZ" 'X' = FLOAT3D(1.0f, 1.0f, 1.0f), // 4 FLOAT m_vStretchXYZ(1) "StretchX" 'X' = 1.0f, // 5 FLOAT m_vStretchXYZ(2) "StretchY" 'Y' = 1.0f, // 6 FLOAT m_vStretchXYZ(3) "StretchZ" 'Z' = 1.0f, 7 CTString m_strName "Name" 'N' ="", 12 CTString m_strDescription = "", 8 BOOL m_bColliding "Collision" 'L' = FALSE, // set if model is not immatierial // 9 ANIMATION m_iModelAnimation "Model animation" = 0, // 10 ANIMATION m_iTextureAnimation "Texture animation" = 0, 11 enum SkaShadowType m_stClusterShadows "Shadows" 'W' = SST_CLUSTER, // set if model uses cluster shadows 13 BOOL m_bBackground "Background" 'B' = FALSE, // set if model is rendered in background 21 BOOL m_bTargetable "Targetable" = FALSE, // st if model should be targetable // parameters for custom shading of a model (overrides automatic shading calculation) 14 enum SkaCustomShadingType m_cstCustomShading "Shading mode" 'H' = SCST_NONE, 15 ANGLE3D m_aShadingDirection "Shade. Light direction" 'D' = ANGLE3D( AngleDeg(45.0f),AngleDeg(45.0f),AngleDeg(45.0f)), 16 COLOR m_colLight "Shade. Light color" 'O' = C_WHITE, 17 COLOR m_colAmbient "Shade. Ambient color" 'A' = C_BLACK, // 18 CTFileName m_fnmLightAnimation "Light animation file" = CTString(""), // 19 ANIMATION m_iLightAnimation "Light animation" = 0, // 20 CAnimObject m_aoLightAnimation, // 25 BOOL m_bAttachments "Attachments" = TRUE, // set if model should auto load attachments*/ 26 BOOL m_bActive "Active" = TRUE, // 31 FLOAT m_fMipAdd "Mip Add" = 0.0f, // 32 FLOAT m_fMipMul "Mip Mul" = 1.0f, //33 FLOAT m_fMipFadeDist "Mip Fade Dist" = 0.0f, //34 FLOAT m_fMipFadeLen "Mip Fade Len" = 0.0f, // 33 FLOAT m_fMipFadeDist = 0.0f, // 34 FLOAT m_fMipFadeLen = 0.0f, // 35 RANGE m_rMipFadeDistMetric "Mip Fade Dist (Metric)" = -1.0f, // 36 FLOAT m_fMipFadeLenMetric "Mip Fade Len (Metric)" = -1.0f, // random values variables // 50 BOOL m_bRandomStretch "Apply RND stretch" = FALSE, // apply random stretch // 52 FLOAT m_fStretchRndX "Stretch RND X (%)" = 0.2f, // random stretch width // 51 FLOAT m_fStretchRndY "Stretch RND Y (%)" = 0.2f, // random stretch height // 53 FLOAT m_fStretchRndZ "Stretch RND Z (%)" = 0.2f, // random stretch depth // 54 FLOAT m_fStretchRndAll "Stretch RND All (%)" = 0.0f, // random stretch all // 55 FLOAT3D m_fStretchRandom = FLOAT3D(1, 1, 1), // destruction values // 60 CEntityPointer m_penDestruction "Destruction" 'Q' COLOR(C_BLACK|0x20), // model destruction entity // 61 FLOAT3D m_vDamage = FLOAT3D(0,0,0), // current damage impact // 62 FLOAT m_tmLastDamage = -1000.0f, // 63 CEntityPointer m_penDestroyTarget "Destruction Target" COLOR(C_WHITE|0xFF), // targeted when destroyed // 64 CEntityPointer m_penLastDamager, // 65 FLOAT m_tmSpraySpawned = 0.0f, // time when damage has been applied // 66 FLOAT m_fSprayDamage = 0.0f, // total ammount of damage // 67 CEntityPointer m_penSpray, // the blood spray // 68 FLOAT m_fMaxDamageAmmount = 0.0f, // max ammount of damage recived in in last xxx ticks 70 FLOAT m_fClassificationStretch "Classification stretch" = 1.0f, // classification box multiplier // 80 COLOR m_colBurning = COLOR(C_WHITE|CT_OPAQUE), // color applied when burning // 90 enum DamageType m_dmtLastDamageType=DMT_CHAINSAW, // 91 FLOAT m_fChainSawCutDamage "Chain saw cut dammage" 'C' = 300.0f, // 93 INDEX m_iFirstRandomAnimation "First random animation" 'R' = -1, 100 FLOAT m_fMaxTessellationLevel "Max tessellation level" = 0.0f, /*201 FLOAT m_tmFadeStart = -1.0f, // time when model starts fading 202 FLOAT m_tmFadeEnd = -1.0f, // time when model stops fading 203 INDEX m_iMinModelOpacity "Faded Min. Alpha" = 32, 205 FLOAT m_fFadeSpeed "Fadeout Speed" = 0.25f, 206 FLOAT m_fFadeEndWait "Fade end delay" = 0.1f, 207 BOOL m_bFadeChildren "Fade Children" = TRUE, 210 BOOL m_bFade "Fade" = TRUE,*/ /*{ CTFileName m_fnOldModel; // used for remembering last selected model (not saved at all) }*/ components: // 1 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", functions: // void Precache(void) { // PrecacheClass(CLASS_BLOOD_SPRAY, 0); // }; /* Fill in entity statistics - for AI purposes only */ BOOL FillEntityStatistics(EntityStats *pes) { //pes->es_strName = m_fnModel.FileName()+", "+m_fnTexture.FileName(); pes->es_strName = m_fnModel.FileName(); pes->es_ctCount = 1; pes->es_ctAmmount = 1; /*if (m_penDestruction!=NULL) { pes->es_strName += " (destroyable)"; pes->es_fValue = GetDestruction()->m_fHealth; pes->es_iScore = 0; } else {*/ pes->es_fValue = 0; pes->es_iScore = 0; /*}*/ return TRUE; } // classification box multiplier FLOAT3D GetClassificationBoxStretch(void) { return FLOAT3D( m_fClassificationStretch, m_fClassificationStretch, m_fClassificationStretch); } // maximum allowed tessellation level for this model (for Truform/N-Patches support) FLOAT GetMaxTessellationLevel(void) { return m_fMaxTessellationLevel; } /* Receive damage */ void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) { // if not destroyable /*if (m_penDestruction==NULL) { // do nothing return; } FLOAT fNewDamage = fDamageAmmount; if( dmtType==DMT_BURNING) { UBYTE ubR, ubG, ubB, ubA; ColorToRGBA(m_colBurning, ubR, ubG, ubB, ubA); ubR=ClampDn(ubR-4, 32); m_colBurning=RGBAToColor(ubR, ubR, ubR, ubA); } CModelDestruction *penDestruction = GetDestruction(); // adjust damage fNewDamage *=DamageStrength(penDestruction->m_eibtBodyType, dmtType); // if no damage if (fNewDamage==0) { // do nothing return; } FLOAT fKickDamage = fNewDamage; if( (dmtType == DMT_EXPLOSION) || (dmtType == DMT_IMPACT) || (dmtType == DMT_CANNONBALL_EXPLOSION) ) { fKickDamage*=1.5f; } if (dmtType == DMT_CLOSERANGE) { fKickDamage=0.0f; } if (dmtType == DMT_CHAINSAW) { fKickDamage=0.0f; } if(dmtType == DMT_BULLET && penDestruction->m_eibtBodyType==EIBT_ROCK) { fKickDamage=0.0f; } if( dmtType==DMT_BURNING) { fKickDamage=0.0f; } // get passed time since last damage TIME tmNow = _pTimer->CurrentTick(); TIME tmDelta = tmNow-m_tmLastDamage; m_tmLastDamage = tmNow; // remember who damaged you m_penLastDamager = penInflictor; // fade damage out if (tmDelta>=_pTimer->TickQuantum*3) { m_vDamage=FLOAT3D(0,0,0); } // add new damage FLOAT3D vDirectionFixed; if (vDirection.ManhattanNorm()>0.5f) { vDirectionFixed = vDirection; } else { vDirectionFixed = FLOAT3D(0,1,0); } FLOAT3D vDamageOld = m_vDamage; m_vDamage += vDirectionFixed*fKickDamage; // NOTE: we don't receive damage here, but handle death differently if (m_vDamage.Length()>GetHealth()) { if (!penDestruction->m_bRequireExplosion || dmtType==DMT_EXPLOSION || dmtType==DMT_CANNONBALL || dmtType==DMT_CANNONBALL_EXPLOSION) { EDeath eDeath; // we don't need any extra parameters SendEvent(eDeath); //remember last dammage type m_dmtLastDamageType=dmtType; } } if( m_fMaxDamageAmmountCurrentTick()-_pTimer->TickQuantum*8 || m_fSprayDamage+fNewDamage>50.0f)) { // spawn blood spray CPlacement3D plSpray = CPlacement3D( vHitPoint, ANGLE3D(0, 0, 0)); m_penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); m_penSpray->SetParent( this); ESpawnSpray eSpawnSpray; // adjust spray power if( m_fMaxDamageAmmount > 10.0f) { eSpawnSpray.fDamagePower = 3.0f; } else if(m_fSprayDamage+fNewDamage>50.0f) { eSpawnSpray.fDamagePower = 2.0f; } else { eSpawnSpray.fDamagePower = 1.0f; } eSpawnSpray.sptType = penDestruction->m_sptType; eSpawnSpray.fSizeMultiplier = penDestruction->m_fParticleSize; // get your down vector (simulates gravity) FLOAT3D vDn(-en_mRotation(1,2), -en_mRotation(2,2), -en_mRotation(3,2)); // setup direction of spray FLOAT3D vHitPointRelative = vHitPoint - GetPlacement().pl_PositionVector; FLOAT3D vReflectingNormal; GetNormalComponent( vHitPointRelative, vDn, vReflectingNormal); vReflectingNormal.Normalize(); FLOAT3D vProjectedComponent = vReflectingNormal*(vDirection%vReflectingNormal); FLOAT3D vSpilDirection = vDirection-vProjectedComponent*2.0f-vDn*0.5f; eSpawnSpray.vDirection = vSpilDirection; eSpawnSpray.penOwner = this; eSpawnSpray.colCentralColor=penDestruction->m_colParticles; eSpawnSpray.colBurnColor=m_colBurning; eSpawnSpray.fLaunchPower=penDestruction->m_fParticleLaunchPower; // initialize spray m_penSpray->Initialize( eSpawnSpray); m_tmSpraySpawned = _pTimer->CurrentTick(); m_fSprayDamage = 0.0f; m_fMaxDamageAmmount = 0.0f; } if( dmtType==DMT_CHAINSAW && m_fChainSawCutDamage>0) { m_fChainSawCutDamage-=fDamageAmmount; if(m_fChainSawCutDamage<=0) { EDeath eDeath; // we don't need any extra parameters SendEvent(eDeath); //remember last dammage type m_dmtLastDamageType=dmtType; } } m_fSprayDamage+=fNewDamage; */ }; // Entity info void *GetEntityInfo(void) { /*CModelDestruction *pmd=GetDestruction(); if( pmd!=NULL) { return GetStdEntityInfo(pmd->m_eibtBodyType); }*/ return CEntity::GetEntityInfo(); }; /* class CModelDestruction *GetDestruction(void) { ASSERT(m_penDestruction==NULL || IsOfClass(m_penDestruction, "ModelDestruction")); return (CModelDestruction*)&*m_penDestruction; }*/ BOOL IsTargetable(void) const { return m_bTargetable; } /* Get anim data for given animation property - return NULL for none. */ /* CAnimData *GetAnimData(SLONG slPropertyOffset) { if (slPropertyOffset==offsetof(CModelHolder3, m_iModelAnimation)) { return GetModelObject()->GetData(); } else if (slPropertyOffset==offsetof(CModelHolder3, m_iTextureAnimation)) { return GetModelObject()->mo_toTexture.GetData(); } else if (slPropertyOffset==offsetof(CModelHolder3, m_iLightAnimation)) { return m_aoLightAnimation.GetData(); } else { return CEntity::GetAnimData(slPropertyOffset); } };*/ /* Adjust model mip factor if needed. */ /* void AdjustMipFactor(FLOAT &fMipFactor) { // if should fade last mip if (m_fMipFadeDist>0) { CModelObject *pmo = GetModelObject(); if(pmo==NULL) { return; } // adjust for stretch FLOAT fMipForFade = fMipFactor; // if not visible if (fMipForFade>m_fMipFadeDist) { // set mip factor so that model is never rendered fMipFactor = UpperLimit(0.0f); return; } // adjust fading FLOAT fFade = (m_fMipFadeDist-fMipForFade); if (m_fMipFadeLen>0) { fFade/=m_fMipFadeLen; } else { if (fFade>0) { fFade = 1.0f; } } fFade = Clamp(fFade, 0.0f, 1.0f); // make it invisible pmo->mo_colBlendColor = (pmo->mo_colBlendColor&~255)|UBYTE(255*fFade); } fMipFactor = fMipFactor*m_fMipMul+m_fMipAdd; }*/ /* Adjust model shading parameters if needed. */ BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) { switch(m_cstCustomShading) { case SCST_FULL_CUSTOMIZED: { // if there is color animation /*if (m_aoLightAnimation.GetData()!=NULL) { // get lerping info SLONG colFrame0, colFrame1; FLOAT fRatio; m_aoLightAnimation.GetFrame( colFrame0, colFrame1, fRatio); UBYTE ubAnimR0, ubAnimG0, ubAnimB0; UBYTE ubAnimR1, ubAnimG1, ubAnimB1; ColorToRGB( colFrame0, ubAnimR0, ubAnimG0, ubAnimB0); ColorToRGB( colFrame1, ubAnimR1, ubAnimG1, ubAnimB1); // calculate current animation color FLOAT fAnimR = NormByteToFloat( Lerp( ubAnimR0, ubAnimR1, fRatio)); FLOAT fAnimG = NormByteToFloat( Lerp( ubAnimG0, ubAnimG1, fRatio)); FLOAT fAnimB = NormByteToFloat( Lerp( ubAnimB0, ubAnimB1, fRatio)); // decompose constant colors UBYTE ubLightR, ubLightG, ubLightB; UBYTE ubAmbientR, ubAmbientG, ubAmbientB; ColorToRGB( m_colLight, ubLightR, ubLightG, ubLightB); ColorToRGB( m_colAmbient, ubAmbientR, ubAmbientG, ubAmbientB); colLight = RGBToColor( ubLightR *fAnimR, ubLightG *fAnimG, ubLightB *fAnimB); colAmbient = RGBToColor( ubAmbientR*fAnimR, ubAmbientG*fAnimG, ubAmbientB*fAnimB); // if there is no color animation } else {*/ colLight = m_colLight; colAmbient = m_colAmbient; //} // obtain world settings controller /*CWorldSettingsController *pwsc = GetWSC(this); if( pwsc!=NULL && pwsc->m_bApplyShadingToModels) { // apply animating shading COLOR colShade = GetWorld()->wo_atbTextureBlendings[9].tb_colMultiply; colLight=MulColors(colLight, colShade); colAmbient=MulColors(colAmbient, colShade); }*/ AnglesToDirectionVector(m_aShadingDirection, vLightDirection); vLightDirection = -vLightDirection; break; } case SCST_CONSTANT_SHADING: { // combine colors with clamp UBYTE lR,lG,lB,aR,aG,aB,rR,rG,rB; ColorToRGB( colLight, lR, lG, lB); ColorToRGB( colAmbient, aR, aG, aB); colLight = 0; rR = (UBYTE) Clamp( (ULONG)lR+aR, (ULONG)0, (ULONG)255); rG = (UBYTE) Clamp( (ULONG)lG+aG, (ULONG)0, (ULONG)255); rB = (UBYTE) Clamp( (ULONG)lB+aB, (ULONG)0, (ULONG)255); colAmbient = RGBToColor( rR, rG, rB); break; } case SCST_NONE: { // do nothing break; } } /* if(m_colBurning!=COLOR(C_WHITE|CT_OPAQUE)) { colAmbient = MulColors( colAmbient, m_colBurning); colLight = MulColors( colLight, m_colBurning); return TRUE; }*/ return m_stClusterShadows!=SST_NONE; }; // apply mirror and stretch to the entity void MirrorAndStretch(FLOAT fStretch, BOOL bMirrorX) { m_fStretchAll*=fStretch; if (bMirrorX) { m_vStretchXYZ(1)=-m_vStretchXYZ(1); } } // Stretch model void StretchModel(void) { // stretch factors must not have extreme values if (Abs(m_vStretchXYZ(1)) < 0.01f) { m_vStretchXYZ(1) = 0.01f; } if (Abs(m_vStretchXYZ(2)) < 0.01f) { m_vStretchXYZ(2) = 0.01f; } if (Abs(m_vStretchXYZ(3)) < 0.01f) { m_vStretchXYZ(3) = 0.01f; } if (m_fStretchAll< 0.01f) { m_fStretchAll = 0.01f; } if (Abs(m_vStretchXYZ(1)) >1000.0f) { m_vStretchXYZ(1) = 1000.0f*Sgn(m_vStretchXYZ(1)); } if (Abs(m_vStretchXYZ(2)) >1000.0f) { m_vStretchXYZ(2) = 1000.0f*Sgn(m_vStretchXYZ(2)); } if (Abs(m_vStretchXYZ(3)) >1000.0f) { m_vStretchXYZ(3) = 1000.0f*Sgn(m_vStretchXYZ(3)); } if (m_fStretchAll>1000.0f) { m_fStretchAll = 1000.0f; } /* if (m_bRandomStretch) { m_bRandomStretch = FALSE; // stretch m_fStretchRndX = Clamp( m_fStretchRndX , 0.0f, 1.0f); m_fStretchRndY = Clamp( m_fStretchRndY , 0.0f, 1.0f); m_fStretchRndZ = Clamp( m_fStretchRndZ , 0.0f, 1.0f); m_fStretchRndAll = Clamp( m_fStretchRndAll , 0.0f, 1.0f); m_fStretchRandom(1) = (FRnd()*m_fStretchRndX*2 - m_fStretchRndX) + 1; m_fStretchRandom(2) = (FRnd()*m_fStretchRndY*2 - m_fStretchRndY) + 1; m_fStretchRandom(3) = (FRnd()*m_fStretchRndZ*2 - m_fStretchRndZ) + 1; FLOAT fRNDAll = (FRnd()*m_fStretchRndAll*2 - m_fStretchRndAll) + 1; m_fStretchRandom(1) *= fRNDAll; m_fStretchRandom(2) *= fRNDAll; m_fStretchRandom(3) *= fRNDAll; }*/ GetModelInstance()->StretchModel( m_vStretchXYZ*m_fStretchAll ); ModelChangeNotify(); }; /* Init model holder*/ void InitModelHolder(void) { // must not crash when model is removed if (m_fnModel=="") { m_fnModel=CTFILENAME("Models\\Editor\\Ska\\Axis.smc"); } if (m_bActive) { InitAsSkaModel(); } else { InitAsSkaEditorModel(); } BOOL bLoadOK = TRUE; // try to load the model try { SetSkaModel_t(m_fnModel); // if failed } catch(char *strError) { WarningMessage(TRANS("Cannot load ska model '%s':\n%s"), (CTString&)m_fnModel, strError); bLoadOK = FALSE; // set colision info for default model //SetSkaColisionInfo(); } if (!bLoadOK) { SetSkaModel(CTFILENAME("Models\\Editor\\Ska\\Axis.smc")); } /*try { GetModelObject()->mo_toTexture.SetData_t(m_fnTexture); GetModelObject()->mo_toTexture.PlayAnim(m_iTextureAnimation, AOF_LOOPING); GetModelObject()->mo_toReflection.SetData_t(m_fnReflection); GetModelObject()->mo_toSpecular.SetData_t(m_fnSpecular); GetModelObject()->mo_toBump.SetData_t(m_fnBump); } catch (char *strError) { WarningMessage(strError); }*/ // set model stretch StretchModel(); ModelChangeNotify(); if (m_bColliding&&m_bActive) { SetPhysicsFlags(EPF_MODEL_FIXED); SetCollisionFlags(ECF_MODEL_HOLDER); } else { SetPhysicsFlags(EPF_MODEL_IMMATERIAL); SetCollisionFlags(ECF_IMMATERIAL); } switch(m_stClusterShadows) { case SST_NONE: { SetFlags(GetFlags()&~ENF_CLUSTERSHADOWS); //SetFlags(GetFlags()&~ENF_POLYGONALSHADOWS); break; } case SST_CLUSTER: { SetFlags(GetFlags()|ENF_CLUSTERSHADOWS); //SetFlags(GetFlags()&~ENF_POLYGONALSHADOWS); break; } case SST_POLYGONAL: { //SetFlags(GetFlags()|ENF_POLYGONALSHADOWS); SetFlags(GetFlags()&~ENF_CLUSTERSHADOWS); break; } } if (m_bBackground) { SetFlags(GetFlags()|ENF_BACKGROUND); } else { SetFlags(GetFlags()&~ENF_BACKGROUND); } /* try { m_aoLightAnimation.SetData_t(m_fnmLightAnimation); } catch (char *strError) { WarningMessage(TRANS("Cannot load '%s': %s"), (CTString&)m_fnmLightAnimation, strError); m_fnmLightAnimation = ""; } if (m_aoLightAnimation.GetData()!=NULL) { m_aoLightAnimation.PlayAnim(m_iLightAnimation, AOF_LOOPING); } if (m_penDestruction==NULL) { m_strDescription.PrintF("%s,%s undestroyable", (CTString&)m_fnModel.FileName(), (CTString&)m_fnTexture.FileName()); } else { m_strDescription.PrintF("%s,%s -> %s", (CTString&)m_fnModel.FileName(), (CTString&)m_fnTexture.FileName(), m_penDestruction->GetName()); }*/ /*m_iMinModelOpacity = Clamp(m_iMinModelOpacity, (INDEX)0, (INDEX)255); m_fFadeEndWait = ClampDn(m_fFadeEndWait, 0.05f); m_fFadeSpeed = ClampDn(m_fFadeSpeed, 0.05f);*/ m_strDescription.PrintF("%s", (CTString&)m_fnModel.FileName()); return; }; procedures: Die() { // for each child of this entity {FOREACHINLIST(CEntity, en_lnInParent, en_lhChildren, itenChild) { // send it destruction event itenChild->SendEvent(ERangeModelDestruction()); }} /* // spawn debris CModelDestruction *pmd=GetDestruction(); pmd->SpawnDebris(this); // if there is another phase in destruction CModelHolder3 *penNext = pmd->GetNextPhase(); if (penNext!=NULL) { // copy it here CEntity *penNew = GetWorld()->CopyEntityInWorld( *penNext, GetPlacement() ); penNew->GetModelObject()->StretchModel(GetModelObject()->mo_Stretch); penNew->ModelChangeNotify(); ((CModelHolder3 *)penNew)->m_colBurning=m_colBurning; ((CModelHolder3 *)penNew)->m_fChainSawCutDamage=m_fChainSawCutDamage; if( pmd->m_iStartAnim!=-1) { penNew->GetModelObject()->PlayAnim(pmd->m_iStartAnim, 0); } // copy custom shading parameters CModelHolder3 &mhNew=*((CModelHolder3 *)penNew); mhNew.m_cstCustomShading=m_cstCustomShading; mhNew.m_colLight=m_colLight; mhNew.m_colAmbient=m_colAmbient; mhNew.m_fMipFadeDist = m_fMipFadeDist; mhNew.m_fMipFadeLen = m_fMipFadeLen; mhNew.m_fMipAdd = m_fMipAdd; mhNew.m_fMipMul = m_fMipMul; // domino death for cannonball if(m_dmtLastDamageType==DMT_CHAINSAW) { EDeath eDeath; // we don't need any extra parameters mhNew.m_fChainSawCutDamage=0.0f; mhNew.m_dmtLastDamageType=DMT_CHAINSAW; penNew->SendEvent(eDeath); } } // if there is a destruction target if (m_penDestroyTarget!=NULL) { // notify it SendToTarget(m_penDestroyTarget, EET_TRIGGER, m_penLastDamager); }*/ // destroy yourself Destroy(); return; } Main() { // initialize the model InitModelHolder(); /*if (m_fMipFadeLenMetric>m_rMipFadeDistMetric) { m_fMipFadeLenMetric = m_rMipFadeDistMetric; } // convert metric factors to mip factors if (m_rMipFadeDistMetric>0.0f) { m_fMipFadeDist = Log2(m_rMipFadeDistMetric*1024.0f*MIPRATIO); m_fMipFadeLen = Log2((m_rMipFadeDistMetric+m_fMipFadeLenMetric)*1024.0f*MIPRATIO) - m_fMipFadeDist; } else { m_fMipFadeDist = 0.0f; m_fMipFadeLen = 0.0f; }*/ // check your destruction pointer /*if (m_penDestruction!=NULL && !IsOfClass(m_penDestruction, "ModelDestruction")) { WarningMessage("Destruction '%s' is wrong class!", m_penDestruction->GetName()); m_penDestruction=NULL; }*/ // wait forever wait() { // on the beginning on(EBegin): { // set your health /*if (m_penDestruction!=NULL) { SetHealth(GetDestruction()->m_fHealth); }*/ resume; } // activate/deactivate shows/hides model on (EActivate): { SwitchToModel(); m_bActive = TRUE; if (m_bColliding) { SetPhysicsFlags(EPF_MODEL_FIXED); SetCollisionFlags(ECF_MODEL_HOLDER); } resume; } on (EDeactivate): { SwitchToEditorModel(); SetPhysicsFlags(EPF_MODEL_IMMATERIAL); SetCollisionFlags(ECF_IMMATERIAL); m_bActive = FALSE; SetPhysicsFlags(EPF_MODEL_IMMATERIAL); SetCollisionFlags(ECF_IMMATERIAL); resume; } // when your parent is destroyed on(ERangeModelDestruction): { // for each child of this entity {FOREACHINLIST(CEntity, en_lnInParent, en_lhChildren, itenChild) { // send it destruction event itenChild->SendEvent(ERangeModelDestruction()); }} // destroy yourself Destroy(); resume; } // when dead on(EDeath): { /*if (m_penDestruction!=NULL) { jump Die(); }*/ resume; } /* on(EFade): { if (_pTimer->CurrentTick()>m_tmFadeEnd) { m_tmFadeStart = _pTimer->CurrentTick(); } m_tmFadeEnd = _pTimer->CurrentTick() + m_fFadeSpeed + m_fFadeEndWait; // perhaps fade all entities children if (m_bFadeChildren) { {FOREACHINLIST( CEntity, en_lnInParent, en_lhChildren, iten) { iten->SendEvent(EFade()); }} } resume; }*/ // when animation should be changed /*on(EChangeAnim eChange): { m_iModelAnimation = eChange.iModelAnim; m_iTextureAnimation = eChange.iTextureAnim; m_iLightAnimation = eChange.iLightAnim; if (m_aoLightAnimation.GetData()!=NULL) { m_aoLightAnimation.PlayAnim(m_iLightAnimation, eChange.bLightLoop?AOF_LOOPING:0); } if (GetModelObject()->GetData()!=NULL) { GetModelObject()->PlayAnim(m_iModelAnimation, eChange.bModelLoop?AOF_LOOPING:0); } if (GetModelObject()->mo_toTexture.GetData()!=NULL) { GetModelObject()->mo_toTexture.PlayAnim(m_iTextureAnimation, eChange.bTextureLoop?AOF_LOOPING:0); } resume; }*/ otherwise(): { resume; } }; } };