/* ** Command & Conquer Generals Zero Hour(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 . */ //////////////////////////////////////////////////////////////////////////////// // // // (c) 2001-2003 Electronic Arts Inc. // // // //////////////////////////////////////////////////////////////////////////////// // FILE: BeaconClientUpdate.cpp ////////////////////////////////////////////////////////////////// // Author: Matthew D. Campbell, August 2002 // Desc: Beacon client update module /////////////////////////////////////////////////////////////////////////////////////////////////// // INCLUDES /////////////////////////////////////////////////////////////////////////////////////// #include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine #include "GameClient/Drawable.h" #include "GameClient/ParticleSys.h" #include "GameClient/Module/BeaconClientUpdate.h" #include "Common/Player.h" #include "Common/PlayerList.h" #include "Common/Radar.h" #include "Common/Xfer.h" #include "GameLogic/GameLogic.h" //------------------------------------------------------------------------------------------------- BeaconClientUpdateModuleData::BeaconClientUpdateModuleData() : m_framesBetweenRadarPulses(30), m_radarPulseDuration(15) { } //------------------------------------------------------------------------------------------------- BeaconClientUpdateModuleData::~BeaconClientUpdateModuleData() { } //------------------------------------------------------------------------------------------------- void BeaconClientUpdateModuleData::buildFieldParse(MultiIniFieldParse& p) { ClientUpdateModuleData::buildFieldParse(p); static const FieldParse dataFieldParse[] = { { "RadarPulseFrequency", INI::parseDurationUnsignedInt, NULL, offsetof(BeaconClientUpdateModuleData, m_framesBetweenRadarPulses) }, { "RadarPulseDuration", INI::parseDurationUnsignedInt, NULL, offsetof(BeaconClientUpdateModuleData, m_radarPulseDuration) }, { 0, 0, 0, 0 } }; p.add(dataFieldParse); } //------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------- BeaconClientUpdate::BeaconClientUpdate( Thing *thing, const ModuleData* moduleData ) : ClientUpdateModule( thing, moduleData ), m_particleSystemID(INVALID_PARTICLE_SYSTEM_ID), m_lastRadarPulse(TheGameLogic->getFrame()) { } //------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------- BeaconClientUpdate::~BeaconClientUpdate( void ) { } //------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------- static ParticleSystem* createParticleSystem( Drawable *draw ) { ParticleSystem *system = NULL; if (draw) { Object *obj = draw->getObject(); if (obj) { AsciiString templateName; templateName.format("BeaconSmoke%6.6X", (0xffffff & obj->getIndicatorColor())); const ParticleSystemTemplate *particleTemplate = TheParticleSystemManager->findTemplate( templateName ); DEBUG_ASSERTCRASH(particleTemplate, ("Could not find particle system %s\n", templateName.str())); if (particleTemplate) { system = TheParticleSystemManager->createParticleSystem( particleTemplate ); if (system) system->attachToDrawable( draw ); } else// This is a failsafe... if someone has monkeyed with the particle system names, or the MP house colors {// THis this will whip up a new particle system to match the house color provided templateName.format("BeaconSmokeFFFFFF"); const ParticleSystemTemplate *failsafeTemplate = TheParticleSystemManager->findTemplate( templateName ); DEBUG_ASSERTCRASH(failsafeTemplate, ("Doh, this is bad \n I Could not even find the white particle system to make a failsafe system out of.")); if (failsafeTemplate) { system = TheParticleSystemManager->createParticleSystem( failsafeTemplate ); if (system) { system->attachToDrawable( draw ); system->tintAllColors( obj->getIndicatorColor() ); } } } } } return system; } //------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------- void BeaconClientUpdate::hideBeacon( void ) { Drawable *draw = getDrawable(); if (draw) { draw->setDrawableHidden( true ); draw->setShadowsEnabled( false ); } ParticleSystem *system; if (draw && m_particleSystemID == INVALID_PARTICLE_SYSTEM_ID) { system = createParticleSystem( draw ); if (system) m_particleSystemID = system->getSystemID(); } // clean up particle system if (m_particleSystemID != INVALID_PARTICLE_SYSTEM_ID) { ParticleSystem *system = TheParticleSystemManager->findParticleSystem( m_particleSystemID ); if( system ) system->stop(); } // end if // DEBUG_LOG(("in hideBeacon(): draw=%d, m_particleSystemID=%d\n", draw, m_particleSystemID)); } //------------------------------------------------------------------------------------------------- /** The client update callback. */ //------------------------------------------------------------------------------------------------- void BeaconClientUpdate::clientUpdate( void ) { Drawable *draw = getDrawable(); if (!draw) return; if (m_particleSystemID == INVALID_PARTICLE_SYSTEM_ID) { ParticleSystem *system = createParticleSystem( draw ); if( system ) m_particleSystemID = system->getSystemID(); } if (!draw->isDrawableEffectivelyHidden()) { BeaconClientUpdateModuleData *moduleData = (BeaconClientUpdateModuleData *)getModuleData(); if (TheGameLogic->getFrame() > m_lastRadarPulse + moduleData->m_framesBetweenRadarPulses) { TheRadar->createEvent( draw->getPosition(), RADAR_EVENT_BEACON_PULSE, moduleData->m_radarPulseDuration * SECONDS_PER_LOGICFRAME_REAL ); m_lastRadarPulse = TheGameLogic->getFrame(); } } } // ------------------------------------------------------------------------------------------------ /** CRC */ // ------------------------------------------------------------------------------------------------ void BeaconClientUpdate::crc( Xfer *xfer ) { // extend base class ClientUpdateModule::crc( xfer ); } // end crc // ------------------------------------------------------------------------------------------------ /** Xfer method * Version Info: * 1: Initial version */ // ------------------------------------------------------------------------------------------------ void BeaconClientUpdate::xfer( Xfer *xfer ) { // version XferVersion currentVersion = 1; XferVersion version = currentVersion; xfer->xferVersion( &version, currentVersion ); // extend base class ClientUpdateModule::xfer( xfer ); // particle system ID xfer->xferUser( &m_particleSystemID, sizeof( ParticleSystemID ) ); // last radar pulse xfer->xferUnsignedInt( &m_lastRadarPulse ); } // end xfer // ------------------------------------------------------------------------------------------------ /** Load post process */ // ------------------------------------------------------------------------------------------------ void BeaconClientUpdate::loadPostProcess( void ) { // extend base class ClientUpdateModule::loadPostProcess(); } // end loadPostProcess