forked from exult/exult
-
Notifications
You must be signed in to change notification settings - Fork 0
/
actors.h
829 lines (805 loc) · 27.2 KB
/
actors.h
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
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
/*
* actors.h - Game actors.
*
* Copyright (C) 1998-1999 Jeffrey S. Freedman
* Copyright (C) 2000-2013 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 INCL_ACTORS
#define INCL_ACTORS 1
#include "contain.h"
#include "utils.h" // This is only included for Log2...
#include "flags.h"
#include "ready.h"
#include "ignore_unused_variable_warning.h"
class Image_window;
class Game_window;
class Npc_actor;
class Actor_action;
class Schedule;
class Schedule_change;
class Monster_info;
class Monster_actor;
class Weapon_info;
class Dead_body;
class Npc_timer_list;
class Frames_sequence;
class Animator;
class Actor_attributes;
/*
* An actor:
*/
class Actor : public Container_game_object, public Time_sensitive {
static Actor *editing; // NPC being edited by ExultStudio.
protected:
std::string name; // Its name.
int usecode; // # of usecode function.
bool usecode_assigned; // Usecode # explicitly assigned.
std::string usecode_name; // Name of usecode fun explicitly assigned.
bool unused; // If npc_num > 0, this NPC is unused
// in the game.
short npc_num; // # in Game_window::npcs list, or -1.
short face_num; // Which shape for conversations.
short party_id; // Index in party, or -1.
int properties[12]; // Properties set/used in 'usecode'.
Actor_attributes *atts; // Generic atts. (for new games/mods).
unsigned char temperature; // Measure of coldness (0-63).
short shape_save; // Our old shape, or -1.
short oppressor; // NPC ID (>= 0) of oppressor, or -1.
Game_object *target; // Who/what we're attacking.
short casting_mode; //For displaying casting frames.
int casting_shape; //Shape of casting frames.
// These 2 are set by the Usecode function 'set_to_attack':
Game_object *target_object;
Tile_coord target_tile;
int attack_weapon;
public:
enum Attack_mode { // Setting from gump.+++++Save/restore.
nearest = 0,
weakest = 1, // Attack weakest.
strongest = 2,
berserk = 3, // Always attack, never retreat.
protect = 4, // Protect NPC with halo.
defend = 5,
flank = 6, // Attempt to attack from side.
flee = 7,
random = 8, // Choose target at random.
manual = 9
};
enum Casting_mode {
not_casting = 0, // The NPC is not casting.
init_casting = 1, // When set, the next usecode script will
// display casting frames (shape 859).
show_casting_frames = 2 // Used for displaying the casting frames.
// Also flags that the when the script finishes, the
// casting frames should be disabled.
};
protected:
// Party positions
const static short party_pos[4][10][2];
Attack_mode attack_mode;
// A frame sequence for each dir.:
static Frames_sequence *avatar_frames[4];
static Frames_sequence *npc_frames[4];
Frames_sequence **frames;
// Draw weapon in hand
void paint_weapon();
unsigned char schedule_type; // Schedule type (Schedule_type).
Tile_coord schedule_loc; // Location (x,y) of Shedule
Tile_coord old_schedule_loc; // Location (x,y) of old Shedule
unsigned char next_schedule; // Used so correct schedule type
// will be saved
Schedule *schedule; // Current schedule.
int restored_schedule; // Just restored schedule type.
bool dormant; // I.e., off-screen.
bool hit; // Just hit in combat.
bool combat_protected; // 'Halo' on paperdoll screen.
bool user_set_attack; // True if player set attack_mode.
short alignment; // 'Feelings' towards Ava. See below.
short charmalign; // Alignment of charmed NPC.
Game_object *spots[18]; // Where things can go. See 'Spots'
// below for description.
bool two_handed; // Carrying a two-handed item.
bool two_fingered; // Carrying gauntlets (both fingers)
bool use_scabbard; // Carrying an item in scabbard (belt, back 2h, shield).
bool use_neck; // Carrying cloak (amulet, cloak)
unsigned char light_sources; // # of light sources readied.
unsigned char usecode_dir; // Direction (0-7) for usecode anim.
unsigned type_flags: 32; // 32 flags used in movement among other things
unsigned char gear_immunities; // Damage immunities granted by gear.
unsigned short gear_powers; // Other powers granted by gear.
unsigned char ident;
int skin_color;
Actor_action *action; // Controls current animation.
std::vector<Actor_action *> deletedactions; // Halted actions.
int frame_time; // Time between frames in msecs. 0 if
// actor not moving.
int step_index; // Index into walking frames, 1 1st.
int qsteps; // # steps since last quake.
Npc_timer_list *timers; // Timers for poison, hunger, etc.
Rectangle weapon_rect; // Screen area weapon was drawn in.
long rest_time; // # msecs. of not doing anything.
void init(); // Clear stuff during construction.
// Move and change frame.
void movef(Map_chunk *old_chunk, Map_chunk *new_chunk,
int new_sx, int new_sy, int new_frame, int new_lift);
bool is_really_blocked(Tile_coord &t, bool force);
bool empty_hand(Game_object *obj); // Empty one hand
public:
friend class Clear_casting;
friend class Clear_hit;
static void init_default_frames(); // Set usual frame sequence.
Actor(const std::string &nm, int shapenum, int num = -1, int uc = -1);
virtual ~Actor();
// Blocked moving onto tile 't'?
int is_blocked(Tile_coord &t, Tile_coord *f = 0, const int move_flags = 0);
Game_object *find_blocking(Tile_coord const &tile, int dir);
void swap_ammo(Game_object *newammo);
bool ready_ammo(); // Find and ready appropriate ammo.
bool ready_best_weapon(); // Find best weapon and ready it.
bool ready_best_shield(); // Find best shield and ready it.
void empty_hands(); // Make sure both hands are empty.
// Force repaint of area taken.
int get_effective_weapon_shape();//For displaying casting frames.
int add_dirty(int figure_rect = 0);
void change_frame(int frnum); // Change frame & set to repaint.
int figure_weapon_pos(int &weapon_x, int &weapon_y, int &weapon_frame);
void say_hunger_message();
void use_food(); // Decrement food level.
// Increment/decrement temperature.
void check_temperature(bool freeze);
// Get frame seq. for given dir.
Frames_sequence *get_frames(int dir) {
return frames[dir / 2];
}
int &get_step_index() { // Get it (for updating).
return step_index;
}
// Get attack frames.
int get_attack_frames(int weapon, bool projectile,
int dir, signed char *frames) const;
enum Alignment { // Describes alignment field.
neutral = 0, // See [I]nspect NPC screen in SI for names.
good = 1,
evil = 2,
chaotic = 3
}; // Bees have this, & don't attack until
// Spots where items are carried.
int free_hand() const { // Get index of a free hand, or -1.
// PREFER right hand.
return two_handed ? -1 :
(!spots[rhand] ? rhand : (!spots[lhand] ? lhand : -1));
}
int free_finger() const { // Get index of a free finger, or -1.
return two_fingered ? -1 :
(!spots[lfinger] ? lfinger
: (!spots[rfinger] ? rfinger : -1));
}
inline bool is_two_handed() const {
return two_handed;
}
inline bool is_two_fingered() const {
return two_fingered;
}
inline bool is_scabbard_used() const {
return use_scabbard;
}
inline bool is_neck_used() const {
return use_neck;
}
int has_light_source() const { // Carrying a torch?
return light_sources > 0;
}
void add_light_source() { // Add a torch
light_sources++;
}
void remove_light_source() { // Remove a torch
if (light_sources)
light_sources--;
}
Attack_mode get_attack_mode() {
return attack_mode;
}
void set_attack_mode(Attack_mode amode, bool byuser = false) {
attack_mode = amode;
user_set_attack = byuser;
}
bool did_user_set_attack() const {
return user_set_attack;
}
bool is_combat_protected() const {
return combat_protected;
}
void set_combat_protected(bool v) {
combat_protected = v;
}
int get_oppressor() const {
return oppressor;
}
void set_oppressor(int opp) {
oppressor = opp;
}
enum type_flags {
tf_fly = 4,
tf_walk = 5,
tf_swim = 6,
tf_ethereal = 7,
tf_want_primary = 8,
tf_sex = 9,
tf_bleeding = 10,
tf_in_party = 12,
tf_in_action = 13,
tf_conjured = 14,
tf_summonned = 15
};
enum Item_properties { // Trying to figure out properties.
strength = 0, // This is also max. health.
dexterity = 1,
intelligence = 2,
health = 3,
combat = 4,
mana = 5,
magic = 6, // Max. mana.
training = 7, // Training points.
exp = 8, // Experience.
food_level = 9,
sex_flag = 10, // Seems to be get/set sex type flag in SI.
missile_weapon = 11 // Pretty sure it returns 1 if wearing
// weapon with uses >= 2, 0 otherwise.
};
enum Frames { // Frames 0-15. 16-31 are the same,
// only S instead of N.
standing = 0,
step_right_frame = 1,
step_left_frame = 2,
ready_frame = 3, // Ready to fight?
raise1_frame = 4, // 1-handed strikes.
reach1_frame = 5,
strike1_frame = 6,
raise2_frame = 7, // 2-handed strikes.
reach2_frame = 8,
strike2_frame = 9,
sit_frame = 10,
bow_frame = 11,
kneel_frame = 12,
sleep_frame = 13,
up_frame = 14, // Both hands reach up.
out_frame = 15 // Both hands reach out.
};
int get_face_shapenum() const { // Get "portrait" shape #.
return face_num; // It's the NPC's #.
}
int get_usecode() const {
return usecode == -1 ? Game_object::get_usecode() : usecode;
}
void set_usecode(int funid, const char *nm = 0) {
if (funid < 0) {
usecode_assigned = false;
usecode_name.clear();
funid = -1;
return;
}
if (nm)
usecode_name = nm;
else
usecode_name.clear();
usecode = funid;
usecode_assigned = true;
}
Schedule *get_schedule() const {
return schedule;
}
int get_frame_time() const { // Return frame time if moving.
return frame_time;
}
void set_frame_time(int ftime) { // Set walking speed.
frame_time = ftime;
}
void stand_at_rest(); // Stand (if not doing anyting else).
void clear_rest_time() {
rest_time = 0;
}
void resting(int msecs) { // Increment rest time.
if ((rest_time += msecs) > 2000)
stand_at_rest();// Stand (under certain conditions).
}
bool is_moving() const {
return frame_time != 0;
}
bool is_dormant() const { // Inactive (i.e., off-screen)?
return dormant;
}
bool is_dead() const {
return (flags & (1 << Obj_flags::dead)) != 0;
}
bool is_in_party() const { // (Includes Avatar.)
return (flags & (1 << Obj_flags::in_party)) != 0;
}
void set_dormant() {
dormant = true;
}
Actor_action *get_action() { // Return action.
return action;
}
// Set new action.
void set_action(Actor_action *newact);
void purge_deleted_actions();
// Notify scheduler obj. disappeared.
void notify_object_gone(Game_object *obj);
Tile_coord get_dest(); // Get destination.
// Walk to a desired spot.
void walk_to_tile(Tile_coord const &dest, int speed = 250, int delay = 0,
int maxblk = 3);
void walk_to_tile(int tx, int ty, int tz, int speed = 250,
int delay = 0, int maxblk = 3) {
walk_to_tile(Tile_coord(tx, ty, tz), speed, delay, maxblk);
}
// Get there, avoiding obstacles.
int walk_path_to_tile(Tile_coord const &src, Tile_coord const &dest,
int speed = 250, int delay = 0, int dist = 0, int maxblk = 3);
int walk_path_to_tile(Tile_coord const &dest,
int speed = 250, int delay = 0, int dist = 0, int maxblk = 3) {
return walk_path_to_tile(get_tile(), dest,
speed, delay, dist, maxblk);
}
// Start animation.
void start(int speed = 250, int delay = 0);
void start_std(); // Start with std. speed, delay.
void stop(); // Stop animation.
void follow(Actor *leader); // Follow the leader.
// Approach another from offscreen.
int approach_another(Actor *other, bool wait = false);
// Get info. about tile to step onto.
static void get_tile_info(Actor *actor,
Game_window *gwin, Map_chunk *nlist,
int tx, int ty, int &water, int &poison);
// Set combat opponent.
void set_target(Game_object *obj, bool start_combat = false);
Game_object *get_target() { // Get who/what we're attacking.
return target;
}
// Works out if an object fits in a spot
bool fits_in_spot(Game_object *obj, int spot);
// The prefered slot for an object
void get_prefered_slots(Game_object *obj, int &prefered, int &alt1, int &alt2);
// Find where to put object.
int find_best_spot(Game_object *obj);
int get_prev_schedule_type(); // Get previous schedule.
void restore_schedule(); // Set schedule after reading in.
void set_schedule_loc(Tile_coord const &loc) { // For monsters ONLY.
schedule_loc = loc;
}
// Set new schedule.
void set_schedule_type(int new_schedule_type,
Schedule *newsched = 0);
// Change to new schedule at loc
virtual void set_schedule_and_loc(int new_schedule_type,
Tile_coord const &dest, int delay = -1);
bool teleport_offscreen_to_schedule(Tile_coord const &dest, int dist);
int get_schedule_type() const {
return schedule_type;
}
// Get/set 'alignment'.
int get_alignment() const {
return alignment;
}
void set_alignment(short a) {
alignment = a;
}
int get_effective_alignment() const; // Include 'charmed' flag.
void set_effective_alignment(int newalign); // Include 'charmed' flag.
void reset_effective_alignment() {
charmalign = alignment;
}
// Update chunks after NPC moved.
virtual void switched_chunks(Map_chunk *, Map_chunk *)
{ }
// Update schedule for new 3-hour time.
virtual void update_schedule(int hour3, int delay = -1,
Tile_coord *pos = 0) {
ignore_unused_variable_warning(hour3, delay, pos);
}
// Render.
virtual void paint();
// Run usecode function.
virtual void activate(int event = 1);
virtual bool edit(); // Edit in ExultStudio.
// Saved from ExultStudio.
static void update_from_studio(unsigned char *data, int datalen);
// Drop another onto this.
virtual int drop(Game_object *obj);
virtual std::string get_name() const;
std::string get_npc_name() const;
std::string get_npc_name_string() const {
return name;
}
void set_npc_name(const char *n);
void set_property(int prop, int val);
virtual bool try_to_hit(Game_object *attacker, int attval);
// Under attack.
virtual Game_object *attacked(Game_object *attacker, int weapon_shape = 0,
int ammo_shape = 0, bool explosion = false);
virtual int figure_hit_points(Game_object *attacker, int weapon_shape = -1,
int ammo_shape = -1, bool explosion = false);
virtual int apply_damage(Game_object *attacker, int str,
int wpoints, int type, int bias = 0, int *exp = 0);
// Lose HP's and check for death.
virtual int reduce_health(int delta, int damage_type, Game_object *attacker = 0,
int *exp = 0);
void fight_back(Game_object *attacker);
bool get_attack_target(Game_object *&obj, Tile_coord &t) {
static Tile_coord invalidloc(-1, -1, 0);
obj = target_object;
t = target_tile;
return (target_object || target_tile != invalidloc);
}
void set_attack_target(Game_object *t, int w) {
target_tile = Tile_coord(-1, -1, 0);
target_object = t;
attack_weapon = w;
}
void set_attack_target(Tile_coord const &t, int w) {
target_object = 0;
target_tile = t;
target_tile.fixme();
attack_weapon = w;
}
virtual int get_effective_range(const Weapon_info *winf = 0, int reach = -1);
virtual Game_object *find_weapon_ammo(int weapon, int needed = 1,
bool recursive = false);
Game_object *find_best_ammo(int family, int needed = 1);
bool usecode_attack();
int get_property(int prop) const;
int get_effective_prop(int prop) const;
bool is_dying() const { // Dead when health below -1/3 str.
return properties[static_cast<int>(health)] <
-(properties[static_cast<int>(strength)] / 3);
}
bool is_knocked_out() const {
return get_property(static_cast<int>(health)) <= 0;
}
int get_level() const { // Get experience level.
return 1 + Log2(get_property(exp) / 50);
}
// Get/set generic attribute.
void set_attribute(const char *nm, int val);
int get_attribute(const char *nm);
typedef std::vector<std::pair<const char *, int> > Atts_vector;
void get_attributes(Atts_vector &attlst);
// Set atts. from savegame.
virtual void read_attributes(unsigned char *buf, int len);
Npc_timer_list *need_timers();
// Set/clear/get actor flag.
void force_sleep();
void clear_sleep() {
flags &= ~(static_cast<uint32>(1) << Obj_flags::asleep);
}
virtual void set_flag(int flag);
void set_type_flag(int flag);
virtual void clear_flag(int flag);
void clear_type_flag(int flag);
int get_type_flag(int flag) const;
void set_type_flags(unsigned short tflags);
int get_skin_color() const {
return skin_color;
}
void set_skin_color(int color) {
skin_color = color;
set_actor_shape();
}
virtual int get_type_flags() const {
return type_flags;
}
short get_casting_mode() const {
return casting_mode;
}
void end_casting_mode(int delay);
int get_casting_shape() const {
return casting_shape;
}
void begin_casting(int s) {
casting_mode = init_casting;
casting_shape = s;
}
void display_casting_frames() {
casting_mode = show_casting_frames;
}
void hide_casting_frames() {
casting_mode = not_casting;
}
//++++++Is_dead() test messes up training.
// unsigned char get_ident() { return is_dead() ? 0 : ident; }
unsigned char get_ident() {
return ident;
}
void set_ident(unsigned char id) {
ident = id;
}
int get_temperature() const { // Get/set measure of coldness.
return temperature;
}
void set_temperature(int t);
int get_temperature_zone() const {
// SI-verified.
if (temperature < 15)
return 1;
else if (temperature < 25)
return 2;
else if (temperature < 40)
return 3;
else if (temperature < 50)
return 4;
else
return 5;
}
int figure_warmth(); // Based on what's worn.
bool is_unused() const { // Free NPC?
return unused;
}
void set_unused(bool tf) {
unused = tf;
}
int get_npc_num() const { // Get its ID (1-num_npcs).
return npc_num;
}
// Get/set index within party.
int get_party_id() const {
return party_id;
}
void set_party_id(int i) {
party_id = i;
}
// Set for Usecode animations.
void set_usecode_dir(int d) {
usecode_dir = d & 7;
}
int get_usecode_dir() const {
return usecode_dir;
}
virtual Actor *as_actor() { // An actor?
return this;
}
virtual bool is_slime() const {
return false;
}
void init_readied(); // Call Usecode to init. readied objs.
// Remove an object.
virtual void remove(Game_object *obj);
// Add an object.
virtual bool add(Game_object *obj, bool dont_check = false,
bool combine = false, bool noset = false);
// Add to NPC 'readied' spot.
virtual int add_readied(Game_object *obj, int index,
int dont_check = 0, int force_pos = 0, bool noset = false);
virtual int find_readied(Game_object *obj);
virtual Game_object *get_readied(int index) const {
return index >= 0 &&
index < static_cast<int>(sizeof(spots) / sizeof(spots[0])) ?
spots[index] : 0;
}
virtual void call_readied_usecode(int index,
Game_object *obj, int eventid);
virtual int get_max_weight(); // Get max. weight allowed.
// Change member shape.
virtual void change_member_shape(Game_object *obj, int newshape);
// Move out of the way.
virtual int move_aside(Actor *for_actor, int dir);
// Get frame if rotated clockwise.
virtual int get_rotated_frame(int quads);
virtual int get_armor_points(); // Get total armor value.
// Gets whether the actor is immune or vulnerable to a given
// form of damage:
int is_immune(int type) const;
bool is_goblin() const;
bool can_see_invisible() const;
bool can_speak() const;
bool is_sentient() const;
void refigure_gear();
bool check_gear_powers(int flags) const {
return (gear_powers & flags) != 0;
}
// Get total weapon value.
virtual Weapon_info *get_weapon(int &points, int &shape,
Game_object *&obj);
Weapon_info *get_weapon(int &points) {
int sh;
Game_object *o;
return get_weapon(points, sh, o);
}
static bool roll_to_win(int attacker, int defender);
// Hit-point algorithm:
bool can_act();
bool can_act_charmed(); // checks for charmed and charmed_more_difficult
void set_charmed_combat();
virtual void fall_down();
virtual void lay_down(bool die);
virtual void die(Game_object *attacker); // We're dead.
Actor *resurrect(Dead_body *body);// Bring back to life.
Monster_actor *clone(); // Create another nearby to this.
void mend_wounds(bool mendmana); // Restore HP's and MP's.
// Read from file.
void read(DataSource *nfile, int num, bool has_usecode,
bool &fix_unused);
// Don't write out to IREG file.
virtual void write_ireg(DataSource *out) {
ignore_unused_variable_warning(out);
}
virtual int get_ireg_size() {
return 0;
}
void write(DataSource *nfile);// Write out (to 'npc.dat').
virtual void write_contents(DataSource *out); // Write contents
void set_actor_shape(); // Set shape based on sex, skin color
void set_polymorph(int shape); // Set a polymorph shape
void set_polymorph_default(); // Set the default shape
// Get the polymorph shape
int get_polymorph() {
return shape_save;
}
// Get the non polymorph shape (note, doesn't returned skin coloured shapes)
// For usecode
int get_shape_real();
// This does the same, but will return skin coloured shapes
// For paperdolls/face stats
int get_sexed_coloured_shape() {
return shape_save != -1 ? shape_save : get_shapenum();
}
// Set schedule list.
virtual void set_schedules(Schedule_change *list, int cnt) {
ignore_unused_variable_warning(list, cnt);
}
virtual void set_schedule_time_type(int time, int type) {
ignore_unused_variable_warning(time, type);
}
virtual void set_schedule_time_location(int time, int x, int y) {
ignore_unused_variable_warning(time, x, y);
}
virtual void remove_schedule(int time) {
ignore_unused_variable_warning(time);
}
virtual void get_schedules(Schedule_change *&list, int &cnt) {
list = NULL, cnt = 0;
}
virtual int find_schedule_at_time(int hour3) {
ignore_unused_variable_warning(hour3);
return -1;
}
void show_inventory();
int inventory_shapenum();
bool was_hit() {
return hit;
}
// Should be virtual???
void cache_out();
bool in_usecode_control() const;
bool quake_on_walk();
};
/*
* Actor frame descriptions:
0 Standing
1 Walk
2 Walk
3 Beginning to attack
4-6 Attacking with one hand
7-9 Attacking with two hands
9 Also NPC shooting magic
10 Sitting down
11 Bending over (beginning to sit down)
12 Kneeling
11 Lying down
14 Casting spell (hands raised)
15 Casting spell (hands outstretched)
*/
/*
* The main actor.
*/
class Main_actor : public Actor {
public:
Main_actor(const std::string &nm, int shapenum, int num = -1, int uc = -1)
: Actor(nm, shapenum, num, uc) {
frames = &avatar_frames[0];
}
virtual ~Main_actor();
// For Time_sensitive:
virtual void handle_event(unsigned long curtime, uintptr udata);
void get_followers(); // Get party to follow.
// Step onto an (adjacent) tile.
virtual int step(Tile_coord t, int frame, bool force = false);
// Update chunks after NPC moved.
virtual void switched_chunks(Map_chunk *olist,
Map_chunk *nlist);
// Move to new abs. location.
virtual void move(int newtx, int newty, int newlift, int newmap = -1);
virtual void die(Game_object *attacker); // We're dead.
};
/*
* A non-player-character that one can converse (or fight) with:
*/
class Npc_actor : public Actor {
unsigned char nearby; // Queued as a 'nearby' NPC. This is
// to avoid being added twice.
protected:
unsigned char num_schedules; // # entries below.
Schedule_change *schedules; // List of schedule changes.
int find_schedule_change(int hour3);
public:
Npc_actor(const std::string &nm, int shapenum, int num = -1,
int uc = -1);
virtual ~Npc_actor();
void set_nearby() { // Set/clear/test 'nearby' flag.
nearby = true;
}
void clear_nearby() {
nearby = false;
}
bool is_nearby() const {
return nearby != 0;
}
// Set schedule list.
virtual void set_schedules(Schedule_change *list, int cnt);
virtual void set_schedule_time_type(int time, int type);
virtual void set_schedule_time_location(int time, int x, int y);
virtual void remove_schedule(int time);
virtual void get_schedules(Schedule_change *&list, int &cnt);
// Move and change frame.
void movef(Map_chunk *old_chunk, Map_chunk *new_chunk,
int new_sx, int new_sy, int new_frame, int new_lift);
// Update schedule for new 3-hour time.
virtual void update_schedule(int hour3, int delay = -1,
Tile_coord *pos = 0);
virtual int find_schedule_at_time(int hour3);
// Render.
virtual void paint();
// Run usecode function.
virtual void activate(int event = 1);
// For Time_sensitive:
virtual void handle_event(unsigned long curtime, uintptr udata);
// Step onto an (adjacent) tile.
virtual int step(Tile_coord t, int frame, bool force = false);
// Remove/delete this object.
virtual void remove_this(int nodel = 0);
// Update chunks after NPC moved.
virtual void switched_chunks(Map_chunk *olist,
Map_chunk *nlist);
// Move to new abs. location.
virtual void move(int newtx, int newty, int newlift, int newmap = -1);
virtual Npc_actor *as_npc() {
return this;
}
};
/*
* An actor's dead body:
*/
class Dead_body : public Container_game_object {
short npc_num; // # of NPC it came from, or -1.
public:
Dead_body(int shapenum, int framenum, unsigned int tilex,
unsigned int tiley, unsigned int lft, int n)
: Container_game_object(shapenum, framenum, tilex, tiley, lft),
npc_num(n) {
}
virtual ~Dead_body();
virtual int get_live_npc_num() const;
// Under attack.
virtual Game_object *attacked(Game_object *attacker, int weapon_shape = 0,
int ammo_shape = 0, bool explosion = false) {
ignore_unused_variable_warning(attacker, weapon_shape, ammo_shape, explosion);
return this; // Not affected.
}
virtual void write_ireg(DataSource *out);
virtual int get_ireg_size();
};
#endif