forked from electronicarts/CnC_Generals_Zero_Hour
-
Notifications
You must be signed in to change notification settings - Fork 184
Expand file tree
/
Copy pathProductionUpdate.h
More file actions
256 lines (192 loc) · 11.8 KB
/
ProductionUpdate.h
File metadata and controls
256 lines (192 loc) · 11.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/*
** 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: ProductionUpdate.h ///////////////////////////////////////////////////////////////////////
// Author: Colin Day, March 2002
// Desc: This module allows things to be "constructed" from a building
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
#include "Common/ModelState.h"
#include "GameLogic/Module/DieModule.h"
#include "GameLogic/Module/UpdateModule.h"
// FORWARD REFERENCES //////////////////////////////////////////////////////////////////////////////
class ProductionEntry;
class ThingTemplate;
class UpgradeTemplate;
///////////////////////////////////////////////////////////////////////////////////////////////////
enum ProductionID CPP_11(: Int)
{
PRODUCTIONID_INVALID = 0
};
enum ProductionType CPP_11(: Int)
{
PRODUCTION_INVALID = 0,
PRODUCTION_UNIT,
PRODUCTION_UPGRADE
};
//-------------------------------------------------------------------------------------------------
/** A ProductionEntry is a single entry representing something that we are supposed to
* produce */
//-------------------------------------------------------------------------------------------------
class ProductionEntry : public MemoryPoolObject
{
friend class ProductionUpdate;
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ProductionEntry, "ProductionEntry" )
public:
ProductionEntry();
// virtual destructor provided by memory pool object
/// query what kind of thing is being produced by this entry
const ThingTemplate *getProductionObject() const { return m_objectToProduce; }
/// query what kind of upgrade is being produced by this entry
const UpgradeTemplate *getProductionUpgrade() const { return m_upgradeToResearch; }
/// query the production type
ProductionType getProductionType() const { return m_type; }
/// how much progress is done on this entry
Real getPercentComplete() const { return m_percentComplete; }
/// get the unique (to the producer object) production ID
ProductionID getProductionID() const { return m_productionID; }
Int getProductionQuantity() const { return m_productionQuantityTotal; } //How many I try to make
Int getProductionQuantityRemaining() const { return m_productionQuantityTotal - m_productionQuantityProduced; }//How many I have made
void oneProductionSuccessful() { ++m_productionQuantityProduced; m_exitDoor = DOOR_NONE_AVAILABLE; }//increment, and mark door to re-reserve
ExitDoorType getExitDoor() const { return m_exitDoor; }
void setExitDoor(ExitDoorType exitDoor) { m_exitDoor = exitDoor; }
protected:
ProductionType m_type; ///< production type
union
{
const ThingTemplate *m_objectToProduce; ///< what we're going to produce
const UpgradeTemplate *m_upgradeToResearch; ///< what upgrade we're researching
};
ProductionID m_productionID; ///< our very own production ID!
Real m_percentComplete; ///< percent our construction is complete
Int m_framesUnderConstruction; ///< counter for how many frames we've been under construction (incremented once per update)
Int m_productionQuantityTotal; ///< it is now possible to construct multiple units simultaneously.
Int m_productionQuantityProduced; ///< And we need to allow pausing within an entry, so we keep track of number of sub-successes
ExitDoorType m_exitDoor;
ProductionEntry *m_next; ///< next in list
ProductionEntry *m_prev; ///< prev in list
};
//-------------------------------------------------------------------------------------------------
struct QuantityModifier
{
AsciiString m_templateName;
Int m_quantity;
};
//-------------------------------------------------------------------------------------------------
class ProductionUpdateModuleData : public UpdateModuleData
{
public:
Int m_numDoorAnimations; ///< has a door animation(s) upon unit built and exit
UnsignedInt m_doorOpeningTime; ///< in frames, time it takes the door to open
UnsignedInt m_doorWaitOpenTime; ///< in frames, time we should leave the door open
UnsignedInt m_doorClosingTime; ///< in frames, time it takes to close the door
UnsignedInt m_constructionCompleteDuration; ///< in frames, how long we state in "construction complete" condition after making something
std::vector<QuantityModifier> m_quantityModifiers; ///< Quantity modifiers modify the number of specified object to created whenever produced.
Int m_maxQueueEntries; ///< max things that can be queued at once.
DisabledMaskType m_disabledTypesToProcess;
ProductionUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
static void parseAppendQuantityModifier( INI* ini, void *instance, void *store, const void *userData );
};
//-------------------------------------------------------------------------------------------------
enum CanMakeType CPP_11(: Int);
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class ProductionUpdateInterface
{
public:
virtual CanMakeType canQueueCreateUnit( const ThingTemplate *unitType ) const = 0;
virtual CanMakeType canQueueUpgrade( const UpgradeTemplate *upgrade ) const = 0;
virtual ProductionID requestUniqueUnitID() = 0;
virtual Bool queueUpgrade( const UpgradeTemplate *upgrade ) = 0;
virtual void cancelUpgrade( const UpgradeTemplate *upgrade ) = 0;
virtual Bool isUpgradeInQueue( const UpgradeTemplate *upgrade ) const = 0;
virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const = 0;
virtual Bool queueCreateUnit( const ThingTemplate *unitType, ProductionID productionID ) = 0;
virtual void cancelUnitCreate( ProductionID productionID, Bool forceCancel = FALSE ) = 0;
virtual void cancelAllUnitsOfType( const ThingTemplate *unitType) = 0;
virtual void cancelAndRefundAllProduction() = 0;
virtual UnsignedInt getProductionCount() const = 0;
virtual const ProductionEntry *firstProduction() const = 0;
virtual const ProductionEntry *nextProduction( const ProductionEntry *p ) const = 0;
virtual void setHoldDoorOpen(ExitDoorType exitDoor, Bool holdIt) = 0;
};
//-------------------------------------------------------------------------------------------------
/** Production modules do actual unit construction */
//-------------------------------------------------------------------------------------------------
class ProductionUpdate : public UpdateModule, public ProductionUpdateInterface, public DieModuleInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ProductionUpdate, "ProductionUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( ProductionUpdate, ProductionUpdateModuleData )
public:
ProductionUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by MemoryPoolObject
static Int getInterfaceMask() { return UpdateModule::getInterfaceMask() | (MODULEINTERFACE_DIE); }
// Disabled conditions to process (AI will still process held status)
virtual DisabledMaskType getDisabledTypesToProcess() const { return getProductionUpdateModuleData()->m_disabledTypesToProcess; }
virtual ProductionUpdateInterface* getProductionUpdateInterface() { return this; }
virtual DieModuleInterface* getDie() { return this; }
static ProductionUpdateInterface *getProductionUpdateInterfaceFromObject( Object *obj );
virtual CanMakeType canQueueCreateUnit( const ThingTemplate *unitType ) const;
virtual CanMakeType canQueueUpgrade( const UpgradeTemplate *upgrade ) const;
/** this method is used to request a unique ID to assign to the production of a single
unit. It is unique to all units that can be created from this source object, but is
not unique among multiple source objects */
virtual ProductionID requestUniqueUnitID() { ProductionID tmp = m_uniqueID; m_uniqueID = (ProductionID)(m_uniqueID+1); return tmp; }
virtual Bool queueUpgrade( const UpgradeTemplate *upgrade ); ///< queue upgrade "research"
virtual void cancelUpgrade( const UpgradeTemplate *upgrade ); ///< cancel upgrade "research"
virtual Bool isUpgradeInQueue( const UpgradeTemplate *upgrade ) const; ///< is the upgrade in our production queue already
virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const; ///< count number of units with matching unit type in the production queue
virtual Bool queueCreateUnit( const ThingTemplate *unitType, ProductionID productionID ); ///< queue unit to be produced
virtual void cancelUnitCreate( ProductionID productionID, Bool forceCancel = FALSE ); ///< cancel construction of unit with matching production ID
virtual void cancelAllUnitsOfType( const ThingTemplate *unitType); ///< cancel all production of type unitType
virtual void cancelAndRefundAllProduction(); ///< cancel and refund anything in the production queue
virtual UnsignedInt getProductionCount() const { return m_productionCount; } ///< return # of things in the production queue
// walking the production list from outside
virtual const ProductionEntry *firstProduction() const { return m_productionQueue; }
virtual const ProductionEntry *nextProduction( const ProductionEntry *p ) const { return p ? p->m_next : nullptr; }
virtual void setHoldDoorOpen(ExitDoorType exitDoor, Bool holdIt);
virtual UpdateSleepTime update(); ///< the update
// DieModuleInterface
virtual void onDie( const DamageInfo *damageInfo );
protected:
void addToProductionQueue( ProductionEntry *production ); ///< add to *END* of production queue list
void removeFromProductionQueue( ProductionEntry *production ); ///< remove production from the queue list
void updateDoors(); ///< update the door behavior
struct DoorInfo
{
UnsignedInt m_doorOpenedFrame; ///< for producer objects that have a door open/close animation when they make something
UnsignedInt m_doorWaitOpenFrame; ///< frame we entered into wait open state
UnsignedInt m_doorClosedFrame; ///< frame any door was closed on
Bool m_holdOpen; ///< if T, don't allow door to close
};
ProductionEntry* m_productionQueue; ///< queue of things we want to build
ProductionEntry* m_productionQueueTail; ///< tail pointer for m_productionQueue
ProductionID m_uniqueID; ///< unique ID counter for producing units
UnsignedInt m_productionCount; ///< # of things in the production queue
UnsignedInt m_constructionCompleteFrame; ///< frame construction was complete on
DoorInfo m_doors[DOOR_COUNT_MAX];
ModelConditionFlags m_clearFlags; ///< flags to clear from model
ModelConditionFlags m_setFlags; ///< flags to set in model
Bool m_flagsDirty; ///< clearFlags/setFlags needs to be set into the model
};