/* ** 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: StealthUpdate.h ////////////////////////////////////////////////////////////////////////// // Author: Kris Morness, May 2002 // Desc: An update that checks for a status bit to stealth the owning object /////////////////////////////////////////////////////////////////////////////////////////////////// #pragma once #ifndef __STEALTH_UPDATE_H_ #define __STEALTH_UPDATE_H_ // INCLUDES /////////////////////////////////////////////////////////////////////////////////////// #include "GameLogic/Module/UpdateModule.h" // FORWARD REFERENCES ///////////////////////////////////////////////////////////////////////////// class Thing; enum StealthLookType; enum EvaMessage; class FXList; enum { STEALTH_NOT_WHILE_ATTACKING = 0x00000001, STEALTH_NOT_WHILE_MOVING = 0x00000002, STEALTH_NOT_WHILE_USING_ABILITY = 0x00000004, STEALTH_NOT_WHILE_FIRING_PRIMARY = 0x00000008, STEALTH_NOT_WHILE_FIRING_SECONDARY = 0x00000010, STEALTH_NOT_WHILE_FIRING_TERTIARY = 0x00000020, STEALTH_ONLY_WITH_BLACK_MARKET = 0x00000040, STEALTH_NOT_WHILE_TAKING_DAMAGE = 0x00000080, STEALTH_NOT_WHILE_FIRING_WEAPON = (STEALTH_NOT_WHILE_FIRING_PRIMARY | STEALTH_NOT_WHILE_FIRING_SECONDARY | STEALTH_NOT_WHILE_FIRING_TERTIARY), STEALTH_NOT_WHILE_RIDERS_ATTACKING = 0x00000100, }; #ifdef DEFINE_STEALTHLEVEL_NAMES static const char *TheStealthLevelNames[] = { "ATTACKING", "MOVING", "USING_ABILITY", "FIRING_PRIMARY", "FIRING_SECONDARY", "FIRING_TERTIARY", "NO_BLACK_MARKET", "TAKING_DAMAGE", "RIDERS_ATTACKING", NULL }; #endif #define INVALID_OPACITY -1.0f //------------------------------------------------------------------------------------------------- class StealthUpdateModuleData : public UpdateModuleData { public: ObjectStatusMaskType m_hintDetectableStates; ObjectStatusMaskType m_requiredStatus; ObjectStatusMaskType m_forbiddenStatus; FXList *m_disguiseRevealFX; FXList *m_disguiseFX; Real m_stealthSpeed; Real m_friendlyOpacityMin; Real m_friendlyOpacityMax; Real m_revealDistanceFromTarget; UnsignedInt m_disguiseTransitionFrames; UnsignedInt m_disguiseRevealTransitionFrames; UnsignedInt m_pulseFrames; UnsignedInt m_stealthDelay; UnsignedInt m_stealthLevel; UnsignedInt m_blackMarketCheckFrames; EvaMessage m_enemyDetectionEvaEvent; EvaMessage m_ownDetectionEvaEvent; Bool m_innateStealth; Bool m_orderIdleEnemiesToAttackMeUponReveal; Bool m_teamDisguised; Bool m_useRiderStealth; Bool m_grantedBySpecialPower; StealthUpdateModuleData(); static void buildFieldParse(MultiIniFieldParse& p); }; //------------------------------------------------------------------------------------------------- class StealthUpdate : public UpdateModule { MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( StealthUpdate, "StealthUpdate" ) MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( StealthUpdate, StealthUpdateModuleData ); public: StealthUpdate( Thing *thing, const ModuleData* moduleData ); // virtual destructor prototype provided by memory pool declaration virtual StealthUpdate* getStealth() { return this; } virtual UpdateSleepTime update(); //Still gets called, even if held -ML virtual DisabledMaskType getDisabledTypesToProcess() const { return MAKE_DISABLED_MASK( DISABLED_HELD ); } // ??? ugh Bool isDisguised() const { return m_disguiseAsTemplate != NULL; } Int getDisguisedPlayerIndex() const { return m_disguiseAsPlayerIndex; } const ThingTemplate *getDisguisedTemplate() { return m_disguiseAsTemplate; } void markAsDetected( UnsignedInt numFrames = 0 ); void disguiseAsObject( const Object *target ); //wrapper function for ease. Real getFriendlyOpacity() const; UnsignedInt getStealthDelay() const { return getStealthUpdateModuleData()->m_stealthDelay; } UnsignedInt getStealthLevel() const { return getStealthUpdateModuleData()->m_stealthLevel; } EvaMessage getEnemyDetectionEvaEvent() const { return getStealthUpdateModuleData()->m_enemyDetectionEvaEvent; } EvaMessage getOwnDetectionEvaEvent() const { return getStealthUpdateModuleData()->m_ownDetectionEvaEvent; } Bool getOrderIdleEnemiesToAttackMeUponReveal() const { return getStealthUpdateModuleData()->m_orderIdleEnemiesToAttackMeUponReveal; } Object* calcStealthOwner(); //Is it me that can stealth or is it my rider? Bool allowedToStealth( Object *stealthOwner ) const; void receiveGrant( Bool active = TRUE, UnsignedInt frames = 0 ); Bool isGrantedBySpecialPower( void ) { return getStealthUpdateModuleData()->m_grantedBySpecialPower; } Bool isTemporaryGrant() { return m_framesGranted > 0; } protected: StealthLookType calcStealthedStatusForPlayer(const Object* obj, const Player* player); Bool canDisguise() const { return getStealthUpdateModuleData()->m_teamDisguised; } Real getRevealDistanceFromTarget() const { return getStealthUpdateModuleData()->m_revealDistanceFromTarget; } void hintDetectableWhileUnstealthed( void ) ; void changeVisualDisguise(); UpdateSleepTime calcSleepTime() const; private: UnsignedInt m_stealthAllowedFrame; UnsignedInt m_detectionExpiresFrame; mutable UnsignedInt m_nextBlackMarketCheckFrame; Bool m_enabled; Real m_pulsePhaseRate; Real m_pulsePhase; //Disguise only members Int m_disguiseAsPlayerIndex; //The player team we are wanting to disguise as (might not actually be disguised yet). const ThingTemplate *m_disguiseAsTemplate; //The disguise template (might not actually be using it yet) UnsignedInt m_disguiseTransitionFrames; //How many frames are left before transition is complete. Bool m_disguiseHalfpointReached; //In the middle of the transition, we will switch drawables! Bool m_transitioningToDisguise; //Set when we are disguising -- clear when we're transitioning out of. Bool m_disguised; //We're disguised as far as other players are concerned. UnsignedInt m_framesGranted; //0 means forever... everything else is number of frames before stealth lost. // runtime xfer members (does not need saving) Bool m_xferRestoreDisguise; //Tells us we need to restore our disguise WeaponSetType m_requiresWeaponSetType; }; #endif