// * This file is part of the COLOBOT source code // * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch // * // * This program is free software: you can redistribute it and/or modify // * it under the terms of the GNU General Public License as published by // * the Free Software Foundation, either version 3 of the License, or // * (at your option) any later version. // * // * 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, see http://www.gnu.org/licenses/. // particule.cpp #include #include #include #include "common/struct.h" #include "math/const.h" #include "math/geometry.h" #include "math/conv.h" #include "old/d3dmath.h" #include "old/d3dtextr.h" #include "old/d3dengine.h" #include "old/d3dutil.h" #include "common/language.h" #include "common/iman.h" #include "old/math3d.h" #include "common/event.h" #include "object/object.h" #include "physics/physics.h" #include "object/auto/auto.h" #include "object/robotmain.h" #include "old/terrain.h" #include "old/sound.h" #include "old/water.h" #include "old/particule.h" const float FOG_HSUP = 10.0f; const float FOG_HINF = 100.0f; // Check if an object can be destroyed, but is not an enemy. bool IsSoft(ObjectType type) { return ( type == OBJECT_HUMAN || type == OBJECT_MOBILEfa || type == OBJECT_MOBILEta || type == OBJECT_MOBILEwa || type == OBJECT_MOBILEia || type == OBJECT_MOBILEfc || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEwc || type == OBJECT_MOBILEic || type == OBJECT_MOBILEfi || type == OBJECT_MOBILEti || type == OBJECT_MOBILEwi || type == OBJECT_MOBILEii || type == OBJECT_MOBILEfs || type == OBJECT_MOBILEts || type == OBJECT_MOBILEws || type == OBJECT_MOBILEis || type == OBJECT_MOBILErt || type == OBJECT_MOBILErc || type == OBJECT_MOBILErr || type == OBJECT_MOBILErs || type == OBJECT_MOBILEsa || type == OBJECT_MOBILEft || type == OBJECT_MOBILEtt || type == OBJECT_MOBILEwt || type == OBJECT_MOBILEit || type == OBJECT_MOBILEdr || // robot? type == OBJECT_METAL || type == OBJECT_POWER || type == OBJECT_ATOMIC || // cargo? type == OBJECT_DERRICK || type == OBJECT_STATION || type == OBJECT_FACTORY || type == OBJECT_REPAIR || type == OBJECT_DESTROYER|| type == OBJECT_CONVERT || type == OBJECT_TOWER || type == OBJECT_RESEARCH || type == OBJECT_RADAR || type == OBJECT_INFO || type == OBJECT_ENERGY || type == OBJECT_LABO || type == OBJECT_NUCLEAR || type == OBJECT_PARA ); // building? } // Check if an object is a destroyable enemy. bool IsAlien(ObjectType type) { return ( type == OBJECT_ANT || type == OBJECT_SPIDER || type == OBJECT_BEE || type == OBJECT_WORM || type == OBJECT_MOTHER || type == OBJECT_NEST || type == OBJECT_BULLET || type == OBJECT_EGG || type == OBJECT_MOBILEtg || type == OBJECT_TEEN28 || type == OBJECT_TEEN31 ); } // Returns the damping factor for friendly fire. float RetDecay(ObjectType type) { if ( IsSoft(type) ) return 0.2f; return 1.0f; } // Application constructor. CParticule::CParticule(CInstanceManager *iMan, CD3DEngine* engine) { m_iMan = iMan; m_iMan->AddInstance(CLASS_PARTICULE, this); m_pD3DDevice = 0; m_engine = engine; m_main = 0; m_terrain = 0; m_water = 0; m_sound = 0; m_uniqueStamp = 0; m_exploGunCounter = 0; m_lastTimeGunDel = 0.0f; m_absTime = 0.0f; FlushParticule(); } // Application destructor. Free memory. CParticule::~CParticule() { m_iMan->DeleteInstance(CLASS_PARTICULE, this); } void CParticule::SetD3DDevice(LPDIRECT3DDEVICE7 device) { m_pD3DDevice = device; } // Removes all particles. void CParticule::FlushParticule() { int i, j; for ( i=0 ; iSearchInstance(CLASS_MAIN); } #if 0 if ( sheet == SH_WORLD && type != PARTISELY && type != PARTISELR && type != PARTIGUN1 && type != PARTIGUN2 && type != PARTIGUN3 && type != PARTIGUN4 && type != PARTIQUARTZ && !m_main->RetMovieLock() ) { dist = Math::Distance(pos, m_engine->RetEyePt()); if ( dist > 300.0f ) return -1; } #endif t = -1; if ( type == PARTIEXPLOT || type == PARTIEXPLOO || type == PARTIMOTOR || type == PARTIBLITZ || type == PARTICRASH || type == PARTIVAPOR || type == PARTIGAS || type == PARTIBASE || type == PARTIFIRE || type == PARTIFIREZ || type == PARTIBLUE || type == PARTIROOT || type == PARTIRECOVER || type == PARTIEJECT || type == PARTISCRAPS || type == PARTIGUN2 || type == PARTIGUN3 || type == PARTIGUN4 || type == PARTIQUEUE || type == PARTIORGANIC1 || type == PARTIORGANIC2 || type == PARTIFLAME || type == PARTIBUBBLE || type == PARTIERROR || type == PARTIWARNING || type == PARTIINFO || type == PARTISPHERE1 || type == PARTISPHERE2 || type == PARTISPHERE4 || type == PARTISPHERE5 || type == PARTISPHERE6 || type == PARTIPLOUF0 || type == PARTITRACK1 || type == PARTITRACK2 || type == PARTITRACK3 || type == PARTITRACK4 || type == PARTITRACK5 || type == PARTITRACK6 || type == PARTITRACK7 || type == PARTITRACK8 || type == PARTITRACK9 || type == PARTITRACK10 || type == PARTITRACK11 || type == PARTITRACK12 || type == PARTILENS1 || type == PARTILENS2 || type == PARTILENS3 || type == PARTILENS4 || type == PARTIGFLAT || type == PARTIDROP || type == PARTIWATER || type == PARTILIMIT1 || type == PARTILIMIT2 || type == PARTILIMIT3 || type == PARTILIMIT4 || type == PARTIEXPLOG1 || type == PARTIEXPLOG2 ) { t = 1; // effect00 } if ( type == PARTIGLINT || type == PARTIGLINTb || type == PARTIGLINTr || type == PARTITOTO || type == PARTISELY || type == PARTISELR || type == PARTIQUARTZ || type == PARTIGUNDEL || type == PARTICONTROL || type == PARTISHOW || type == PARTICHOC || type == PARTIFOG4 || type == PARTIFOG5 || type == PARTIFOG6 || type == PARTIFOG7 ) { t = 2; // effect01 } if ( type == PARTIGUN1 || type == PARTIFLIC || type == PARTISPHERE0 || type == PARTISPHERE3 || type == PARTIFOG0 || type == PARTIFOG1 || type == PARTIFOG2 || type == PARTIFOG3 ) { t = 3; // effect02 } if ( type == PARTISMOKE1 || type == PARTISMOKE2 || type == PARTISMOKE3 || type == PARTIBLOOD || type == PARTIBLOODM || type == PARTIVIRUS1 || type == PARTIVIRUS2 || type == PARTIVIRUS3 || type == PARTIVIRUS4 || type == PARTIVIRUS5 || type == PARTIVIRUS6 || type == PARTIVIRUS7 || type == PARTIVIRUS8 || type == PARTIVIRUS9 || type == PARTIVIRUS10 ) { t = 4; // text (D3DSTATETTw) } if ( t >= MAXPARTITYPE ) return -1; if ( t == -1 ) return -1; for ( j=0 ; j= PARTIFOG0 && type <= PARTIFOG9 ) { if ( m_fogTotal < MAXPARTIFOG ) m_fog[m_fogTotal++] = i; } return i | ((m_particule[i].uniqueStamp&0xffff)<<16); } } return -1; } // Creates a new triangular particle (debris). // Returns the channel of the particle created or -1 on error. int CParticule::CreateFrag(Math::Vector pos, Math::Vector speed, D3DTriangle *triangle, ParticuleType type, float duration, float mass, float windSensitivity, int sheet) { Math::Vector p1, p2, p3, n; float l1, l2, l3, dx, dy; int i, j, t; t = 0; for ( j=0 ; j= MAXPARTITYPE ) return -1; if ( t == -1 ) return -1; for ( j=0 ; jRetWheelTraceQuantity()*MAXWHEELTRACE); max = MAXWHEELTRACE; i = m_wheelTraceIndex++; if ( m_wheelTraceIndex > max ) m_wheelTraceIndex = 0; m_wheelTrace[i].type = type; m_wheelTrace[i].pos[0] = p1; // ul m_wheelTrace[i].pos[1] = p2; // dl m_wheelTrace[i].pos[2] = p3; // ur m_wheelTrace[i].pos[3] = p4; // dr m_wheelTrace[i].startTime = m_absTime; if ( m_terrain == 0 ) { m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN); } m_terrain->MoveOnFloor(m_wheelTrace[i].pos[0]); m_wheelTrace[i].pos[0].y += 0.2f; // just above the ground m_terrain->MoveOnFloor(m_wheelTrace[i].pos[1]); m_wheelTrace[i].pos[1].y += 0.2f; // just above the ground m_terrain->MoveOnFloor(m_wheelTrace[i].pos[2]); m_wheelTrace[i].pos[2].y += 0.2f; // just above the ground m_terrain->MoveOnFloor(m_wheelTrace[i].pos[3]); m_wheelTrace[i].pos[3].y += 0.2f; // just above the ground if ( m_wheelTraceTotal < max ) { m_wheelTraceTotal ++; } else { m_wheelTraceTotal = max; } } // Check a channel number. // Adapts the channel so it can be used as an offset in m_particule. bool CParticule::CheckChannel(int &channel) { int uniqueStamp; uniqueStamp = (channel>>16)&0xffff; channel &= 0xffff; if ( channel < 0 ) return false; if ( channel >= MAXPARTICULE*MAXPARTITYPE ) return false; #if 0 if ( !m_particule[channel].bUsed ) return false; if ( m_particule[channel].uniqueStamp != uniqueStamp ) return false; #else if ( !m_particule[channel].bUsed ) { OutputDebugString("CheckChannel bUsed=false !\n"); return false; } if ( m_particule[channel].uniqueStamp != uniqueStamp ) { OutputDebugString("CheckChannel uniqueStamp !\n"); return false; } #endif return true; } // Removes a particle after his rank. void CParticule::DeleteRank(int rank) { int i; if ( m_totalInterface[rank/MAXPARTICULE][m_particule[rank].sheet] > 0 ) { m_totalInterface[rank/MAXPARTICULE][m_particule[rank].sheet] --; } i = m_particule[rank].trackRank; if ( i != -1 ) // drag associated? { m_track[i].bUsed = false; // frees the drag } m_particule[rank].bUsed = false; } // Removes all particles of a given type. void CParticule::DeleteParticule(ParticuleType type) { int i; for ( i=0 ; i 0 ) { m_totalInterface[channel/MAXPARTICULE][m_particule[channel].sheet] --; } i = m_particule[channel].trackRank; if ( i != -1 ) // drag associated? { m_track[i].bUsed = false; // frees the drag } m_particule[channel].bUsed = false; } // Specifies the object to which the particle is bound. void CParticule::SetObjectLink(int channel, CObject *object) { if ( !CheckChannel(channel) ) return; m_particule[channel].objLink = object; } // Specifies the parent object that created the particle. void CParticule::SetObjectFather(int channel, CObject *object) { if ( !CheckChannel(channel) ) return; m_particule[channel].objFather = object; } void CParticule::SetPosition(int channel, Math::Vector pos) { if ( !CheckChannel(channel) ) return; m_particule[channel].pos = pos; } void CParticule::SetDimension(int channel, Math::Point dim) { if ( !CheckChannel(channel) ) return; m_particule[channel].dim = dim; } void CParticule::SetZoom(int channel, float zoom) { if ( !CheckChannel(channel) ) return; m_particule[channel].zoom = zoom; } void CParticule::SetAngle(int channel, float angle) { if ( !CheckChannel(channel) ) return; m_particule[channel].angle = angle; } void CParticule::SetIntensity(int channel, float intensity) { if ( !CheckChannel(channel) ) return; m_particule[channel].intensity = intensity; } void CParticule::SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom, float angle, float intensity) { if ( !CheckChannel(channel) ) return; m_particule[channel].pos = pos; m_particule[channel].dim = dim; m_particule[channel].zoom = zoom; m_particule[channel].angle = angle; m_particule[channel].intensity = intensity; } void CParticule::SetPhase(int channel, ParticulePhase phase, float duration) { if ( !CheckChannel(channel) ) return; m_particule[channel].phase = phase; m_particule[channel].duration = duration; m_particule[channel].phaseTime = m_particule[channel].time; } // Returns the position of the particle. bool CParticule::GetPosition(int channel, Math::Vector &pos) { if ( !CheckChannel(channel) ) return false; pos = m_particule[channel].pos; return true; } // Indicates whether a sheet evolves or not. void CParticule::SetFrameUpdate(int sheet, bool bUpdate) { m_bFrameUpdate[sheet] = bUpdate; } // Makes evolve all the particles. void CParticule::FrameParticule(float rTime) { CObject* object; Math::Vector eye, pos, speed, wind; Math::Point ts, ti, dim; bool bPause; float progress, dp, h, duration, mass, amplitude; int i, j, r, total; if ( m_main == 0 ) { m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN); } bPause = ( m_engine->RetPause() && !m_main->RetInfoLock() ); if ( m_terrain == 0 ) { m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN); } if ( m_water == 0 ) { m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER); } if ( !bPause ) { m_lastTimeGunDel += rTime; m_absTime += rTime; } wind = m_terrain->RetWind(); eye = m_engine->RetEyePt(); for ( i=0 ; iRetFloorLevel(m_particule[i].pos, true); } h += m_particule[i].dim.y*0.75f; if ( m_particule[i].pos.y < h ) // impact with the ground? { if ( m_particule[i].type == PARTIPART && m_particule[i].weight > 3.0f && // heavy enough? m_particule[i].bounce < 3 ) { amplitude = m_particule[i].weight*0.1f; amplitude *= 1.0f-0.3f*m_particule[i].bounce; if ( amplitude > 1.0f ) amplitude = 1.0f; if ( amplitude > 0.0f ) { Play(SOUND_BOUM, m_particule[i].pos, amplitude); } } if ( m_particule[i].bounce < 3 ) { m_particule[i].pos.y = h; m_particule[i].speed.y *= -0.4f; m_particule[i].speed.x *= 0.4f; m_particule[i].speed.z *= 0.4f; m_particule[i].bounce ++; // more impact } else // disappears after 3 bounces? { if ( m_particule[i].pos.y < h-10.0f || m_particule[i].time >= 20.0f ) { DeleteRank(i); continue; } } } } // Manages drag associated. r = m_particule[i].trackRank; if ( r != -1 ) // drag exists? { if ( TrackMove(r, m_particule[i].pos, progress) ) { DeleteRank(i); continue; } m_track[r].bDrawParticule = (progress < 1.0f); } if ( m_particule[i].type == PARTITRACK1 ) // explosion technique? { m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration); ts.x = 0.375f; ts.y = 0.000f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTITRACK2 ) // spray blue? { m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration); ts.x = 0.500f; ts.y = 0.000f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTITRACK3 ) // spider? { m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration); ts.x = 0.500f; ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTITRACK4 ) // insect explosion? { m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration); ts.x = 0.625f; ts.y = 0.000f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTITRACK5 ) // derrick? { m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration); ts.x = 0.750f; ts.y = 0.000f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTITRACK6 ) // reset in/out? { ts.x = 0.0f; ts.y = 0.0f; ti.x = 0.0f; ti.y = 0.0f; } if ( m_particule[i].type == PARTITRACK7 || // win-1 ? m_particule[i].type == PARTITRACK8 || // win-2 ? m_particule[i].type == PARTITRACK9 || // win-3 ? m_particule[i].type == PARTITRACK10 ) // win-4 ? { m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration); ts.x = 0.25f*(m_particule[i].type-PARTITRACK7); ts.y = 0.25f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTITRACK11 ) // phazer shot? { object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather); m_particule[i].goal = m_particule[i].pos; if ( object != 0 ) { if ( object->RetType() == OBJECT_MOTHER ) { object->ExploObject(EXPLO_BOUM, 0.1f); } else { object->ExploObject(EXPLO_BOUM, 0.0f, RetDecay(object->RetType())); } } m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration); ts.x = 0.375f; ts.y = 0.000f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTITRACK12 ) // drag reactor? { m_particule[i].zoom = 1.0f; ts.x = 0.375f; ts.y = 0.000f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIMOTOR ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f-progress; m_particule[i].intensity = 1.0f-progress; ts.x = 0.000f; ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIBLITZ ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f-progress; m_particule[i].angle = Math::Rand()*Math::PI*2.0f; ts.x = 0.125f; ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTICRASH ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } //? m_particule[i].intensity = 1.0f-progress; if ( progress < 0.25f ) { m_particule[i].zoom = progress/0.25f; } else { m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f; } //? ts.x = 0.250f; ts.x = 0.000f; //? ts.x = 0.375f; ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIVAPOR ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].intensity = 1.0f-progress; m_particule[i].zoom = 1.0f+progress*3.0f; ts.x = 0.000f; ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIGAS ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f-progress; ts.x = 0.375f; ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIBASE ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f+progress*7.0f; m_particule[i].intensity = powf(1.0f-progress, 3.0f); ts.x = 0.375f; ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIFIRE || m_particule[i].type == PARTIFIREZ ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( m_particule[i].type == PARTIFIRE ) { m_particule[i].zoom = 1.0f-progress; } else { m_particule[i].zoom = progress; } ts.x = 0.500f; ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIGUN1 ) // fireball shot? { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( m_particule[i].testTime >= 0.1f ) { m_particule[i].testTime = 0.0f; if ( m_terrain->RetFloorHeight(m_particule[i].pos, true) < -2.0f ) { m_exploGunCounter ++; if ( m_exploGunCounter%2 == 0 ) { pos = m_particule[i].goal; m_terrain->MoveOnFloor(pos, true); speed.x = 0.0f; speed.z = 0.0f; speed.y = 0.0f; dim.x = Math::Rand()*6.0f+6.0f; dim.y = dim.x; duration = Math::Rand()*1.0f+1.0f; mass = 0.0f; CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f); pos.y += 1.0f; total = (int)(2.0f*m_engine->RetParticuleDensity()); for ( j=0 ; jExploObject(EXPLO_BURN, 0.0f, RetDecay(object->RetType())); m_exploGunCounter ++; if ( m_exploGunCounter%2 == 0 ) { pos = m_particule[i].pos; speed.x = 0.0f; speed.z = 0.0f; speed.y = 0.0f; dim.x = Math::Rand()*6.0f+6.0f; dim.y = dim.x; duration = Math::Rand()*1.0f+1.0f; mass = 0.0f; CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f); pos.y += 1.0f; total = (int)(2.0f*m_engine->RetParticuleDensity()); for ( j=0 ; j= 1.0f ) { DeleteRank(i); continue; } if ( m_particule[i].testTime >= 0.2f ) { m_particule[i].testTime = 0.0f; object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather); m_particule[i].goal = m_particule[i].pos; if ( object != 0 ) { if ( object->RetShieldRadius() > 0.0f ) // protected by shield? { CreateParticule(m_particule[i].pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f); if ( m_lastTimeGunDel > 0.2f ) { m_lastTimeGunDel = 0.0f; Play(SOUND_GUNDEL, m_particule[i].pos, 1.0f); } DeleteRank(i); continue; } else { if ( object->RetType() != OBJECT_HUMAN ) { Play(SOUND_TOUCH, m_particule[i].pos, 1.0f); } object->ExploObject(EXPLO_BOUM, 0.0f); // starts explosion } } } m_particule[i].angle = Math::Rand()*Math::PI*2.0f; m_particule[i].zoom = 1.0f-progress; ts.x = 0.125f; ts.y = 0.875f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIGUN3 ) // spider suicides? { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( m_particule[i].testTime >= 0.2f ) { m_particule[i].testTime = 0.0f; object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather); m_particule[i].goal = m_particule[i].pos; if ( object != 0 ) { if ( object->RetShieldRadius() > 0.0f ) { CreateParticule(m_particule[i].pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f); if ( m_lastTimeGunDel > 0.2f ) { m_lastTimeGunDel = 0.0f; Play(SOUND_GUNDEL, m_particule[i].pos, 1.0f); } DeleteRank(i); continue; } else { object->ExploObject(EXPLO_BURN, 1.0f); // starts explosion } } } //? ts.x = 0.875f; //? ts.y = 0.750f; ts.x = 0.500f; ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIGUN4 ) // orgaball shot? { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( m_particule[i].testTime >= 0.1f ) { m_particule[i].testTime = 0.0f; if ( m_terrain->RetFloorHeight(m_particule[i].pos, true) < -2.0f ) { m_exploGunCounter ++; if ( m_exploGunCounter%2 == 0 ) { pos = m_particule[i].goal; m_terrain->MoveOnFloor(pos, true); speed.x = 0.0f; speed.z = 0.0f; speed.y = 0.0f; dim.x = Math::Rand()*4.0f+2.0f; dim.y = dim.x; duration = Math::Rand()*0.7f+0.7f; mass = 0.0f; CreateParticule(pos, speed, dim, PARTIEXPLOG2, duration, mass, 1.0f); } if ( m_exploGunCounter%4 == 0 ) { Play(SOUND_EXPLOg2, pos, 0.5f); } DeleteRank(i); continue; } object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather); m_particule[i].goal = m_particule[i].pos; if ( object != 0 ) { object->ExploObject(EXPLO_BOUM, 0.0f, RetDecay(object->RetType())); m_exploGunCounter ++; if ( m_exploGunCounter%2 == 0 ) { pos = m_particule[i].pos; speed.x = 0.0f; speed.z = 0.0f; speed.y = 0.0f; dim.x = Math::Rand()*4.0f+2.0f; dim.y = dim.x; duration = Math::Rand()*0.7f+0.7f; mass = 0.0f; CreateParticule(pos, speed, dim, PARTIEXPLOG2, duration, mass, 1.0f); } if ( m_exploGunCounter%4 == 0 ) { Play(SOUND_EXPLOg2, pos, 0.5f); } DeleteRank(i); continue; } } m_particule[i].angle = Math::Rand()*Math::PI*2.0f; m_particule[i].zoom = 1.0f-progress; ts.x = 0.125f; ts.y = 0.875f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIFLIC ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 0.1f+progress; m_particule[i].intensity = 1.0f-progress; ts.x = 0.00f; ts.y = 0.75f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTISHOW ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( progress < 0.5f ) m_particule[i].intensity = progress/0.5f; else m_particule[i].intensity = 2.0f-progress/0.5f; m_particule[i].zoom = 1.0f-progress*0.8f; m_particule[i].angle -= rTime*Math::PI*0.5f; ts.x = 0.50f; ts.y = 0.00f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTICHOC ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 0.1f+progress; m_particule[i].intensity = 1.0f-progress; ts.x = 0.50f; ts.y = 0.50f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIGFLAT ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 0.1f+progress; m_particule[i].intensity = 1.0f-progress; m_particule[i].angle -= rTime*Math::PI*2.0f; ts.x = 0.00f; ts.y = 0.50f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTILIMIT1 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f; m_particule[i].intensity = 1.0f; ts.x = 0.000f; ts.y = 0.125f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTILIMIT2 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f; m_particule[i].intensity = 1.0f; ts.x = 0.375f; ts.y = 0.125f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTILIMIT3 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f; m_particule[i].intensity = 1.0f; ts.x = 0.500f; ts.y = 0.125f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIFOG0 ) { m_particule[i].zoom = progress; m_particule[i].intensity = 0.3f+sinf(progress)*0.15f; m_particule[i].angle += rTime*0.05f; ts.x = 0.25f; ts.y = 0.75f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIFOG1 ) { m_particule[i].zoom = progress; m_particule[i].intensity = 0.3f+sinf(progress)*0.15f; m_particule[i].angle -= rTime*0.07f; ts.x = 0.25f; ts.y = 0.75f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIFOG2 ) { m_particule[i].zoom = progress; m_particule[i].intensity = 0.6f+sinf(progress)*0.15f; m_particule[i].angle += rTime*0.05f; ts.x = 0.75f; ts.y = 0.75f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIFOG3 ) { m_particule[i].zoom = progress; m_particule[i].intensity = 0.6f+sinf(progress)*0.15f; m_particule[i].angle -= rTime*0.07f; ts.x = 0.75f; ts.y = 0.75f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIFOG4 ) { m_particule[i].zoom = progress; m_particule[i].intensity = 0.5f+sinf(progress)*0.2f; m_particule[i].angle += rTime*0.05f; ts.x = 0.00f; ts.y = 0.25f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIFOG5 ) { m_particule[i].zoom = progress; m_particule[i].intensity = 0.5f+sinf(progress)*0.2f; m_particule[i].angle -= rTime*0.07f; ts.x = 0.00f; ts.y = 0.25f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIFOG6 ) { m_particule[i].zoom = progress; m_particule[i].intensity = 0.5f+sinf(progress)*0.2f; m_particule[i].angle += rTime*0.05f; ts.x = 0.50f; ts.y = 0.25f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIFOG7 ) { m_particule[i].zoom = progress; m_particule[i].intensity = 0.5f+sinf(progress)*0.2f; m_particule[i].angle -= rTime*0.07f; ts.x = 0.50f; ts.y = 0.25f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } // Decreases the intensity if the camera // is almost at the same height (fog was eye level). if ( m_particule[i].type >= PARTIFOG0 && m_particule[i].type <= PARTIFOG9 ) { h = 10.0f; if ( m_particule[i].pos.y >= eye.y && m_particule[i].pos.y < eye.y+h ) { m_particule[i].intensity *= (m_particule[i].pos.y-eye.y)/h; } if ( m_particule[i].pos.y > eye.y-h && m_particule[i].pos.y < eye.y ) { m_particule[i].intensity *= (eye.y-m_particule[i].pos.y)/h; } } if ( m_particule[i].type == PARTIEXPLOT || m_particule[i].type == PARTIEXPLOO ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f-progress/2.0f; m_particule[i].intensity = 1.0f-progress; if ( m_particule[i].type == PARTIEXPLOT ) ts.x = 0.750f; else ts.x = 0.875f; ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIEXPLOG1 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].intensity = 1.0f-progress; ts.x = 0.375f; ts.y = 0.000f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIEXPLOG2 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].intensity = 1.0f-progress; ts.x = 0.625f; ts.y = 0.000f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIFLAME ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f-progress/2.0f; if ( progress < 0.5f ) { m_particule[i].intensity = progress/0.5f; } else { m_particule[i].intensity = 2.0f-progress/0.5f; } ts.x = 0.750f; ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIBUBBLE ) { if ( progress >= 1.0f || m_particule[i].pos.y >= m_water->RetLevel() ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f-progress/2.0f; m_particule[i].intensity = 1.0f-progress; ts.x = 0.250f; ts.y = 0.875f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTISMOKE1 || m_particule[i].type == PARTISMOKE2 || m_particule[i].type == PARTISMOKE3 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( progress < 0.25f ) { m_particule[i].zoom = progress/0.25f; } else { m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f; } ts.x = 0.500f+0.125f*(m_particule[i].type-PARTISMOKE1); ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIBLOOD ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].intensity = 1.0f-progress; ts.x = 0.750f+(rand()%2)*0.125f; ts.y = 0.875f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIBLOODM ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].intensity = 1.0f-progress; ts.x = 0.875f; ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIVIRUS1 || m_particule[i].type == PARTIVIRUS2 || m_particule[i].type == PARTIVIRUS3 || m_particule[i].type == PARTIVIRUS4 || m_particule[i].type == PARTIVIRUS5 || m_particule[i].type == PARTIVIRUS6 || m_particule[i].type == PARTIVIRUS7 || m_particule[i].type == PARTIVIRUS8 || m_particule[i].type == PARTIVIRUS9 || m_particule[i].type == PARTIVIRUS10 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( progress < 0.25f ) { m_particule[i].zoom = progress/0.25f; } else { m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f; } m_particule[i].angle += rTime*Math::PI*1.0f; if ( m_particule[i].type == PARTIVIRUS1 ) // A ? { ts.x = 0.0f/256.0f; ts.y = 19.0f/256.0f; ti.x = 10.0f/256.0f; ti.y = 30.0f/256.0f; } if ( m_particule[i].type == PARTIVIRUS2 ) // C ? { ts.x = 19.0f/256.0f; ts.y = 19.0f/256.0f; ti.x = 28.0f/256.0f; ti.y = 30.0f/256.0f; } if ( m_particule[i].type == PARTIVIRUS3 ) // E ? { ts.x = 36.0f/256.0f; ts.y = 19.0f/256.0f; ti.x = 45.0f/256.0f; ti.y = 30.0f/256.0f; } if ( m_particule[i].type == PARTIVIRUS4 ) // N ? { ts.x = 110.0f/256.0f; ts.y = 19.0f/256.0f; ti.x = 120.0f/256.0f; ti.y = 30.0f/256.0f; } if ( m_particule[i].type == PARTIVIRUS5 ) // R ? { ts.x = 148.0f/256.0f; ts.y = 19.0f/256.0f; ti.x = 158.0f/256.0f; ti.y = 30.0f/256.0f; } if ( m_particule[i].type == PARTIVIRUS6 ) // T ? { ts.x = 166.0f/256.0f; ts.y = 19.0f/256.0f; ti.x = 175.0f/256.0f; ti.y = 30.0f/256.0f; } if ( m_particule[i].type == PARTIVIRUS7 ) // 0 ? { ts.x = 90.0f/256.0f; ts.y = 2.0f/256.0f; ti.x = 98.0f/256.0f; ti.y = 13.0f/256.0f; } if ( m_particule[i].type == PARTIVIRUS8 ) // 2 ? { ts.x = 103.0f/256.0f; ts.y = 2.0f/256.0f; ti.x = 111.0f/256.0f; ti.y = 13.0f/256.0f; } if ( m_particule[i].type == PARTIVIRUS9 ) // 5 ? { ts.x = 125.0f/256.0f; ts.y = 2.0f/256.0f; ti.x = 132.0f/256.0f; ti.y = 13.0f/256.0f; } if ( m_particule[i].type == PARTIVIRUS10 ) // 9 ? { ts.x = 153.0f/256.0f; ts.y = 2.0f/256.0f; ti.x = 161.0f/256.0f; ti.y = 13.0f/256.0f; } } if ( m_particule[i].type == PARTIBLUE ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f-progress; ts.x = 0.625f; ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIROOT ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( progress < 0.25f ) { m_particule[i].zoom = progress/0.25f; } else { m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f; } ts.x = 0.000f; ts.y = 0.000f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIRECOVER ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( progress < 0.25f ) { m_particule[i].zoom = progress/0.25f; } else { m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f; } ts.x = 0.875f; ts.y = 0.000f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIEJECT ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f+powf(progress, 2.0f)*5.0f; m_particule[i].intensity = 1.0f-progress; ts.x = 0.625f; ts.y = 0.875f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTISCRAPS ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f-progress; ts.x = 0.625f; ts.y = 0.875f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIFRAG ) { m_particule[i].angle += rTime*Math::PI*0.5f; ts.x = 0.0f; ts.y = 0.0f; ti.x = 0.0f; ti.y = 0.0f; } if ( m_particule[i].type == PARTIPART ) { ts.x = 0.0f; ts.y = 0.0f; ti.x = 0.0f; ti.y = 0.0f; } if ( m_particule[i].type == PARTIQUEUE ) { if ( m_particule[i].testTime >= 0.05f ) { m_particule[i].testTime = 0.0f; Math::Vector pos, speed; Math::Point dim; pos = m_particule[i].pos; //? speed = -m_particule[i].speed*0.5f; speed = Math::Vector(0.0f, 0.0f, 0.0f); dim.x = 1.0f*(Math::Rand()*0.8f+0.6f); dim.y = dim.x; CreateParticule(pos, speed, dim, PARTIGAS, 0.5f); } ts.x = 0.375f; ts.y = 0.750f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIORGANIC1 ) { if ( progress >= 1.0f ) { DeleteRank(i); pos = m_particule[i].pos; dim.x = m_particule[i].dim.x/4.0f; dim.y = dim.x; duration = m_particule[i].duration; mass = m_particule[i].mass; total = (int)(10.0f*m_engine->RetParticuleDensity()); for ( i=0 ; iRetParticuleDensity()); for ( i=0 ; i= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration); ts.x = 0.125f; ts.y = 0.875f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIGLINT ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( progress > 0.5f ) { //? m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration/2.0f); m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f; } m_particule[i].angle = m_particule[i].time*Math::PI; ts.x = 0.75f; ts.y = 0.25f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIGLINTb ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( progress > 0.5f ) { m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f; } m_particule[i].angle = m_particule[i].time*Math::PI; ts.x = 0.75f; ts.y = 0.50f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIGLINTr ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( progress > 0.5f ) { m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f; } m_particule[i].angle = m_particule[i].time*Math::PI; ts.x = 0.75f; ts.y = 0.00f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type >= PARTILENS1 && m_particule[i].type <= PARTILENS4 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( progress < 0.5f ) { m_particule[i].zoom = progress*2.0f; } else { m_particule[i].intensity = 1.0f-(progress-0.5f)*2.0f; } //? m_particule[i].angle = m_particule[i].time*Math::PI; ts.x = 0.25f*(m_particule[i].type-PARTILENS1); ts.y = 0.25f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTICONTROL ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( progress < 0.3f ) { m_particule[i].zoom = progress/0.3f; } else { m_particule[i].zoom = 1.0f; m_particule[i].intensity = 1.0f-(progress-0.3f)/0.7f; } ts.x = 0.00f; ts.y = 0.00f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIGUNDEL ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( progress > 0.5f ) { m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration/2.0f); } m_particule[i].angle = m_particule[i].time*Math::PI; ts.x = 0.75f; ts.y = 0.50f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIQUARTZ ) { if ( progress >= 1.0f ) { m_particule[i].time = 0.0f; m_particule[i].duration = 0.5f+Math::Rand()*2.0f; m_particule[i].pos.x = m_particule[i].speed.x + (Math::Rand()-0.5f)*m_particule[i].mass; m_particule[i].pos.y = m_particule[i].speed.y + (Math::Rand()-0.5f)*m_particule[i].mass; m_particule[i].pos.z = m_particule[i].speed.z + (Math::Rand()-0.5f)*m_particule[i].mass; m_particule[i].dim.x = 0.5f+Math::Rand()*1.5f; m_particule[i].dim.y = m_particule[i].dim.x; progress = 0.0f; } if ( progress < 0.2f ) { m_particule[i].zoom = progress/0.2f; m_particule[i].intensity = 1.0f; } else { m_particule[i].zoom = 1.0f; m_particule[i].intensity = 1.0f-(progress-0.2f)/0.8f; } ts.x = 0.25f; ts.y = 0.25f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTITOTO ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f-progress; if ( progress < 0.15f ) { m_particule[i].intensity = progress/0.15f; } else { m_particule[i].intensity = 1.0f-(progress-0.15f)/0.85f; } m_particule[i].intensity *= 0.5f; ts.x = 0.25f; ts.y = 0.50f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIERROR ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = progress*1.0f; m_particule[i].intensity = 1.0f-progress; ts.x = 0.500f; ts.y = 0.875f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIWARNING ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = progress*1.0f; m_particule[i].intensity = 1.0f-progress; ts.x = 0.875f; ts.y = 0.875f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIINFO ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = progress*1.0f; m_particule[i].intensity = 1.0f-progress; ts.x = 0.750f; ts.y = 0.875f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTISELY ) { ts.x = 0.75f; ts.y = 0.25f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTISELR ) { ts.x = 0.75f; ts.y = 0.00f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTISPHERE0 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = progress*m_particule[i].dim.x; //? m_particule[i].intensity = 1.0f-progress; if ( progress < 0.65f ) { m_particule[i].intensity = progress/0.65f; } else { m_particule[i].intensity = 1.0f-(progress-0.65f)/0.35f; } m_particule[i].intensity *= 0.5f; ts.x = 0.50f; ts.y = 0.75f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTISPHERE1 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( progress < 0.30f ) { m_particule[i].intensity = progress/0.30f; } else { m_particule[i].intensity = 1.0f-(progress-0.30f)/0.70f; } m_particule[i].zoom = progress*m_particule[i].dim.x; m_particule[i].angle = m_particule[i].time*Math::PI*2.0f; ts.x = 0.000f; ts.y = 0.000f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTISPHERE2 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( progress < 0.20f ) { m_particule[i].intensity = 1.0f; } else { m_particule[i].intensity = 1.0f-(progress-0.20f)/0.80f; } m_particule[i].zoom = progress*m_particule[i].dim.x; m_particule[i].angle = m_particule[i].time*Math::PI*2.0f; ts.x = 0.125f; ts.y = 0.000f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTISPHERE3 ) { if ( m_particule[i].phase == PARPHEND && progress >= 1.0f ) { DeleteRank(i); continue; } if ( m_particule[i].phase == PARPHSTART ) { m_particule[i].intensity = progress; if ( m_particule[i].intensity > 1.0f ) { m_particule[i].intensity = 1.0f; } } if ( m_particule[i].phase == PARPHEND ) { m_particule[i].intensity = 1.0f-progress; } m_particule[i].zoom = m_particule[i].dim.x; m_particule[i].angle = m_particule[i].time*Math::PI*0.2f; ts.x = 0.25f; ts.y = 0.75f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTISPHERE4 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = progress*m_particule[i].dim.x; if ( progress < 0.65f ) { m_particule[i].intensity = progress/0.65f; } else { m_particule[i].intensity = 1.0f-(progress-0.65f)/0.35f; } m_particule[i].intensity *= 0.5f; ts.x = 0.125f; ts.y = 0.000f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTISPHERE5 ) { m_particule[i].intensity = 0.7f+sinf(progress)*0.3f; m_particule[i].zoom = m_particule[i].dim.x*(1.0f+sinf(progress*0.7f)*0.01f); m_particule[i].angle = m_particule[i].time*Math::PI*0.2f; ts.x = 0.25f; ts.y = 0.50f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTISPHERE6 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = (1.0f-progress)*m_particule[i].dim.x; m_particule[i].intensity = progress*0.5f; ts.x = 0.125f; ts.y = 0.000f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIPLOUF0 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } m_particule[i].zoom = progress; #if 0 if ( progress <= 0.5f ) { m_particule[i].intensity = 1.0f; } else { m_particule[i].intensity = 1.0f-(progress-0.5f)/0.5f; } #else //? m_particule[i].intensity = 1.0f; m_particule[i].intensity = 1.0f-progress; #endif ts.x = 0.50f; ts.y = 0.50f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIDROP ) { if ( progress >= 1.0f || m_particule[i].pos.y < m_water->RetLevel() ) { DeleteRank(i); continue; } m_particule[i].zoom = 1.0f-progress; m_particule[i].intensity = 1.0f-progress; ts.x = 0.750f; ts.y = 0.500f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIWATER ) { if ( progress >= 1.0f || m_particule[i].pos.y < m_water->RetLevel() ) { DeleteRank(i); continue; } m_particule[i].intensity = 1.0f-progress; ts.x = 0.125f; ts.y = 0.125f; ti.x = ts.x+0.125f; ti.y = ts.y+0.125f; } if ( m_particule[i].type == PARTIRAY1 ) // rayon tour ? { if ( progress >= 1.0f ) { DeleteRank(i); continue; } if ( m_particule[i].testTime >= 0.2f ) { m_particule[i].testTime = 0.0f; object = SearchObjectRay(m_particule[i].pos, m_particule[i].goal, m_particule[i].type, m_particule[i].objFather); if ( object != 0 ) { object->ExploObject(EXPLO_BOUM, 0.0f); } } ts.x = 0.00f; ts.y = 0.00f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } if ( m_particule[i].type == PARTIRAY2 || m_particule[i].type == PARTIRAY3 ) { if ( progress >= 1.0f ) { DeleteRank(i); continue; } ts.x = 0.00f; ts.y = 0.25f; ti.x = ts.x+0.25f; ti.y = ts.y+0.25f; } dp = (1.0f/256.0f)/2.0f; m_particule[i].texSup.x = ts.x+dp; m_particule[i].texSup.y = ts.y+dp; m_particule[i].texInf.x = ti.x-dp; m_particule[i].texInf.y = ti.y-dp; m_particule[i].time += rTime; m_particule[i].testTime += rTime; } } // Moves a drag. // Returns true if the drag is finished. bool CParticule::TrackMove(int i, Math::Vector pos, float progress) { Math::Vector last; int h, hh; if ( i < 0 || i >= MAXTRACK ) return true; if ( m_track[i].bUsed == false ) return true; if ( progress < 1.0f ) // particle exists? { h = m_track[i].head; if ( m_track[i].used == 1 || m_track[i].last+m_track[i].step <= progress ) { m_track[i].last = progress; last = m_track[i].pos[h]; h ++; if ( h == MAXTRACKLEN ) h = 0; if ( m_track[i].used < MAXTRACKLEN ) m_track[i].used ++; } else { hh = h-1; if ( hh < 0 ) hh = MAXTRACKLEN-1; last = m_track[i].pos[hh]; } m_track[i].pos[h] = pos; m_track[i].len[h] = Math::Distance(pos, last); m_track[i].head = h; //? m_track[i].intensity = 1.0f; m_track[i].intensity = 1.0f-progress; } else // mort lente de la tra�n�e ? { //? m_track[i].intensity = 1.0f-(progress-1.0f)/(m_track[i].step*MAXTRACKLEN); m_track[i].intensity = 0.0f; } return (m_track[i].intensity <= 0.0f); } // Draws a drag. void CParticule::TrackDraw(int i, ParticuleType type) { D3DVERTEX2 vertex[4]; // 2 triangles Math::Vector corner[4], p1, p2, p, n, eye; Math::Matrix matrix; Math::Point texInf, texSup, rot; float lTotal, f1, f2, a; int counter, h; // Calculates the total length memorized. lTotal = 0.0f; h = m_track[i].head; for ( counter=0 ; counterSetTransform(D3DTRANSFORMSTATE_WORLD, &mat); } if ( type == PARTITRACK1 ) // explosion technique? { texInf.x = 64.5f/256.0f; texInf.y = 21.0f/256.0f; texSup.x = 95.5f/256.0f; texSup.y = 22.0f/256.0f; // orange } if ( type == PARTITRACK2 ) // blue spray? { texInf.x = 64.5f/256.0f; texInf.y = 13.0f/256.0f; texSup.x = 95.5f/256.0f; texSup.y = 14.0f/256.0f; // blue } if ( type == PARTITRACK3 ) // spider? { texInf.x = 64.5f/256.0f; texInf.y = 5.0f/256.0f; texSup.x = 95.5f/256.0f; texSup.y = 6.0f/256.0f; // brown } if ( type == PARTITRACK4 ) // insect explosion? { texInf.x = 64.5f/256.0f; texInf.y = 9.0f/256.0f; texSup.x = 95.5f/256.0f; texSup.y = 10.0f/256.0f; // dark green } if ( type == PARTITRACK5 ) // derrick? { texInf.x = 64.5f/256.0f; texInf.y = 29.0f/256.0f; texSup.x = 95.5f/256.0f; texSup.y = 30.0f/256.0f; // dark brown } if ( type == PARTITRACK6 ) // reset in/out? { texInf.x = 64.5f/256.0f; texInf.y = 17.0f/256.0f; texSup.x = 95.5f/256.0f; texSup.y = 18.0f/256.0f; // cyan } if ( type == PARTITRACK7 ) // win-1? { texInf.x = 64.5f/256.0f; texInf.y = 41.0f/256.0f; texSup.x = 95.5f/256.0f; texSup.y = 42.0f/256.0f; // orange } if ( type == PARTITRACK8 ) // win-2? { texInf.x = 64.5f/256.0f; texInf.y = 45.0f/256.0f; texSup.x = 95.5f/256.0f; texSup.y = 46.0f/256.0f; // yellow } if ( type == PARTITRACK9 ) // win-3? { texInf.x = 64.5f/256.0f; texInf.y = 49.0f/256.0f; texSup.x = 95.5f/256.0f; texSup.y = 50.0f/256.0f; // red } if ( type == PARTITRACK10 ) // win-4? { texInf.x = 64.5f/256.0f; texInf.y = 53.0f/256.0f; texSup.x = 95.5f/256.0f; texSup.y = 54.0f/256.0f; // violet } if ( type == PARTITRACK11 ) // phazer shot? { texInf.x = 64.5f/256.0f; texInf.y = 21.0f/256.0f; texSup.x = 95.5f/256.0f; texSup.y = 22.0f/256.0f; // orange } if ( type == PARTITRACK12 ) // drag reactor? { texInf.x = 64.5f/256.0f; texInf.y = 21.0f/256.0f; texSup.x = 95.5f/256.0f; texSup.y = 22.0f/256.0f; // orange } h = m_track[i].head; p1 = m_track[i].pos[h]; f1 = m_track[i].intensity; eye = m_engine->RetEyePt(); a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z); for ( counter=0 ; counterDrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL); m_engine->AddStatisticTriangle(2); if ( f2 < 0.0f ) break; f1 = f2; p1 = p2; } } // Draws a triangular particle. void CParticule::DrawParticuleTriangle(int i) { CObject* object; Math::Matrix matrix; Math::Vector eye, pos, angle; if ( m_particule[i].zoom == 0.0f ) return; eye = m_engine->RetEyePt(); pos = m_particule[i].pos; object = m_particule[i].objLink; if ( object != 0 ) { pos += object->RetPosition(0); } angle.x = -Math::RotateAngle(Math::DistanceProjected(pos, eye), pos.y-eye.y); angle.y = Math::RotateAngle(pos.z-eye.z, pos.x-eye.x); angle.z = m_particule[i].angle; Math::LoadRotationXZYMatrix(matrix, angle); matrix.Set(1, 4, pos.x); matrix.Set(2, 4, pos.y); matrix.Set(3, 4, pos.z); { D3DMATRIX mat = MAT_TO_D3DMAT(matrix); m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); } m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX2, m_triangle[i].triangle, 3, NULL); m_engine->AddStatisticTriangle(1); } // Draw a normal particle. void CParticule::DrawParticuleNorm(int i) { CObject* object; D3DVERTEX2 vertex[4]; // 2 triangles Math::Matrix matrix; Math::Vector corner[4], eye, pos, n, angle; Math::Point dim; float zoom; zoom = m_particule[i].zoom; if ( !m_engine->RetStateColor() && m_particule[i].intensity < 0.5f ) { zoom *= m_particule[i].intensity/0.5f; } if ( zoom == 0.0f ) return; if ( m_particule[i].intensity == 0.0f ) return; if ( m_particule[i].sheet == SH_INTERFACE ) { pos = m_particule[i].pos; n = Math::Vector(0.0f, 0.0f, -1.0f); dim.x = m_particule[i].dim.x * zoom; dim.y = m_particule[i].dim.y * zoom; corner[0].x = pos.x+dim.x; corner[0].y = pos.y+dim.y; corner[0].z = 0.0f; corner[1].x = pos.x-dim.x; corner[1].y = pos.y+dim.y; corner[1].z = 0.0f; corner[2].x = pos.x+dim.x; corner[2].y = pos.y-dim.y; corner[2].z = 0.0f; corner[3].x = pos.x-dim.x; corner[3].y = pos.y-dim.y; corner[3].z = 0.0f; vertex[0] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y); vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y); vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y); vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y); m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL); m_engine->AddStatisticTriangle(2); } else { eye = m_engine->RetEyePt(); pos = m_particule[i].pos; object = m_particule[i].objLink; if ( object != 0 ) { pos += object->RetPosition(0); } angle.x = -Math::RotateAngle(Math::DistanceProjected(pos, eye), pos.y-eye.y); angle.y = Math::RotateAngle(pos.z-eye.z, pos.x-eye.x); angle.z = m_particule[i].angle; Math::LoadRotationXZYMatrix(matrix, angle); matrix.Set(1, 4, pos.x); matrix.Set(2, 4, pos.y); matrix.Set(3, 4, pos.z); { D3DMATRIX mat = MAT_TO_D3DMAT(matrix); m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); } n = Math::Vector(0.0f, 0.0f, -1.0f); dim.x = m_particule[i].dim.x * zoom; dim.y = m_particule[i].dim.y * zoom; corner[0].x = dim.x; corner[0].y = dim.y; corner[0].z = 0.0f; corner[1].x = -dim.x; corner[1].y = dim.y; corner[1].z = 0.0f; corner[2].x = dim.x; corner[2].y = -dim.y; corner[2].z = 0.0f; corner[3].x = -dim.x; corner[3].y = -dim.y; corner[3].z = 0.0f; vertex[0] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y); vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y); vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y); vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y); m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL); m_engine->AddStatisticTriangle(2); } } // Draw a particle flat (horizontal). void CParticule::DrawParticuleFlat(int i) { CObject* object; D3DVERTEX2 vertex[4]; // 2 triangles Math::Matrix matrix; Math::Vector corner[4], pos, n, angle, eye; Math::Point dim; if ( m_particule[i].zoom == 0.0f ) return; if ( m_particule[i].intensity == 0.0f ) return; pos = m_particule[i].pos; object = m_particule[i].objLink; if ( object != 0 ) { pos += object->RetPosition(0); } angle.x = Math::PI/2.0f; angle.y = 0.0f; angle.z = m_particule[i].angle; #if 0 if ( m_engine->RetRankView() == 1 ) // underwater? { angle.x = -Math::PI/2.0f; pos.y -= 1.0f; } #else if ( m_engine->RetRankView() == 1 ) // underwater? { pos.y -= 1.0f; } eye = m_engine->RetEyePt(); if ( pos.y > eye.y ) // seen from below? { angle.x = -Math::PI/2.0f; } #endif Math::LoadRotationXZYMatrix(matrix, angle); matrix.Set(1, 4, pos.x); matrix.Set(2, 4, pos.y); matrix.Set(3, 4, pos.z); { D3DMATRIX mat = MAT_TO_D3DMAT(matrix); m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); } n = Math::Vector(0.0f, 0.0f, -1.0f); dim.x = m_particule[i].dim.x * m_particule[i].zoom; dim.y = m_particule[i].dim.y * m_particule[i].zoom; corner[0].x = dim.x; corner[0].y = dim.y; corner[0].z = 0.0f; corner[1].x = -dim.x; corner[1].y = dim.y; corner[1].z = 0.0f; corner[2].x = dim.x; corner[2].y = -dim.y; corner[2].z = 0.0f; corner[3].x = -dim.x; corner[3].y = -dim.y; corner[3].z = 0.0f; vertex[0] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y); vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y); vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y); vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y); m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL); m_engine->AddStatisticTriangle(2); } // Draw a particle to a flat sheet of fog. void CParticule::DrawParticuleFog(int i) { CObject* object; D3DVERTEX2 vertex[4]; // 2 triangles Math::Matrix matrix; Math::Vector corner[4], pos, n, angle, eye; Math::Point dim, zoom; if ( !m_engine->RetFog() ) return; if ( m_particule[i].intensity == 0.0f ) return; pos = m_particule[i].pos; dim.x = m_particule[i].dim.x; dim.y = m_particule[i].dim.y; if ( m_particule[i].type == PARTIFOG0 || m_particule[i].type == PARTIFOG2 || m_particule[i].type == PARTIFOG4 || m_particule[i].type == PARTIFOG6 ) { //? pos.x += sinf(m_particule[i].zoom*1.2f)*dim.x*0.1f; //? pos.y += cosf(m_particule[i].zoom*1.5f)*dim.y*0.1f; zoom.x = 1.0f+sinf(m_particule[i].zoom*2.0f)/6.0f; zoom.y = 1.0f+cosf(m_particule[i].zoom*2.7f)/6.0f; } if ( m_particule[i].type == PARTIFOG1 || m_particule[i].type == PARTIFOG3 || m_particule[i].type == PARTIFOG5 || m_particule[i].type == PARTIFOG7 ) { //? pos.x += sinf(m_particule[i].zoom*1.0f)*dim.x*0.1f; //? pos.y += cosf(m_particule[i].zoom*1.3f)*dim.y*0.1f; zoom.x = 1.0f+sinf(m_particule[i].zoom*3.0f)/6.0f; zoom.y = 1.0f+cosf(m_particule[i].zoom*3.7f)/6.0f; } dim.x *= zoom.x; dim.y *= zoom.y; object = m_particule[i].objLink; if ( object != 0 ) { pos += object->RetPosition(0); } angle.x = Math::PI/2.0f; angle.y = 0.0f; angle.z = m_particule[i].angle; if ( m_engine->RetRankView() == 1 ) // underwater? { pos.y -= 1.0f; } eye = m_engine->RetEyePt(); if ( pos.y > eye.y ) // seen from below? { angle.x = -Math::PI/2.0f; } Math::LoadRotationXZYMatrix(matrix, angle); matrix.Set(1, 4, pos.x); matrix.Set(2, 4, pos.y); matrix.Set(3, 4, pos.z); { D3DMATRIX mat = MAT_TO_D3DMAT(matrix); m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); } n = Math::Vector(0.0f, 0.0f, -1.0f); corner[0].x = dim.x; corner[0].y = dim.y; corner[0].z = 0.0f; corner[1].x = -dim.x; corner[1].y = dim.y; corner[1].z = 0.0f; corner[2].x = dim.x; corner[2].y = -dim.y; corner[2].z = 0.0f; corner[3].x = -dim.x; corner[3].y = -dim.y; corner[3].z = 0.0f; vertex[0] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y); vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y); vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y); vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y); m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL); m_engine->AddStatisticTriangle(2); } // Draw a particle in the form of radius. void CParticule::DrawParticuleRay(int i) { CObject* object; D3DVERTEX2 vertex[4]; // 2 triangles Math::Matrix matrix; Math::Vector corner[4], eye, pos, goal, n, angle, proj; Math::Point dim, texInf, texSup; bool bLeft; float a, len, adv, prop, vario1, vario2; int r, rank, step, first, last; if ( m_particule[i].zoom == 0.0f ) return; if ( m_particule[i].intensity == 0.0f ) return; eye = m_engine->RetEyePt(); pos = m_particule[i].pos; goal = m_particule[i].goal; object = m_particule[i].objLink; if ( object != 0 ) { pos += object->RetPosition(0); } a = Math::RotateAngle(Math::Point(pos.x,pos.z), Math::Point(goal.x,goal.z), Math::Point(eye.x,eye.z)); bLeft = (a < Math::PI); proj = Math::Projection(pos, goal, eye); angle.x = -Math::RotateAngle(Math::DistanceProjected(proj, eye), proj.y-eye.y); angle.y = Math::RotateAngle(pos.z-goal.z, pos.x-goal.x)+Math::PI/2.0f; angle.z = -Math::RotateAngle(Math::DistanceProjected(pos, goal), pos.y-goal.y); if ( bLeft ) angle.x = -angle.x; Math::LoadRotationZXYMatrix(matrix, angle); matrix.Set(1, 4, pos.x); matrix.Set(2, 4, pos.y); matrix.Set(3, 4, pos.z); { D3DMATRIX mat = MAT_TO_D3DMAT(matrix); m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); } n = Math::Vector(0.0f, 0.0f, bLeft?1.0f:-1.0f); dim.x = m_particule[i].dim.x * m_particule[i].zoom; dim.y = m_particule[i].dim.y * m_particule[i].zoom; if ( bLeft ) dim.y = -dim.y; len = Math::Distance(pos, goal); adv = 0.0f; step = (int)(len/(dim.x*2.0f))+1; if ( step == 1 ) { vario1 = 1.0f; vario2 = 1.0f; } else { vario1 = 0.0f; vario2 = 2.0f; } if ( m_particule[i].type == PARTIRAY2 ) { first = 0; last = step; vario1 = 0.0f; vario2 = 0.0f; } else if ( m_particule[i].type == PARTIRAY3 ) { if ( m_particule[i].time < m_particule[i].duration*0.40f ) { prop = m_particule[i].time / (m_particule[i].duration*0.40f); first = 0; last = (int)(prop*step); } else if ( m_particule[i].time < m_particule[i].duration*0.60f ) { first = 0; last = step; } else { prop = (m_particule[i].time-m_particule[i].duration*0.60f) / (m_particule[i].duration*0.40f); first = (int)(prop*step); last = step; } } else { if ( m_particule[i].time < m_particule[i].duration*0.50f ) { prop = m_particule[i].time / (m_particule[i].duration*0.50f); first = 0; last = (int)(prop*step); } else if ( m_particule[i].time < m_particule[i].duration*0.75f ) { first = 0; last = step; } else { prop = (m_particule[i].time-m_particule[i].duration*0.75f) / (m_particule[i].duration*0.25f); first = (int)(prop*step); last = step; } } corner[0].x = adv; corner[2].x = adv; corner[0].y = dim.y; corner[2].y = -dim.y; corner[0].z = (Math::Rand()-0.5f)*vario1; corner[1].z = (Math::Rand()-0.5f)*vario1; corner[2].z = (Math::Rand()-0.5f)*vario1; corner[3].z = (Math::Rand()-0.5f)*vario1; for ( rank=0 ; rank= first && rank <= last ) { #if 1 texInf = m_particule[i].texInf; texSup = m_particule[i].texSup; r = rand()%16; texInf.x += 0.25f*(r/4); texSup.x += 0.25f*(r/4); if ( r%2 < 1 && adv > 0.0f && m_particule[i].type != PARTIRAY1 ) { Math::Swap(texInf.x, texSup.x); } if ( r%4 < 2 ) { Math::Swap(texInf.y, texSup.y); } #else texInf.x = Math::Mod(texInf.x+0.25f, 1.0f); texSup.x = Math::Mod(texSup.x+0.25f, 1.0f); #endif vertex[0] = D3DVERTEX2(corner[1], n, texSup.x, texSup.y); vertex[1] = D3DVERTEX2(corner[0], n, texInf.x, texSup.y); vertex[2] = D3DVERTEX2(corner[3], n, texSup.x, texInf.y); vertex[3] = D3DVERTEX2(corner[2], n, texInf.x, texInf.y); m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL); m_engine->AddStatisticTriangle(2); } adv += dim.x*2.0f; } } // Draws a spherical particle. void CParticule::DrawParticuleSphere(int i) { D3DVERTEX2 vertex[2*16*(16+1)]; // triangles Math::Matrix matrix, rot; Math::Vector angle, v0, v1; Math::Point ts, ti; float zoom, deltaRingAngle, deltaSegAngle; float r0,r1, tu0,tv0, tu1,tv1; int j, ring, seg, numRings, numSegments; zoom = m_particule[i].zoom; #if 0 if ( !m_engine->RetStateColor() && m_particule[i].intensity < 0.5f ) { zoom *= m_particule[i].intensity/0.5f; } #endif if ( zoom == 0.0f ) return; m_engine->SetState(D3DSTATETTb|D3DSTATE2FACE|D3DSTATEWRAP, RetColor(m_particule[i].intensity)); matrix.LoadIdentity(); matrix.Set(1, 1, zoom); matrix.Set(2, 2, zoom); matrix.Set(3, 3, zoom); matrix.Set(1, 4, m_particule[i].pos.x); matrix.Set(2, 4, m_particule[i].pos.y); matrix.Set(3, 4, m_particule[i].pos.z); if ( m_particule[i].angle != 0.0f ) { angle.x = m_particule[i].angle*0.4f; angle.y = m_particule[i].angle*1.0f; angle.z = m_particule[i].angle*0.7f; Math::LoadRotationZXYMatrix(rot, angle); matrix = Math::MultiplyMatrices(rot, matrix); } { D3DMATRIX mat = MAT_TO_D3DMAT(matrix); m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); } ts.x = m_particule[i].texSup.x; ts.y = m_particule[i].texSup.y; ti.x = m_particule[i].texInf.x; ti.y = m_particule[i].texInf.y; // Choose a tesselation level. if ( m_particule[i].type == PARTISPHERE3 || m_particule[i].type == PARTISPHERE5 ) { numRings = 16; numSegments = 16; } else { numRings = 8; numSegments = 10; } // Establish constants used in sphere generation. deltaRingAngle = Math::PI/numRings; deltaSegAngle = 2.0f*Math::PI/numSegments; // Generate the group of rings for the sphere. j = 0; for ( ring=0 ; ringDrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, j, NULL); m_engine->AddStatisticTriangle(j); m_engine->SetState(D3DSTATETTb, RetColor(m_particule[i].intensity)); } // Returns the height depending on the progress. float ProgressCylinder(float progress) { if ( progress < 0.5f ) { return 1.0f - (powf(1.0f-progress*2.0f, 2.0f)); } else { return 1.0f - (powf(progress*2.0f-1.0f, 2.0f)); } } // Draws a cylindrical particle. void CParticule::DrawParticuleCylinder(int i) { D3DVERTEX2 vertex[2*5*(10+1)]; // triangles Math::Matrix matrix, rot; Math::Vector angle, v0, v1; Math::Point ts, ti; float progress, zoom, diam, deltaSegAngle, h[6], d[6]; float r0,r1, tu0,tv0, tu1,tv1, p1, p2, pp; int j, ring, seg, numRings, numSegments; progress = m_particule[i].zoom; zoom = m_particule[i].dim.x; diam = m_particule[i].dim.y; if ( progress >= 1.0f || zoom == 0.0f ) return; m_engine->SetState(D3DSTATETTb|D3DSTATE2FACE|D3DSTATEWRAP, RetColor(m_particule[i].intensity)); matrix.LoadIdentity(); matrix.Set(1, 1, zoom); matrix.Set(2, 2, zoom); matrix.Set(3, 3, zoom); matrix.Set(1, 4, m_particule[i].pos.x); matrix.Set(2, 4, m_particule[i].pos.y); matrix.Set(3, 4, m_particule[i].pos.z); { D3DMATRIX mat = MAT_TO_D3DMAT(matrix); m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); } ts.x = m_particule[i].texSup.x; ts.y = m_particule[i].texSup.y; ti.x = m_particule[i].texInf.x; ti.y = m_particule[i].texInf.y; numRings = 5; numSegments = 10; deltaSegAngle = 2.0f*Math::PI/numSegments; if ( m_particule[i].type == PARTIPLOUF0 ) { #if 0 if ( progress <= 0.5f ) { p1 = progress/0.5f; // front p2 = 0.0f; // back } else { p1 = 1.0f; // front p2 = (progress-0.5f)/0.5f; // back ts.y += (ti.y-ts.y)*p2; } #else p1 = progress; // front p2 = powf(progress, 5.0f); // back #endif for ( ring=0 ; ring<=numRings ; ring++ ) { pp = p2+(p1-p2)*((float)ring/numRings); d[ring] = diam/zoom+pp*2.0f; h[ring] = ProgressCylinder(pp); } } j = 0; for ( ring=0 ; ringDrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, j, NULL); m_engine->AddStatisticTriangle(j); m_engine->SetState(D3DSTATETTb, RetColor(m_particule[i].intensity)); } // Draws a tire mark. void CParticule::DrawParticuleWheel(int i) { Math::Vector pos[4], center; D3DVERTEX2 vertex[4]; // 2 triangles Math::Vector n; Math::Point ts, ti; float dist, dp; dist = Math::DistanceProjected(m_engine->RetEyePt(), m_wheelTrace[i].pos[0]); if ( dist > 300.0f ) return; pos[0] = m_wheelTrace[i].pos[0]; pos[1] = m_wheelTrace[i].pos[1]; pos[2] = m_wheelTrace[i].pos[2]; pos[3] = m_wheelTrace[i].pos[3]; if ( m_wheelTrace[i].type == PARTITRACE0 ) // white ground track? { ts.x = 8.0f/256.0f; ts.y = 224.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE1 ) // black ground track? { ts.x = 0.0f/256.0f; ts.y = 224.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE2 ) // gray ground track? { ts.x = 0.0f/256.0f; ts.y = 232.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE3 ) // light gray ground track? { ts.x = 8.0f/256.0f; ts.y = 232.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE4 ) // red ground track? { ts.x = 32.0f/256.0f; ts.y = 224.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE5 ) // pink ground track? { ts.x = 40.0f/256.0f; ts.y = 224.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE6 ) // violet ground track? { ts.x = 32.0f/256.0f; ts.y = 232.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE7 ) // orange ground track? { ts.x = 40.0f/256.0f; ts.y = 232.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE8 ) // yellow ground track? { ts.x = 16.0f/256.0f; ts.y = 224.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE9 ) // beige ground track? { ts.x = 24.0f/256.0f; ts.y = 224.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE10 ) // brown ground track? { ts.x = 16.0f/256.0f; ts.y = 232.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE11 ) // skin ground track? { ts.x = 24.0f/256.0f; ts.y = 232.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE12 ) // green ground track? { ts.x = 48.0f/256.0f; ts.y = 224.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE13 ) // light green ground track? { ts.x = 56.0f/256.0f; ts.y = 224.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE14 ) // blue ground track? { ts.x = 48.0f/256.0f; ts.y = 232.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE15 ) // light blue ground track? { ts.x = 56.0f/256.0f; ts.y = 232.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE16 ) // black arrow ground track? { ts.x = 160.0f/256.0f; ts.y = 224.0f/256.0f; } else if ( m_wheelTrace[i].type == PARTITRACE17 ) // red arrow ground track? { ts.x = 176.0f/256.0f; ts.y = 224.0f/256.0f; } else { return; } if ( m_wheelTrace[i].type == PARTITRACE16 || m_wheelTrace[i].type == PARTITRACE17 ) { ti.x = ts.x+16.0f/256.0f; ti.y = ts.y+16.0f/256.0f; } else { ti.x = ts.x+8.0f/256.0f; ti.y = ts.y+8.0f/256.0f; } dp = (1.0f/256.0f)/2.0f; ts.x = ts.x+dp; ts.y = ts.y+dp; ti.x = ti.x-dp; ti.y = ti.y-dp; n = Math::Vector(0.0f, 1.0f, 0.0f); vertex[0] = D3DVERTEX2(pos[0], n, ts.x, ts.y); vertex[1] = D3DVERTEX2(pos[1], n, ti.x, ts.y); vertex[2] = D3DVERTEX2(pos[2], n, ts.x, ti.y); vertex[3] = D3DVERTEX2(pos[3], n, ti.x, ti.y); m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL); m_engine->AddStatisticTriangle(2); } // Draws all the particles. void CParticule::DrawParticule(int sheet) { D3DMATERIAL7 mat; Math::Matrix matrix; bool bLoadTexture; char name[20]; int state, t, i, j, r; m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff); m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true); //? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false); m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false); // Draw the basic particles of triangles. if ( m_totalInterface[0][sheet] > 0 ) { for ( i=0 ; iSetTexture(m_triangle[i].texName1); m_engine->SetMaterial(m_triangle[i].material); m_engine->SetState(m_triangle[i].state); DrawParticuleTriangle(i); } } // Draw the particles was calculated based on edge. m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false); ZeroMemory( &mat, sizeof(D3DMATERIAL7) ); mat.diffuse.r = 1.0f; mat.diffuse.g = 1.0f; mat.diffuse.b = 1.0f; // white mat.ambient.r = 0.5f; mat.ambient.g = 0.5f; mat.ambient.b = 0.5f; m_engine->SetMaterial(mat); // Draw tire marks. if ( m_wheelTraceTotal > 0 && sheet == SH_WORLD ) { #if _POLISH m_engine->SetTexture("textp.tga"); #else m_engine->SetTexture("text.tga"); #endif m_engine->SetState(D3DSTATETTw); //? m_engine->SetState(D3DSTATENORMAL); matrix.LoadIdentity(); { D3DMATRIX mat = MAT_TO_D3DMAT(matrix); m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); } for ( i=0 ; i=1 ; t-- ) // black behind! { if ( m_totalInterface[t][sheet] == 0 ) continue; bLoadTexture = false; if ( t == 4 ) state = D3DSTATETTw; // text.tga else state = D3DSTATETTb; // effect[00..02].tga m_engine->SetState(state); for ( j=0 ; jSetTexture(name); bLoadTexture = true; } r = m_particule[i].trackRank; if ( r != -1 ) { m_engine->SetState(state); TrackDraw(r, m_particule[i].type); // draws the drag if ( !m_track[r].bDrawParticule ) continue; } m_engine->SetState(state, RetColor(m_particule[i].intensity)); if ( m_particule[i].bRay ) // ray? { DrawParticuleRay(i); } else if ( m_particule[i].type == PARTIFLIC || // circle in the water? m_particule[i].type == PARTISHOW || m_particule[i].type == PARTICHOC || m_particule[i].type == PARTIGFLAT ) { DrawParticuleFlat(i); } else if ( m_particule[i].type >= PARTIFOG0 && m_particule[i].type <= PARTIFOG9 ) { DrawParticuleFog(i); } else if ( m_particule[i].type >= PARTISPHERE0 && m_particule[i].type <= PARTISPHERE9 ) // sphere? { DrawParticuleSphere(i); } else if ( m_particule[i].type >= PARTIPLOUF0 && m_particule[i].type <= PARTIPLOUF4 ) // cylinder? { DrawParticuleCylinder(i); } else // normal? { DrawParticuleNorm(i); } } } //? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, true); m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true); } // Seeks if an object collided with a bullet. CObject* CParticule::SearchObjectGun(Math::Vector old, Math::Vector pos, ParticuleType type, CObject *father) { CObject *pObj, *pBest; Math::Vector box1, box2, oPos, p; ObjectType oType; bool bShield; float min, oRadius, dist, shieldRadius; int i, j; bool bHimself; if ( m_main->RetMovieLock() ) return 0; // current movie? bHimself = m_main->RetHimselfDamage(); min = 5.0f; if ( type == PARTIGUN2 ) min = 2.0f; // shooting insect? if ( type == PARTIGUN3 ) min = 3.0f; // suiciding spider? box1 = old; box2 = pos; if ( box1.x > box2.x ) Math::Swap(box1.x, box2.x); // box1 < box2 if ( box1.y > box2.y ) Math::Swap(box1.y, box2.y); if ( box1.z > box2.z ) Math::Swap(box1.z, box2.z); box1.x -= min; box1.y -= min; box1.z -= min; box2.x += min; box2.y += min; box2.z += min; pBest = 0; bShield = false; for ( i=0 ; i<1000000 ; i++ ) { pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); if ( pObj == 0 ) break; if ( !pObj->RetActif() ) continue; // inactive? if ( pObj == father ) continue; oType = pObj->RetType(); if ( oType == OBJECT_TOTO ) continue; if ( type == PARTIGUN1 ) // fireball shooting? { if ( oType == OBJECT_MOTHER ) continue; if ( bHimself ) // damage is oneself? { if ( !IsAlien(oType) && !IsSoft(oType) ) continue; } else // damage only to enemies? { if ( !IsAlien(oType) ) continue; } } else if ( type == PARTIGUN2 ) // shooting insect? { if ( !IsSoft(oType) ) continue; } else if ( type == PARTIGUN3 ) // suiciding spider? { if ( !IsSoft(oType) ) continue; } else if ( type == PARTIGUN4 ) // orgaball shooting? { if ( oType == OBJECT_MOTHER ) continue; if ( bHimself ) // damage is oneself? { if ( !IsAlien(oType) && !IsSoft(oType) ) continue; } else // damage only to enemies? { if ( !IsAlien(oType) ) continue; } } else if ( type == PARTITRACK11 ) // phazer shooting? { if ( bHimself ) // damage is oneself? { if ( !IsAlien(oType) && !IsSoft(oType) ) continue; } else // damage only to enemies? { if ( !IsAlien(oType) ) continue; } } else { continue; } oPos = pObj->RetPosition(0); if ( type == PARTIGUN2 || // shooting insect? type == PARTIGUN3 ) // suiciding spider? { // Test if the ball is entered into the sphere of a shield. shieldRadius = pObj->RetShieldRadius(); if ( shieldRadius > 0.0f ) { dist = Math::Distance(oPos, pos); if ( dist <= shieldRadius ) { pBest = pObj; bShield = true; } } } if ( bShield ) continue; // Test the center of the object, which is necessary for objects // that have no sphere in the center (station). dist = Math::Distance(oPos, pos)-4.0f; if ( dist < min ) { pBest = pObj; } // Test with all spheres of the object. j = 0; while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) { if ( oPos.x+oRadius < box1.x || oPos.x-oRadius > box2.x || // outside the box? oPos.y+oRadius < box1.y || oPos.y-oRadius > box2.y || oPos.z+oRadius < box1.z || oPos.z-oRadius > box2.z ) continue; p = Math::Projection(old, pos, oPos); dist = Math::Distance(p, oPos)-oRadius; if ( dist < min ) { pBest = pObj; } } } return pBest; } // Seeks if an object collided with a ray. CObject* CParticule::SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticuleType type, CObject *father) { CObject* pObj; Math::Vector box1, box2, oPos, p; ObjectType oType; float min, dist; int i; if ( m_main->RetMovieLock() ) return 0; // current movie? min = 10.0f; box1 = pos; box2 = goal; if ( box1.x > box2.x ) Math::Swap(box1.x, box2.x); // box1 < box2 if ( box1.y > box2.y ) Math::Swap(box1.y, box2.y); if ( box1.z > box2.z ) Math::Swap(box1.z, box2.z); box1.x -= min; box1.y -= min; box1.z -= min; box2.x += min; box2.y += min; box2.z += min; for ( i=0 ; i<1000000 ; i++ ) { pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); if ( pObj == 0 ) break; if ( !pObj->RetActif() ) continue; // inactive? if ( pObj == father ) continue; oType = pObj->RetType(); if ( oType == OBJECT_TOTO ) continue; if ( type == PARTIRAY1 && oType != OBJECT_MOBILEtg && oType != OBJECT_TEEN28 && oType != OBJECT_TEEN31 && oType != OBJECT_ANT && oType != OBJECT_SPIDER && oType != OBJECT_BEE && oType != OBJECT_WORM && oType != OBJECT_MOTHER && oType != OBJECT_NEST ) continue; oPos = pObj->RetPosition(0); if ( oPos.x < box1.x || oPos.x > box2.x || // outside the box? oPos.y < box1.y || oPos.y > box2.y || oPos.z < box1.z || oPos.z > box2.z ) continue; p = Math::Projection(pos, goal, oPos); dist = Math::Distance(p, oPos); if ( dist < min ) return pObj; } return 0; } // Sounded one. void CParticule::Play(Sound sound, Math::Vector pos, float amplitude) { if ( m_sound == 0 ) { m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND); } m_sound->Play(sound, pos, amplitude); } // Seeks the color if you're in the fog. // Returns black if you're not in the fog. D3DCOLORVALUE CParticule::RetFogColor(Math::Vector pos) { D3DCOLORVALUE result, color; float dist, factor; int fog, i; result.r = 0.0f; result.g = 0.0f; result.b = 0.0f; result.a = 0.0f; for ( fog=0 ; fog= m_particule[i].pos.y+FOG_HSUP ) continue; if ( pos.y <= m_particule[i].pos.y-FOG_HINF ) continue; dist = Math::DistanceProjected(pos, m_particule[i].pos); if ( dist >= m_particule[i].dim.x*1.5f ) continue; // Calculates the horizontal distance. factor = 1.0f-powf(dist/(m_particule[i].dim.x*1.5f), 4.0f); // Calculates the vertical distance. if ( pos.y > m_particule[i].pos.y ) { factor *= 1.0f-(pos.y-m_particule[i].pos.y)/FOG_HSUP; } else { factor *= 1.0f-(m_particule[i].pos.y-pos.y)/FOG_HINF; } factor *= 0.3f; if ( m_particule[i].type == PARTIFOG0 || m_particule[i].type == PARTIFOG1 ) // blue? { color.r = 0.0f; color.g = 0.5f; color.b = 1.0f; } else if ( m_particule[i].type == PARTIFOG2 || m_particule[i].type == PARTIFOG3 ) // red? { color.r = 2.0f; color.g = 1.0f; color.b = 0.0f; } else if ( m_particule[i].type == PARTIFOG4 || m_particule[i].type == PARTIFOG5 ) // white? { color.r = 1.0f; color.g = 1.0f; color.b = 1.0f; } else if ( m_particule[i].type == PARTIFOG6 || m_particule[i].type == PARTIFOG7 ) // yellow? { color.r = 0.8f; color.g = 1.0f; color.b = 0.4f; } else { color.r = 0.0f; color.g = 0.0f; color.b = 0.0f; } result.r += color.r*factor; result.g += color.g*factor; result.b += color.b*factor; } if ( result.r > 0.6f ) result.r = 0.6f; if ( result.g > 0.6f ) result.g = 0.6f; if ( result.b > 0.6f ) result.b = 0.6f; return result; } // Writes a file. BMP containing all the tire tracks. bool CParticule::WriteWheelTrace(char *filename, int width, int height, Math::Vector dl, Math::Vector ur) { HDC hDC; HDC hDCImage; HBITMAP hb; PBITMAPINFO info; HBRUSH hBrush; HPEN hPen; HGDIOBJ old; RECT rect; COLORREF color; Math::Point pos[4]; POINT list[4]; int i; if ( !m_engine->GetRenderDC(hDC) ) return false; hDCImage = CreateCompatibleDC(hDC); if ( hDCImage == 0 ) { m_engine->ReleaseRenderDC(hDC); return false; } hb = CreateCompatibleBitmap(hDC, width, height); if ( hb == 0 ) { DeleteDC(hDCImage); m_engine->ReleaseRenderDC(hDC); return false; } SelectObject(hDCImage, hb); rect.left = 0; rect.right = width; rect.top = 0; rect.bottom = height; FillRect(hDCImage, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH)); hPen = CreatePen(PS_NULL, 1, 0); SelectObject(hDCImage, hPen); for ( i=0 ; iCreateBitmapInfoStruct(hb); if ( info == 0 ) { DeleteObject(hb); DeleteDC(hDCImage); m_engine->ReleaseRenderDC(hDC); return false; } m_engine->CreateBMPFile(filename, info, hb, hDCImage); DeleteObject(hb); DeleteDC(hDCImage); m_engine->ReleaseRenderDC(hDC); return true; }