217 %{ #include "Entities/StdH/StdH.h" %} uses "Entities/ModelHolder2"; uses "Entities/BasicEffects"; uses "Entities/Debris"; uses "Entities/BloodSpray"; // event sent to entities in range of model destroy // (e.g light can turn off) event ERangeModelDestruction { }; // type of debris enum DestructionDebrisType { 1 DDT_STONE "Stone", 2 DDT_WOOD "Wood", 3 DDT_PALM "Palm", }; class CModelDestruction : CEntity { name "ModelDestruction"; thumbnail "Thumbnails\\ModelDestruction.tbn"; features "HasName", "IsTargetable", "IsImportant"; properties: 1 CTString m_strName "Name" 'N' = "ModelDestruction", 2 CTString m_strDescription = "", 10 CEntityPointer m_penModel0 "Model 0" 'M' COLOR(C_RED|0x00), 11 CEntityPointer m_penModel1 "Model 1" COLOR(C_RED|0x00), 12 CEntityPointer m_penModel2 "Model 2" COLOR(C_RED|0x00), 13 CEntityPointer m_penModel3 "Model 3" COLOR(C_RED|0x00), 14 CEntityPointer m_penModel4 "Model 4" COLOR(C_RED|0x00), 20 FLOAT m_fHealth "Health" 'H' = 50.0f, // health of the model pointing to this 22 enum DestructionDebrisType m_ddtDebris "Debris" 'D' = DDT_STONE, // type of debris 23 INDEX m_ctDebris "Debris Count" = 3, 24 FLOAT m_fDebrisSize "Debris Size" = 1.0f, 25 enum EntityInfoBodyType m_eibtBodyType "Body Type" = EIBT_ROCK, 26 enum SprayParticlesType m_sptType "Particle Type" = SPT_NONE, // type of particles components: 1 model MODEL_MODELDESTRUCTION "Models\\Editor\\ModelDestruction.mdl", 2 texture TEXTURE_MODELDESTRUCTION "Models\\Editor\\ModelDestruction.tex", 3 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", // ************** WOOD PARTS ************** 10 model MODEL_WOOD "Models\\Effects\\Debris\\Wood01\\Wood.mdl", 11 texture TEXTURE_WOOD "Models\\Effects\\Debris\\Wood01\\Wood.tex", // ************** STONE PARTS ************** 14 model MODEL_STONE "Models\\Effects\\Debris\\Stone\\Stone.mdl", 15 texture TEXTURE_STONE "Models\\Effects\\Debris\\Stone\\Stone.tex", functions: void Precache(void) { PrecacheClass(CLASS_BASIC_EFFECT, BET_EXPLOSIONSTAIN); switch(m_ddtDebris) { case DDT_STONE: { PrecacheModel(MODEL_STONE); PrecacheTexture(TEXTURE_STONE); } break; case DDT_WOOD: { PrecacheModel(MODEL_WOOD); PrecacheTexture(TEXTURE_WOOD); } break; case DDT_PALM: { PrecacheModel(MODEL_WOOD); PrecacheTexture(TEXTURE_WOOD); } break; } }; const CTString &GetDescription(void) const { INDEX ct = GetModelsCount(); if(ct==0) { ((CTString&)m_strDescription).PrintF("(%g): no more", m_fHealth); } else if(ct==1) { ((CTString&)m_strDescription).PrintF("(%g): %s", m_fHealth, (const char*)m_penModel0->GetName()); } else if (TRUE) { ((CTString&)m_strDescription).PrintF("(%g): %s,...(%d)", m_fHealth, (const char*)m_penModel0->GetName(), ct); } return m_strDescription; } // check if one model target is valid void CheckOneModelTarget(CEntityPointer &pen) { if (pen!=NULL && !IsOfClass(pen, "ModelHolder2")) { WarningMessage("Model '%s' is not ModelHolder2!", (const char*)pen->GetName()); pen=NULL; } } // get next phase in destruction class CModelHolder2 *GetNextPhase(void) { INDEX ct = GetModelsCount(); // if not more models if (ct==0) { // return none return NULL; // if there are some } else { // choose by random return GetModel(IRnd()%ct); } } // get number of models set by user INDEX GetModelsCount(void) const { // note: only first N that are no NULL are used if (m_penModel0==NULL) { return 0; }; if (m_penModel1==NULL) { return 1; }; if (m_penModel2==NULL) { return 2; }; if (m_penModel3==NULL) { return 3; }; if (m_penModel4==NULL) { return 4; }; return 5; } // get model by its index class CModelHolder2 *GetModel(INDEX iModel) { ASSERT(iModel<=GetModelsCount()); iModel = Clamp(iModel, INDEX(0), GetModelsCount()); return (CModelHolder2 *)&*(&m_penModel0)[iModel]; } // spawn debris for given model void SpawnDebris(CModelHolder2 *penModel) { FLOATaabbox3D box; penModel->GetBoundingBox(box); FLOAT fEntitySize = box.Size().MaxNorm(); FLOAT fSize = m_fDebrisSize; switch(m_ddtDebris) { case DDT_STONE: { Debris_Begin(EIBT_ROCK, DPT_NONE, BET_NONE, fEntitySize, FLOAT3D(0,0,0), FLOAT3D(0,0,0), 1.0f, 0.0f); for(INDEX iDebris = 0; iDebrism_vDamage*0.3f, FLOAT3D(0,0,0), 1.0f, 0.0f); Debris_Spawn(penModel, this, MODEL_WOOD, TEXTURE_WOOD, 0, 0, 0, 0, fSize, FLOAT3D(0.5f, 0.2f, 0.5f)); Debris_Spawn(penModel, this, MODEL_WOOD, TEXTURE_WOOD, 0, 0, 0, 1, fSize, FLOAT3D(0.5f, 0.3f, 0.5f)); Debris_Spawn(penModel, this, MODEL_WOOD, TEXTURE_WOOD, 0, 0, 0, 2, fSize, FLOAT3D(0.5f, 0.4f, 0.5f)); Debris_Spawn(penModel, this, MODEL_WOOD, TEXTURE_WOOD, 0, 0, 0, 3, fSize, FLOAT3D(0.5f, 0.5f, 0.5f)); Debris_Spawn(penModel, this, MODEL_WOOD, TEXTURE_WOOD, 0, 0, 0, 1, fSize, FLOAT3D(0.5f, 0.6f, 0.5f)); Debris_Spawn(penModel, this, MODEL_WOOD, TEXTURE_WOOD, 0, 0, 0, 2, fSize, FLOAT3D(0.5f, 0.8f, 0.5f)); Debris_Spawn(penModel, this, MODEL_WOOD, TEXTURE_WOOD, 0, 0, 0, 1, fSize, FLOAT3D(0.5f, 0.9f, 0.5f)); } break; default: {} break; }; } procedures: Main() { // must not allow invalid classes CheckOneModelTarget(m_penModel0); CheckOneModelTarget(m_penModel1); CheckOneModelTarget(m_penModel2); CheckOneModelTarget(m_penModel3); CheckOneModelTarget(m_penModel4); InitAsEditorModel(); SetPhysicsFlags(EPF_MODEL_IMMATERIAL); SetCollisionFlags(ECF_IMMATERIAL); // set appearance SetModel(MODEL_MODELDESTRUCTION); SetModelMainTexture(TEXTURE_MODELDESTRUCTION); return; } };