| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** 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/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: LaserUpdate.cpp //////////////////////////////////////////////////////////////////////////
- // Author: Kris Morness, July 2002
- // Desc: Handles laser update processing for render purposes and game control.
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #include "Common/Xfer.h"
- #include "Common/DrawModule.h"
- #include "GameClient/Drawable.h"
- #include "GameClient/GameClient.h"
- #include "GameClient/ParticleSys.h"
- #include "GameLogic/GameLogic.h"
- #include "GameLogic/Object.h"
- #include "GameLogic/Module/LaserUpdate.h"
- #include "WWMath/Vector3.h"
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- LaserUpdateModuleData::LaserUpdateModuleData()
- {
- m_parentFireBoneOnTurret = FALSE;
- }
- //-------------------------------------------------------------------------------------------------
- /*static*/ void LaserUpdateModuleData::buildFieldParse(MultiIniFieldParse& p)
- {
- ModuleData::buildFieldParse(p);
- static const FieldParse dataFieldParse[] =
- {
- { "MuzzleParticleSystem", INI::parseAsciiString, NULL, offsetof( LaserUpdateModuleData, m_particleSystemName ) },
- { "TargetParticleSystem", INI::parseAsciiString, NULL, offsetof( LaserUpdateModuleData, m_targetParticleSystemName ) },
- { "ParentFireBoneName", INI::parseAsciiString, NULL, offsetof( LaserUpdateModuleData, m_parentFireBoneName ) },
- { "ParentFireBoneOnTurret", INI::parseAsciiString, NULL, offsetof( LaserUpdateModuleData, m_parentFireBoneOnTurret ) },
- { 0, 0, 0, 0 }
- };
- p.add(dataFieldParse);
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- LaserUpdate::LaserUpdate( Thing *thing, const ModuleData* moduleData ) : ClientUpdateModule( thing, moduleData )
- {
- //Added By Sadullah Nader
- //Initialization missing and needed
- m_dirty = FALSE;
- m_endPos.zero();
- m_startPos.zero();
- //
- m_particleSystemID = INVALID_PARTICLE_SYSTEM_ID;
- m_targetParticleSystemID = INVALID_PARTICLE_SYSTEM_ID;
- m_widening = false;
- m_widenStartFrame = 0;
- m_widenFinishFrame = 0;
- m_currentWidthScalar = 1.0f;
- m_decaying = false;
- m_decayStartFrame = 0;
- m_decayFinishFrame = 0;
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- LaserUpdate::~LaserUpdate( void )
- {
- if( m_particleSystemID )
- TheParticleSystemManager->destroyParticleSystemByID( m_particleSystemID );
- if( m_targetParticleSystemID )
- TheParticleSystemManager->destroyParticleSystemByID( m_targetParticleSystemID );
- }
- //-------------------------------------------------------------------------------------------------
- /** The update callback. */
- //-------------------------------------------------------------------------------------------------
- void LaserUpdate::clientUpdate( void )
- {
- /// @todo srj use SLEEPY_UPDATE here
- if( m_decaying )
- {
- UnsignedInt now = TheGameLogic->getFrame();
- m_currentWidthScalar = 1.0f - (Real)(now - m_decayStartFrame) / (Real)(m_decayFinishFrame - m_decayStartFrame);
- m_dirty = true;
- if( m_currentWidthScalar <= 0.0f )
- {
- m_currentWidthScalar = 0.0f;
- //When decay is finished... delete the laser.
- //TheGameLogic->destroyObject( getObject() );
- return;
- }
- }
- else if( m_widening )
- {
- //We need to resize our laser width based on the growth ratio completed.
- UnsignedInt now = TheGameLogic->getFrame();
- m_currentWidthScalar = (Real)(now - m_widenStartFrame) / (Real)(m_widenFinishFrame - m_widenStartFrame);
- m_dirty = true;
- if( m_currentWidthScalar >= 1.0f )
- {
- m_currentWidthScalar = 1.0f;
- m_widening = false;
- }
- }
- return;
- }
- void LaserUpdate::setDecayFrames( UnsignedInt decayFrames )
- {
- if( decayFrames > 0 )
- {
- m_decaying = true;
- m_decayStartFrame = TheGameLogic->getFrame();
- m_decayFinishFrame = m_decayStartFrame + decayFrames;
- m_currentWidthScalar = 1.0f;
- }
- }
- //-------------------------------------------------------------------------------------------------
- void LaserUpdate::initLaser( const Object *parent, const Coord3D *startPos, const Coord3D *endPos, Int sizeDeltaFrames )
- {
- const LaserUpdateModuleData *data = getLaserUpdateModuleData();
- ParticleSystem *system;
- if( sizeDeltaFrames > 0 )
- {
- m_widening = true;
- m_widenStartFrame = TheGameLogic->getFrame();
- m_widenFinishFrame = m_widenStartFrame + sizeDeltaFrames;
- m_currentWidthScalar = 0.0f;
- }
- else if( sizeDeltaFrames < 0 )
- {
- m_decaying = true;
- m_decayStartFrame = TheGameLogic->getFrame();
- m_decayFinishFrame = m_decayStartFrame - sizeDeltaFrames;
- m_currentWidthScalar = 1.0f;
- }
- //Compute startPos
- if( parent && data->m_parentFireBoneName.isNotEmpty() )
- {
- // Override startPos with the logic bone position
- if( data->m_parentFireBoneOnTurret )
- {
- if( !parent->getSingleLogicalBonePositionOnTurret( TURRET_MAIN, data->m_parentFireBoneName.str(), &m_startPos, NULL ) )
- {
- // failed to find the required bone, so just die
- TheGameClient->destroyDrawable( getDrawable() );
- return;
- }
- }
- else
- {
- if( !parent->getSingleLogicalBonePosition( data->m_parentFireBoneName.str(), &m_startPos, NULL ) )
- {
- // failed to find the required bone, so just die
- TheGameClient->destroyDrawable( getDrawable() );
- return;
- }
- }
- }
- else if( startPos )
- {
- // or just use what they gave
- m_startPos = *startPos;
- }
- else
- {
- // if they gave nothing, then we are screwed
- TheGameClient->destroyDrawable( getDrawable() );
- return;
- }
- //Compute endPos
- if( endPos != NULL )
- {
- // just use what they gave, no override here
- m_endPos = *endPos;
- }
- else
- {
- // if they gave nothing, then we are screwed
- TheGameClient->destroyDrawable( getDrawable() );
- return;
- }
- if( !m_particleSystemID )
- {
- //If we don't have a particle system for the lense flare (muzzle flare), create it.
- if( data->m_particleSystemName.isNotEmpty() )
- {
- const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate( data->m_particleSystemName );
- if( tmp )
- {
- system = TheParticleSystemManager->createParticleSystem( tmp );
- if( system )
- {
- m_particleSystemID = system->getSystemID();
- }
- }
- }
- //If we don't have a particle system for the target effect, create it.
- if( data->m_targetParticleSystemName.isNotEmpty() )
- {
- const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate( data->m_targetParticleSystemName );
- if( tmp )
- {
- system = TheParticleSystemManager->createParticleSystem( tmp );
- if( system )
- {
- m_targetParticleSystemID = system->getSystemID();
- }
- }
- }
- }
- //Adjust the position of any existing particle system.
- if( m_particleSystemID )
- {
- system = TheParticleSystemManager->findParticleSystem( m_particleSystemID );
- if( system )
- {
- system->setPosition( &m_startPos );
- }
- }
- if( m_targetParticleSystemID )
- {
- system = TheParticleSystemManager->findParticleSystem( m_targetParticleSystemID );
- if( system )
- {
- system->setPosition( &m_endPos );
- }
- }
- //Important! Set the laser position to the average of both points or else
- //it probably won't get rendered!!!
- Coord3D avgPos;
- avgPos.set( startPos );
- avgPos.add( endPos );
- avgPos.scale( 0.5 );
- getDrawable()->setPosition( &avgPos );
- Object *laser = getDrawable()->getObject();
- if( laser )
- {
- laser->setPosition( &avgPos );
- }
- m_dirty = true;
- }
- //-------------------------------------------------------------------------------------------------
- Real LaserUpdate::getCurrentLaserRadius() const
- {
- const Drawable *draw = getDrawable();
- const LaserDrawInterface* ldi = NULL;
- for( const DrawModule** d = draw->getDrawModules(); *d; ++d )
- {
- ldi = (*d)->getLaserDrawInterface();
- if( ldi )
- {
- //***NOTE***
- //While it appears the logic is accessing client data, it is actually accessing template module
- //data from the client. This value is INI constant thus can't change. It's grouped with other
- //laser defining attributes and having it there makes it easier for artists.
- return ldi->getLaserTemplateWidth() * m_currentWidthScalar;
- }
- }
- return 0.0f;
- }
- // ------------------------------------------------------------------------------------------------
- /** CRC */
- // ------------------------------------------------------------------------------------------------
- void LaserUpdate::crc( Xfer *xfer )
- {
- // extend base class
- ClientUpdateModule::crc( xfer );
- } // end crc
- // ------------------------------------------------------------------------------------------------
- /** Xfer method
- * Version Info:
- * 1: Initial version */
- // ------------------------------------------------------------------------------------------------
- void LaserUpdate::xfer( Xfer *xfer )
- {
- // version
- XferVersion currentVersion = 1;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
- // extend base class
- ClientUpdateModule::xfer( xfer );
- // start pos
- xfer->xferCoord3D( &m_startPos );
- // end pos
- xfer->xferCoord3D( &m_endPos );
- // dirty
- xfer->xferBool( &m_dirty );
- // particle system ID
- xfer->xferUser( &m_particleSystemID, sizeof( ParticleSystemID ) );
- // target particle system id
- xfer->xferUser( &m_targetParticleSystemID, sizeof( ParticleSystemID ) );
- // widening
- xfer->xferBool( &m_widening );
- // decaying
- xfer->xferBool( &m_decaying );
- // widen start frame
- xfer->xferUnsignedInt( &m_widenStartFrame );
- // widen finish frame
- xfer->xferUnsignedInt( &m_widenFinishFrame );
- // current width scalar
- xfer->xferReal( &m_currentWidthScalar );
- // decay start frame
- xfer->xferUnsignedInt( &m_decayStartFrame );
- // decay finish frame
- xfer->xferUnsignedInt( &m_decayFinishFrame );
- } // end xfer
- // ------------------------------------------------------------------------------------------------
- /** Load post process */
- // ------------------------------------------------------------------------------------------------
- void LaserUpdate::loadPostProcess( void )
- {
- // extend base class
- ClientUpdateModule::loadPostProcess();
- } // end loadPostProcess
|