585 lines
16 KiB
C++
585 lines
16 KiB
C++
/*
|
||
* This file is part of the Colobot: Gold Edition source code
|
||
* Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||
* http://epsiteс.ch; http://colobot.info; http://github.com/colobot
|
||
*
|
||
* 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://gnu.org/licenses
|
||
*/
|
||
|
||
|
||
#include "object/auto/autoresearch.h"
|
||
|
||
#include "common/global.h"
|
||
|
||
#include "math/geometry.h"
|
||
|
||
#include "object/robotmain.h"
|
||
#include "object/level/parserline.h"
|
||
#include "object/level/parserparam.h"
|
||
#include "object/interface/powered_object.h"
|
||
|
||
#include "ui/interface.h"
|
||
#include "ui/gauge.h"
|
||
#include "ui/window.h"
|
||
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
|
||
|
||
const float SEARCH_TIME = 30.0f; // duration of a research
|
||
|
||
|
||
|
||
// Object's constructor.
|
||
|
||
CAutoResearch::CAutoResearch(CObject* object) : CAuto(object)
|
||
{
|
||
for (int i = 0; i < 6; i++)
|
||
{
|
||
m_partiStop[i] = -1;
|
||
}
|
||
m_channelSound = -1;
|
||
|
||
Init();
|
||
|
||
assert(m_object->Implements(ObjectInterfaceType::Powered));
|
||
m_poweredObject = dynamic_cast<CPoweredObject*>(m_object);
|
||
}
|
||
|
||
// Object's destructor.
|
||
|
||
CAutoResearch::~CAutoResearch()
|
||
{
|
||
}
|
||
|
||
|
||
// Destroys the object.
|
||
|
||
void CAutoResearch::DeleteObject(bool bAll)
|
||
{
|
||
if ( m_channelSound != -1 )
|
||
{
|
||
m_sound->FlushEnvelope(m_channelSound);
|
||
m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
|
||
m_channelSound = -1;
|
||
}
|
||
|
||
FireStopUpdate(0.0f, false);
|
||
CAuto::DeleteObject(bAll);
|
||
}
|
||
|
||
|
||
// Initialize the object.
|
||
|
||
void CAutoResearch::Init()
|
||
{
|
||
m_phase = ALP_WAIT;
|
||
m_progress = 0.0f;
|
||
m_speed = 1.0f/1.0f;
|
||
|
||
m_time = 0.0f;
|
||
m_timeVirus = 0.0f;
|
||
m_lastUpdateTime = 0.0f;
|
||
m_lastParticle = 0.0f;
|
||
}
|
||
|
||
|
||
// Starts an action
|
||
|
||
Error CAutoResearch::StartAction(int param)
|
||
{
|
||
if ( m_phase != ALP_WAIT )
|
||
{
|
||
return ERR_GENERIC;
|
||
}
|
||
|
||
m_research = static_cast<ResearchType>(param);
|
||
|
||
if ( g_researchDone & m_research )
|
||
{
|
||
return ERR_RESEARCH_ALREADY;
|
||
}
|
||
|
||
CObject* power = m_poweredObject->GetPower();
|
||
if (power == nullptr)
|
||
{
|
||
return ERR_RESEARCH_POWER;
|
||
}
|
||
if ( power->GetCapacity() > 1.0f )
|
||
{
|
||
return ERR_RESEARCH_TYPE;
|
||
}
|
||
if ( power->GetEnergy() < 1.0f )
|
||
{
|
||
return ERR_RESEARCH_ENERGY;
|
||
}
|
||
|
||
float time = SEARCH_TIME;
|
||
if ( m_research == RESEARCH_TANK ) time *= 0.3f;
|
||
if ( m_research == RESEARCH_FLY ) time *= 0.3f;
|
||
if ( m_research == RESEARCH_ATOMIC ) time *= 2.0f;
|
||
|
||
SetBusy(true);
|
||
InitProgressTotal(time);
|
||
UpdateInterface();
|
||
|
||
m_channelSound = m_sound->Play(SOUND_RESEARCH, m_object->GetPosition(), 0.0f, 1.0f, true);
|
||
m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
|
||
m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, time-4.0f, SOPER_CONTINUE);
|
||
m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
|
||
|
||
m_phase = ALP_SEARCH;
|
||
m_progress = 0.0f;
|
||
m_speed = 1.0f/time;
|
||
return ERR_OK;
|
||
}
|
||
|
||
|
||
// Management of an event.
|
||
|
||
bool CAutoResearch::EventProcess(const Event &event)
|
||
{
|
||
CObject* power;
|
||
Math::Vector pos, speed;
|
||
Error message;
|
||
Math::Point dim;
|
||
float angle;
|
||
|
||
CAuto::EventProcess(event);
|
||
|
||
if ( m_engine->GetPause() ) return true;
|
||
|
||
if ( event.type == EVENT_UPDINTERFACE )
|
||
{
|
||
if ( m_object->GetSelect() ) CreateInterface(true);
|
||
}
|
||
|
||
if ( m_object->GetSelect() ) // center selected?
|
||
{
|
||
Error err = ERR_GENERIC;
|
||
if ( event.type == EVENT_OBJECT_RTANK ) err = StartAction(RESEARCH_TANK);
|
||
if ( event.type == EVENT_OBJECT_RFLY ) err = StartAction(RESEARCH_FLY);
|
||
if ( event.type == EVENT_OBJECT_RTHUMP ) err = StartAction(RESEARCH_THUMP);
|
||
if ( event.type == EVENT_OBJECT_RCANON ) err = StartAction(RESEARCH_CANON);
|
||
if ( event.type == EVENT_OBJECT_RTOWER ) err = StartAction(RESEARCH_TOWER);
|
||
if ( event.type == EVENT_OBJECT_RPHAZER ) err = StartAction(RESEARCH_PHAZER);
|
||
if ( event.type == EVENT_OBJECT_RSHIELD ) err = StartAction(RESEARCH_SHIELD);
|
||
if ( event.type == EVENT_OBJECT_RATOMIC ) err = StartAction(RESEARCH_ATOMIC);
|
||
|
||
if( err != ERR_OK && err != ERR_GENERIC )
|
||
m_main->DisplayError(err, m_object);
|
||
|
||
if( err != ERR_GENERIC )
|
||
return false;
|
||
}
|
||
|
||
if ( event.type != EVENT_FRAME ) return true;
|
||
|
||
m_progress += event.rTime*m_speed;
|
||
m_timeVirus -= event.rTime;
|
||
|
||
if ( m_object->GetVirusMode() ) // contaminated by a virus?
|
||
{
|
||
if ( m_timeVirus <= 0.0f )
|
||
{
|
||
m_timeVirus = 0.1f+Math::Rand()*0.3f;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
UpdateInterface(event.rTime);
|
||
EventProgress(event.rTime);
|
||
|
||
angle = m_time*0.1f;
|
||
m_object->SetAngleY(1, angle); // rotates the antenna
|
||
|
||
angle = (30.0f+sinf(m_time*0.3f)*20.0f)*Math::PI/180.0f;
|
||
m_object->SetAngleZ(2, angle); // directs the antenna
|
||
|
||
if ( m_phase == ALP_WAIT )
|
||
{
|
||
FireStopUpdate(m_progress, false); // extinguished
|
||
return true;
|
||
}
|
||
|
||
if ( m_phase == ALP_SEARCH )
|
||
{
|
||
FireStopUpdate(m_progress, true); // flashes
|
||
if ( m_progress < 1.0f )
|
||
{
|
||
power = m_poweredObject->GetPower();
|
||
if ( power == 0 ) // more battery?
|
||
{
|
||
SetBusy(false);
|
||
UpdateInterface();
|
||
|
||
m_phase = ALP_WAIT;
|
||
m_progress = 0.0f;
|
||
m_speed = 1.0f/1.0f;
|
||
return true;
|
||
}
|
||
power->SetEnergy(1.0f-m_progress);
|
||
|
||
if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
|
||
{
|
||
m_lastParticle = m_time;
|
||
|
||
pos = m_object->GetPosition();
|
||
pos.x += (Math::Rand()-0.5f)*6.0f;
|
||
pos.z += (Math::Rand()-0.5f)*6.0f;
|
||
pos.y += 11.0f;
|
||
speed.x = (Math::Rand()-0.5f)*2.0f;
|
||
speed.z = (Math::Rand()-0.5f)*2.0f;
|
||
speed.y = Math::Rand()*20.0f;
|
||
dim.x = Math::Rand()*1.0f+1.0f;
|
||
dim.y = dim.x;
|
||
m_particle->CreateParticle(pos, speed, dim, Gfx::PARTIVAPOR);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
g_researchDone |= m_research; // research done
|
||
|
||
m_main->WriteFreeParam();
|
||
|
||
Event newEvent(EVENT_UPDINTERFACE);
|
||
m_eventQueue->AddEvent(newEvent);
|
||
UpdateInterface();
|
||
|
||
m_main->DisplayError(INFO_RESEARCH, m_object);
|
||
|
||
message = ERR_OK;
|
||
if ( m_research == RESEARCH_TANK ) message = INFO_RESEARCHTANK;
|
||
if ( m_research == RESEARCH_FLY ) message = INFO_RESEARCHFLY;
|
||
if ( m_research == RESEARCH_THUMP ) message = INFO_RESEARCHTHUMP;
|
||
if ( m_research == RESEARCH_CANON ) message = INFO_RESEARCHCANON;
|
||
if ( m_research == RESEARCH_TOWER ) message = INFO_RESEARCHTOWER;
|
||
if ( m_research == RESEARCH_PHAZER ) message = INFO_RESEARCHPHAZER;
|
||
if ( m_research == RESEARCH_SHIELD ) message = INFO_RESEARCHSHIELD;
|
||
if ( m_research == RESEARCH_ATOMIC ) message = INFO_RESEARCHATOMIC;
|
||
if ( message != ERR_OK )
|
||
{
|
||
m_main->DisplayError(message, m_object);
|
||
}
|
||
|
||
SetBusy(false);
|
||
UpdateInterface();
|
||
|
||
m_phase = ALP_WAIT;
|
||
m_progress = 0.0f;
|
||
m_speed = 1.0f/1.0f;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
// Returns an error due the state of the automation.
|
||
|
||
Error CAutoResearch::GetError()
|
||
{
|
||
if ( m_phase == ALP_SEARCH )
|
||
{
|
||
return ERR_OK;
|
||
}
|
||
|
||
if ( m_object->GetVirusMode() )
|
||
{
|
||
return ERR_BAT_VIRUS;
|
||
}
|
||
|
||
CObject* power = m_poweredObject->GetPower();
|
||
if ( power == 0 )
|
||
{
|
||
return ERR_RESEARCH_POWER;
|
||
}
|
||
if ( power != 0 && power->GetCapacity() > 1.0f )
|
||
{
|
||
return ERR_RESEARCH_TYPE;
|
||
}
|
||
if ( power != 0 && power->GetEnergy() < 1.0f )
|
||
{
|
||
return ERR_RESEARCH_ENERGY;
|
||
}
|
||
|
||
return ERR_OK;
|
||
}
|
||
|
||
|
||
// Creates all the interface when the object is selected.
|
||
|
||
bool CAutoResearch::CreateInterface(bool bSelect)
|
||
{
|
||
Ui::CWindow* pw;
|
||
Math::Point pos, dim, ddim;
|
||
float ox, oy, sx, sy;
|
||
|
||
CAuto::CreateInterface(bSelect);
|
||
|
||
if ( !bSelect ) return true;
|
||
|
||
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
|
||
if ( pw == 0 ) return false;
|
||
|
||
dim.x = 33.0f/640.0f;
|
||
dim.y = 33.0f/480.0f;
|
||
ox = 3.0f/640.0f;
|
||
oy = 3.0f/480.0f;
|
||
sx = 33.0f/640.0f;
|
||
sy = 33.0f/480.0f;
|
||
|
||
pos.x = ox+sx*7.0f;
|
||
pos.y = oy+sy*1.0f;
|
||
pw->CreateButton(pos, dim, 64+0, EVENT_OBJECT_RTANK);
|
||
|
||
pos.x = ox+sx*8.0f;
|
||
pos.y = oy+sy*1.0f;
|
||
pw->CreateButton(pos, dim, 64+1, EVENT_OBJECT_RFLY);
|
||
|
||
pos.x = ox+sx*9.0f;
|
||
pos.y = oy+sy*1.0f;
|
||
pw->CreateButton(pos, dim, 64+3, EVENT_OBJECT_RCANON);
|
||
|
||
pos.x = ox+sx*10.0f;
|
||
pos.y = oy+sy*1.0f;
|
||
pw->CreateButton(pos, dim, 64+4, EVENT_OBJECT_RTOWER);
|
||
|
||
pos.x = ox+sx*7.0f;
|
||
pos.y = oy+sy*0.0f;
|
||
pw->CreateButton(pos, dim, 64+7, EVENT_OBJECT_RATOMIC);
|
||
|
||
pos.x = ox+sx*8.0f;
|
||
pos.y = oy+sy*0.0f;
|
||
pw->CreateButton(pos, dim, 64+2, EVENT_OBJECT_RTHUMP);
|
||
|
||
pos.x = ox+sx*9.0f;
|
||
pos.y = oy+sy*0.0f;
|
||
pw->CreateButton(pos, dim, 64+6, EVENT_OBJECT_RSHIELD);
|
||
|
||
pos.x = ox+sx*10.0f;
|
||
pos.y = oy+sy*0.0f;
|
||
pw->CreateButton(pos, dim, 64+5, EVENT_OBJECT_RPHAZER);
|
||
|
||
pos.x = ox+sx*14.5f;
|
||
pos.y = oy+sy*0;
|
||
ddim.x = 14.0f/640.0f;
|
||
ddim.y = 66.0f/480.0f;
|
||
pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
|
||
|
||
pos.x = ox+sx*0.0f;
|
||
pos.y = oy+sy*0;
|
||
ddim.x = 66.0f/640.0f;
|
||
ddim.y = 66.0f/480.0f;
|
||
pw->CreateGroup(pos, ddim, 102, EVENT_OBJECT_TYPE);
|
||
|
||
UpdateInterface();
|
||
|
||
return true;
|
||
}
|
||
|
||
// Updates the status of all interface buttons.
|
||
|
||
void CAutoResearch::UpdateInterface()
|
||
{
|
||
Ui::CWindow* pw;
|
||
|
||
if ( !m_object->GetSelect() ) return;
|
||
|
||
CAuto::UpdateInterface();
|
||
|
||
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
|
||
if ( pw == 0 ) return;
|
||
|
||
DeadInterface(pw, EVENT_OBJECT_RTANK, g_researchEnable&RESEARCH_TANK);
|
||
DeadInterface(pw, EVENT_OBJECT_RFLY, g_researchEnable&RESEARCH_FLY);
|
||
DeadInterface(pw, EVENT_OBJECT_RTHUMP, g_researchEnable&RESEARCH_THUMP);
|
||
DeadInterface(pw, EVENT_OBJECT_RCANON, g_researchEnable&RESEARCH_CANON);
|
||
DeadInterface(pw, EVENT_OBJECT_RTOWER, g_researchEnable&RESEARCH_TOWER);
|
||
DeadInterface(pw, EVENT_OBJECT_RPHAZER, g_researchEnable&RESEARCH_PHAZER);
|
||
DeadInterface(pw, EVENT_OBJECT_RSHIELD, g_researchEnable&RESEARCH_SHIELD);
|
||
DeadInterface(pw, EVENT_OBJECT_RATOMIC, g_researchEnable&RESEARCH_ATOMIC);
|
||
|
||
OkayButton(pw, EVENT_OBJECT_RTANK);
|
||
OkayButton(pw, EVENT_OBJECT_RFLY);
|
||
OkayButton(pw, EVENT_OBJECT_RTHUMP);
|
||
OkayButton(pw, EVENT_OBJECT_RCANON);
|
||
OkayButton(pw, EVENT_OBJECT_RTOWER);
|
||
OkayButton(pw, EVENT_OBJECT_RPHAZER);
|
||
OkayButton(pw, EVENT_OBJECT_RSHIELD);
|
||
OkayButton(pw, EVENT_OBJECT_RATOMIC);
|
||
|
||
VisibleInterface(pw, EVENT_OBJECT_RTANK, !m_bBusy);
|
||
VisibleInterface(pw, EVENT_OBJECT_RFLY, !m_bBusy);
|
||
VisibleInterface(pw, EVENT_OBJECT_RTHUMP, !m_bBusy);
|
||
VisibleInterface(pw, EVENT_OBJECT_RCANON, !m_bBusy);
|
||
VisibleInterface(pw, EVENT_OBJECT_RTOWER, !m_bBusy);
|
||
VisibleInterface(pw, EVENT_OBJECT_RPHAZER, !m_bBusy);
|
||
VisibleInterface(pw, EVENT_OBJECT_RSHIELD, !m_bBusy);
|
||
VisibleInterface(pw, EVENT_OBJECT_RATOMIC, !m_bBusy);
|
||
}
|
||
|
||
// Updates the state of all buttons on the interface,
|
||
// following the time that elapses ...
|
||
|
||
void CAutoResearch::UpdateInterface(float rTime)
|
||
{
|
||
CAuto::UpdateInterface(rTime);
|
||
|
||
if ( m_time < m_lastUpdateTime+0.1f ) return;
|
||
m_lastUpdateTime = m_time;
|
||
|
||
if ( !m_object->GetSelect() ) return;
|
||
|
||
Ui::CWindow* pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
|
||
if ( pw == nullptr ) return;
|
||
|
||
Ui::CGauge* pg = static_cast< Ui::CGauge* >(pw->SearchControl(EVENT_OBJECT_GENERGY));
|
||
if ( pg != nullptr )
|
||
{
|
||
float energy = GetObjectEnergy(m_object);
|
||
pg->SetLevel(energy);
|
||
}
|
||
}
|
||
|
||
// Research shows already performed button.
|
||
|
||
void CAutoResearch::OkayButton(Ui::CWindow *pw, EventType event)
|
||
{
|
||
Ui::CControl* control;
|
||
|
||
control = pw->SearchControl(event);
|
||
if ( control == 0 ) return;
|
||
|
||
control->SetState(Ui::STATE_OKAY, TestResearch(event));
|
||
}
|
||
|
||
|
||
// Test whether a search has already been done.
|
||
|
||
bool CAutoResearch::TestResearch(EventType event)
|
||
{
|
||
if ( event == EVENT_OBJECT_RTANK ) return (g_researchDone & RESEARCH_TANK );
|
||
if ( event == EVENT_OBJECT_RFLY ) return (g_researchDone & RESEARCH_FLY );
|
||
if ( event == EVENT_OBJECT_RTHUMP ) return (g_researchDone & RESEARCH_THUMP );
|
||
if ( event == EVENT_OBJECT_RCANON ) return (g_researchDone & RESEARCH_CANON );
|
||
if ( event == EVENT_OBJECT_RTOWER ) return (g_researchDone & RESEARCH_TOWER );
|
||
if ( event == EVENT_OBJECT_RPHAZER ) return (g_researchDone & RESEARCH_PHAZER );
|
||
if ( event == EVENT_OBJECT_RSHIELD ) return (g_researchDone & RESEARCH_SHIELD);
|
||
if ( event == EVENT_OBJECT_RATOMIC ) return (g_researchDone & RESEARCH_ATOMIC);
|
||
|
||
return false;
|
||
}
|
||
|
||
|
||
// Updates the stop lights.
|
||
|
||
void CAutoResearch::FireStopUpdate(float progress, bool bLightOn)
|
||
{
|
||
Math::Matrix* mat;
|
||
Math::Vector pos, speed;
|
||
Math::Point dim;
|
||
int i;
|
||
|
||
static float listpos[12] =
|
||
{
|
||
9.5f, 0.0f,
|
||
4.7f, 8.2f,
|
||
-4.7f, 8.2f,
|
||
-9.5f, 0.0f,
|
||
-4.7f, -8.2f,
|
||
4.7f, -8.2f,
|
||
};
|
||
|
||
if ( !bLightOn ) // <20>teint ?
|
||
{
|
||
for ( i=0 ; i<6 ; i++ )
|
||
{
|
||
if ( m_partiStop[i] != -1 )
|
||
{
|
||
m_particle->DeleteParticle(m_partiStop[i]);
|
||
m_partiStop[i] = -1;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
mat = m_object->GetWorldMatrix(0);
|
||
|
||
speed = Math::Vector(0.0f, 0.0f, 0.0f);
|
||
dim.x = 2.0f;
|
||
dim.y = dim.x;
|
||
|
||
for ( i=0 ; i<6 ; i++ )
|
||
{
|
||
if ( Math::Mod(progress, 0.025f) < 0.005f )
|
||
{
|
||
if ( m_partiStop[i] != -1 )
|
||
{
|
||
m_particle->DeleteParticle(m_partiStop[i]);
|
||
m_partiStop[i] = -1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ( m_partiStop[i] == -1 )
|
||
{
|
||
pos.x = listpos[i*2+0];
|
||
pos.y = 11.5f;
|
||
pos.z = listpos[i*2+1];
|
||
pos = Math::Transform(*mat, pos);
|
||
m_partiStop[i] = m_particle->CreateParticle(pos, speed,
|
||
dim, Gfx::PARTISELY,
|
||
1.0f, 0.0f, 0.0f);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
// Saves all parameters of the controller.
|
||
|
||
bool CAutoResearch::Write(CLevelParserLine* line)
|
||
{
|
||
if ( m_phase == ALP_WAIT ) return false;
|
||
|
||
line->AddParam("aExist", CLevelParserParamUPtr{new CLevelParserParam(true)});
|
||
CAuto::Write(line);
|
||
line->AddParam("aPhase", CLevelParserParamUPtr{new CLevelParserParam(static_cast<int>(m_phase))});
|
||
line->AddParam("aProgress", CLevelParserParamUPtr{new CLevelParserParam(m_progress)});
|
||
line->AddParam("aSpeed", CLevelParserParamUPtr{new CLevelParserParam(m_speed)});
|
||
line->AddParam("aResearch", CLevelParserParamUPtr{new CLevelParserParam(static_cast<int>(m_research))});
|
||
|
||
return true;
|
||
}
|
||
|
||
// Restores all parameters of the controller.
|
||
|
||
bool CAutoResearch::Read(CLevelParserLine* line)
|
||
{
|
||
if ( !line->GetParam("aExist")->AsBool(false) ) return false;
|
||
|
||
CAuto::Read(line);
|
||
m_phase = static_cast< AutoResearchPhase >(line->GetParam("aPhase")->AsInt(ALP_WAIT));
|
||
m_progress = line->GetParam("aProgress")->AsFloat(0.0f);
|
||
m_speed = line->GetParam("aSpeed")->AsFloat(1.0f);
|
||
m_research = static_cast< ResearchType >(line->GetParam("aResearch")->AsInt(0));
|
||
|
||
m_lastUpdateTime = 0.0f;
|
||
m_lastParticle = 0.0f;
|
||
|
||
return true;
|
||
}
|
||
|