Control: Change controls to use new callback infrastrucure.
[gemrb.git] / gemrb / core / EffectQueue.h
blob4cdc41fa1edb90b8925d0afaf388b3017a6fd631
1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 /**
22 * @file EffectQueue.h
23 * Declares EffectQueue class holding and processing all spell effects
24 * on a single Actor
25 * @author The GemRB Project
28 #ifndef EFFECTQUEUE_H
29 #define EFFECTQUEUE_H
31 #include "exports.h"
33 #include "Effect.h"
34 #include "Region.h"
36 #include <list>
38 class Actor;
39 class Map;
40 class Scriptable;
42 /** Maximum number of different Effect opcodes */
43 #define MAX_EFFECTS 512
45 ///** if the effect returns this, stop adding any other effect */
46 #define FX_ABORT 0
47 /** these effects don't stick around if used as permanent,
48 * in that case they modify a base stat like charisma modifier */
49 #define FX_PERMANENT 2
50 /** these effects never stick around, use them for instant effects like damage */
51 #define FX_NOT_APPLIED 3
52 /** these effects always stick around when applied as permanent or duration */
53 #define FX_APPLIED 1
54 ///** insert the effect instead of push back */
55 #define FX_INSERT 4
57 //remove level effects flags
58 #define RL_DISPELLABLE 1 //only dispellables
59 #define RL_MATCHSCHOOL 2 //match school
60 #define RL_MATCHSECTYPE 4 //match secondary type
61 #define RL_REMOVEFIRST 8 //remove only one spell (could be more effects)
63 //bouncing immunities
64 #define BNC_PROJECTILE 1
65 #define BNC_OPCODE 2
66 #define BNC_LEVEL 4
67 #define BNC_SCHOOL 8
68 #define BNC_SECTYPE 0x10
69 #define BNC_RESOURCE 0x20
70 #define BNC_PROJECTILE_DEC 0x100
71 #define BNC_OPCODE_DEC 0x200
72 #define BNC_LEVEL_DEC 0x400
73 #define BNC_SCHOOL_DEC 0x800
74 #define BNC_SECTYPE_DEC 0x1000
75 #define BNC_RESOURCE_DEC 0x2000
77 //normal immunities
78 #define IMM_PROJECTILE 1
79 #define IMM_OPCODE 2
80 #define IMM_LEVEL 4
81 #define IMM_SCHOOL 8
82 #define IMM_SECTYPE 16
83 #define IMM_RESOURCE 32
84 #define IMM_PROJECTILE_DEC 0x100
85 #define IMM_OPCODE_DEC 0x200
86 #define IMM_LEVEL_DEC 0x400
87 #define IMM_SCHOOL_DEC 0x800
88 #define IMM_SECTYPE_DEC 0x1000
89 #define IMM_RESOURCE_DEC 0x2000
91 // FIXME: Dice roll should be probably done just once, e.g. when equipping
92 // the item, not each time the fx are applied
93 // <avenger> the dice values are actually level limits, except in 3 hp modifier functions
94 // the damage function is an instant (the other 2 functions might be tricky with random values)
95 //#define DICE_ROLL(max_val) ((fx->DiceThrown && fx->DiceSides) ? ((max_val >=0) ? (MIN( core->Roll( fx->DiceThrown, fx->DiceSides, 0 ), max_val )) : (MAX( core->Roll( fx->DiceThrown, fx->DiceSides, 0 ), max_val ))) : max_val)
97 //sometimes damage doesn't comply with the calculated value
98 #define DICE_ROLL(adjustment) (core->Roll( fx->DiceThrown, fx->DiceSides, adjustment) )
100 // You will need to get GameTime somehow to use this macro
101 #define PrepareDuration(fx) fx->Duration = (fx->Duration*AI_UPDATE_TIME + GameTime)
103 // often used stat modifications, usually Parameter2 types 0, 1 and 2
104 //these macros should work differently in permanent mode (modify base too)
105 #define STAT_GET(stat) (target->Modified[ stat ])
106 #define STAT_ADD(stat, mod) target->SetStat( stat, STAT_GET( stat ) + ( mod ), 0 )
107 #define STAT_SUB(stat, mod) target->SetStat( stat, STAT_GET( stat ) - ( mod ), 0 )
108 #define STAT_BIT_OR(stat, mod) target->SetStat( stat, STAT_GET( stat ) | ( mod ), 0 )
109 #define STAT_SET(stat, mod) target->SetStat( stat, ( mod ), 0 )
110 #define STAT_SET_PCF(stat, mod) target->SetStat( stat, ( mod ), 1 )
111 #define STAT_BIT_OR_PCF(stat, mod) target->SetStat( stat, STAT_GET( stat ) | ( mod ), 1 )
112 #define STAT_MUL(stat, mod) target->SetStat( stat, STAT_GET(stat) * ( mod ) / 100, 0 )
113 //if an effect sticks around
114 #define STATE_CURE( mod ) target->Modified[ IE_STATE_ID ] &= ~(ieDword) ( mod )
115 #define STATE_SET( mod ) target->Modified[ IE_STATE_ID ] |= (ieDword) ( mod )
116 #define EXTSTATE_SET( mod ) target->Modified[ IE_EXTSTATE_ID ] |= (ieDword) ( mod )
117 #define STATE_GET( mod ) (target->Modified[ IE_STATE_ID ] & (ieDword) ( mod ) )
118 #define EXTSTATE_GET( mod ) (target->Modified[ IE_EXTSTATE_ID ] & (ieDword) ( mod ) )
119 #define STAT_MOD( stat ) target->NewStat(stat, fx->Parameter1, fx->Parameter2)
120 #define STAT_MOD_VAR( stat, mod ) target->NewStat(stat, ( mod ) , fx->Parameter2 )
121 #define BASE_GET(stat) (target->BaseStats[ stat ])
122 #define BASE_SET(stat, mod) target->SetBase( stat, ( mod ) )
123 #define BASE_ADD(stat, mod) target->SetBase( stat, BASE_GET(stat)+ ( mod ) )
124 #define BASE_SUB(stat, mod) target->SetBase( stat, BASE_GET(stat)- ( mod ) )
125 #define BASE_MUL(stat, mod) target->SetBase( stat, BASE_GET(stat)* ( mod ) / 100 )
126 #define BASE_MOD(stat) target->NewBase( stat, fx->Parameter1, fx->Parameter2)
127 #define BASE_MOD_VAR(stat, mod) target->NewBase( stat, (mod), fx->Parameter2 )
128 //if an effect doesn't stick (and has permanent until cured effect) then
129 //it has to modify the base stat (which is saved)
130 //also use this one if the effect starts a cure effect automatically
131 #define BASE_STATE_SET( mod ) target->SetBaseBit( IE_STATE_ID, ( mod ), true )
132 #define BASE_STATE_CURE( mod ) target->SetBaseBit( IE_STATE_ID, ( mod ), false )
134 /** Prototype of a function implementing a particular Effect opcode */
135 typedef int (* EffectFunction)(Scriptable*, Actor*, Effect*);
138 /** Links Effect name to a function implementing the effect */
139 struct EffectRef {
140 const char* Name;
141 EffectFunction Function;
142 int opcode;
145 /** Initializes table of available spell Effects used by all the queues. */
146 /** The available effects should already be registered by the effect plugins */
147 bool Init_EffectQueue();
149 /** Registers opcodes implemented by an effect plugin */
150 void EffectQueue_RegisterOpcodes(int count, const EffectRef *opcodes);
152 /** release effect list when Interface is destroyed */
153 void EffectQueue_ReleaseMemory();
155 /** Check if opcode is for an effect that takes a color slot as parameter. */
156 bool IsColorslotEffect(int opcode);
159 * @class EffectQueue
160 * Class holding and processing spell Effects on a single Actor
163 class GEM_EXPORT EffectQueue {
164 private:
165 /** List of Effects applied on the Actor */
166 std::list< Effect* > effects;
167 /** Actor which is target of the Effects */
168 Scriptable* Owner;
170 public:
171 EffectQueue();
172 virtual ~EffectQueue();
174 /** Sets Actor which is affected by these effects */
175 void SetOwner(Scriptable* act) { Owner = act; }
176 /** Returns Actor affected by these effects */
177 Scriptable* GetOwner() const { return Owner; }
179 /** adds an effect to the queue, it could also insert it if flagged so
180 * fx should be freed by the caller
182 void AddEffect(Effect* fx, bool insert=false);
183 /** Adds an Effect to the queue, subject to level and other checks.
184 * Returns FX_ABORT is unsuccessful. fx is just a reference, AddEffect()
185 * will malloc its own copy */
186 int AddEffect(Effect* fx, Scriptable* self, Actor* pretarget, const Point &dest) const;
187 /** Removes first Effect matching fx from the queue.
188 * Effects are matched based on their contents */
189 bool RemoveEffect(Effect* fx);
191 int AddAllEffects(Actor* target, const Point &dest) const;
192 void ApplyAllEffects(Actor* target) const;
193 /** remove effects marked for removal */
194 void Cleanup();
196 /* directly removes effects with specified opcode, use effect_reference when you can */
197 void RemoveAllEffects(ieDword opcode) const;
198 void RemoveAllEffectsWithResource(ieDword opcode, const ieResRef resource) const;
200 /* removes any effects (delayed or not) which were using projectile */
201 void RemoveAllEffectsWithProjectile(ieDword projectile) const;
203 /* removes equipping effects with specified inventory slot code */
204 void RemoveEquippingEffects(ieDwordSigned slotcode) const;
206 /* removes all effects of a given spell */
207 void RemoveAllEffects(const ieResRef Removed) const;
208 void RemoveAllEffects(const ieResRef Removed, ieByte timing) const;
209 /* removes all effects of type */
210 void RemoveAllEffects(EffectRef &effect_reference) const;
211 /* removes expired or to be expired effects */
212 void RemoveExpiredEffects(ieDword futuretime) const;
213 /* removes all effects except timing mode 9 */
214 void RemoveAllNonPermanentEffects() const;
215 void RemoveAllDetrimentalEffects(EffectRef &effect_reference, ieDword current) const;
216 void RemoveAllEffectsWithParam(EffectRef &effect_reference, ieDword param2) const;
217 void RemoveAllEffectsWithResource(EffectRef &effect_reference, const ieResRef resource) const;
218 void RemoveLevelEffects(ieDword level, ieDword flags, ieDword match) const;
220 /* returns true if the timing method supports simplified duration */
221 static bool HasDuration(Effect *fx);
222 /* returns true if the effect should be saved */
223 static bool Persistent(Effect* fx);
224 /* returns next saved effect, increases index */
225 std::list< Effect* >::const_iterator GetFirstEffect() const
227 return effects.begin();
229 const Effect *GetNextSavedEffect(std::list< Effect* >::const_iterator &f) const;
230 Effect *GetNextEffect(std::list< Effect* >::const_iterator &f) const;
231 ieDword CountEffects(EffectRef &effect_reference, ieDword param1, ieDword param2, const char *ResRef) const;
232 void ModifyEffectPoint(EffectRef &effect_reference, ieDword x, ieDword y) const;
233 /* returns the number of saved effects */
234 ieDword GetSavedEffectsCount() const;
235 size_t GetEffectsCount() const { return effects.size(); }
236 /* this method hacks the offhand weapon color effects */
237 static void HackColorEffects(Actor *Owner, Effect *fx);
238 static Effect *CreateEffect(EffectRef &effect_reference, ieDword param1, ieDword param2, ieWord timing);
239 EffectQueue *CopySelf() const;
240 static Effect *CreateEffectCopy(Effect *oldfx, EffectRef &effect_reference, ieDword param1, ieDword param2);
241 static Effect *CreateUnsummonEffect(Effect *fx);
242 //locating opcodes
243 Effect *HasEffect(EffectRef &effect_reference) const;
244 Effect *HasEffectWithParam(EffectRef &effect_reference, ieDword param2) const;
245 Effect *HasEffectWithParamPair(EffectRef &effect_reference, ieDword param1, ieDword param2) const;
246 Effect *HasEffectWithResource(EffectRef &effect_reference, const ieResRef resource) const;
247 Effect *HasEffectWithSource(EffectRef &effect_reference, const ieResRef source) const;
248 void DecreaseParam1OfEffect(EffectRef &effect_reference, ieDword amount) const;
249 int SpecificDamageBonus(ieDword damage_type) const;
250 bool HasAnyDispellableEffect() const;
251 //transforming timing modes
252 static void TransformToDelay(ieByte &TimingMode);
253 //getting summarised effects
254 int BonusAgainstCreature(EffectRef &effect_reference, Actor *actor) const;
255 //getting weapon immunity flag
256 bool WeaponImmunity(int enchantment, ieDword weapontype) const;
257 // checks if spells of type "types" are disabled (usually by armor)
258 // returns a bitfield of disabled spelltypes
259 int DisabledSpellcasting(int types) const;
261 // returns -1 if bounced, 0 if resisted, 1 if accepted spell
262 int CheckImmunity(Actor *target) const;
263 // apply this effectqueue on all actors matching ids targeting
264 // from pos, in range (no cone size yet)
265 void AffectAllInRange(Map *map, const Point &pos, int idstype, int idsvalue, unsigned int range, Actor *except);
266 /** Lists contents of the queue on a terminal for debugging */
267 void dump() const;
268 //resolve effect
269 static int ResolveEffect(EffectRef &effect_reference);
270 static bool match_ids(Actor *target, int table, ieDword value);
271 /** returns true if the process should abort applying a stack of effects */
272 int ApplyEffect(Actor* target, Effect* fx, ieDword first_apply) const;
273 private:
274 /** counts effects of specific opcode, parameters and resource */
275 ieDword CountEffects(ieDword opcode, ieDword param1, ieDword param2, const char *ResRef) const;
276 void ModifyEffectPoint(ieDword opcode, ieDword x, ieDword y) const;
277 //use the effect reference style calls from outside
278 static Effect *CreateEffect(ieDword opcode, ieDword param1, ieDword param2, ieWord timing);
279 static Effect *CreateEffectCopy(Effect *oldfx, ieDword opcode, ieDword param1, ieDword param2);
280 void RemoveAllDetrimentalEffects(ieDword opcode, ieDword current) const;
281 void RemoveAllEffectsWithParam(ieDword opcode, ieDword param2) const;
282 Effect *HasOpcode(ieDword opcode) const;
283 Effect *HasOpcodeWithParam(ieDword opcode, ieDword param2) const;
284 Effect *HasOpcodeWithParamPair(ieDword opcode, ieDword param1, ieDword param2) const;
285 Effect *HasOpcodeWithResource(ieDword opcode, const ieResRef resource) const;
286 Effect *HasOpcodeWithSource(ieDword opcode, const ieResRef source) const;
287 void DecreaseParam1OfEffect(ieDword opcode, ieDword amount) const;
288 int SpecificDamageBonus(ieDword opcode, ieDword param2) const;
289 int BonusAgainstCreature(ieDword opcode, Actor *actor) const;
290 bool WeaponImmunity(ieDword opcode, int enchantment, ieDword weapontype) const;
293 #endif // ! EFFECTQUEUE_H