Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Core/GameEngine/Include/Common/INI.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ class INI
static void parseMetaMapDefinition( INI *ini );
static void parseFXListDefinition( INI *ini );
static void parseBuffTemplateDefinition( INI* ini );
static void parseChatCommandDefinition( INI* ini );
static void parseObjectCreationListDefinition( INI* ini );
static void parseMultiplayerSettingsDefinition( INI* ini );
static void parseMultiplayerColorDefinition( INI* ini );
Expand Down
1 change: 1 addition & 0 deletions Core/GameEngine/Source/Common/INI/INI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ static const BlockParse theTypeTable[] =
{ "BuffTemplate", INI::parseBuffTemplateDefinition },
{ "Campaign", INI::parseCampaignDefinition },
{ "ChallengeGenerals", INI::parseChallengeModeDefinition },
{ "ChatCommand", INI::parseChatCommandDefinition },
{ "CommandButton", INI::parseCommandButtonDefinition },
{ "CommandMap", INI::parseMetaMapDefinition },
{ "CommandSet", INI::parseCommandSetDefinition },
Expand Down
2 changes: 2 additions & 0 deletions GeneralsMD/Code/GameEngine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ set(GAMEENGINE_SRC
# Include/Common/GameAudio.h
# Include/Common/GameCommon.h
# Include/Common/GameDefines.h
Include/Common/ChatCommand.h
Include/Common/GameEngine.h
Include/Common/GameLOD.h
# Include/Common/GameMemory.h
Expand Down Expand Up @@ -601,6 +602,7 @@ set(GAMEENGINE_SRC
Source/Common/Bezier/BezFwdIterator.cpp
Source/Common/Bezier/BezierSegment.cpp
Source/Common/BitFlags.cpp
Source/Common/ChatCommand.cpp
Source/Common/CommandLine.cpp
# Source/Common/crc.cpp
# Source/Common/CRCDebug.cpp
Expand Down
112 changes: 112 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/ChatCommand.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/

// FILE: ChatCommand.h //////////////////////////////////////////////////////////////////////////
// Desc: Parsing and storage for ChatCommand blocks defined in the optional ChatCommands.ini.
// Commands carry no behavior yet; key/value attributes and dispatch logic come later.
//////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#ifndef _ChatCommand_H_
#define _ChatCommand_H_

// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/AsciiString.h"
#include "Common/SubsystemInterface.h"
#include <vector>

// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class INI;
struct FieldParse;

//-------------------------------------------------------------------------------------------------
/** A single chat command parsed from a "ChatCommand <name> ... End" block. */
//-------------------------------------------------------------------------------------------------
class ChatCommand
{
public:
ChatCommand() {}

const AsciiString& getName() const { return m_name; }
void setName( const AsciiString& name ) { m_name = name; }

const FieldParse* getFieldParse() const { return s_fieldParseTable; }

Int getAddMoney() const { return m_addMoney; }
UnsignedInt getAddRank() const { return m_addRank; }
Bool getReadyTimers() const { return m_readyTimers; }
const AsciiString& getSpawnObjectAtCursor() const { return m_spawnObjectAtCursor; }
Bool getTogglePrerequisites() const { return m_togglePrerequisites; }
Bool getToggleInfiniteEnergy() const { return m_toggleInfiniteEnergy; }
Bool getGrantAllUpgrades() const { return m_grantAllUpgrades; }
Int getAddVeterancyLevel() const { return m_addVeterancyLevel; }
Int getAddSalvageTier() const { return m_addSalvageTier; }
Real getProductionSpeedMultiplier() const { return m_productionSpeedMultiplier; }

/** Run this command's effects. Inspects the parsed members and acts accordingly. */
void execute() const;

private:
AsciiString m_name;
Int m_addMoney = 0; ///< "AddMoney" attribute; signed amount, defaults to 0.
UnsignedInt m_addRank = 0; ///< "AddRank" attribute; ranks to grant, capped at the max rank. Defaults to 0.
Bool m_readyTimers = FALSE; ///< "ReadyTimers" attribute; when TRUE, set all of the player's special power timers to ready.
AsciiString m_spawnObjectAtCursor; ///< "SpawnObjectAtCursor" attribute; ObjectTemplate name to spawn for the local player at the mouse cursor.
Bool m_togglePrerequisites = FALSE; ///< "TogglePrerequisites" attribute; when TRUE, toggles ignoring unit/building build prereqs (science still applies).
Bool m_toggleInfiniteEnergy = FALSE; ///< "ToggleInfiniteEnergy" attribute; when TRUE, toggles infinite power for the local player.
Bool m_grantAllUpgrades = FALSE; ///< "GrantAllUpgrades" attribute; when TRUE, grants the local player all player-type upgrades.
Int m_addVeterancyLevel = 0; ///< "AddVeterancyLevel" attribute; promote selected units by this many veterancy levels (negative demotes), capped to the valid range.
Int m_addSalvageTier = 0; ///< "AddSalvageTier" attribute; change selected salvagers' crate-upgrade tier by this much (negative removes), capped 0..2.
Real m_productionSpeedMultiplier = 0.0f; ///< "ProductionSpeedMultiplier" attribute; build-speed multiplier for the local player (>1 builds faster). 0 means the field was absent (no change).

static const FieldParse s_fieldParseTable[];
};

//-------------------------------------------------------------------------------------------------
/** The store that owns all ChatCommands parsed from ChatCommands.ini. */
//-------------------------------------------------------------------------------------------------
class ChatCommandStore : public SubsystemInterface
{
public:
ChatCommandStore() {}
virtual ~ChatCommandStore();

virtual void init() {}
virtual void reset();
virtual void update() {}

/** Return the command with the given name, or NULL if none exists. */
const ChatCommand* findChatCommand( const AsciiString& name ) const;

/** Number of parsed commands. */
UnsignedInt getChatCommandCount() const { return (UnsignedInt)m_commands.size(); }

// INI block parser, registered in INI's block table.
static void parseChatCommandDefinition( INI* ini );

private:
void clear();

std::vector<ChatCommand*> m_commands;
};

// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
extern ChatCommandStore* TheChatCommandStore;

#endif // _ChatCommand_H_
6 changes: 6 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/Energy.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class Energy : public Snapshot
m_energyProduction = 0;
m_energyConsumption = 0;
m_powerSabotagedTillFrame = 0;
m_infinitePower = FALSE;
m_owner = owner;
}

Expand Down Expand Up @@ -98,6 +99,10 @@ class Energy : public Snapshot
void setPowerSabotagedTillFrame( UnsignedInt frame ) { m_powerSabotagedTillFrame = frame; }
UnsignedInt getPowerSabotagedTillFrame() const { return m_powerSabotagedTillFrame; }

/// when set, the player always has sufficient power (overrides production/consumption and sabotage).
void setInfinitePower( Bool enable ) { m_infinitePower = enable; }
Bool hasInfinitePower() const { return m_infinitePower; }

/**
return the percentage of energy needed that we actually produce, as a 0.0 ... 1.0 fraction.
*/
Expand All @@ -118,5 +123,6 @@ class Energy : public Snapshot
Int m_energyProduction; ///< level of energy production, in kw
Int m_energyConsumption; ///< level of energy consumption, in kw
UnsignedInt m_powerSabotagedTillFrame; ///< If power is sabotaged, the frame will be greater than now.
Bool m_infinitePower; ///< cheat: always have sufficient power
Player *m_owner; ///< Tight pointer to the Player I am intrinsic to.
};
2 changes: 2 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/GlobalData.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ class GlobalData : public SubsystemInterface
// Latency insertion, packet loss for network debugging
Int m_netMinPlayers; ///< Min players needed to start a net game

Bool m_enableSingleplayerChatWindow; ///< Allow the in-game chat window in singleplayer/skirmish (for chat commands)

UnsignedInt m_defaultIP; ///< preferred IP address for LAN
UnsignedInt m_firewallBehavior; ///< Last detected firewall behavior
Bool m_firewallSendDelay; ///< Use send delay for firewall connection negotiations
Expand Down
18 changes: 18 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,10 @@ class Player : public Snapshot
void addPowerBonus(Object *obj) { m_energy.addPowerBonus(obj); }
void removePowerBonus(Object *obj) { m_energy.removePowerBonus(obj); }

/// cheat: set/toggle infinite power, refreshing power-dependent objects to match.
void setInfinitePower(Bool enable);
void toggleInfinitePower() { setInfinitePower( !m_energy.hasInfinitePower() ); }

ResourceGatheringManager *getResourceGatheringManager(){ return m_resourceGatheringManager; }
TunnelTracker* getTunnelSystem(){ return m_tunnelSystem; }

Expand Down Expand Up @@ -348,6 +352,11 @@ class Player : public Snapshot
Bool buildsInstantly() const { return m_DEMO_instantBuild; }
#endif

/// When set, unit/building build prerequisites are ignored for this player (science prereqs still apply).
void toggleIgnoreUnitPrereqs() { m_ignoreUnitPrereqs = !m_ignoreUnitPrereqs; }
void setIgnoreUnitPrereqs(Bool enable) { m_ignoreUnitPrereqs = enable; }
Bool ignoresUnitPrereqs() const { return m_ignoreUnitPrereqs; }

///< Power just changed at all. Didn't make two functions so you can't forget to undo something you didin one of them.
///< @todo Can't do edge trigger until after demo; make things check for power on creation
void onPowerBrownOutChange( Bool brownOut );
Expand Down Expand Up @@ -405,6 +414,10 @@ class Player : public Snapshot
/// Returns production cost change based on typeof (Used for upgrades)
Real getProductionTimeChangeBasedOnKindOf(KindOfMaskType kindOf) const;

/// Build-speed multiplier applied to units, upgrades and buildings. >1 builds faster. Set via the ProductionSpeedMultiplier chat command.
Real getProductionSpeedMultiplier() const { return m_productionSpeedMultiplier; }
void setProductionSpeedMultiplier( Real m ) { m_productionSpeedMultiplier = m; }


/** Return bonus or penalty for construction of this thing.
*/
Expand Down Expand Up @@ -842,6 +855,8 @@ class Player : public Snapshot
Bool m_DEMO_instantBuild; ///< Can I build anything in one frame?
#endif

Bool m_ignoreUnitPrereqs; ///< ignore unit/building build prereqs (science prereqs still apply)

ScoreKeeper m_scoreKeeper; ///< The local scorekeeper for this player

// Production Cost modifier
Expand All @@ -851,6 +866,9 @@ class Player : public Snapshot
// Production Time modifier (we can re-use the same types)
mutable KindOfPercentProductionChangeList m_kindOfPercentProductionTimeChangeList;

// Global build-speed multiplier for this player (>1 = faster). Defaults to 1.0 (no change).
Real m_productionSpeedMultiplier;


typedef std::list<SpecialPowerReadyTimerType> SpecialPowerReadyTimerList;
typedef SpecialPowerReadyTimerList::iterator SpecialPowerReadyTimerListIterator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ class ProductionPrerequisite
/// not satisfied yet
UnicodeString getRequiresList(const Player *player) const;

/// return true iff the player satisfies our set of prerequisites
Bool isSatisfied(const Player *player) const;
/// return true iff the player satisfies our set of prerequisites.
/// if ignoreUnitPrereqs is set, only science prerequisites are enforced.
Bool isSatisfied(const Player *player, Bool ignoreUnitPrereqs = FALSE) const;

/**
return the BuildFacilityTemplate, if any.
Expand Down
Loading
Loading