/*
** 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: Upgrade.h ////////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, March 2002
// Desc: Upgrade system for players
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __UPGRADE_H_
#define __UPGRADE_H_
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
#include "Common/AudioEventRTS.h"
#include "Common/INI.h"
#include "Common/Snapshot.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Player;
class UpgradeTemplate;
enum NameKeyType;
class Image;
enum AcademyClassificationType;
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
enum UpgradeStatusType
{
UPGRADE_STATUS_INVALID = 0,
UPGRADE_STATUS_IN_PRODUCTION,
UPGRADE_STATUS_COMPLETE
};
//The maximum number of upgrades.
#define UPGRADE_MAX_COUNT 128
typedef BitFlags UpgradeMaskType;
#define MAKE_UPGRADE_MASK(k) UpgradeMaskType(UpgradeMaskType::kInit, (k))
#define MAKE_UPGRADE_MASK2(k,a) UpgradeMaskType(UpgradeMaskType::kInit, (k), (a))
#define MAKE_UPGRADE_MASK3(k,a,b) UpgradeMaskType(UpgradeMaskType::kInit, (k), (a), (b))
#define MAKE_UPGRADE_MASK4(k,a,b,c) UpgradeMaskType(UpgradeMaskType::kInit, (k), (a), (b), (c))
#define MAKE_UPGRADE_MASK5(k,a,b,c,d) UpgradeMaskType(UpgradeMaskType::kInit, (k), (a), (b), (c), (d))
inline Bool TEST_UPGRADE_MASK( const UpgradeMaskType& m, Int index )
{
return m.test( index );
}
inline Bool TEST_UPGRADE_MASK_ANY( const UpgradeMaskType& m, const UpgradeMaskType& mask )
{
return m.anyIntersectionWith( mask );
}
inline Bool TEST_UPGRADE_MASK_MULTI( const UpgradeMaskType& m, const UpgradeMaskType& mustBeSet, const UpgradeMaskType& mustBeClear )
{
return m.testSetAndClear( mustBeSet, mustBeClear );
}
inline Bool UPGRADE_MASK_ANY_SET( const UpgradeMaskType& m)
{
return m.any();
}
inline void CLEAR_UPGRADE_MASK( UpgradeMaskType& m )
{
m.clear();
}
inline void SET_ALL_UPGRADE_MASK_BITS( UpgradeMaskType& m )
{
m.clear( );
m.flip( );
}
inline void FLIP_UPGRADE_MASK( UpgradeMaskType& m )
{
m.flip();
}
//-------------------------------------------------------------------------------------------------
/** A single upgrade *INSTANCE* */
//-------------------------------------------------------------------------------------------------
class Upgrade : public MemoryPoolObject,
public Snapshot
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( Upgrade, "Upgrade" )
public:
Upgrade( const UpgradeTemplate *upgradeTemplate );
// virtual destructor prototypes provided by memory pool object
/// get the upgrade template for this instance
const UpgradeTemplate *getTemplate( void ) const { return m_template; }
// status access
UpgradeStatusType getStatus( void ) const { return m_status; } ///< get status
void setStatus( UpgradeStatusType status ) { m_status = status; } ///< set the status
// friend access methods
void friend_setNext( Upgrade *next ) { m_next = next; }
void friend_setPrev( Upgrade *prev ) { m_prev = prev; }
Upgrade *friend_getNext( void ) { return m_next; }
Upgrade *friend_getPrev( void ) { return m_prev; }
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
const UpgradeTemplate *m_template; ///< template this upgrade instance is based on
UpgradeStatusType m_status; ///< status of upgrade
Upgrade *m_next; ///< next
Upgrade *m_prev; ///< prev
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
enum UpgradeType
{
UPGRADE_TYPE_PLAYER = 0, // upgrade applies to a player as a whole
UPGRADE_TYPE_OBJECT, // upgrade applies to an object instance only
NUM_UPGRADE_TYPES, // keep this last
};
extern const char *TheUpgradeTypeNames[]; //Change above, change this!
//-------------------------------------------------------------------------------------------------
/** A single upgrade template definition */
//-------------------------------------------------------------------------------------------------
class UpgradeTemplate : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( UpgradeTemplate, "UpgradeTemplate" )
public:
UpgradeTemplate( void );
// virtual destructor defined by memory pool object
Int calcTimeToBuild( Player *player ) const; ///< time in logic frames it will take this player to "build" this UpgradeTemplate
Int calcCostToBuild( Player *player ) const; ///< calc the cost to build this upgrade
// field access
void setUpgradeName( const AsciiString& name ) { m_name = name; }
const AsciiString& getUpgradeName( void ) const { return m_name; }
void setUpgradeNameKey( NameKeyType key ) { m_nameKey = key; }
NameKeyType getUpgradeNameKey( void ) const { return m_nameKey; }
const AsciiString& getDisplayNameLabel( void ) const { return m_displayNameLabel; }
UpgradeMaskType getUpgradeMask() const { return m_upgradeMask; }
UpgradeType getUpgradeType( void ) const { return m_type; }
const AudioEventRTS* getResearchCompleteSound() const { return &m_researchSound; }
const AudioEventRTS* getUnitSpecificSound() const { return &m_unitSpecificSound; }
AcademyClassificationType getAcademyClassificationType() const { return m_academyClassificationType; }
/// inventory pictures
void cacheButtonImage();
const Image* getButtonImage() const { return m_buttonImage; }
/// INI parsing
const FieldParse *getFieldParse() const { return m_upgradeFieldParseTable; }
// friend access methods for the UpgradeCenter ONLY
void friend_setNext( UpgradeTemplate *next ) { m_next = next; }
void friend_setPrev( UpgradeTemplate *prev ) { m_prev = prev; }
UpgradeTemplate *friend_getNext( void ) { return m_next; }
UpgradeTemplate *friend_getPrev( void ) { return m_prev; }
const UpgradeTemplate *friend_getNext( void ) const { return m_next; }
const UpgradeTemplate *friend_getPrev( void ) const { return m_prev; }
void friend_setUpgradeMask( UpgradeMaskType mask ) { m_upgradeMask = mask; }
void friend_makeVeterancyUpgrade(VeterancyLevel v);
protected:
UpgradeType m_type; ///< upgrade type (PLAYER or OBJECT)
AsciiString m_name; ///< upgrade name
NameKeyType m_nameKey; ///< name key
AsciiString m_displayNameLabel; ///< String manager label for UI display name
Real m_buildTime; ///< database # for how long it takes to "build" this
Int m_cost; ///< cost for production
UpgradeMaskType m_upgradeMask; ///< Unique bitmask for this upgrade template
AudioEventRTS m_researchSound; ///< Sound played when upgrade researched.
AudioEventRTS m_unitSpecificSound; ///< Secondary sound played when upgrade researched.
AcademyClassificationType m_academyClassificationType; ///< A value used by the academy to evaluate advice based on what players do.
UpgradeTemplate *m_next; ///< next
UpgradeTemplate *m_prev; ///< prev
AsciiString m_buttonImageName; ///< "Queue" images to show in the build queue
const Image *m_buttonImage;
/// INI field table
static const FieldParse m_upgradeFieldParseTable[]; ///< the parse table
};
//-------------------------------------------------------------------------------------------------
/** The upgrade center keeps some basic information about the possible upgrades */
//-------------------------------------------------------------------------------------------------
class UpgradeCenter : public SubsystemInterface
{
public:
UpgradeCenter( void );
virtual ~UpgradeCenter( void );
void init( void ); ///< subsystem interface
void reset( void ); ///< subsystem interface
void update( void ) { } ///< subsystem interface
UpgradeTemplate *firstUpgradeTemplate( void ); ///< return the first upgrade template
const UpgradeTemplate *findUpgradeByKey( NameKeyType key ) const; ///< find upgrade by name key
const UpgradeTemplate *findUpgrade( const AsciiString& name ) const; ///< find and return upgrade by name
const UpgradeTemplate *findVeterancyUpgrade(VeterancyLevel level) const; ///< find and return upgrade by name
UpgradeTemplate *newUpgrade( const AsciiString& name ); ///< allocate, link, and return new upgrade
/// does this player have all the necessary things to make this upgrade
Bool canAffordUpgrade( Player *player, const UpgradeTemplate *upgradeTemplate, Bool displayReason = FALSE ) const;
std::vector getUpgradeNames( void ) const; // For WorldBuilder only!!!
static void parseUpgradeDefinition( INI *ini );
protected:
UpgradeTemplate *findNonConstUpgradeByKey( NameKeyType key ); ///< find upgrade by name key
void linkUpgrade( UpgradeTemplate *upgrade ); ///< link upgrade to list
void unlinkUpgrade( UpgradeTemplate *upgrade ); ///< remove upgrade from list
UpgradeTemplate *m_upgradeList; ///< list of all upgrades we can have
Int m_nextTemplateMaskBit; ///< Each instantiated UpgradeTemplate will be given a Int64 bit as an identifier
Bool buttonImagesCached;
};
// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
extern UpgradeCenter *TheUpgradeCenter;
#endif // end __UPGRADE_H_