1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef NUVIE_CORE_EFFECT_H
24 #define NUVIE_CORE_EFFECT_H
25 
26 
27 #include "ultima/nuvie/misc/call_back.h"
28 #include "ultima/nuvie/core/map.h"
29 #include "ultima/nuvie/core/obj_manager.h"
30 #include "ultima/nuvie/core/anim_manager.h"
31 
32 namespace Ultima {
33 namespace Nuvie {
34 
35 //class Actor;
36 class EffectManager;
37 class Game;
38 class MapWindow;
39 class NuvieAnim;
40 class Screen;
41 class TimedAdvance;
42 class TimedCallback;
43 class ObjManager;
44 
45 // Effects add themselves to EffectManager and most start immediately.
46 
47 /* Effects: * = unwritten or untested
48  * Quake - earthquake from cyclops or volcanos
49  * Hit - hit actor anim + sfx
50  * Explosive - explosion caused by powder keg, volcanos, or cannonball hit
51  * ThrowObject - any thrown object or tile
52  * Cannonball (FIX: change to UseCodeThrow)
53  * Missile - throw object to ground or actor; optionally cause damage
54  * *Boomerang - spin Missile and return to sender
55  * Drop - throw obj from inventory to ground
56  * Sleep - pause game & advance time quickly
57  * Fade - fade the mapwindow in or out
58  * GameFadeIn - blocks user-input until Fade is complete
59  * *Palette - do something with the color palette
60  * Vanish - fade from an image of the mapwindow to the real mapwindow
61  * *FadeObject - might not need this since Vanish can be used
62  * U6WhitePotion - will probably make PaletteEffect to do this
63  */
64 
65 
66 /* Control animation and sounds in the game world.
67  */
68 class Effect : public CallBack {
69 protected:
70 	Game *game;
71 	EffectManager *effect_manager;
72 	bool defunct;
73 
74 	uint32 retain_count;
75 
76 public:
77 	Effect();
78 	~Effect() override;
79 
retain()80 	void retain() {
81 		retain_count++;
82 	}
release()83 	void release() {
84 		if (retain_count > 0) retain_count--;
85 	}
is_retained()86 	bool is_retained() {
87 		return retain_count == 0 ? false : true;
88 	}
89 
delete_self()90 	void delete_self() {
91 		defunct = true;
92 	}
93 	void add_anim(NuvieAnim *anim);
94 
is_defunct()95 	bool is_defunct()  {
96 		return (defunct);
97 	}
callback(uint16,CallBack *,void *)98 	uint16 callback(uint16, CallBack *, void *) override {
99 		return (0);
100 	}
101 };
102 
103 #define CANNON_SPEED 320
104 /* Toss a cannon ball from one actor to another, or from an object towards
105  * a numbered direction.
106  */
107 class CannonballEffect : public Effect {
108 	UseCode *usecode;
109 	NuvieAnim *anim;
110 //  *sfx;
111 	Obj *obj;
112 	MapCoord target_loc; // where cannonball will hit
113 
114 	void start_anim();
115 
116 public:
117 	CannonballEffect(Obj *src_obj, sint8 direction = -1);
118 //    CannonballEffect(Actor *src_actor, Actor *target_actor); from a ship
119 
120 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
121 };
122 
123 class ProjectileEffect : public Effect {
124 protected:
125 	uint16 tile_num;
126 
127 	MapCoord start_loc; // where explosion will start
128 	vector<MapCoord> targets;
129 	uint8 anim_speed;
130 	bool trail;
131 	uint16 initial_tile_rotation;
132 	uint16 rotation_amount;
133 	uint8 src_tile_y_offset;
134 	uint16 finished_tiles;
135 
136 	vector<MapEntity> hit_entities;
137 
138 	virtual void start_anim();
139 
140 public:
ProjectileEffect()141 	ProjectileEffect() {
142 		tile_num = 0;
143 		anim_speed = 0;
144 		trail = false;
145 		initial_tile_rotation = 0;
146 		rotation_amount = 0;
147 		src_tile_y_offset = 0;
148 		finished_tiles = 0;
149 	}
150 	ProjectileEffect(uint16 tileNum, MapCoord start, MapCoord target, uint8 speed, bool trailFlag, uint16 initialTileRotation, uint16 rotationAmount, uint8 src_y_offset);
151 	ProjectileEffect(uint16 tileNum, MapCoord start, vector<MapCoord> t, uint8 speed, bool trailFlag, uint16 initialTileRotation);
152 
153 	void init(uint16 tileNum, MapCoord start, vector<MapCoord> t, uint8 speed, bool trailFlag, uint16 initialTileRotation, uint16 rotationAmount, uint8 src_y_offset);
154 
155 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
156 
get_hit_entities()157 	vector<MapEntity> *get_hit_entities() {
158 		return &hit_entities;
159 	}
160 };
161 
162 class ExpEffect : public ProjectileEffect {
163 	UseCode *usecode;
164 	NuvieAnim *anim;
165 
166 	Obj *obj;
167 	uint16 exp_tile_num;
168 
169 protected:
170 	void start_anim() override;
171 public:
172 	ExpEffect(uint16 tileNum, MapCoord location);
173 
174 };
175 
176 /* Use to add an effect with timed activity. Self-contained timer must be
177  * stopped/started with the included methods.
178  */
179 class TimedEffect : public Effect {
180 protected:
181 	TimedCallback *timer;
182 public:
TimedEffect()183 	TimedEffect()                  {
184 		timer = NULL;
185 	}
TimedEffect(uint32 delay)186 	TimedEffect(uint32 delay)      {
187 		timer = NULL;
188 		start_timer(delay);
189 	}
~TimedEffect()190 	~TimedEffect() override                 {
191 		stop_timer();
192 	}
193 
194 	void start_timer(uint32 delay);
195 	void stop_timer();
196 
delete_self()197 	void delete_self() {
198 		stop_timer();
199 		Effect::delete_self();
200 	}
201 
callback(uint16 msg,CallBack * caller,void * data)202 	uint16 callback(uint16 msg, CallBack *caller, void *data) override {
203 		if (msg == MESG_TIMED) delete_self();    //= 0;
204 		return (0);
205 	}
206 };
207 
208 
209 /* Shake the visible play area around.
210  */
211 class QuakeEffect : public TimedEffect {
212 	MapWindow *map_window;
213 	static QuakeEffect *current_quake; // do nothing if already active
214 	sint32 sx, sy; // last map_window movement amount
215 	MapCoord orig; // map_window location at start
216 	Actor *orig_actor; // center map_window on actor
217 	uint32 stop_time;
218 	uint8 strength; // magnitude
219 
220 public:
221 	QuakeEffect(uint8 magnitude, uint32 duration, Actor *keep_on = NULL);
222 	~QuakeEffect() override;
223 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
224 
225 	void init_directions();
226 	void recenter_map();
227 	void stop_quake();
228 };
229 
230 
231 /* Hit target actor.
232  */
233 class HitEffect : public Effect {
234 public:
235 	HitEffect(Actor *target, uint32 duration = 300);
236 	HitEffect(MapCoord location);
237 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
238 };
239 
240 /* Print text to MapWindow for a given duration
241  */
242 class TextEffect : public Effect {
243 
244 public:
245 	TextEffect(Std::string text);
246 	TextEffect(Std::string text, MapCoord location);
247 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
248 };
249 
250 
251 /* Create explosion animation and sounds from the source location out to
252  * specified radius. Hit actors and objects for `dmg'.
253  */
254 class ExplosiveEffect : public Effect {
255 protected:
256 	NuvieAnim *anim;
257 //  *sfx;
258 	MapCoord start_at;
259 	uint32 radius;
260 	uint16 hit_damage; // hp taken off actors hit by explosion
261 
262 	void start_anim();
263 
264 public:
265 	ExplosiveEffect(uint16 x, uint16 y, uint32 size, uint16 dmg = 0);
266 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
267 
268 	// children can override
delete_self()269 	virtual void delete_self() {
270 		Effect::delete_self();
271 	}
hit_object(Obj * obj)272 	virtual bool hit_object(Obj *obj) {
273 		return (false);    // explosion hit something
274 	}
275 	// true return=end effect
276 };
277 
278 
279 /* Explosion that sends usecode event to an object on completion.
280  */
281 class UseCodeExplosiveEffect : public ExplosiveEffect {
282 	Obj *obj; // explosion came from this object (can be NULL)
283 	Obj *original_obj; // don't hit this object (chain-reaction avoidance hack)
284 
285 public:
286 	UseCodeExplosiveEffect(Obj *src_obj, uint16 x, uint16 y, uint32 size, uint16 dmg = 0, Obj *dont_hit_me = NULL)
ExplosiveEffect(x,y,size,dmg)287 		: ExplosiveEffect(x, y, size, dmg), obj(src_obj), original_obj(dont_hit_me) {
288 	}
289 	void delete_self() override;
290 	bool hit_object(Obj *hit_obj) override; // explosion hit something
291 
292 
293 
294 };
295 
296 
297 /* Toss object tile from one location to another with a TossAnim, and play a
298  * sound effect. The ThrowObjectEffect is constructed with uninitialized
299  * parameters and isn't started until start_anim() is called.
300  */
301 class ThrowObjectEffect : public Effect {
302 protected:
303 	ObjManager *obj_manager;
304 	NuvieAnim *anim; // TossAnim
305 //  *sfx;
306 	MapCoord start_at, stop_at; // start_at -> stop_at
307 	Obj *throw_obj; // object being thrown
308 	Tile *throw_tile; // graphic to use (default is object's tile)
309 	uint16 throw_speed; // used in animation
310 	uint16 degrees; // rotation of tile
311 	uint8 stop_flags; // TossAnim blocking flags
312 
313 public:
314 	ThrowObjectEffect();
~ThrowObjectEffect()315 	~ThrowObjectEffect() override { }
316 
317 	void hit_target(); // stops effect
318 	void start_anim();
319 
320 	uint16 callback(uint16 msg, CallBack *caller, void *data) override = 0;
321 };
322 
323 
324 /* Drop an object from an actor's inventory. Object is removed from the actor
325  * after starting the effect, and added to the map when the effect is complete.
326  * Effect speed is gametype-defined.
327  */
328 class DropEffect : public ThrowObjectEffect {
329 	Actor *drop_from_actor;
330 public:
331 	DropEffect(Obj *obj, uint16 qty, Actor *actor, MapCoord *drop_loc);
332 
333 	void hit_target();
334 
335 	void get_obj(Obj *obj, uint16 qty);
336 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
337 };
338 
339 #define MISSILE_DEFAULT_SPEED 200
340 #define MISSILE_HIT_TARGET  TOSS_TO_BLOCKING
341 #define MISSILE_HIT_OBJECTS (TOSS_TO_BLOCKING|TOSS_TO_OBJECT)
342 #define MISSILE_HIT_ACTORS  (TOSS_TO_BLOCKING|TOSS_TO_ACTOR)
343 #define MISSILE_HIT_ALL     (TOSS_TO_BLOCKING|TOSS_TO_OBJECT|TOSS_TO_ACTOR)
344 
345 /* Throw a missile towards a target location. If the target is an actor or
346  * object, it will be hit for the requested damage. If the target is an empty
347  * map location, the object will be added to the map. The missile always stops
348  * if hitting a blocking tile.
349  *
350  * Decide in the attack logic, before constructing this, whether or not it was
351  * successful, and use the appropriate constructor. You can set the effect to
352  * hit any actors or objects in the way if the attack missed.
353  */
354 class MissileEffect : public ThrowObjectEffect {
355 	ActorManager *actor_manager;
356 
357 	uint16 hit_damage; // hp taken off actor/object hit by missile
358 	Actor *hit_actor;
359 	Obj *hit_obj;
360 
361 public:
362 	MissileEffect(uint16 tile_num, uint16 obj_n, const MapCoord &source,
363 	              const MapCoord &target, uint8 dmg, uint8 intercept = MISSILE_HIT_TARGET, uint16 speed = MISSILE_DEFAULT_SPEED);
364 
365 	void init(uint16 tile_num, uint16 obj_n, const MapCoord &source,
366 	          const MapCoord &target, uint32 dmg, uint8 intercept, uint32 speed);
367 	void hit_target();
368 	void hit_blocking();
369 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
370 };
371 
372 #if 0
373 /* Throw an object and bring it back.
374  */
375 class BoomerangEffect : public ThrowObjectEffect {
376 // I might even add an arc from the center line for a cool effect.
377 };
378 
379 
380 /* Cycle or modify the game palette in some way.
381  */
382 class PaletteEffect : public TimedEffect {
383 // palette effects are created from child classes (new BlackPotionEffect();)
384 // ...and these can include SFX like any other effect
385 // but PaletteEffect is not abstract (new PaletteEffect(timing & color params...);)
386 };
387 
388 
389 #endif
390 
391 
392 /* For sleeping at inns. Fade-out, advance time, and fade-in.
393  */
394 class SleepEffect : public Effect {
395 	TimedAdvance *timer; // timed event
396 	uint8 stop_hour, stop_minute; // sleep until this time
397 	Std::string stop_time;
398 public:
399 	SleepEffect(Std::string until);
400 	SleepEffect(uint8 to_hour);
401 	~SleepEffect() override;
402 
403 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
404 	void delete_self();
405 };
406 
407 
408 typedef enum { FADE_PIXELATED, FADE_CIRCLE, FADE_PIXELATED_ONTOP } FadeType;
409 typedef enum { FADE_IN, FADE_OUT } FadeDirection;
410 
411 #define FADE_EFFECT_MAX_ITERATIONS 20
412 
413 /* Manipulate the MapWindow for two types of fades. One is a stippled-like fade
414  * that draws pixels to random locations on the screen until completely flooded
415  * with a set color. The other changes the ambient light until fully black.
416  */
417 class FadeEffect : public TimedEffect {
418 protected:
419 	static FadeEffect *current_fade; // do nothing if already active
420 
421 	MapWindow *map_window;
422 	Screen *screen; // for PIXELATED, the overlay is blitted to the screen...
423 	Common::Rect *viewport; // ...at the MapWindow coordinates set here
424 	Graphics::ManagedSurface *overlay; // this is what gets blitted
425 
426 	FadeType fade_type; // PIXELATED[_ONTOP] or CIRCLE
427 	FadeDirection fade_dir; // IN (removing color) or OUT (adding color)
428 	uint32 fade_speed; // meaning of this depends on fade_type
429 	uint8 pixelated_color; // color from palette that is being faded to/from
430 	Graphics::ManagedSurface *fade_from; // image being faded from or to (or NULL if coloring)
431 	uint16 fade_x, fade_y; // start fade from this point (to fade_from size)
432 
433 	uint32 evtime, prev_evtime; // time of last message to callback()
434 	uint32 pixel_count, colored_total; // number of pixels total/colored
435 	uint16 fade_iterations; // number of times we've updated the fade effect
436 
437 public:
438 	FadeEffect(FadeType fade, FadeDirection dir, uint32 color = 0, uint32 speed = 0);
439 	FadeEffect(FadeType fade, FadeDirection dir, Graphics::ManagedSurface *capture, uint32 speed = 0);
440 	FadeEffect(FadeType fade, FadeDirection dir, Graphics::ManagedSurface *capture, uint16 x, uint16 y, uint32 speed = 0);
441 	~FadeEffect() override;
442 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
443 
444 	bool pixelated_fade_out();
445 	bool pixelated_fade_in();
446 	bool circle_fade_out();
447 	bool circle_fade_in();
448 
449 	void delete_self();
450 
451 protected:
452 	void init(FadeType fade, FadeDirection dir, uint32 color, Graphics::ManagedSurface *capture, uint16 x, uint16 y, uint32 speed);
453 	void init_pixelated_fade();
454 	void init_circle_fade();
455 
456 	inline bool find_free_pixel(uint32 &rnum, uint32 pixel_count);
457 	uint32 pixels_to_check();
458 	bool pixelated_fade_core(uint32 pixels_to_check, sint16 fade_to);
459 //    inline uint32 get_random_pixel(uint16 center_thresh = 0);
460 };
461 
462 
463 /* Front-end to FadeEffect that fades in, and resumes game.
464  */
465 class GameFadeInEffect : public FadeEffect {
466 public:
467 	GameFadeInEffect(uint32 color);
468 	~GameFadeInEffect() override;
469 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
470 };
471 
472 
473 /* Captures an image of the MapWindow without an object, then places the object
474  * on the map and fades to the new image. (or the opposite if FADE_OUT is used)
475  */
476 class FadeObjectEffect : public Effect {
477 	ObjManager *obj_manager;
478 	Obj *fade_obj;
479 	FadeDirection fade_dir;
480 public:
481 	FadeObjectEffect(Obj *obj, FadeDirection dir);
482 	~FadeObjectEffect() override;
483 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
484 };
485 
486 
487 /* Do a blocking fade-to (FADE_OUT) from a captured image of the game area, to
488  * the active game area. (transparent) This is used for vanish or morph effects.
489  */
490 #define VANISH_WAIT true
491 #define VANISH_NOWAIT false
492 class VanishEffect : public Effect {
493 	bool input_blocked;
494 public:
495 	VanishEffect(bool pause_user = VANISH_NOWAIT);
496 	~VanishEffect() override;
497 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
498 };
499 
500 class TileFadeEffect : public TimedEffect {
501 	TileAnim *anim;
502 	Tile *to_tile;
503 	Tile *anim_tile;
504 	Actor *actor;
505 	uint8 color_from, color_to;
506 	bool inc_reverse;
507 	uint16 spd;
508 
509 	uint16 num_anim_running;
510 public:
511 	TileFadeEffect(MapCoord loc, Tile *from, Tile *to, FadeType type, uint16 speed);
512 	//TileFadeEffect(MapCoord loc, Tile *from, uint8 color_from, uint8 color_to, bool reverse, uint16 speed);
513 	TileFadeEffect(Actor *a, uint16 speed);
514 	~TileFadeEffect() override;
515 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
516 
517 protected:
518 	void add_actor_anim();
519 	void add_fade_anim(MapCoord loc, Tile *tile);
520 	void add_tile_anim(MapCoord loc, Tile *tile);
521 	void add_obj_anim(Obj *obj);
522 };
523 
524 class TileBlackFadeEffect : public TimedEffect {
525 	Actor *actor;
526 	Obj *obj;
527 	uint8 color;
528 	bool reverse;
529 	uint16 fade_speed;
530 
531 	uint16 num_anim_running;
532 public:
533 	TileBlackFadeEffect(Actor *a, uint8 fade_color, uint16 speed);
534 	TileBlackFadeEffect(Obj *o, uint8 fade_color, uint16 speed);
535 	~TileBlackFadeEffect() override;
536 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
537 protected:
538 	void init(uint8 fade_color, uint16 speed);
539 	void add_actor_anim();
540 	void add_obj_anim(Obj *o);
541 	void add_tile_anim(MapCoord loc, Tile *tile);
542 };
543 
544 /* Briefly modify the mapwindow colors, disable map-blacking and player
545  * movement for a few seconds, then enable both.
546  */
547 class XorEffect : public TimedEffect {
548 	MapWindow *map_window;
549 	uint32 length;
550 	Graphics::ManagedSurface *capture; // this is what gets blitted
551 
552 	void xor_capture(uint8 mod);
553 	void init_effect();
554 
555 public:
556 	/* eff_ms=length of visual effect */
557 	XorEffect(uint32 eff_ms);
~XorEffect()558 	~XorEffect() override { }
559 
560 	/* Called by the timer between each effect stage. */
561 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
562 };
563 
564 /* Briefly modify the mapwindow colors, disable map-blacking and player
565  * movement for a few seconds, then enable both.
566  */
567 class U6WhitePotionEffect : public TimedEffect {
568 	MapWindow *map_window;
569 	uint8 state; // 0=start, 1=eff1, 2=eff2, 3=x-ray, 4=complete
570 	uint32 start_length, eff1_length, eff2_length, xray_length;
571 	Graphics::ManagedSurface *capture; // this is what gets blitted
572 	Obj *potion; // allows effect to call usecode and delete object
573 
574 	void xor_capture(uint8 mod);
575 	void init_effect();
576 
577 public:
578 	/* eff_ms=length of visual effect; delay_ms=length of x-ray effect */
579 	U6WhitePotionEffect(uint32 eff_ms, uint32 delay_ms, Obj *callback_obj = NULL);
~U6WhitePotionEffect()580 	~U6WhitePotionEffect() override { }
581 
582 	/* Called by the timer between each effect stage. */
583 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
584 };
585 
586 
587 class XRayEffect : public TimedEffect {
588 	uint32 xray_length;
589 	void init_effect();
590 
591 public:
592 	/* eff_ms=length of x-ray effect */
593 	XRayEffect(uint32 eff_ms);
~XRayEffect()594 	~XRayEffect() override { }
595 
596 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
597 };
598 
599 /* Pause the game, create an effect, and wait for user input to continue. */
600 class PauseEffect: public Effect {
601 public:
602 	/* Called by the Effect handler when input is available. */
603 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
delete_self()604 	virtual void delete_self() {
605 		Effect::delete_self();
606 	}
607 	PauseEffect();
~PauseEffect()608 	~PauseEffect() override { }
609 };
610 
611 /* Gather text from scroll input then continue. */
612 class TextInputEffect: public Effect {
613 	Std::string input;
614 public:
615 	/* Called by the Effect handler when input is available. */
616 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
617 	TextInputEffect(const char *allowed_chars, bool can_escape);
~TextInputEffect()618 	~TextInputEffect() override { }
get_input()619 	Std::string get_input() {
620 		return input;
621 	}
622 };
623 
624 class WizardEyeEffect: public Effect {
625 public:
626 	/* Called by the Effect handler when input is available. */
627 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
delete_self()628 	virtual void delete_self() {
629 		Effect::delete_self();
630 	}
631 	WizardEyeEffect(MapCoord location, uint16 duration);
~WizardEyeEffect()632 	~WizardEyeEffect() override { }
633 };
634 
635 /* colors for PeerEffect */
636 const uint8 peer_tilemap[4] = {
637 	0x0A, // GROUND/PASSABLE
638 	0x09, // WATER
639 	0x07, // WALLS/BLOCKED
640 	0x0C  // DANGER/DAMAGING
641 };
642 
643 #define PEER_TILEW 4
644 const uint8 peer_tile[PEER_TILEW * PEER_TILEW] = {
645 	0, 1, 0, 1,
646 	1, 0, 1, 0,
647 	0, 1, 0, 1,
648 	1, 0, 1, 0
649 };
650 
651 /* Display an overview of the current area in the MapWindow. Any new actions
652  * cancel the effect and return to the prompt.
653  * (area is 48x48 tiles around the player, regardless of MapWindow size)
654  */
655 class PeerEffect : public PauseEffect {
656 	MapWindow *map_window;
657 	Graphics::ManagedSurface *overlay; // this is what gets blitted
658 	Obj *gem; // allows effect to call usecode and delete object
659 	MapCoord area; // area to display (top-left corner)
660 	uint8 tile_trans; // peer_tile transparency mask (0 or 1)
661 	uint16 map_pitch;
662 
663 	inline void blit_tile(uint16 x, uint16 y, uint8 c);
664 	inline void blit_actor(Actor *actor);
665 	inline uint8 get_tilemap_type(uint16 wx, uint16 wy, uint8 wz);
666 	void fill_buffer(uint8 *mapbuffer, uint16 x, uint16 y);
667 	void peer();
668 
669 public:
670 	PeerEffect(uint16 x, uint16 y, uint8 z, Obj *callback_obj = 0);
~PeerEffect()671 	~PeerEffect() override { }
672 	void init_effect();
673 	void delete_self() override;
674 };
675 
676 class WingStrikeEffect : public Effect {
677 protected:
678 
679 	Actor *actor;
680 
681 public:
682 	WingStrikeEffect(Actor *target_actor);
683 
684 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
685 };
686 
687 class HailStormEffect : public Effect {
688 protected:
689 
690 public:
691 	HailStormEffect(MapCoord target);
692 
693 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
694 };
695 
696 #define EFFECT_PROCESS_GUI_INPUT true
697 
698 /* Run an effect asynchronously and keep updating the world until the effect completes. */
699 class AsyncEffect : public Effect {
700 protected:
701 	Effect *effect;
702 	bool effect_complete;
703 
704 public:
705 	AsyncEffect(Effect *e);
706 	~AsyncEffect() override;
707 	void run(bool process_gui_input = false);
708 	uint16 callback(uint16 msg, CallBack *caller, void *data) override;
709 };
710 
711 } // End of namespace Nuvie
712 } // End of namespace Ultima
713 
714 #endif
715