forked from electronicarts/CnC_Generals_Zero_Hour
-
Notifications
You must be signed in to change notification settings - Fork 188
Expand file tree
/
Copy pathAutoHealBehavior.h
More file actions
189 lines (155 loc) · 8.22 KB
/
AutoHealBehavior.h
File metadata and controls
189 lines (155 loc) · 8.22 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
/*
** 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/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: AutoHealBehavior.h /////////////////////////////////////////////////////////////////////////
// Author: Colin Day, December 2001
// Desc: Update that heals itself
//------------------------------------------
// Modified by Kris Morness, September 2002
// Kris: Added the ability to add effects, radius healing, and restricting the type of objects
// subjected to the heal (or repair).
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameClient/ParticleSys.h"
#include "GameLogic/Module/BehaviorModule.h"
#include "GameLogic/Module/UpgradeModule.h"
#include "GameLogic/Module/UpdateModule.h"
#include "GameLogic/Module/DamageModule.h"
#include "Common/BitFlagsIO.h"
class ParticleSystem;
class ParticleSystemTemplate;
//-------------------------------------------------------------------------------------------------
class AutoHealBehaviorModuleData : public UpdateModuleData
{
public:
UpgradeMuxData m_upgradeMuxData;
Bool m_initiallyActive;
Bool m_singleBurst;
Int m_healingAmount;
UnsignedInt m_healingDelay;
UnsignedInt m_startHealingDelay; ///< how long since our last damage till autoheal starts.
Real m_radius; //If non-zero, then it becomes a area effect.
Bool m_affectsWholePlayer; ///< I have more than a range, I try to affect everything the player owns
Bool m_skipSelfForHealing; ///< Don't heal myself.
KindOfMaskType m_kindOf; //Only these types can heal -- defaults to everything.
KindOfMaskType m_forbiddenKindOf; //Only these types can heal -- defaults to everything.
const ParticleSystemTemplate* m_radiusParticleSystemTmpl; //Optional particle system meant to apply to entire effect for entire duration.
const ParticleSystemTemplate* m_unitHealPulseParticleSystemTmpl; //Optional particle system applying to each object getting healed each heal pulse.
AutoHealBehaviorModuleData()
{
m_initiallyActive = false;
m_singleBurst = FALSE;
m_healingAmount = 0;
m_healingDelay = UINT_MAX;
m_startHealingDelay = 0;
m_radius = 0.0f;
m_radiusParticleSystemTmpl = nullptr;
m_unitHealPulseParticleSystemTmpl = nullptr;
m_affectsWholePlayer = FALSE;
m_skipSelfForHealing = FALSE;
SET_ALL_KINDOFMASK_BITS( m_kindOf );
m_forbiddenKindOf.clear();
}
static void buildFieldParse(MultiIniFieldParse& p)
{
static const FieldParse dataFieldParse[] =
{
{ "StartsActive", INI::parseBool, nullptr, offsetof( AutoHealBehaviorModuleData, m_initiallyActive ) },
{ "SingleBurst", INI::parseBool, nullptr, offsetof( AutoHealBehaviorModuleData, m_singleBurst ) },
{ "HealingAmount", INI::parseInt, nullptr, offsetof( AutoHealBehaviorModuleData, m_healingAmount ) },
{ "HealingDelay", INI::parseDurationUnsignedInt, nullptr, offsetof( AutoHealBehaviorModuleData, m_healingDelay ) },
{ "Radius", INI::parseReal, nullptr, offsetof( AutoHealBehaviorModuleData, m_radius ) },
{ "KindOf", KindOfMaskType::parseFromINI, nullptr, offsetof( AutoHealBehaviorModuleData, m_kindOf ) },
{ "ForbiddenKindOf", KindOfMaskType::parseFromINI, nullptr, offsetof( AutoHealBehaviorModuleData, m_forbiddenKindOf ) },
{ "RadiusParticleSystemName", INI::parseParticleSystemTemplate, nullptr, offsetof( AutoHealBehaviorModuleData, m_radiusParticleSystemTmpl ) },
{ "UnitHealPulseParticleSystemName", INI::parseParticleSystemTemplate, nullptr, offsetof( AutoHealBehaviorModuleData, m_unitHealPulseParticleSystemTmpl ) },
{ "StartHealingDelay", INI::parseDurationUnsignedInt, nullptr, offsetof( AutoHealBehaviorModuleData, m_startHealingDelay ) },
{ "AffectsWholePlayer", INI::parseBool, nullptr, offsetof( AutoHealBehaviorModuleData, m_affectsWholePlayer ) },
{ "SkipSelfForHealing", INI::parseBool, nullptr, offsetof( AutoHealBehaviorModuleData, m_skipSelfForHealing ) },
{ 0, 0, 0, 0 }
};
UpdateModuleData::buildFieldParse(p);
p.add(dataFieldParse);
p.add(UpgradeMuxData::getFieldParse(), offsetof( AutoHealBehaviorModuleData, m_upgradeMuxData ));
}
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class AutoHealBehavior : public UpdateModule,
public UpgradeMux,
public DamageModuleInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AutoHealBehavior, "AutoHealBehavior" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( AutoHealBehavior, AutoHealBehaviorModuleData )
public:
AutoHealBehavior( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
// module methods
static Int getInterfaceMask() { return UpdateModule::getInterfaceMask() | MODULEINTERFACE_UPGRADE | MODULEINTERFACE_DAMAGE; }
// BehaviorModule
virtual UpgradeModuleInterface* getUpgrade() override { return this; }
virtual DamageModuleInterface* getDamage() override { return this; }
// DamageModuleInterface
virtual void onDamage( DamageInfo *damageInfo ) override;
virtual void onHealing( DamageInfo *damageInfo ) override { }
virtual void onBodyDamageStateChange(const DamageInfo* damageInfo, BodyDamageType oldState, BodyDamageType newState) override { }
// UpdateModuleInterface
virtual UpdateSleepTime update() override;
virtual DisabledMaskType getDisabledTypesToProcess() const override { return MAKE_DISABLED_MASK( DISABLED_HELD ); }
void stopHealing();
void undoUpgrade(); ///<pretend like we have not been activated yet, so we can be reactivated later
protected:
virtual void upgradeImplementation() override
{
setWakeFrame(getObject(), UPDATE_SLEEP_NONE);
}
virtual void getUpgradeActivationMasks(UpgradeMaskType& activation, UpgradeMaskType& conflicting) const override
{
getAutoHealBehaviorModuleData()->m_upgradeMuxData.getUpgradeActivationMasks(activation, conflicting);
}
virtual void performUpgradeFX() override
{
getAutoHealBehaviorModuleData()->m_upgradeMuxData.performUpgradeFX(getObject());
}
virtual void processUpgradeRemoval() override
{
// I can't take it any more. Let the record show that I think the UpgradeMux multiple inheritance is CRAP.
getAutoHealBehaviorModuleData()->m_upgradeMuxData.muxDataProcessUpgradeRemoval(getObject());
}
virtual Bool requiresAllActivationUpgrades() const override
{
return getAutoHealBehaviorModuleData()->m_upgradeMuxData.m_requiresAllTriggers;
}
Bool isUpgradeActive() const { return isAlreadyUpgraded(); }
virtual Bool isSubObjectsUpgrade() override { return false; }
private:
void pulseHealObject( Object *obj );
void createEmitters();
ParticleSystemID m_radiusParticleSystemID;
UnsignedInt m_soonestHealFrame;/** I need to record this, because with multiple wake up sources,
I can't rely solely on my sleeping. So this will guard onDamage's wake up.
I could guard the act of healing, but that would defeat the gain of being
a sleepy module. I never want to run update unless I am going to heal.
*/
Bool m_stopped;
};