-
Notifications
You must be signed in to change notification settings - Fork 96
Expand file tree
/
Copy pathactions.h
More file actions
507 lines (426 loc) · 14.4 KB
/
Copy pathactions.h
File metadata and controls
507 lines (426 loc) · 14.4 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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
/*
* actions.h - Action controllers for actors.
*
* Copyright (C) 2000-2025 The Exult Team
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef ACTIONS_H
#define ACTIONS_H 1
#include "ignore_unused_variable_warning.h"
#include "tiles.h"
#include <memory>
#include <vector>
class Actor;
class Game_object;
class Tile_coord;
class PathFinder;
class Pathfinder_client;
class Path_walking_actor_action;
class If_else_path_actor_action;
using Game_object_weak = std::weak_ptr<Game_object>;
/*
* This class controls the current actions of an actor:
*/
class Actor_action {
static long seqcnt; // Sequence # to check for deletion.
protected:
bool get_party = false; // At each step (of the Avatar), have
// the party follow.
long seq; // 'unique' sequence #.
public:
Actor_action() {
seq = ++seqcnt;
}
virtual ~Actor_action() = default;
void set_get_party(bool tf = true) {
ignore_unused_variable_warning(tf);
get_party = true;
}
int handle_event_safely(Actor* actor, bool& deleted);
// Handle time event.
virtual int handle_event(Actor* actor) = 0;
virtual void stop(Actor* actor) { // Stop moving.
ignore_unused_variable_warning(actor);
}
// Set simple path to destination.
virtual Actor_action* walk_to_tile(
Actor* npc, const Tile_coord& src, const Tile_coord& dest, int dist = 0, bool ignnpc = false);
// Set action to walk to dest, then
// exec. another action when there.
static Actor_action* create_action_sequence(
Actor* actor, const Tile_coord& dest, Actor_action* when_there, bool from_off_screen = false, bool persistant = false);
// Get destination, or ret. 0.
virtual bool get_dest(Tile_coord& dest) const {
ignore_unused_variable_warning(dest);
return false;
}
// Check for Astar.
virtual bool following_smart_path() const {
return false;
}
virtual If_else_path_actor_action* as_usecode_path() {
return nullptr;
}
virtual int get_speed() const {
return 0;
}
virtual Actor_action* kill() {
delete this;
return nullptr;
}
};
/*
* A null action just returns 0 the first time.
*/
class Null_action : public Actor_action {
public:
Null_action() = default;
int handle_event(Actor* actor) override;
};
/*
* Follow a path.
*/
class Path_walking_actor_action : public Actor_action {
protected:
bool reached_end = false; // Reached end of path.
PathFinder* path; // Allocated pathfinder.
bool deleted = false; // True if the action has been killed.
private:
int original_dir; // From src. to dest. (0-7).
int speed = 0; // Time between frames.
bool from_offscreen = false; // Walking from offscreen.
Actor_action* subseq = nullptr; // For opening doors.
Game_object_weak door_obj; // Store the door object
bool handling_door = false;
bool door_sequence_complete = false;
unsigned char blocked = 0; // Blocked-tile retries.
unsigned char max_blocked; // Try this many times.
unsigned char blocked_frame = 0; // Frame for blocked tile.
unsigned char persistence;
Tile_coord blocked_tile; // Tile to retry.
void set_subseq(Actor_action* sub) {
delete subseq;
subseq = sub;
}
public:
Path_walking_actor_action(PathFinder* p = nullptr, int maxblk = 3, int pers = 0);
~Path_walking_actor_action() override;
static Path_walking_actor_action* create_path(const Tile_coord& src, const Tile_coord& dest, const Pathfinder_client& cost);
// Handle time event.
int handle_event(Actor* actor) override;
bool open_door(Actor* actor, Game_object* door);
void stop(Actor* actor) override; // Stop moving.
// Set simple path to destination.
Actor_action* walk_to_tile(
Actor* npc, const Tile_coord& src, const Tile_coord& dest, int dist = 0, bool ignnpc = false) override;
// Get destination, or ret. 0.
bool get_dest(Tile_coord& dest) const override;
// Check for Astar.
bool following_smart_path() const override;
int get_speed() const override {
return speed;
}
Actor_action* kill() override {
deleted = true;
return this;
}
};
/*
* Follow a path to approach a given object, and stop half-way if it
* moved.
*/
class Approach_actor_action : public Path_walking_actor_action {
Game_object_weak dest_obj; // Destination object.
int goal_dist; // Stop if within this distance.
Tile_coord orig_dest_pos; // Dest_obj's pos. when we start.
int cur_step; // Count steps.
int check_step; // Check at this step.
bool for_projectile; // Check for proj. path.
public:
Approach_actor_action(PathFinder* p, Game_object* d, int gdist = -1, bool for_proj = false);
static Approach_actor_action* create_path(const Tile_coord& src, Game_object* dest, int gdist, Pathfinder_client& cost);
// Handle time event.
int handle_event(Actor* actor) override;
};
/*
* Follow a path and execute one action if successful, another if
* failed.
*/
class If_else_path_actor_action : public Path_walking_actor_action {
bool succeeded, failed, done;
Actor_action *success, *failure;
public:
If_else_path_actor_action(Actor* actor, const Tile_coord& dest, Actor_action* s, Actor_action* f = nullptr);
~If_else_path_actor_action() override;
void set_failure(Actor_action* f);
bool done_and_failed() const { // Happens if no path found in ctor.
return done && failed;
}
bool is_done() const {
return done;
}
// Handle time event.
int handle_event(Actor* actor) override;
If_else_path_actor_action* as_usecode_path() override {
return this;
}
};
/*
* Just move (i.e. teleport) to a desired location.
*/
class Move_actor_action : public Actor_action {
Tile_coord dest; // Where to go.
public:
Move_actor_action(const Tile_coord& d) : dest(d) {}
// Handle time event.
int handle_event(Actor* actor) override;
};
/*
* Activate an object.
*/
class Activate_actor_action : public Actor_action {
Game_object_weak obj;
public:
Activate_actor_action(Game_object* o);
// Handle time event.
int handle_event(Actor* actor) override;
};
/*
* Go through a series of frames.
*/
class Frames_actor_action : public Actor_action {
std::vector<signed char> frames; // List to go through (a -1 means to
// leave frame alone.)
size_t index; // Index for next.
int speed; // Frame delay in 1/1000 secs.
Game_object_weak obj; // Object to animate
bool use_actor;
int sound_id = -1; // Sound effect to play (-1 = none)
int volume = 255; // Volume (0-255)
int repeat = 0; // Repeat count
Game_object_weak sound_src; // Optional custom sound source
bool sound_played = false;
public:
Frames_actor_action(
const signed char* f, int c, int spd = 200, Game_object* o = nullptr, int sfx = -1, int vol = 255, int rep = 0,
Game_object* src = nullptr);
Frames_actor_action(
signed char f, int spd = 200, Game_object* o = nullptr, int sfx = -1, int vol = 255, int rep = 0,
Game_object* src = nullptr);
// Handle time event.
int handle_event(Actor* actor) override;
size_t get_index() const {
return index;
}
int get_speed() const override {
return speed;
}
};
/*
* Call a usecode function.
*/
class Usecode_actor_action : public Actor_action {
int fun; // Fun. #.
Game_object_weak item; // Call it on this item.
int eventid;
public:
Usecode_actor_action(int f, Game_object* i, int ev);
// Handle time event.
int handle_event(Actor* actor) override;
};
/*
* Do a sequence of actions.
*/
class Sequence_actor_action : public Actor_action {
Actor_action** actions; // List of actions, ending with null.
int index; // Index into list.
int speed; // Frame delay in 1/1000 secs. between
// actions.
public:
// Create with allocated list.
Sequence_actor_action(Actor_action** act, int spd = 100) : actions(act), index(0), speed(spd) {}
// Create with up to 4.
Sequence_actor_action(Actor_action* a0, Actor_action* a1, Actor_action* a2 = nullptr, Actor_action* a3 = nullptr);
int get_speed() const override {
return speed;
}
void set_speed(int spd) {
speed = spd;
}
~Sequence_actor_action() override;
// Handle time event.
int handle_event(Actor* actor) override;
};
//
// The below could perhaps go into a highact.h file.
//
/*
* Rotate through an object's frames.
*/
class Object_animate_actor_action : public Actor_action {
Game_object_weak obj;
int nframes; // # of frames.
int cycles; // # of cycles to do.
int speed; // Time between frames.
public:
Object_animate_actor_action(Game_object* o, int cy, int spd);
Object_animate_actor_action(Game_object* o, int nframes, int cy, int spd);
// Handle time event.
int handle_event(Actor* actor) override;
int get_speed() const override {
return speed;
}
};
/*
* Action to pick up an item or put it down.
*/
class Pickup_actor_action : public Actor_action {
Game_object_weak obj; // What to pick up/put down.
int pickup; // 1 to pick up, 0 to put down.
int speed; // Time between frames.
int cnt; // 0, 1, 2.
Tile_coord objpos; // Where to put it.
int dir; // Direction to face.
bool temp; // True to make object temporary on drop.
bool to_del; // Delete after picking up object.
int sound_id; // ID of sound effect to play
int volume; // Volume (0-256)
int repeat; // Repeat count
bool play_sfx; // Whether to play a sound effect
public:
// To pick up an object:
Pickup_actor_action(Game_object* o, int spd = 250, bool del = false, int sfx = -1, int vol = 255, int rep = 0);
// Put down an object:
Pickup_actor_action(
Game_object* o, const Tile_coord& opos, int spd = 250, bool t = false, int sfx = -1, int vol = 255, int rep = 0);
int handle_event(Actor* actor) override;
int get_speed() const override {
return speed;
}
void stop(Actor* actor) override {
ignore_unused_variable_warning(actor);
}
};
/*
* Action to turn towards an object or spot.
*/
class Face_pos_actor_action : public Actor_action {
int speed; // Time between frames.
Tile_coord pos; // Where to put it.
public:
Face_pos_actor_action(const Tile_coord& p, int spd);
// To pick up an object:
Face_pos_actor_action(Game_object* o, int spd);
int handle_event(Actor* actor) override;
int get_speed() const override {
return speed;
}
};
/*
* Action to modify another actor.
*/
class Change_actor_action : public Actor_action {
Game_object_weak obj; // What to modify.
int shnum, frnum, qual; // New shape, frame and quality.
public:
Change_actor_action(Game_object* o, int sh, int fr, int ql);
int handle_event(Actor* actor) override;
};
/*
* Action to play an effect.
*/
class Effect_actor_action : public Actor_action {
private:
int effect_type; // Type of effect
Game_object_weak object; // Object to attach effect to
int deltax, deltay; // Offsets
int delay; // Delay before starting
int starting_frame; // Starting frame
int repetitions; // Repetitions
public:
Effect_actor_action(int type, Game_object* obj, int dx = 0, int dy = 0, int d = 0, int frm = 0, int reps = 0);
int handle_event(Actor* actor) override;
int get_speed() const override {
return 0;
}
void stop(Actor* actor) override {
ignore_unused_variable_warning(actor);
}
};
/*
* Action to play a sound effect.
*/
class Play_sfx_actor_action : public Actor_action {
private:
int sound_id; // ID of sound effect to play
Game_object_weak object; // Object that is the source of sound
int volume; // Volume (0-256)
int repeat; // Repeat count (0 = once)
public:
Play_sfx_actor_action(int sfx_id, Game_object* obj, int vol = 255, int rep = 0);
int handle_event(Actor* actor) override;
int get_speed() const override {
return 0;
}
void stop(Actor* actor) override {
ignore_unused_variable_warning(actor);
}
};
/*
* Action that groups multiple actions to execute simultaneously in one frame.
*/
class Group_actor_action : public Actor_action {
private:
std::vector<Actor_action*> actions; // Actions to execute together
int max_delay = 0; // Use max delay of all actions
public:
// Constructor takes a vector of actions (takes ownership)
Group_actor_action(std::vector<Actor_action*>&& acts) : actions(std::move(acts)), max_delay(0) {}
// Constructors for convenience with 2-5 actions
Group_actor_action(Actor_action* a1, Actor_action* a2) {
actions.push_back(a1);
actions.push_back(a2);
}
Group_actor_action(Actor_action* a1, Actor_action* a2, Actor_action* a3) {
actions.push_back(a1);
actions.push_back(a2);
actions.push_back(a3);
}
Group_actor_action(Actor_action* a1, Actor_action* a2, Actor_action* a3, Actor_action* a4) {
actions.push_back(a1);
actions.push_back(a2);
actions.push_back(a3);
actions.push_back(a4);
}
Group_actor_action(Actor_action* a1, Actor_action* a2, Actor_action* a3, Actor_action* a4, Actor_action* a5) {
actions.push_back(a1);
actions.push_back(a2);
actions.push_back(a3);
actions.push_back(a4);
actions.push_back(a5);
}
~Group_actor_action() override {
for (auto* act : actions) {
delete act;
}
}
int handle_event(Actor* actor) override;
int get_speed() const override {
return max_delay;
}
void stop(Actor* actor) override;
};
#endif /* INCL_ACTIONS */