1 /*
2 Copyright © 2011-2012 Clint Bellanger
3 Copyright © 2012 Igor Paliychuk
4 Copyright © 2012 Stefan Beller
5 Copyright © 2013 Henrik Andersson
6 Copyright © 2012-2016 Justin Jacobs
7 
8 This file is part of FLARE.
9 
10 FLARE is free software: you can redistribute it and/or modify it under the terms
11 of the GNU General Public License as published by the Free Software Foundation,
12 either version 3 of the License, or (at your option) any later version.
13 
14 FLARE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
16 PARTICULAR PURPOSE.  See the GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License along with
19 FLARE.  If not, see http://www.gnu.org/licenses/
20 */
21 
22 /**
23  * class PowerManager
24  *
25  * Special code for handling spells, special powers, item effects, etc.
26  */
27 
28 #ifndef POWER_MANAGER_H
29 #define POWER_MANAGER_H
30 
31 #include "Map.h"
32 #include "MapCollision.h"
33 #include "Utils.h"
34 
35 class Animation;
36 class AnimationSet;
37 class EffectDef;
38 class Hazard;
39 
40 class PostEffect {
41 public:
42 	std::string id;
43 	int magnitude;
44 	int duration;
45 	int chance;
46 	bool target_src;
47 
PostEffect()48 	PostEffect()
49 		: id("")
50 		, magnitude(0)
51 		, duration(0)
52 		, chance(100)
53 		, target_src(false) {
54 	}
55 };
56 
57 class PowerReplaceByEffect {
58 public:
59 	int power_id;
60 	int count;
61 	std::string effect_id;
62 };
63 
64 class PowerRequiredItem {
65 public:
66 	ItemID id;
67 	int quantity;
68 	bool equipped;
69 
PowerRequiredItem()70 	PowerRequiredItem()
71 		: id(0)
72 		, quantity(0)
73 		, equipped(false)
74 	{}
75 };
76 
77 class Power {
78 public:
79 	enum {
80 		HPMPSTATE_ANY = 0,
81 		HPMPSTATE_ALL = 1
82 	};
83 	enum {
84 		HPMPSTATE_IGNORE = 0,
85 		HPMPSTATE_PERCENT = 1,
86 		HPMPSTATE_NOT_PERCENT = 2
87 	};
88 	class HPMPState {
89 	public:
90 		int mode;
91 		int hp_state;
92 		int mp_state;
93 		int hp;
94 		int mp;
HPMPState()95 		HPMPState()
96 			: mode(HPMPSTATE_ANY)
97 			, hp_state(HPMPSTATE_IGNORE)
98 			, mp_state(HPMPSTATE_IGNORE)
99 			, hp(-1)
100 			, mp(-1)
101 		{}
~HPMPState()102 		~HPMPState() {}
103 	};
104 
105 	enum {
106 		TYPE_FIXED = 0,
107 		TYPE_MISSILE = 1,
108 		TYPE_REPEATER = 2,
109 		TYPE_SPAWN = 3,
110 		TYPE_TRANSFORM = 4,
111 		TYPE_EFFECT = 5,
112 		TYPE_BLOCK = 6
113 	};
114 
115 	enum {
116 		STATE_INSTANT = 1,
117 		STATE_ATTACK = 2
118 	};
119 
120 	enum {
121 		STARTING_POS_SOURCE = 0,
122 		STARTING_POS_TARGET = 1,
123 		STARTING_POS_MELEE = 2
124 	};
125 
126 	enum {
127 		TRIGGER_BLOCK = 0,
128 		TRIGGER_HIT = 1,
129 		TRIGGER_HALFDEATH = 2,
130 		TRIGGER_JOINCOMBAT = 3,
131 		TRIGGER_DEATH = 4
132 	};
133 
134 	enum {
135 		SPAWN_LIMIT_MODE_FIXED = 0,
136 		SPAWN_LIMIT_MODE_STAT = 1,
137 		SPAWN_LIMIT_MODE_UNLIMITED = 2
138 	};
139 
140 	enum {
141 		SPAWN_LEVEL_MODE_DEFAULT = 0,
142 		SPAWN_LEVEL_MODE_FIXED = 1,
143 		SPAWN_LEVEL_MODE_STAT = 2,
144 		SPAWN_LEVEL_MODE_LEVEL = 3
145 	};
146 
147 	enum {
148 		STAT_MODIFIER_MODE_MULTIPLY = 0,
149 		STAT_MODIFIER_MODE_ADD = 1,
150 		STAT_MODIFIER_MODE_ABSOLUTE = 2
151 	};
152 
153 	enum {
154 		SOURCE_TYPE_HERO = 0,
155 		SOURCE_TYPE_NEUTRAL = 1,
156 		SOURCE_TYPE_ENEMY = 2,
157 		SOURCE_TYPE_ALLY = 3
158 	};
159 
160 	enum {
161 		SCRIPT_TRIGGER_CAST = 0,
162 		SCRIPT_TRIGGER_HIT = 1,
163 		SCRIPT_TRIGGER_WALL = 2
164 	};
165 
166 	// base info
167 	bool is_empty;
168 	int type; // what kind of activate() this is
169 	std::string name;
170 	std::string description;
171 	int icon; // just the number.  The caller menu will have access to the surface.
172 	int new_state; // when using this power the user (avatar/enemy) starts a new state
173 	int state_duration; // can be used to extend the length of a state animation by pausing on the last frame
174 	bool prevent_interrupt; // prevents hits from interrupting the casting state
175 	std::string attack_anim; // name of the animation to play when using this power, if it is not block
176 	bool face; // does the user turn to face the mouse cursor when using this power?
177 	int source_type; //hero, neutral, or enemy
178 	bool beacon; //true if it's just an ememy calling its allies
179 	int count; // number of hazards/effects or spawns created
180 	bool passive; // if unlocked when the user spawns, automatically cast it
181 	int passive_trigger; // only activate passive powers under certain conditions (block, hit, death, etc)
182 	bool meta_power; // this power can't be used on its own and must be replaced via equipment
183 	bool no_actionbar; // prevents this power from being placed on the actionbar
184 
185 	// power requirements
186 	std::set<std::string> requires_flags; // checked against equip_flags granted from items
187 	int requires_mp;
188 	int requires_hp;
189 	bool sacrifice;
190 	bool requires_los; // line of sight
191 	bool requires_los_default;
192 	bool requires_empty_target; // target square must be empty
193 	std::vector<PowerRequiredItem> required_items;
194 	bool consumable;
195 	bool requires_targeting; // power only makes sense when using click-to-target
196 	int requires_spawns;
197 	int cooldown; // milliseconds before you can use the power again
198 	HPMPState requires_max_hpmp;
199 
200 	// animation info
201 	std::string animation_name;
202 	int sfx_index;
203 	SoundID sfx_hit;
204 	bool sfx_hit_enable;
205 	bool directional; // sprite sheet contains options for 8 directions, one per row
206 	int visual_random; // sprite sheet contains rows of random options
207 	int visual_option; // sprite sheet contains rows of similar effects.  use a specific option
208 	bool aim_assist;
209 	float speed; // for missile hazards, tiles per frame
210 	int lifespan; // how long the hazard/animation lasts
211 	bool on_floor; // the hazard is drawn between the background and object layers
212 	bool complete_animation;
213 	float charge_speed;
214 	float attack_speed;
215 
216 	// hazard traits
217 	bool use_hazard;
218 	bool no_attack;
219 	bool no_aggro;
220 	float radius;
221 	size_t base_damage;
222 	int starting_pos; // enum. (source, target, or melee)
223 	bool relative_pos;
224 	bool multitarget;
225 	bool multihit;
226 	bool expire_with_caster;
227 	bool ignore_zero_damage;
228 	bool lock_target_to_direction;
229 	int movement_type;
230 	float target_range;
231 	bool target_party;
232 	std::vector<std::string> target_categories;
233 	float combat_range;
234 
235 	int mod_accuracy_mode;
236 	int mod_accuracy_value;
237 
238 	int mod_crit_mode;
239 	int mod_crit_value;
240 
241 	int mod_damage_mode;
242 	int mod_damage_value_min;
243 	int mod_damage_value_max;//only used if mode is absolute
244 
245 	//steal effects (in %, eg. hp_steal=50 turns 50% damage done into HP regain.)
246 	int hp_steal;
247 	int mp_steal;
248 
249 	//missile traits
250 	int missile_angle;
251 	int angle_variance;
252 	float speed_variance;
253 
254 	//repeater traits
255 	int delay;
256 
257 	int trait_elemental; // enum. of elements
258 	bool trait_armor_penetration;
259 	int trait_crits_impaired; // crit bonus vs. movement impaired enemies (slowed, immobilized, stunned)
260 	bool trait_avoidance_ignore;
261 
262 	int transform_duration;
263 	bool manual_untransform; // true binds to the power another recurrence power
264 	bool keep_equipment;
265 	bool untransform_on_hit;
266 
267 	// special effects
268 	bool buff;
269 	bool buff_teleport;
270 	bool buff_party;
271 	PowerID buff_party_power_id;
272 
273 	std::vector<PostEffect> post_effects;
274 
275 	PowerID pre_power;
276 	int pre_power_chance;
277 	PowerID post_power;
278 	int post_power_chance;
279 	PowerID wall_power;
280 	int wall_power_chance;
281 	bool wall_reflect;
282 
283 	// spawn info
284 	std::string spawn_type;
285 	int target_neighbor;
286 	int spawn_limit_mode;
287 	int spawn_limit_qty;
288 	int spawn_limit_every;
289 	size_t spawn_limit_stat;
290 
291 	int spawn_level_mode;
292 	int spawn_level_qty;
293 	int spawn_level_every;
294 	size_t spawn_level_stat;
295 
296 	// targeting by movement type
297 	bool target_movement_normal;
298 	bool target_movement_flying;
299 	bool target_movement_intangible;
300 
301 	bool walls_block_aoe;
302 
303 	int script_trigger;
304 	std::string script;
305 
306 	std::vector< std::pair<std::string, int> > remove_effects;
307 
308 	std::vector<PowerReplaceByEffect> replace_by_effect;
309 
310 	bool requires_corpse;
311 	bool remove_corpse;
312 
313 	float target_nearest;
314 
315 	std::vector<std::string> disable_equip_slots;
316 
317 	Power();
~Power()318 	~Power() {
319 	}
320 };
321 
322 class PowerManager {
323 private:
324 
325 	MapCollision *collider;
326 
327 	void loadEffects();
328 	void loadPowers();
329 
330 	bool isValidEffect(const std::string& type);
331 	int loadSFX(const std::string& filename);
332 
333 	void initHazard(PowerID power_index, StatBlock *src_stats, const FPoint& target, Hazard *haz);
334 	void buff(PowerID power_index, StatBlock *src_stats, const FPoint& target);
335 	void playSound(PowerID power_index);
336 
337 	bool fixed(PowerID power_index, StatBlock *src_stats, const FPoint& target);
338 	bool missile(PowerID power_index, StatBlock *src_stats, const FPoint& target);
339 	bool repeater(PowerID power_index, StatBlock *src_stats, const FPoint& target);
340 	bool spawn(PowerID power_index, StatBlock *src_stats, const FPoint& target);
341 	bool transform(PowerID power_index, StatBlock *src_stats, const FPoint& target);
342 	bool block(PowerID power_index, StatBlock *src_stats);
343 
344 	void payPowerCost(PowerID power_index, StatBlock *src_stats);
345 
346 	bool activatePassiveByTrigger(PowerID power_id, StatBlock *src_stats, bool& triggered_others);
347 	void activatePassivePostPowers(StatBlock *src_stats);
348 
349 	std::map<PowerID, Animation*> power_animations;
350 	std::vector<Animation*> effect_animations;
351 
352 public:
353 	static const bool ALLOW_ZERO_ID = true;
354 
355 	explicit PowerManager();
356 	~PowerManager();
357 
358 	void handleNewMap(MapCollision *_collider);
359 	bool activate(PowerID power_index, StatBlock *src_stats, const FPoint& target);
360 	bool canUsePower(PowerID id) const;
361 	bool hasValidTarget(PowerID power_index, StatBlock *src_stats, const FPoint& target);
362 	bool effect(StatBlock *target_stats, StatBlock *caster_stats, PowerID power_index, int source_type);
363 	void activatePassives(StatBlock *src_stats);
364 	void activateSinglePassive(StatBlock *src_stats, PowerID id);
365 	PowerID verifyID(PowerID power_id, FileParser* infile, bool allow_zero);
366 	bool checkNearestTargeting(const Power &pow, const StatBlock *src_stats, bool check_corpses);
367 	bool checkRequiredItems(const Power &pow, const StatBlock *src_stats);
368 	bool checkRequiredMaxHPMP(const Power &pow, const StatBlock *src_stats);
369 	bool checkCombatRange(PowerID power_index, StatBlock *src_stats, FPoint target);
370 	PowerID checkReplaceByEffect(PowerID power_index, StatBlock *src_stats);
371 
372 	EffectDef* getEffectDef(const std::string& id);
373 
374 	std::vector<EffectDef> effects;
375 	std::map<PowerID, Power> powers;
376 	std::queue<Hazard *> hazards; // output; read by HazardManager
377 	std::queue<Map_Enemy> map_enemies; // output; read by PowerManager
378 
379 	// shared sounds for power special effects
380 	std::vector<SoundID> sfx;
381 
382 	std::vector<ItemID> used_items;
383 	std::vector<ItemID> used_equipped_items;
384 };
385 
386 #endif
387