00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef INCL_ACTORS
00023 #define INCL_ACTORS 1
00024
00025 #include "contain.h"
00026 #include "utils.h"
00027 #include "flags.h"
00028
00029 class Image_window;
00030 class Game_window;
00031 class Npc_actor;
00032 class Actor_action;
00033 class Schedule;
00034 class Schedule_change;
00035 class Monster_info;
00036 class Monster_actor;
00037 class Weapon_info;
00038 class Dead_body;
00039 class Npc_timer_list;
00040 class Frames_sequence;
00041 class Animator;
00042
00043 const int ACTOR_FIRST_GUMP = 57, ACTOR_LAST_GUMP = 68;
00044
00045
00046
00047
00048 class Actor : public Container_game_object, public Time_sensitive
00049 {
00050 static Actor *editing;
00051 protected:
00052 std::string name;
00053 int usecode;
00054 bool usecode_assigned;
00055 bool unused;
00056
00057 short npc_num;
00058 short face_num;
00059 short party_id;
00060 int properties[12];
00061 unsigned char temperature;
00062 short shape_save;
00063 short oppressor;
00064 Game_object *target;
00065 public:
00066 enum Attack_mode {
00067 nearest = 0,
00068 weakest = 1,
00069 strongest = 2,
00070 beserk = 3,
00071 protect = 4,
00072 defend = 5,
00073 flank = 6,
00074 flee = 7,
00075 random = 8,
00076 manual = 9
00077 };
00078 protected:
00079
00080 const static short party_pos[4][10][2];
00081
00082 Attack_mode attack_mode;
00083
00084 static Frames_sequence *avatar_frames[4];
00085 static Frames_sequence *npc_frames[4];
00086 Frames_sequence **frames;
00087
00088 void paint_weapon();
00089 unsigned char schedule_type;
00090 Tile_coord schedule_loc;
00091 unsigned char next_schedule;
00092
00093 Schedule *schedule;
00094 bool dormant;
00095 bool hit;
00096 bool combat_protected;
00097 bool user_set_attack;
00098 short alignment;
00099 Game_object *spots[18];
00100
00101 bool two_handed;
00102 bool two_fingered;
00103 unsigned char light_sources;
00104 unsigned char usecode_dir;
00105 unsigned siflags:32;
00106 unsigned type_flags:32;
00107
00108 unsigned char ident;
00109
00110 int skin_color;
00111 Actor_action *action;
00112 int frame_time;
00113
00114 int step_index;
00115 Npc_timer_list *timers;
00116 Rectangle weapon_rect;
00117 long rest_time;
00118 void init();
00119
00120 void movef(Map_chunk *old_chunk, Map_chunk *new_chunk,
00121 int new_sx, int new_sy, int new_frame, int new_lift);
00122 public:
00123 friend class Clear_hit;
00124 static void init_default_frames();
00125 Actor(const std::string &nm, int shapenum, int num = -1, int uc = -1);
00126 ~Actor();
00127
00128 int is_blocked(Tile_coord& t, Tile_coord *f = 0);
00129 int ready_ammo();
00130 void ready_best_weapon();
00131 void unready_weapon(int spot);
00132
00133 int add_dirty(int figure_rect = 0);
00134 void change_frame(int frnum);
00135 int figure_weapon_pos(int& weapon_x, int& weapon_y, int& weapon_frame);
00136 void use_food();
00137
00138 void check_temperature(bool freeze);
00139
00140 Frames_sequence *get_frames(int dir)
00141 { return frames[dir/2]; }
00142 int& get_step_index()
00143 { return step_index; }
00144
00145 int get_attack_frames(int weapon, bool projectile,
00146 int dir, signed char *frames) const;
00147 enum Alignment {
00148 neutral = 0,
00149 friendly = 1,
00150 hostile = 2,
00151 unknown_align = 3 };
00152
00153 enum Spots {
00154
00155 head = 0,
00156 back = 1,
00157 belt = 2,
00158 lhand = 3,
00159 lfinger = 4,
00160 legs = 5,
00161 feet = 6,
00162 rfinger = 7,
00163 rhand = 8,
00164 torso = 9,
00165 neck = 10,
00166 ammo = 11,
00167 back2h_spot = 12,
00168
00169 shield_spot = 13,
00170 ears_spot = 14,
00171 cloak_spot = 15,
00172 hands2_spot = 16,
00173 ucont_spot = 17,
00174 lrhand = 100,
00175 lrfinger = 101,
00176 special_spot = 102
00177 };
00178 int free_hand() const
00179 {
00180 return two_handed ? -1 :
00181 (!spots[rhand] ? rhand : (!spots[lhand] ? lhand : -1));
00182 }
00183 int free_finger() const
00184 {
00185 return two_fingered ? -1 :
00186 (!spots[lfinger] ? lfinger
00187 : (!spots[rfinger] ? rfinger : -1));
00188 }
00189 inline bool is_two_handed() const { return two_handed; }
00190 inline bool is_two_fingered() const { return two_fingered; }
00191 int has_light_source() const
00192 { return light_sources > 0; }
00193 Attack_mode get_attack_mode()
00194 { return attack_mode; }
00195 void set_attack_mode(Attack_mode amode, bool byuser = false)
00196 { attack_mode = amode; user_set_attack = byuser; }
00197 bool did_user_set_attack() const
00198 { return user_set_attack; }
00199 bool is_combat_protected() const
00200 { return combat_protected; }
00201 void set_combat_protected(bool v)
00202 { combat_protected = v; }
00203 int get_oppressor() const
00204 { return oppressor; }
00205 void set_oppressor(int opp)
00206 { oppressor = opp; }
00207
00208 enum Serpent_flags {
00209
00210
00211
00212 naked = 8,
00213
00214 };
00215 enum type_flags {
00216 tf_fly = 4,
00217 tf_walk = 5,
00218 tf_swim = 6,
00219 tf_ethereal = 7,
00220 tf_want_primary = 8,
00221 tf_sex = 9,
00222 tf_bleeding = 10,
00223 tf_in_party = 12,
00224 tf_in_action = 13,
00225 tf_conjured = 14,
00226 tf_summonned = 15
00227 };
00228 enum Item_properties {
00229 strength = 0,
00230 dexterity = 1,
00231 intelligence = 2,
00232 health = 3,
00233 combat = 4,
00234 mana = 5,
00235 magic = 6,
00236 training = 7,
00237 exp = 8,
00238 food_level = 9
00239 };
00240 enum Frames {
00241
00242 standing = 0,
00243 step_right_frame = 1,
00244 step_left_frame = 2,
00245 ready_frame = 3,
00246 raise1_frame = 4,
00247 reach1_frame = 5,
00248 strike1_frame = 6,
00249 raise2_frame = 7,
00250 reach2_frame = 8,
00251 strike2_frame = 9,
00252 sit_frame = 10,
00253 bow_frame = 11,
00254 kneel_frame = 12,
00255 sleep_frame = 13,
00256 up_frame = 14,
00257 out_frame = 15
00258 };
00259 enum FIS_Type {
00260 FIS_Other = 0,
00261 FIS_2Hand = 1,
00262 FIS_2Finger = 2,
00263 FIS_Spell = 3
00264 };
00265
00266 int get_face_shapenum() const
00267 { return face_num; }
00268 int get_usecode() const
00269 { return usecode == -1 ? get_shapenum() : usecode; }
00270 Schedule *get_schedule() const
00271 { return schedule; }
00272 int get_frame_time() const
00273 { return frame_time; }
00274 void set_frame_time(int ftime)
00275 { frame_time = ftime; }
00276 void stand_at_rest();
00277 void clear_rest_time()
00278 { rest_time = 0; }
00279 void resting(int msecs)
00280 {
00281 if ((rest_time += msecs) > 2000)
00282 stand_at_rest();
00283 }
00284 bool is_moving() const
00285 { return frame_time != 0; }
00286 bool is_dormant() const
00287 { return dormant; }
00288 bool is_dead() const
00289 { return (flags&(1<<Obj_flags::dead)) != 0; }
00290 bool is_in_party() const
00291 { return (flags&(1<<Obj_flags::in_party)) != 0; }
00292 void set_dormant()
00293 { dormant = true; }
00294 Actor_action *get_action()
00295 { return action; }
00296
00297 void set_action(Actor_action *newact);
00298
00299 void notify_object_gone(Game_object *obj);
00300 Tile_coord get_dest();
00301
00302 void walk_to_tile(Tile_coord dest, int speed = 250, int delay = 0,
00303 int maxblk = 3);
00304 void walk_to_tile(int tx, int ty, int tz, int speed = 250,
00305 int delay = 0, int maxblk = 3)
00306 { walk_to_tile(Tile_coord(tx, ty, tz), speed, delay, maxblk); }
00307
00308 int walk_path_to_tile(Tile_coord src, Tile_coord dest,
00309 int speed = 250, int delay = 0, int dist = 0, int maxblk = 3);
00310 int walk_path_to_tile(Tile_coord dest,
00311 int speed = 250, int delay = 0, int dist = 0, int maxblk = 3)
00312 { return walk_path_to_tile(get_tile(), dest,
00313 speed, delay, dist, maxblk); }
00314
00315 void start(int speed = 250, int delay = 0);
00316 void stop();
00317 void follow(Actor *leader);
00318
00319 int approach_another(Actor *other, bool wait = false);
00320
00321 static void get_tile_info(Actor *actor,
00322 Game_window *gwin, Map_chunk *nlist,
00323 int tx, int ty, int& water, int& poison);
00324
00325 void set_target(Game_object *obj, bool start_combat = false);
00326 Game_object *get_target()
00327 { return target; }
00328
00329 bool fits_in_spot (Game_object *obj, int spot, FIS_Type type = FIS_Other);
00330
00331 void get_prefered_slots (Game_object *obj, int &prefered, int &alternate, FIS_Type &fistype);
00332
00333 int find_best_spot(Game_object *obj);
00334 int get_prev_schedule_type();
00335 void restore_schedule();
00336
00337 void set_schedule_type(int new_schedule_type,
00338 Schedule *newsched = 0);
00339
00340 virtual void set_schedule_and_loc(int new_schedule_type,
00341 Tile_coord dest, int delay = -1);
00342 int get_schedule_type() const
00343 { return schedule_type; }
00344
00345 int get_alignment() const
00346 { return alignment; }
00347 void set_alignment(short a)
00348 { alignment = a; }
00349
00350 virtual void switched_chunks(Map_chunk *, Map_chunk *)
00351 { }
00352
00353 virtual void update_schedule(int hour3,
00354 int backwards = 0, int delay = -1)
00355 { }
00356
00357 virtual void paint();
00358
00359 virtual void activate(int event = 1);
00360 virtual bool edit();
00361
00362 static void update_from_studio(unsigned char *data, int datalen);
00363
00364 virtual int drop(Game_object *obj);
00365 virtual std::string get_name() const;
00366 std::string get_npc_name() const;
00367 void set_npc_name(const char *n);
00368 void set_property(int prop, int val);
00369
00370 bool reduce_health(int delta, Actor *attacker = 0);
00371 int get_property(int prop) const
00372 { return (prop >= 0 && prop < 12) ? properties[prop] : 0; }
00373 int get_effective_prop(int prop) const;
00374 bool is_dying() const
00375 { return properties[(int) health] <
00376 -(properties[(int) strength]/3); }
00377 int get_level() const
00378 { return 1 + Log2(get_property(exp)/50); }
00379 Npc_timer_list *need_timers();
00380
00381 virtual void set_flag(int flag);
00382 virtual void set_siflag(int flag);
00383 void set_type_flag(int flag);
00384 virtual void clear_flag(int flag);
00385 virtual void clear_siflag(int flag);
00386 void clear_type_flag(int flag);
00387 virtual int get_siflag(int flag) const;
00388 int get_type_flag(int flag) const;
00389 void set_type_flags(unsigned short tflags);
00390 int get_skin_color () const { return skin_color; }
00391 void set_skin_color (int color) { skin_color = color; set_actor_shape();}
00392 virtual int get_type_flags() const
00393 { return type_flags; }
00394
00395
00396 unsigned char get_ident() { return ident; }
00397 void set_ident(unsigned char id) { ident = id; }
00398
00399 int get_temperature() const
00400 { return temperature; }
00401 void set_temperature(int t);
00402 int figure_warmth();
00403 bool is_unused() const
00404 { return unused; }
00405 void set_unused(bool tf)
00406 { unused = tf; }
00407
00408 int get_npc_num() const
00409 { return npc_num; }
00410
00411 int get_party_id() const
00412 { return party_id; }
00413 void set_party_id(int i)
00414 { party_id = i; }
00415
00416 void set_usecode_dir(int d)
00417 { usecode_dir = d&7; }
00418 int get_usecode_dir() const
00419 { return usecode_dir; }
00420 virtual Actor *as_actor()
00421 { return this; }
00422 void init_readied();
00423
00424 virtual void remove(Game_object *obj);
00425
00426 virtual bool add(Game_object *obj, bool dont_check = false,
00427 bool combine = false);
00428
00429 virtual int add_readied(Game_object *obj, int index, int dont_check = 0, int force_pos = 0);
00430 virtual int find_readied(Game_object *obj);
00431 virtual Game_object *get_readied(int index) const
00432 {
00433 return index >= 0 &&
00434 index < (int)(sizeof(spots)/sizeof(spots[0])) ?
00435 spots[index] : 0;
00436 }
00437 virtual void call_readied_usecode(int index,
00438 Game_object *obj, int eventid);
00439 virtual int get_max_weight();
00440
00441 virtual void change_member_shape(Game_object *obj, int newshape);
00442
00443 virtual int move_aside(Actor *for_actor, int dir);
00444
00445 virtual int get_rotated_frame(int quads);
00446 virtual int get_armor_points();
00447
00448 virtual Weapon_info *get_weapon(int& points, int& shape);
00449 Weapon_info *get_weapon(int& points)
00450 { int sh; return get_weapon(points, sh); }
00451 static bool roll_to_win(int attacker, int defender);
00452
00453 bool figure_hit_points(Actor *attacker, int weapon_shape,
00454 int ammo_shape);
00455
00456 virtual Game_object *attacked(Actor *attacker, int weapon_shape = 0,
00457 int ammo_shape = 0);
00458 virtual void die(Actor *attacker);
00459 Actor *resurrect(Dead_body *body);
00460 Monster_actor *clone();
00461 void mend_hourly();
00462
00463 void read(DataSource* nfile, int num, bool has_usecode,
00464 bool& fix_unused);
00465
00466 virtual void write_ireg(DataSource* out) { }
00467 virtual int get_ireg_size() { return 0; }
00468 void write(DataSource* nfile);
00469 virtual void write_contents(DataSource* out);
00470 void set_actor_shape();
00471 void set_polymorph(int shape);
00472 void set_polymorph_default();
00473
00474 int get_polymorph () { return shape_save; }
00475
00476
00477 int get_shape_real();
00478
00479
00480 int get_sexed_coloured_shape() { return shape_save!=-1?shape_save:get_shapenum(); }
00481
00482
00483 virtual void set_schedules(Schedule_change *list, int cnt) { }
00484 virtual void set_schedule_time_type(int time, int type) { }
00485 virtual void set_schedule_time_location(int time, int x, int y) { }
00486 virtual void remove_schedule(int time) { }
00487 virtual void get_schedules(Schedule_change *&list, int &cnt)
00488 { list = NULL, cnt = 0; }
00489
00490 void show_inventory();
00491 int inventory_shapenum();
00492
00493 bool was_hit() { return hit; }
00494
00495
00496 void cache_out();
00497 };
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 class Main_actor : public Actor
00521 {
00522 public:
00523 Main_actor(const std::string &nm, int shapenum, int num = -1, int uc = -1)
00524 : Actor(nm, shapenum, num, uc)
00525 { frames = &avatar_frames[0]; }
00526
00527 virtual void handle_event(unsigned long curtime, long udata);
00528 void get_followers();
00529
00530 virtual int step(Tile_coord t, int frame);
00531
00532 virtual void switched_chunks(Map_chunk *olist,
00533 Map_chunk *nlist);
00534
00535 virtual void move(int newtx, int newty, int newlift);
00536 virtual void die(Actor *attacker);
00537 };
00538
00539
00540
00541
00542 class Npc_actor : public Actor
00543 {
00544 unsigned char nearby;
00545
00546 protected:
00547 unsigned char num_schedules;
00548 Schedule_change *schedules;
00549 int find_schedule_change(int hour3);
00550 public:
00551 Npc_actor(const std::string &nm, int shapenum, int num = -1,
00552 int uc = -1);
00553 ~Npc_actor();
00554 void set_nearby()
00555 { nearby = true; }
00556 void clear_nearby()
00557 { nearby = false; }
00558 bool is_nearby() const
00559 { return nearby!=0; }
00560
00561 virtual void set_schedules(Schedule_change *list, int cnt);
00562 virtual void set_schedule_time_type(int time, int type);
00563 virtual void set_schedule_time_location(int time, int x, int y);
00564 virtual void remove_schedule(int time);
00565 virtual void get_schedules(Schedule_change *&list, int &cnt);
00566
00567 void movef(Map_chunk *old_chunk, Map_chunk *new_chunk,
00568 int new_sx, int new_sy, int new_frame, int new_lift);
00569
00570 virtual void update_schedule(int hour3,
00571 int backwards = 0, int delay = -1);
00572
00573 virtual void paint();
00574
00575 virtual void activate(int event = 1);
00576
00577 virtual void handle_event(unsigned long curtime, long udata);
00578
00579 virtual int step(Tile_coord t, int frame);
00580
00581 virtual void remove_this(int nodel = 0);
00582
00583 virtual void switched_chunks(Map_chunk *olist,
00584 Map_chunk *nlist);
00585
00586 virtual void move(int newtx, int newty, int newlift);
00587
00588 virtual Npc_actor *as_npc() { return this; }
00589 };
00590
00591
00592
00593
00594 class Dead_body : public Container_game_object
00595 {
00596 short npc_num;
00597 public:
00598 Dead_body(int shapenum, int framenum, unsigned int tilex,
00599 unsigned int tiley, unsigned int lft, int n)
00600 : Container_game_object(shapenum, framenum, tilex, tiley, lft),
00601 npc_num(n)
00602 {
00603 }
00604 virtual ~Dead_body();
00605 virtual int get_live_npc_num();
00606
00607 virtual Game_object *attacked(Actor *attacker, int weapon_shape = 0,
00608 int ammo_shape = 0)
00609 { return this; }
00610 };
00611
00612 #endif