1 /*
2  *  actors.cc - Game actors.
3  *
4  *  Copyright (C) 1998-1999  Jeffrey S. Freedman
5  *  Copyright (C) 2000-2013  The Exult Team
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #  include <config.h>
24 #endif
25 
26 #include <memory>
27 
28 #include <iostream>           /* Debugging. */
29 #include <cstdlib>
30 #include <cstring>
31 #include <algorithm>        /* swap. */
32 #include <set>
33 #include <map>
34 #include "chunks.h"
35 #include "gamemap.h"
36 #include "Astar.h"
37 #include "Audio.h"
38 #include "Gump_manager.h"
39 #include "Paperdoll_gump.h"
40 #include "Zombie.h"
41 #include "actions.h"
42 #include "actors.h"
43 #include "cheat.h"
44 #include "combat.h"
45 #include "combat_opts.h"
46 #include "dir.h"
47 #include "egg.h"
48 #include "exult.h"
49 #include "Face_stats.h"
50 #include "frameseq.h"
51 #include "game.h"
52 #include "gamewin.h"
53 #include "gameclk.h"
54 #include "imagewin.h"
55 #include "items.h"
56 #include "npctime.h"
57 #include "ready.h"
58 #include "ucmachine.h"
59 #include "party.h"
60 #include "monstinf.h"
61 #include "exult_constants.h"
62 #include "monsters.h"
63 #include "effects.h"
64 #include "palette.h"
65 #include "ucsched.h"
66 #include "ucscriptop.h"
67 #include "miscinf.h"
68 #include "animate.h"
69 #include "objiter.h"
70 #include "ammoinf.h"
71 #include "armorinf.h"
72 #include "frflags.h"
73 #include "weaponinf.h"
74 #include "npcdollinf.h"
75 #include "spellbook.h"
76 #include "usefuns.h"
77 #include "ignore_unused_variable_warning.h"
78 #include "array_size.h"
79 
80 #ifdef USE_EXULTSTUDIO
81 #include "server.h"
82 #include "objserial.h"
83 #include "mouse.h"
84 #include "servemsg.h"
85 #endif
86 
87 using std::cerr;
88 using std::cout;
89 using std::endl;
90 using std::memcpy;
91 using std::rand;
92 using std::string;
93 using std::swap;
94 
95 Game_object_shared Actor::editing;
96 
97 extern bool combat_trace;
98 
99 // Party positions
100 // Direction, Party num, xy (tile) from leader
101 //
102 // Please Don't Touch - Colourless
103 //
104 const short Actor::party_pos[4][10][2] = {
105 	// North Facing
106 	{
107 		{ -2, 2 },
108 		{ 2, 2 },
109 		{ 0, 4 },
110 		{ -4, 4 },
111 		{ 4, 4 },
112 		{ -2, 6 },
113 		{ 2, 6 },
114 		{ 0, 8 },
115 		{ -4, 8 },
116 		{ 4, 8 }
117 	},
118 	// East Facing,
119 	{
120 		{ -2, -2 },
121 		{ -2, 2 },
122 		{ -4, 0 },
123 		{ -4, -4 },
124 		{ -4, 4 },
125 		{ -6, -2 },
126 		{ -6, 2 },
127 		{ -8, 0 },
128 		{ -8, -4 },
129 		{ -8, 4 }
130 	},
131 	// South Facing
132 	{
133 		{ -2, -2 },
134 		{ 2, -2 },
135 		{ 0, -4 },
136 		{ -4, -4 },
137 		{ 4, -4 },
138 		{ -2, -6 },
139 		{ 2, -6 },
140 		{ 0, -8 },
141 		{ -4, -8 },
142 		{ 4, -8 }
143 	},
144 	// West Facing
145 	{
146 		{ 2, -2 },
147 		{ 2, 2 },
148 		{ 4, 0 },
149 		{ 4, -4 },
150 		{ 4, 4 },
151 		{ 6, -2 },
152 		{ 6, 2 },
153 		{ 8, 0 },
154 		{ 8, -4 },
155 		{ 8, 4 }
156 	}
157 };
158 
159 //	Actor frame to substitute when a frame is empty (as some are):
160 uint8 visible_frames[16] = {
161 	Actor::standing,        // Standing.
162 	Actor::standing,        // Steps.
163 	Actor::standing,
164 	Actor::standing,        // Ready.
165 	Actor::raise2_frame,        // 1-handed strikes => 2-handed.
166 	Actor::reach2_frame,
167 	Actor::strike2_frame,
168 	Actor::raise1_frame,        // 2-handed => 1-handed.
169 	Actor::reach1_frame,
170 	Actor::strike1_frame,
171 	Actor::standing,        // When you can't sit...
172 	Actor::kneel_frame,     // When you can't bow.
173 	Actor::bow_frame,       // When you can't kneel.
174 	Actor::standing,        // Can't lie.
175 	Actor::strike2_frame,       // Can't raise hands.
176 	Actor::ready_frame
177 };   // Can't strech arms outward.
178 
179 
180 // Set up actor's frame lists.
181 // Most NPC's walk with a 'stand'
182 //   frame between steps.
183 const int FRAME_NUM = 5;
184 uint8 npc_north_framenums[FRAME_NUM] = { 0,  1,  0,  2,  0},
185       npc_south_framenums[FRAME_NUM] = {16, 17, 16, 18, 16},
186       npc_east_framenums[FRAME_NUM] = {48, 49, 48, 50, 48},
187       npc_west_framenums[FRAME_NUM] = {32, 33, 32, 34, 32};
188 static Frames_sequence npc_north_frames(FRAME_NUM, npc_north_framenums);
189 static Frames_sequence npc_south_frames(FRAME_NUM, npc_south_framenums);
190 static Frames_sequence npc_east_frames(FRAME_NUM, npc_east_framenums);
191 static Frames_sequence npc_west_frames(FRAME_NUM, npc_west_framenums);
192 // Avatar just walks left, right.
193 uint8 avatar_north_framenums[3] = {0, 1, 2},
194       avatar_south_framenums[3] = {16, 17, 18},
195       avatar_east_framenums[3] = {48, 49, 50},
196       avatar_west_framenums[3] = {32, 33, 34};
197 static Frames_sequence avatar_north_frames(3, avatar_north_framenums);
198 static Frames_sequence avatar_south_frames(3, avatar_south_framenums);
199 static Frames_sequence avatar_east_frames(3, avatar_east_framenums);
200 static Frames_sequence avatar_west_frames(3, avatar_west_framenums);
201 
202 Frames_sequence *Actor::avatar_frames[4] = {nullptr, nullptr, nullptr, nullptr};
203 Frames_sequence *Actor::npc_frames[4] = {nullptr, nullptr, nullptr, nullptr};
204 
205 const signed char sea_serpent_attack_frames[] = {1, 2, 3};
206 const signed char reach_attack_frames1[] = {3, 6};
207 const signed char raise_attack_frames1[] = {3, 4, 6};
208 const signed char fast_swing_attack_frames1[] = {3, 5, 6};
209 const signed char slow_swing_attack_frames1[] = {3, 4, 5, 6};
210 const signed char reach_attack_frames2[] = {3, 9};
211 const signed char raise_attack_frames2[] = {3, 7, 9};
212 const signed char fast_swing_attack_frames2[] = {3, 8, 9};
213 const signed char slow_swing_attack_frames2[] = {3, 7, 8, 9};
214 
215 // inline int Is_attack_frame(int i) { return i >= 3 && i <= 9; }
Is_attack_frame(int i)216 inline bool Is_attack_frame(int i) {
217 	return i == 6 || i == 9;
218 }
Get_dir_from_frame(int i)219 inline int Get_dir_from_frame(int i) {
220 	return ((((i & 16) / 8) - ((i & 32) / 32)) + 4) % 4;
221 }
222 
223 /**
224  *  Provides attribute/value pairs.
225  */
226 class Actor_attributes {
227 	/// The attribute names. These are shared among all actors.
228 	static std::set<string> *strings;
229 	using Att_map = std::map<const char *, int>;
230 	/// The attribute name > value map.
231 	Att_map map;
232 public:
233 	/// Basic constructor. Initializes the attribute names.
Actor_attributes()234 	Actor_attributes() {
235 		if (!strings)
236 			strings = new std::set<string>;
237 	}
238 	/// Sets an attribute's value and, if needed, adds it to
239 	/// the attribute name list.
240 	/// @param nm The name of the attribute to be set.
241 	/// @param val Value to set the attribute to.
set(const char * nm,int val)242 	void set(const char *nm, int val) {
243 		auto siter = strings->find(nm);
244 		if (siter == strings->end())
245 			siter = strings->insert(nm).first;
246 		nm = (*siter).c_str();
247 		map[nm] = val;
248 	}
249 	/// Gets an attribute's value, if it is in the list.
250 	/// @param nm The name of the attribute to be gotten.
251 	/// @return val Current value of the attribute, or
252 	/// zero if the attribute is not on the list.
get(const char * nm)253 	int get(const char *nm) {   // Returns 0 if not set.
254 		auto siter = strings->find(nm);
255 		if (siter == strings->end())
256 			return 0;
257 		nm = (*siter).c_str();
258 		auto it = map.find(nm);
259 		return it == map.end() ? 0 : (*it).second;
260 	}
261 	/// Gets all attributes for the current actor.
262 	/// @param attlist (name, value) vector containig all attributes.
get_all(std::vector<std::pair<const char *,int>> & attlist)263 	void get_all(std::vector<std::pair<const char *, int> > &attlist) {
264 		for (auto& it : map)
265 			attlist.emplace_back(it);
266 	}
267 };
268 std::set<string> *Actor_attributes::strings = nullptr;
269 
270 /**
271  *  Get/create timers.
272  *  @return
273  */
274 
need_timers()275 Npc_timer_list *Actor::need_timers(
276 ) {
277 	if (!timers)
278 		timers = new Npc_timer_list(this);
279 	return timers;
280 }
281 
282 /**
283  *  Initialize frames, properties and spots.
284  */
285 
init()286 void Actor::init(
287 ) {
288 	if (!avatar_frames[0])
289 		init_default_frames();
290 	size_t i;
291 	for (i = 0; i < array_size(properties); i++)
292 		properties[i] = 0;
293 	for (i = 0; i < array_size(spots); i++)
294 		spots[i] = nullptr;
295 }
296 
297 /**
298  *  Find (best) ammo of given type.
299  *  @param family Desired ammo family shape.
300  *  @param needed Minimum quantity needed.
301  *  @return Pointer to object, if found.
302  */
303 
find_best_ammo(int family,int needed)304 Game_object *Actor::find_best_ammo(
305     int family,
306     int needed
307 ) {
308 	Game_object *best = nullptr;
309 	int best_strength = -20;
310 	Game_object_vector vec;     // Get list of all possessions.
311 	vec.reserve(50);
312 	get_objects(vec, c_any_shapenum, c_any_qual, c_any_framenum);
313 	for (auto *obj : vec) {
314 		if (obj->inside_locked() || !In_ammo_family(obj->get_shapenum(), family))
315 			continue;
316 		const Ammo_info *ainf = obj->get_info().get_ammo_info();
317 		if (!ainf)  // E.g., musket ammunition doesn't have it.
318 			continue;
319 		// Can't use it.
320 		if (obj->get_quantity() < needed)
321 			continue;
322 		// Calc ammo strength.
323 		int strength = ainf->get_base_strength();
324 		// Favor those with more shots remaining.
325 		if (obj->get_quantity() < 5 * needed)
326 			strength /= 3;
327 		else if (obj->get_quantity() < 10 * needed)
328 			strength /= 2;
329 		if (strength > best_strength) {
330 			best = obj;
331 			best_strength = strength;
332 		}
333 	}
334 	return best;
335 }
336 
337 /**
338  *  Get effective maximum range for weapon taking in consideration
339  *  the actor's strength and combat.
340  *  @param winf Pointer to weapon information of the current weapon,
341  *  or null for no weapon.
342  *  @param reach Weapon reach, or -1 to use weapon's.
343  *  @return Weapon's effective range.
344  */
get_effective_range(const Weapon_info * winf,int reach) const345 int Actor::get_effective_range(
346     const Weapon_info *winf,
347     int reach
348 ) const {
349 	if (reach < 0) {
350 		if (!winf) {
351 			const Monster_info *minf = get_info().get_monster_info();
352 			return minf ? minf->get_reach()
353 			       : Monster_info::get_default()->get_reach();
354 		}
355 		reach = winf->get_range();
356 	}
357 	int uses = winf ? winf->get_uses() : static_cast<int>(Weapon_info::melee);
358 	if (!uses || uses == Weapon_info::ranged)
359 		return reach;
360 	else {
361 		int eff_range;
362 		int str = get_effective_prop(static_cast<int>(Actor::strength));
363 		int combat = get_effective_prop(static_cast<int>(Actor::combat));
364 		if (str < combat)
365 			eff_range = str;
366 		else
367 			eff_range = combat;
368 		if (uses == Weapon_info::good_thrown)
369 			eff_range *= 2;
370 		if (eff_range < reach)
371 			eff_range = reach;
372 		if (eff_range > 31)
373 			eff_range = 31;
374 		return eff_range;
375 	}
376 }
377 
378 /**
379  *  Find ammo used by weapon.
380  *  @param weapon The weapon shape.
381  *  @param needed Minimum quantity needed.
382  *  @param recursive Whether or not to search inside backpacks and bags.
383  *  @return Pointer to object if found.
384  */
385 
find_weapon_ammo(int weapon,int needed,bool recursive)386 Game_object *Actor::find_weapon_ammo(
387     int weapon,
388     int needed,
389     bool recursive
390 ) {
391 	if (weapon < 0)
392 		return nullptr;
393 	const Weapon_info *winf = ShapeID::get_info(weapon).get_weapon_info();
394 	if (!winf)
395 		return nullptr;
396 	int family = winf->get_ammo_consumed();
397 	if (family >= 0) {
398 		Game_object *aobj = get_readied(quiver);
399 		if (aobj && In_ammo_family(aobj->get_shapenum(), family) &&
400 		        aobj->get_quantity() >= needed)
401 			return aobj;        // Already readied.
402 		else if (recursive)
403 			return find_best_ammo(family, needed);
404 		return nullptr;
405 	}
406 
407 	// Search readied weapons first.
408 	static Ready_type_Exult wspots[] = {lhand, rhand, back_2h, belt};
409 	for (auto wspot : wspots) {
410 		Game_object *obj = spots[static_cast<int>(wspot)];
411 		if (!obj || obj->get_shapenum() != weapon)
412 			continue;
413 		const Shape_info &inf = obj->get_info();
414 		if (family == -2) {
415 			if (!inf.has_quality() || obj->get_quality() >= needed)
416 				return obj;
417 		}
418 		// Family -1 and family -3.
419 		else if (obj->get_quantity() >= needed)
420 			return obj;
421 	}
422 
423 	// Now recursively search all contents.
424 	return recursive ? Container_game_object::find_weapon_ammo(weapon) : nullptr;
425 }
426 
427 /**
428  *  Swap new ammo with old.
429  *  @param newammo Pointer to new ammo object.
430  */
431 
swap_ammo(Game_object * newammo)432 void Actor::swap_ammo(
433     Game_object *newammo
434 ) {
435 	Game_object *aobj = get_readied(quiver);
436 	if (aobj == newammo)
437 		return;         // Already what we need.
438 						// Keep these from getting deleted:
439     Game_object_shared aobj_shared;
440     Game_object_shared newammo_shared;
441     if (aobj) {           // Something there already?
442 		aobj->remove_this(&aobj_shared);   // Remove it.
443 	}
444 	newammo->remove_this(&newammo_shared);
445 	add(newammo, true);        // Should go to the right place.
446 	if (aobj)           // Put back old ammo.
447 		add(aobj, true);
448 }
449 
450 /**
451  *  Recursivelly searches for ammunition for a given weapon, if needed.
452  *  @param npc The NPC to be searched.
453  *  @param bobj The weapon we want to check.
454  *  @param ammo Optional pointer that receives a pointer to the best ammunition
455  *  found for the given weapon.
456  *  @param recursive Whether or not to search inside backpacks and bags.
457  *  @return true if the weapon can be used, ammo is pointer to best ammunition.
458  */
459 
Is_weapon_usable(Actor * npc,Game_object * bobj,Game_object ** ammo=nullptr,bool recursive=true)460 static inline bool Is_weapon_usable(
461     Actor *npc,
462     Game_object *bobj,
463     Game_object **ammo = nullptr,
464     bool recursive = true
465 ) {
466 	if (ammo)
467 		*ammo = nullptr;
468 	const Weapon_info *winf = bobj->get_info().get_weapon_info();
469 	if (!winf)
470 		return false;       // Not a weapon.
471 	Game_object *aobj = nullptr;  // Check ranged first.
472 	int need_ammo = npc->get_weapon_ammo(bobj->get_shapenum(),
473 	                                     winf->get_ammo_consumed(), winf->get_projectile(),
474 	                                     true, &aobj, recursive);
475 	if (!need_ammo)
476 		return true;
477 	// Try melee if the weapon is not ranged.
478 	else if (!aobj && winf->get_uses() != Weapon_info::ranged)
479 		need_ammo = npc->get_weapon_ammo(bobj->get_shapenum(),
480 		                                 winf->get_ammo_consumed(), winf->get_projectile(),
481 		                                 false, &aobj, recursive);
482 	if (need_ammo && !aobj)
483 		return false;
484 	if (ammo)
485 		*ammo = aobj;
486 	return true;
487 }
488 
489 /**
490  *  Ready ammo for weapon being carried.
491  *  @return Returns true if successful.
492  */
493 
ready_ammo()494 bool Actor::ready_ammo(
495 ) {
496 	Game_object *weapon = spots[static_cast<int>(lhand)];
497 	if (!weapon)
498 		return false;
499 	const Shape_info &info = weapon->get_info();
500 	const Weapon_info *winf = info.get_weapon_info();
501 	if (!winf)
502 		return false;
503 	int ammo = winf->get_ammo_consumed();
504 	if (ammo < 0) {
505 		// Ammo not needed.
506 		return !(winf->uses_charges() && info.has_quality() &&
507 		        weapon->get_quality() <= 0);   // Uses charges, but none left.
508 	}
509 	Game_object *found = nullptr;
510 	// Try non-recursive search for ammo first.
511 	bool usable = Is_weapon_usable(this, weapon, &found, false);
512 	if (usable) // Ammo is available and ready.
513 		return true;
514 	// Try recursive search now.
515 	found = find_best_ammo(ammo);
516 	if (!found)
517 		return false;
518 	swap_ammo(found);
519 	return true;
520 }
521 
522 /**
523  *  If no shield readied, look through all possessions for the best one.
524  *  @return Returns true if successful.
525  */
526 
ready_best_shield()527 bool Actor::ready_best_shield(
528 ) {
529 	if (two_handed)
530 		return false;
531 	if (spots[rhand]) {
532 		const Shape_info &inf = spots[rhand]->get_info();
533 		if (is_in_party() || inf.get_armor() || inf.get_armor_immunity())
534 			return inf.get_armor() || inf.get_armor_immunity();
535 	}
536 	Game_object *old_rhand = nullptr;
537 	Game_object_shared rhand_keep;
538 	Game_object_shared best_keep;
539 	if (spots[rhand]) {     // remove old offhand item
540 		old_rhand = spots[rhand];
541 		old_rhand->remove_this(&rhand_keep);
542 	}
543 	Game_object_vector vec;     // Get list of all possessions.
544 	vec.reserve(50);
545 	get_objects(vec, c_any_shapenum, c_any_qual, c_any_framenum);
546 	Game_object *best = nullptr;
547 	int best_strength = -20;
548 	for (auto *obj : vec) {
549 		if (obj->inside_locked())
550 			continue;
551 		const Shape_info &info = obj->get_info();
552 		// Only want those that can be readied in hand.
553 		int ready = info.get_ready_type();
554 		if (ready != lhand && ready != backpack)
555 			continue;
556 		const Armor_info *arinf = info.get_armor_info();
557 		if (!arinf)
558 			continue;   // Not a shield.
559 		if (spots[lhand] == obj) // Don't take the weapon.
560 			continue;
561 		int strength = arinf->get_base_strength();
562 		if (strength > best_strength) {
563 			best = obj;
564 			best_strength = strength;
565 		}
566 	}
567 	if (!best) {
568 		if (old_rhand)  // add offhand item back to where it was
569 			add(old_rhand, true);
570 		return false;
571 	}
572 	// Spot is free already.
573 	best->remove_this(&best_keep);
574 	add(best, true);           // Should go to the right place.
575 	if (old_rhand && old_rhand != best) // don't add twice
576 		add(old_rhand, true);
577 	return true;
578 }
579 
580 
581 /**
582  *  If no weapon readied, look through all possessions for the best one.
583  *  @return Returns true if successful.
584  */
585 
ready_best_weapon()586 bool Actor::ready_best_weapon(
587 ) {
588 	int points;
589 	if (Actor::get_weapon(points) != nullptr && ready_ammo()) {
590 		ready_best_shield();
591 		return true;        // Already have one.
592 	}
593 	// Check for spellbook.
594 	Game_object *obj = get_readied(lhand);
595 	if (obj && obj->get_info().get_shape_class() == Shape_info::spellbook) {
596 		if ((static_cast<Spellbook_object *>(obj))->can_do_spell(this)) {
597 			ready_best_shield();
598 			return true;
599 		}
600 	}
601 	Game_object_vector vec;     // Get list of all possessions.
602 	vec.reserve(50);
603 	get_objects(vec, c_any_shapenum, c_any_qual, c_any_framenum);
604 	Game_object *best = nullptr;
605 	Game_object *best_ammo = nullptr;
606 	Game_object_shared keep1;
607 	Game_object_shared keep2;
608 	Game_object_shared best_keep;
609 	int best_strength = -20;
610 	int wtype = backpack;
611 	for (auto *obj : vec) {
612 		if (obj->inside_locked())
613 			continue;
614 		const Shape_info &info = obj->get_info();
615 		int ready = info.get_ready_type();
616 		// backpack and rhand added for dragon breath and some spells
617 		if (ready != lhand && ready != both_hands &&
618 		        ready != rhand && ready != backpack)
619 			continue;
620 		const Weapon_info *winf = info.get_weapon_info();
621 		if (!winf)
622 			continue;   // Not a weapon.
623 		Game_object *ammo_obj = nullptr;
624 		if (!Is_weapon_usable(this, obj, &ammo_obj))
625 			continue;
626 		int strength = winf->get_base_strength();
627 		strength += get_effective_range(winf);
628 		if (strength > best_strength) {
629 			wtype = ready;
630 			best = obj;
631 			best_ammo = ammo_obj != obj ? ammo_obj : nullptr;
632 			best_strength = strength;
633 		}
634 	}
635 	if (!best) {
636 		ready_best_shield();
637 		return false;
638 	}
639 	// If nothing is in left hand, nothing will happen.
640 	Game_object* remove1 = spots[lhand];
641 	Game_object* remove2 = nullptr;
642 	if (wtype == both_hands && spots[rhand])
643 		remove2 = spots[rhand];
644 	// Prevent double removal and double add (can corrupt objects list).
645 	// No need for similar check for remove1 as we wouldn't be here
646 	// if remove1 were a weapon we could use.
647 	if (remove2 == best)
648 		remove2 = nullptr;
649 	// Free the spot(s).
650 	if (remove1)
651 		remove1->remove_this(&keep1);
652 	if (remove2)
653 		remove2->remove_this(&keep2);
654 	best->remove_this(&best_keep);
655 	if (wtype == rhand) // tell it the correct ready spot
656 		add_readied(best, lhand);
657 	else
658 		add(best, true);            // Should go to the right place.
659 	ready_best_shield();    // Also add a shield for 1-handed weapons.
660 	if (remove1)            // Put back other things.
661 		add(remove1, true);
662 	if (remove2)
663 		add(remove2, true);
664 	if (best_ammo)
665 		swap_ammo(best_ammo);
666 	return true;
667 }
668 
669 /**
670  *  Try to store given object.
671  */
672 
empty_hand(Game_object * obj,Game_object_shared * keep)673 bool Actor::empty_hand(
674     Game_object *obj,
675     Game_object_shared *keep
676 ) {
677 	if (!obj)
678 		return true;
679 	static int chkspots[] = {belt, backpack};
680 	add_dirty();
681 	obj->remove_this(keep);
682 	for (int chkspot : chkspots)
683 		if (add_readied(obj, chkspot, true, true))      // Slot free?
684 			return true;
685 
686 	return false;
687 }
688 
689 /**
690  *  Try to store what is the hands.
691  */
692 
empty_hands()693 void Actor::empty_hands(
694 ) {
695 	Game_object *obj = spots[lhand];
696 	Game_object_shared keep;
697 	if (!empty_hand(obj, &keep))
698 		add(obj, true);
699 	obj = spots[rhand];
700 	if (!empty_hand(obj, &keep))
701 		add(obj, true);
702 }
703 
704 /**
705  *  Get effective weapon shape, taking casting frames in consideration.
706  *  @return The shape to be displayed in-hand.
707  */
708 
get_effective_weapon_shape() const709 int Actor::get_effective_weapon_shape(
710 ) const {
711 	if (get_casting_mode() == Actor::show_casting_frames)
712 		// Casting frames
713 		return casting_shape;
714 	else {
715 		Game_object *weapon = spots[lhand];
716 		return weapon->get_shapenum();
717 	}
718 }
719 
720 /**
721  *  Add dirty rectangle(s).
722  *  @return Returns false if not on screen.
723  */
add_dirty(bool figure_rect)724 bool Actor::add_dirty(
725     bool figure_rect         // Recompute weapon rectangle.
726 ) {
727 	if (!gwin->add_dirty(this))
728 		return false;
729 	if (figure_rect || get_casting_mode() == Actor::show_casting_frames) {
730 		int weapon_x;
731 		int weapon_y;
732 		int weapon_frame;
733 		if (figure_weapon_pos(weapon_x, weapon_y, weapon_frame)) {
734 			int shnum = get_effective_weapon_shape();
735 
736 			Shape_frame *wshape = ShapeID(shnum, weapon_frame).get_shape();
737 
738 			if (wshape) // Set dirty area rel. to NPC.
739 				weapon_rect = gwin->get_shape_rect(wshape,
740 				                                   weapon_x, weapon_y);
741 			else
742 				weapon_rect.w = 0;
743 		} else
744 			weapon_rect.w = 0;
745 	}
746 	if (weapon_rect.w > 0) {    // Repaint weapon area too.
747 		TileRect r = weapon_rect;
748 		int xoff;
749 		int yoff;
750 		gwin->get_shape_location(this, xoff, yoff);
751 		r.shift(xoff, yoff);
752 		r.enlarge(c_tilesize / 2);
753 		gwin->add_dirty(gwin->clip_to_win(r));
754 	}
755 	return true;
756 }
757 
758 /**
759  *  Change the frame and set to repaint areas.
760  *  @param frnum The new frame.
761  */
762 
change_frame(int frnum)763 void Actor::change_frame(
764     int frnum
765 ) {
766 	add_dirty();            // Set to repaint old area.
767 	ShapeID id(get_shapenum(), frnum, get_shapefile());
768 	Shape_frame *shape = id.get_shape();
769 	if (!shape || shape->is_empty()) {
770 		// Swap 1hand <=> 2hand frames.
771 		frnum = (frnum & 48) | visible_frames[frnum & 15];
772 		id.set_frame(frnum);
773 		if (!(shape = id.get_shape()) || shape->is_empty())
774 			frnum = (frnum & 48) | Actor::standing;
775 	}
776 	rest_time = 0;
777 	set_frame(frnum);
778 	add_dirty(true);           // Set to repaint new.
779 }
780 
781 /**
782  *  See if it's blocked when trying to move to a new tile.
783  *  @param t Tile to step to. Tz is possibly updated by this function.
784  *  @param f Pointer to tile we are stepping from, or null for current tile.
785  *  @param move_flags Additional movement flags to consider for step.
786  *  @return Returns true if so, else false.
787  */
788 
is_blocked(Tile_coord & t,Tile_coord * f,const int move_flags)789 bool Actor::is_blocked(
790     Tile_coord &t,          // Tz possibly updated.
791     Tile_coord *f,          // Step from here, or curpos if null.
792     const int move_flags
793 ) {
794 	const Shape_info &info = get_info();
795 	// Get dim. in tiles.
796 	int frame = get_framenum();
797 	int xtiles = info.get_3d_xtiles(frame);
798 	int ytiles = info.get_3d_ytiles(frame);
799 	int ztiles = info.get_3d_height();
800 	t.fixme();
801 	if (xtiles == 1 && ytiles == 1) { // Simple case?
802 		Map_chunk *nlist = gmap->get_chunk(
803 		                       t.tx / c_tiles_per_chunk, t.ty / c_tiles_per_chunk);
804 		nlist->setup_cache();
805 		int new_lift;
806 		bool blocked = nlist->is_blocked(ztiles, t.tz,
807 		                                t.tx % c_tiles_per_chunk, t.ty % c_tiles_per_chunk,
808 		                                new_lift, move_flags | get_type_flags());
809 		t.tz = new_lift;
810 		return blocked;
811 	}
812 	return Map_chunk::is_blocked(xtiles, ytiles, ztiles,
813 	                             f ? *f : get_tile(), t, move_flags | get_type_flags());
814 }
815 
816 /**
817  *  Finds an object which blocks the destination tile.
818  *  @param tile The (blocked) tile to check.
819  *  @param dir Direction we are stepping from.
820  */
821 
find_blocking(Tile_coord const & tile,int dir)822 Game_object *Actor::find_blocking(
823     Tile_coord const &tile,
824     int dir
825 ) {
826 	ignore_unused_variable_warning(tile);
827 	TileRect footprint = get_footprint();
828 	TileRect base = get_footprint();
829 	switch (dir) {
830 	case north:
831 		footprint.shift(0, -1);
832 		break;
833 	case northeast:
834 		footprint.shift(1, -1);
835 		break;
836 	case east:
837 		footprint.shift(1, 0);
838 		break;
839 	case southeast:
840 		footprint.shift(1, 1);
841 		break;
842 	case south:
843 		footprint.shift(0, 1);
844 		break;
845 	case southwest:
846 		footprint.shift(-1, 1);
847 		break;
848 	case west:
849 		footprint.shift(-1, 0);
850 		break;
851 	case northwest:
852 		footprint.shift(-1, -1);
853 		break;
854 	}
855 	Game_object *block;
856 	for (int i = footprint.x; i < footprint.x + footprint.w; i++)
857 		for (int j = footprint.y; j < footprint.y + footprint.h; j++)
858 			if (base.has_world_point(i, j))
859 				continue;
860 			else if ((block = Game_object::find_blocking(
861 			                      Tile_coord(i, j, get_tile().tz))) != nullptr)
862 				return block;
863 	return nullptr;
864 }
865 
866 /**
867  *  Move an object, and possibly change its shape too.
868  *  @param old_chunk The actor's old chunk.
869  *  @param new_chunk The chunk to which the actor is moving.
870  *  @param new_sx New x coordinate.
871  *  @param new_sy New y coordinate.
872  *  @param new_frame The new frame.
873  *  @param new_lift The new z coordinate.
874  */
movef(Map_chunk * old_chunk,Map_chunk * new_chunk,int new_sx,int new_sy,int new_frame,int new_lift)875 inline void Actor::movef(
876     Map_chunk *old_chunk,
877     Map_chunk *new_chunk,
878     int new_sx, int new_sy, int new_frame,
879     int new_lift
880 ) {
881     Game_object_shared keep = shared_from_this();
882     if (old_chunk)          // Remove from current chunk.
883 		old_chunk->remove(this);
884 	set_shape_pos(new_sx, new_sy);
885 	if (new_frame >= 0)
886 		change_frame(new_frame);
887 	if (new_lift >= 0)
888 		set_lift(new_lift);
889 	new_chunk->add(this);
890 }
891 
892 /**
893  *  Create character.
894  *  @param nm The actor's name.
895  *  @param shapenum The initial shape.
896  *  @param num The NPC's number from npc.dat.
897  *  @param uc The usecofe function to use.
898  */
899 
Actor(const std::string & nm,int shapenum,int num,int uc)900 Actor::Actor(
901     const std::string &nm,
902     int shapenum,
903     int num,
904     int uc
905 ) : name(nm), usecode(uc),
906 	usecode_assigned(false), unused(false),
907 	npc_num(num), face_num(num), party_id(-1), atts(nullptr), temperature(0),
908 	shape_save(-1), oppressor(-1),
909 	casting_mode(not_casting), casting_shape(-1),
910 	target_tile(Tile_coord(-1, -1, 0)), attack_weapon(-1),
911 	attack_mode(nearest),
912 	schedule_type(Schedule::loiter), next_schedule(255), schedule(nullptr),
913 	restored_schedule(-1), dormant(true), hit(false), combat_protected(false),
914 	user_set_attack(false), alignment(0), charmalign(0), two_handed(false),
915 	two_fingered(false), use_scabbard(false), use_neck(false),
916 	light_sources(0), usecode_dir(0), type_flags(0),
917 	gear_immunities(0), gear_powers(0), ident(0),
918 	skin_color(-1), action(nullptr),
919 	frame_time(0), step_index(0), qsteps(0), timers(nullptr),
920 	weapon_rect(0, 0, 0, 0), rest_time(0) {
921 	set_shape(shapenum, 0);
922 	init();
923 	frames = &npc_frames[0];    // Default:  5-frame walking.
924 }
925 
926 /**
927  *  Deletes actor.
928  */
929 
~Actor()930 Actor::~Actor(
931 ) {
932 	purge_deleted_actions();
933 	if (in_queue() && gwin->get_tqueue())
934 		gwin->get_tqueue()->remove(this);
935 	delete schedule;
936 	delete action;
937 	delete timers;
938 	delete atts;
939 }
940 
941 /**
942  *  Goes through the actor's readied gear and caches powers
943  *  and immunities.
944  */
945 
refigure_gear()946 void Actor::refigure_gear() {
947 	static Ready_type_Exult locs[] = {head, belt, lhand, lfinger, legs,
948 	                                  feet, rfinger, rhand, torso, amulet,
949 	                                  earrings, cloak, gloves
950 	                                 };
951 	int powers = 0;
952 	int immune = 0;
953 	light_sources = 0;
954 	for (auto loc : locs) {
955 		Game_object *worn = spots[static_cast<int>(loc)];
956 		if (worn) {
957 			const Shape_info &info = worn->get_info();
958 			char rdy = info.get_ready_type();
959 			if (info.is_light_source() && (loc != belt ||
960 			                               (rdy != lhand && rdy != rhand && rdy != both_hands)))
961 				add_light_source(info.get_object_light(worn->get_framenum()));
962 			powers |= info.get_object_flags(worn->get_framenum(),
963 			                                info.has_quality() ? worn->get_quality() : -1);
964 			immune |= info.get_armor_immunity();
965 		}
966 	}
967 	gear_immunities = immune;
968 	gear_powers = powers;
969 }
970 
say_hunger_message()971 void Actor::say_hunger_message() {
972 	int food = get_property(static_cast<int>(food_level));
973 	if (food <= 0) {        // Really low?
974 		if (rand() % 4)
975 			say(first_starving, last_starving);
976 	} else if (food <= 4) {
977 		if (rand() % 3)
978 			say(first_needfood, last_needfood);
979 	} else { //if (food <= 9)
980 		if (rand() % 2)
981 			say(first_hunger, last_hunger);
982 	}
983 }
984 
985 /**
986  *  Decrement food level and print complaints if it gets too low.
987  *  NOTE:  Should be called every hour.
988  */
989 
use_food()990 void Actor::use_food(
991 ) {
992 	if (get_info().does_not_eat() || (gear_powers & Frame_flags::doesnt_eat))
993 		return;
994 	int food = get_property(static_cast<int>(food_level));
995 	food -= (rand() % 4);   // Average 1.5 level/hour.
996 	set_property(static_cast<int>(food_level), food);
997 	if (food > 9)
998 		return;
999 	say_hunger_message();
1000 	need_timers()->start_hunger(); // minute checks for damage and messages.
1001 }
1002 
1003 /**
1004  *  Periodic check for freezing.
1005  *  @param freeze True if the actor is freezing. This is usually the
1006  *  Avatar's freeze flag.
1007  */
1008 
check_temperature(bool freeze)1009 void Actor::check_temperature(
1010     bool freeze
1011 ) {
1012 	if (!freeze) {          // Not in a cold area?
1013 		if (!temperature)   // 0 means warm.
1014 			return;     // Nothing to do.
1015 		// Warming up.
1016 		temperature -= (temperature >= 5 ? 5 : temperature);
1017 		if (rand() % 3 == 0) {
1018 			if (temperature >= 30)
1019 				say(first_warming_up, last_warming_up);
1020 			else
1021 				say(first_warming_up_2, last_warming_up_2);
1022 		}
1023 		return;
1024 	}
1025 	// Immune to cold by nature or an item?
1026 	if (get_info().is_cold_immune() || (gear_powers & Frame_flags::cold_immune))
1027 		return;
1028 	if (get_schedule_type() == Schedule::wait)
1029 		return;         // Not following leader?  Leave alone.
1030 	int warmth = figure_warmth();   // (This could be saved for speed.)
1031 	if (warmth >= 100) {    // Enough clothing?
1032 		if (!temperature)
1033 			return;     // Already warm.
1034 		int decr = 1 + (warmth - 100) / 10;
1035 		decr = decr > temperature ? temperature : decr;
1036 		temperature -= decr;
1037 		if (rand() % 3 == 0) {
1038 			if (temperature >= 30)
1039 				say(first_warming_in_cold, last_warming_in_cold);
1040 			else
1041 				say(first_warming_in_cold_2, last_warming_in_cold_2);
1042 		}
1043 		return;
1044 	}
1045 	int incr = 1 + (100 - warmth) / 20;
1046 	temperature += incr;
1047 	if (temperature > 63)
1048 		temperature = 63;
1049 	if (rand() % 3 == 0)
1050 		switch (temperature / 10) {
1051 		case 0:
1052 			say(first_chilly, last_chilly); // A bit chilly.
1053 			break;
1054 		case 1:
1055 			say(first_cold, last_cold); // It's colder.
1056 			break;
1057 		case 2:
1058 			say(first_colder, last_colder);
1059 			break;
1060 		case 3:
1061 			say(first_frostbite, last_frostbite);   // Frostbite.
1062 			break;
1063 		case 4:
1064 			say(first_frostbite_2, last_frostbite_2);
1065 			break;
1066 		case 5:
1067 			say(first_frostbite_3, last_frostbite_3);
1068 			reduce_health(1, Weapon_data::sonic_damage);
1069 			break;
1070 		case 6:
1071 			say(first_frozen, last_frozen); // Frozen.
1072 			reduce_health(1 + rand() % 3, Weapon_data::sonic_damage);
1073 			break;
1074 		}
1075 }
1076 
1077 /*
1078  *  Get sequence of frames for an attack.
1079  *
1080  *  Output: # of frames stored.
1081  */
1082 
get_attack_frames(int weapon,bool projectile,int dir,signed char * frames) const1083 int Actor::get_attack_frames(
1084     int weapon,         // Weapon shape, or -1 for innate.
1085     bool projectile,        // Shooting/throwing.
1086     int dir,            // 0-7 (as in dir.h).
1087     signed char *frames         // Frames stored here.
1088 ) const {
1089 	const signed char *which;
1090 	int cnt = 0;
1091 	if (is_slime())
1092 		return 0;
1093 	else if (get_info().has_strange_movement()) {
1094 		which = sea_serpent_attack_frames;
1095 		cnt = sizeof(sea_serpent_attack_frames);
1096 	} else {
1097 		const signed char *reach_attack_frames;
1098 		const signed char *raise_attack_frames;
1099 		const signed char *fast_swing_attack_frames;
1100 		const signed char *slow_swing_attack_frames;
1101 		if (two_handed) {
1102 			reach_attack_frames = reach_attack_frames2;
1103 			raise_attack_frames = raise_attack_frames2;
1104 			fast_swing_attack_frames = fast_swing_attack_frames2;
1105 			slow_swing_attack_frames = slow_swing_attack_frames2;
1106 		} else {
1107 			reach_attack_frames = reach_attack_frames1;
1108 			raise_attack_frames = raise_attack_frames1;
1109 			fast_swing_attack_frames = fast_swing_attack_frames1;
1110 			slow_swing_attack_frames = slow_swing_attack_frames1;
1111 		}
1112 		unsigned char frame_flags;  // Get Actor_frame flags.
1113 		const Weapon_info *winfo;
1114 		if (weapon >= 0 &&
1115 		        (winfo = ShapeID::get_info(weapon).get_weapon_info()) != nullptr)
1116 			frame_flags = winfo->get_actor_frames(projectile);
1117 		else                // Default to normal swing.
1118 			frame_flags = projectile ? Weapon_info::reach : Weapon_info::fast_swing;
1119 		switch (frame_flags) {
1120 		case Weapon_info::reach:
1121 			which = reach_attack_frames;
1122 			cnt = sizeof(reach_attack_frames1);
1123 			break;
1124 		case Weapon_info::raise:
1125 			which = raise_attack_frames;
1126 			cnt = sizeof(raise_attack_frames1);
1127 			break;
1128 		case Weapon_info::fast_swing:
1129 			which = fast_swing_attack_frames;
1130 			cnt = sizeof(fast_swing_attack_frames1);
1131 			break;
1132 		case Weapon_info::slow_swing:
1133 		default:
1134 			which = slow_swing_attack_frames;
1135 			cnt = sizeof(slow_swing_attack_frames1);
1136 			break;
1137 		}
1138 	}
1139 	for (int i = 0; i < cnt; i++) { // Copy frames with correct dir.
1140 		int frame = get_dir_framenum(dir, *which++);
1141 		// Check for empty shape.
1142 		ShapeID id(get_shapenum(), frame, get_shapefile());
1143 		Shape_frame *shape = id.get_shape();
1144 		if (!shape || shape->is_empty()) {
1145 			// Swap 1hand <=> 2hand frames.
1146 			frame = get_dir_framenum(dir, visible_frames[frame & 15]);
1147 			id.set_frame(frame);
1148 			if (!(shape = id.get_shape()) || shape->is_empty())
1149 				frame = get_dir_framenum(dir, Actor::standing);
1150 		}
1151 		*frames++ = frame;
1152 	}
1153 	return cnt;
1154 }
1155 
add_light_source(Game_object * obj)1156 void Actor::add_light_source(Game_object *obj) {
1157 	const Shape_info &info = obj->get_info();
1158 	add_light_source(info.get_object_light(obj->get_framenum()));
1159 }
1160 
remove_light_source(Game_object * obj)1161 void Actor::remove_light_source(Game_object *obj) {
1162 	const Shape_info &info = obj->get_info();
1163 	remove_light_source(info.get_object_light(obj->get_framenum()));
1164 }
1165 
1166 /*
1167  *  Set default set of frames.
1168  */
1169 
init_default_frames()1170 void Actor::init_default_frames(
1171 ) {
1172 	// Set up actor's frame lists.
1173 	npc_frames[static_cast<int>(north) / 2] = &npc_north_frames;
1174 	npc_frames[static_cast<int>(south) / 2] = &npc_south_frames;
1175 	npc_frames[static_cast<int>(east) / 2] =  &npc_east_frames;
1176 	npc_frames[static_cast<int>(west) / 2] =  &npc_west_frames;
1177 	avatar_frames[static_cast<int>(north) / 2] = &avatar_north_frames;
1178 	avatar_frames[static_cast<int>(south) / 2] = &avatar_south_frames;
1179 	avatar_frames[static_cast<int>(east) / 2] =  &avatar_east_frames;
1180 	avatar_frames[static_cast<int>(west) / 2] =  &avatar_west_frames;
1181 }
1182 
1183 /*
1184  *  This is called for the Avatar to return to a normal standing position
1185  *  when not doing anything else.
1186  */
1187 
stand_at_rest()1188 void Actor::stand_at_rest(
1189 ) {
1190 	rest_time = 0;          // Reset timer.
1191 	int frame = get_framenum() & 0xf; // Base frame #.
1192 	if (frame == standing || frame == sit_frame || frame == sleep_frame)
1193 		return;         // Already standing/sitting/sleeping.
1194 	if (!is_dead() && schedule_type == Schedule::follow_avatar &&
1195 	        !get_flag(Obj_flags::asleep))
1196 		change_frame(get_dir_framenum(standing));
1197 }
1198 
1199 /*
1200  *  Set new action.
1201  */
1202 
set_action(Actor_action * newact)1203 void Actor::set_action(
1204     Actor_action *newact
1205 ) {
1206 	if (newact != action) {
1207 		Actor_action *todel;
1208 		if (action && (todel = action->kill()) != nullptr)
1209 			deletedactions.push_back(todel);
1210 		action = newact;
1211 	}
1212 	if (!action)            // No action?  We're stopped.
1213 		frame_time = 0;
1214 }
1215 
1216 /*
1217  *  Empty deleted action list.
1218  */
1219 
purge_deleted_actions()1220 void Actor::purge_deleted_actions() {
1221 	while (!deletedactions.empty()) {
1222 		Actor_action *act = deletedactions.back();
1223 		deletedactions.pop_back();
1224 		delete act;
1225 	}
1226 }
1227 
1228 /*
1229  *  Get destination, or current spot if no destination.
1230  */
1231 
get_dest() const1232 Tile_coord Actor::get_dest(
1233 ) const {
1234 	Tile_coord dest;
1235 	if (action && action->get_dest(dest))
1236 		return dest;
1237 	else
1238 		return get_tile();
1239 }
1240 
1241 /*
1242  *  Walk towards a given tile.
1243  */
1244 
walk_to_tile(Tile_coord const & dest,int speed,int delay,int maxblk)1245 void Actor::walk_to_tile(
1246     Tile_coord const &dest,     // Destination.
1247     int speed,          // Time between frames (msecs).
1248     int delay,          // Delay before starting (msecs) (only
1249     //   if not already moving).
1250     int maxblk          // Max. # retries if blocked.
1251 ) {
1252 	if (!action)
1253 		action = new Path_walking_actor_action(new Zombie(), maxblk);
1254 	set_action(action->walk_to_tile(this, get_tile(), dest));
1255 	if (action)         // Successful at setting path?
1256 		start(speed, delay);
1257 	else
1258 		frame_time = 0;     // Not moving.
1259 }
1260 
1261 /*
1262  *  Find a path towards a given tile.
1263  *
1264  *  Output: 0 if failed.
1265  */
1266 
walk_path_to_tile(Tile_coord const & src,Tile_coord const & dest,int speed,int delay,int dist,int maxblk)1267 int Actor::walk_path_to_tile(
1268     Tile_coord const &src,          // Our location, or an off-screen
1269     //   location to try path from.
1270     Tile_coord const &dest,     // Destination.
1271     int speed,          // Time between frames (msecs).
1272     int delay,          // Delay before starting (msecs) (only
1273     //   if not already moving).
1274     int dist,           // Distance to get within dest.
1275     int maxblk          // Max. # retries if blocked.
1276 ) {
1277 	set_action(new Path_walking_actor_action(new Astar(), maxblk));
1278 	set_action(action->walk_to_tile(this, src, dest, dist));
1279 	if (action) {       // Successful at setting path?
1280 		start(speed, delay);
1281 		return 1;
1282 	}
1283 	frame_time = 0;         // Not moving.
1284 	return 0;
1285 }
1286 
1287 /*
1288  *  Begin animation.
1289  */
1290 
start(int speed,int delay)1291 void Actor::start(
1292     int speed,          // Time between frames (msecs).
1293     int delay           // Delay before starting (msecs) (only
1294     //   if not already moving).
1295 ) {
1296 	dormant = false;        // 14-jan-2001 - JSF.
1297 	frame_time = speed;
1298 	if (!in_queue() || delay) { // Not already in queue?
1299 		if (delay)
1300 			gwin->get_tqueue()->remove(this);
1301 		uint32 curtime = Game::get_ticks();
1302 		gwin->get_tqueue()->add(curtime + delay, this, gwin);
1303 	}
1304 }
1305 
1306 /*
1307  *  Start with standard delay.
1308  */
start_std()1309 void Actor::start_std(
1310 ) {
1311 	start(gwin->get_std_delay(), gwin->get_std_delay());
1312 }
1313 
1314 /*
1315  *  Stop animation.
1316  */
stop()1317 void Actor::stop(
1318 ) {
1319 	/* +++ This might cause jerky walking. Needs to be done above? */
1320 	if (action) {
1321 		action->stop(this);
1322 		add_dirty();
1323 	}
1324 	frame_time = 0;
1325 }
1326 
1327 /*
1328  *  Want one value to approach another.
1329  */
1330 
Approach(int from,int to,int dist)1331 inline int Approach(
1332     int from,
1333     int to,
1334     int dist            // Desired distance.
1335 ) {
1336 	if (from <= to)         // Going forwards?
1337 		return to - from <= dist ? from : to - dist;
1338 	else                // Going backwards.
1339 		return from - to <= dist ? from : to + dist;
1340 }
1341 
1342 /*
1343  *  Follow the leader.
1344  */
1345 
follow(const Actor * leader)1346 void Actor::follow(
1347     const Actor *leader
1348 ) {
1349 	if (Actor::is_dead() || !can_act())
1350 		return;         // Not when dead, paralyzed, or asleep.
1351 	int delay = 0;
1352 	int dist;           // How close to aim for.
1353 	Tile_coord leaderpos = leader->get_tile();
1354 	Tile_coord pos = get_tile();
1355 	Tile_coord goal;
1356 	if (leader->is_moving()) {  // Figure where to aim.
1357 		// Aim for leader's dest.
1358 		dist = 2 + party_id / 3;
1359 		goal = leader->get_dest();
1360 		goal.tx = Approach(pos.tx, goal.tx, dist);
1361 		goal.ty = Approach(pos.ty, goal.ty, dist);
1362 	} else {            // Leader stopped?
1363 		goal = leaderpos;   // Aim for leader.
1364 		if (gwin->walk_in_formation && distance(leader) <= 6)
1365 			return;     // In formation, & close enough.
1366 //		cout << "Follow:  Leader is stopped" << endl;
1367 		// +++++For formation, why not get correct positions?
1368 		static int xoffs[10] = { -1, 1, -2, 2, -3, 3, -4, 4, -5, 5};
1369 		static int yoffs[10] = {1, -1, 2, -2, 3, -3, 4, -4, 5, -5};
1370 		goal.tx += xoffs[party_id] + 1 - rand() % 3;
1371 		goal.ty += yoffs[party_id] + 1 - rand() % 3;
1372 		dist = 1;
1373 	}
1374 	// Already aiming along a path?
1375 	if (is_moving() && action && action->following_smart_path() &&
1376 	        // And leader moving, or dest ~= goal?
1377 	        (leader->is_moving() || goal.distance(get_dest()) <= 5))
1378 		return;
1379 	// Tiles to goal.
1380 	int goaldist = goal.distance(pos);
1381 	if (goaldist < dist) {      // Already close enough?
1382 		if (!leader->is_moving())
1383 			stop();
1384 		return;
1385 	}
1386 	// Is leader following a path?
1387 	bool leaderpath = leader->action &&
1388 	                  leader->action->following_smart_path();
1389 	// Get leader's distance from goal.
1390 	int leaderdist = leader->distance(goal);
1391 	// Get his speed.
1392 	int speed = leader->get_frame_time();
1393 	if (!speed) {       // Not moving?
1394 		speed = 100;
1395 		if (goaldist < leaderdist)  // Closer than leader?
1396 			// Delay a bit IF not moving.
1397 			delay = (1 + leaderdist - goaldist) * 100;
1398 	}
1399 	if (goaldist - leaderdist >= 5)
1400 		speed -= 20;        // Speed up if too far.
1401 	// Get window rect. in tiles.
1402 	TileRect wrect = gwin->get_win_tile_rect();
1403 	int dist2lead = leader->distance(pos);
1404 	// Getting kind of far away?
1405 	if (dist2lead > wrect.w + wrect.w / 2 &&
1406 	        party_id >= 0 &&        // And a member of the party.
1407 	        !leaderpath) {      // But leader is not following path.
1408 		// Approach, or teleport.
1409 		// Try to approach from offscreen.
1410 		if (approach_another(leader))
1411 			return;
1412 		// Find a free spot.
1413 		goal = Map_chunk::find_spot(
1414 		           leader->get_tile(), 2, this);
1415 		if (goal.tx != -1) {
1416 			move(goal.tx, goal.ty, goal.tz);
1417 			if (rand() % 2)
1418 				say(first_catchup, last_catchup);
1419 			gwin->paint();
1420 			return;
1421 		}
1422 	}
1423 	// NOTE:  Avoid delay when moving,
1424 	//  as it creates jerkiness.  AND,
1425 	//  0 retries if blocked.
1426 	walk_to_tile(goal, speed, delay, 0);
1427 }
1428 
1429 /*
1430  *  Approach another actor from offscreen.
1431  *
1432  *  Output: 0 if failed.
1433  */
1434 
approach_another(const Actor * other,bool wait)1435 int Actor::approach_another(
1436     const Actor *other,
1437     bool wait           // If true, game hangs until arrival.
1438 ) {
1439 	Tile_coord dest = other->get_tile();
1440 	// Look outwards for free spot.
1441 	dest = Map_chunk::find_spot(dest, 8, get_shapenum(), get_framenum());
1442 	if (dest.tx == -1)
1443 		return 0;
1444 	// Where are we now?
1445 	Tile_coord src = get_tile();
1446 	if (!gwin->get_win_tile_rect().has_world_point(src.tx - src.tz / 2,
1447 	        src.ty - src.tz / 2))
1448 		// Off-screen?
1449 		src = Tile_coord(-1, -1, 0);
1450 	int destmap = other->get_map_num();
1451 	int srcmap = get_map_num();
1452 	if (destmap != -1 && srcmap != -1 && srcmap != destmap) {
1453 		src = Tile_coord(-1, -1, 0);
1454 		move(src, destmap);
1455 	}
1456 	Actor_action *action = new Path_walking_actor_action();
1457 	if (!action->walk_to_tile(this, src, dest)) {
1458 		delete action;
1459 		return 0;
1460 	}
1461 	set_action(action);
1462 	int speed = gwin->get_std_delay() / 2;
1463 	start(speed);           // Walk fairly fast.
1464 	if (wait)           // Only wait ~1/5 sec.
1465 		Wait_for_arrival(this, dest, 2 * gwin->get_std_delay());
1466 	return 1;
1467 }
1468 
1469 /*
1470  *  Get information about a tile that an actor is about to step onto.
1471  */
1472 
get_tile_info(Actor * actor,Game_window * gwin,Map_chunk * nlist,int tx,int ty,bool & water,bool & poison)1473 void Actor::get_tile_info(
1474     Actor *actor,           // May be 0 if not known.
1475     Game_window *gwin,
1476     Map_chunk *nlist,   // Chunk.
1477     int tx, int ty,         // Tile within chunk.
1478     bool &water,         // Returns 1 if water.
1479     bool &poison         // Returns 1 if poison.
1480 ) {
1481 	ignore_unused_variable_warning(gwin);
1482 	ShapeID flat = nlist->get_flat(tx, ty);
1483 	if (flat.get_shapenum() == -1)
1484 		water = poison = false;
1485 	else {
1486 		const Shape_info &finfo = flat.get_info();
1487 		water = finfo.is_water();
1488 		poison = finfo.is_poisonous();
1489 		// Check for swamp/swamp boots.
1490 		if (poison && actor) {
1491 			if ((actor->gear_powers &
1492 			        (Frame_flags::swamp_safe | Frame_flags::poison_safe)) != 0)
1493 				poison = false;
1494 			else {      // Not protected by gear?
1495 				// Safe from poisoning?
1496 				const Monster_info *minf =
1497 				    actor->get_info().get_monster_info();
1498 				if (minf && minf->poison_safe())
1499 					poison = false;
1500 			}
1501 		}
1502 	}
1503 }
1504 
1505 /*
1506  *  Set combat opponent.
1507  */
1508 
set_target(Game_object * obj,bool start_combat)1509 void Actor::set_target(
1510     Game_object *obj,
1511     bool start_combat       // If true, set sched. to combat.
1512 ) {
1513 	target = weak_from_obj(obj);
1514 	bool im_party = is_in_party() || this == gwin->get_main_actor();
1515 	if (start_combat && !im_party &&
1516 	        (schedule_type != Schedule::combat || !schedule))
1517 		set_schedule_type(Schedule::combat);
1518 	Actor *opponent = obj ? obj->as_actor() : nullptr;
1519 	if (opponent)
1520 		opponent->set_oppressor(get_npc_num());
1521 	// Pure guess.
1522 	Actor *oppr = oppressor >= 0 ? gwin->get_npc(oppressor) : nullptr;
1523 	if (oppr && (oppr->get_target() != this ||
1524 	             oppr->get_schedule_type() != Schedule::combat))
1525 		oppressor = -1;
1526 }
1527 
1528 /*
1529  *  Works out if an item can be readied in a spot
1530  *
1531  *  Output: true if it does fit, or false if it can't
1532  */
1533 
fits_in_spot(Game_object * obj,int spot)1534 bool Actor::fits_in_spot(Game_object *obj, int spot) {
1535 	const Shape_info &inf = obj->get_info();
1536 	int rtype = inf.get_ready_type();
1537 	int alt1 = inf.get_alt_ready1();
1538 	int alt2 = inf.get_alt_ready2();
1539 	bool can_scabbard = (alt1 == scabbard || alt2 == scabbard);
1540 	bool can_neck = (rtype == neck || alt1 == neck || alt2 == neck);
1541 	if (spot == both_hands)
1542 		spot = lhand;
1543 	else if (spot == lrgloves)
1544 		spot = lfinger;
1545 	else if (spot == neck)
1546 		spot = amulet;
1547 	else if (spot == scabbard)
1548 		spot = belt;
1549 
1550 	// If occupied, can't place
1551 	if (spots[spot])
1552 		return false;
1553 	// If want to use 2h or a 2h is already equiped, can't go in right
1554 	else if ((rtype == both_hands || two_handed) && spot == rhand)
1555 		return false;
1556 	// If want to use 2f or a 2f is already equiped, can't go in right or gloves
1557 	else if ((rtype == lrgloves || two_fingered) &&
1558 	         (spot == rfinger || spot == gloves))
1559 		return false;
1560 	// If want to use scabbard or a scabbard is already equiped, can't go in others
1561 	else if ((can_scabbard || use_scabbard) &&
1562 	         (spot == back_2h || spot == back_shield))
1563 		return false;
1564 	// If want to use neck or neck is already filled, can't go in cloak
1565 	else if ((can_neck || use_neck) && spot == cloak)
1566 		return false;
1567 	// Can't use 2h in left if right occupied
1568 	else if (rtype == both_hands && spot == lhand && spots[rhand])
1569 		return false;
1570 	// Can't use 2f in left if right occupied
1571 	else if (rtype == lrgloves && spot == lfinger && spots[rfinger])
1572 		return false;
1573 	// Can't use scabbard in belt if back 2h or back shield occupied
1574 	else if (can_scabbard && spot == belt &&
1575 	         (spots[back_2h] || spots[back_shield]))
1576 		return false;
1577 	// Can't use neck in amulet if cloak occupied
1578 	else if (can_neck && spot == amulet && spots[cloak])
1579 		return false;
1580 	// If in left or right hand allow it
1581 	else if (spot == lhand || spot == rhand)
1582 		return true;
1583 	// Special Checks for Belt
1584 	else if (spot == belt) {
1585 		if (inf.is_spell() || can_scabbard)
1586 			return true;
1587 	}
1588 	// Special Checks for back 2h and back shield
1589 	else if (spot == back_2h || spot == back_shield) {
1590 		if (can_scabbard)
1591 			return true;
1592 	}
1593 	// Special Checks for amulet and cloak
1594 	else if (spot == amulet || spot == cloak) {
1595 		if (can_neck)
1596 			return true;
1597 	}
1598 
1599 	// Lastly if we have gotten here, check the paperdoll table
1600 	return inf.is_object_allowed(obj->get_framenum(), spot);
1601 }
1602 
1603 /*
1604  *  Find the spot(s) where an item would prefer to be readied
1605  *
1606  *  Output: prefered slot, alternative slots
1607  */
1608 
get_prefered_slots(Game_object * obj,int & prefered,int & alt1,int & alt2) const1609 void Actor::get_prefered_slots(
1610     Game_object *obj,
1611     int &prefered,
1612     int &alt1,
1613     int &alt2
1614 ) const {
1615 	const Shape_info &info = obj->get_info();
1616 
1617 	// Defaults
1618 	prefered = info.get_ready_type();
1619 	alt1 = info.get_alt_ready1();
1620 	alt2 = info.get_alt_ready2();
1621 	if (alt1 == invalid_spot)
1622 		alt1 = lhand;
1623 	if (alt2 == invalid_spot)
1624 		alt2 = lhand;
1625 
1626 	if (prefered == lhand) {
1627 		if (info.is_object_allowed(obj->get_framenum(), rhand))
1628 			if (!info.is_object_allowed(obj->get_framenum(), lhand))
1629 				prefered = rhand;
1630 			else
1631 				alt1 = rhand;
1632 		else
1633 			alt1 = rhand;
1634 	}
1635 }
1636 
1637 
1638 /*
1639  *  Find the best spot where an item may be readied.
1640  *
1641  *  Output: Index, or -1 if none found.
1642  */
1643 
find_best_spot(Game_object * obj)1644 int Actor::find_best_spot(
1645     Game_object *obj
1646 ) {
1647 	int prefered;
1648 	int alternate1;
1649 	int alternate2;
1650 
1651 	// Get the preferences
1652 	get_prefered_slots(obj, prefered, alternate1, alternate2);
1653 
1654 	// Check Prefered
1655 	if (fits_in_spot(obj, prefered)) return prefered;
1656 	// Alternate
1657 	else if (alternate1 >= 0 && fits_in_spot(obj, alternate1)) return alternate1;
1658 	// Second alternate
1659 	else if (alternate2 >= 0 && fits_in_spot(obj, alternate2)) return alternate2;
1660 	// Belt
1661 	else if (fits_in_spot(obj, belt)) return belt;
1662 	// Back - required???
1663 	else if (fits_in_spot(obj, backpack)) return backpack;
1664 	// Back2h
1665 	else if (fits_in_spot(obj, back_2h)) return back_2h;
1666 	// Sheild Spot
1667 	else if (fits_in_spot(obj, back_shield)) return back_shield;
1668 	// Left Hand
1669 	else if (fits_in_spot(obj, lhand)) return lhand;
1670 	// Right Hand
1671 	else if (fits_in_spot(obj, rhand)) return rhand;
1672 
1673 	return -1;
1674 }
1675 
1676 /*
1677  *  Get previous schedule type.
1678  *
1679  *  Output: Prev. schedule #, or -1 if not known.
1680  */
1681 
get_prev_schedule_type() const1682 int Actor::get_prev_schedule_type(
1683 ) const {
1684 	return schedule ? schedule->get_prev_type() : -1;
1685 }
1686 
1687 /*
1688  *  Restore actor's schedule after reading.  This CANNOT be called from
1689  *  a constructor, since it may call virtual methods when setting up
1690  *  the schedule.
1691  */
1692 
restore_schedule()1693 void Actor::restore_schedule(
1694 ) {
1695 	// Make sure it's in valid chunk.
1696 	Map_chunk *olist = get_chunk();
1697 	// Activate schedule if not in party.
1698 	if (olist && !is_in_party()) {
1699 		if (next_schedule != 255 &&
1700 		        schedule_type == Schedule::walk_to_schedule)
1701 			set_schedule_and_loc(next_schedule, schedule_loc);
1702 		else {
1703 			old_schedule_loc = schedule_loc;
1704 			restored_schedule = schedule_type;
1705 			set_schedule_type(schedule_type);
1706 		}
1707 	}
1708 }
1709 
1710 /*
1711  *  Set new schedule by type.
1712  */
1713 
set_schedule_type(int new_schedule_type,Schedule * newsched)1714 void Actor::set_schedule_type(
1715     int new_schedule_type,
1716     Schedule *newsched      // New sched., or nullptr to create here.
1717 ) {
1718 	// Don't stop path_run_usecode unless it is done.
1719 	If_else_path_actor_action *act = action ? action->as_usecode_path() : nullptr;
1720 	if (!act || act->is_done()) {
1721 		stop();             // Stop moving
1722 		set_action(nullptr);      // Clear out old action.
1723 	}
1724 	if (schedule)           // Finish up old if necessary.
1725 		schedule->ending(new_schedule_type);
1726 	// Save old for a moment.
1727 	auto old_schedule =
1728 	    static_cast<Schedule::Schedule_types>(schedule_type);
1729 	delete schedule;        // Done with the old.
1730 	schedule = newsched;
1731 	if (!schedule)
1732 		switch (static_cast<Schedule::Schedule_types>(new_schedule_type)) {
1733 		case Schedule::combat:
1734 			schedule = new Combat_schedule(this, old_schedule);
1735 			break;
1736 		case Schedule::horiz_pace:
1737 			ready_best_weapon();
1738 			schedule = Pace_schedule::create_horiz(this);
1739 			break;
1740 		case Schedule::vert_pace:
1741 			ready_best_weapon();
1742 			schedule = Pace_schedule::create_vert(this);
1743 			break;
1744 		case Schedule::talk:
1745 			schedule = new Talk_schedule(this);
1746 			break;
1747 		case Schedule::dance:
1748 			empty_hands();
1749 			schedule = new Dance_schedule(this);
1750 			break;
1751 		case Schedule::farm:    // Use a scythe.
1752 			schedule = new Farmer_schedule(this);
1753 			break;
1754 		case Schedule::tend_shop:// For now.
1755 			empty_hands();
1756 			schedule = new Loiter_schedule(this, 3);
1757 			break;
1758 		case Schedule::miner:   // Use a pick.
1759 			schedule = new Miner_schedule(this);
1760 			break;
1761 		case Schedule::hound:
1762 			ready_best_weapon();
1763 			schedule = new Hound_schedule(this);
1764 			break;
1765 		case Schedule::loiter:
1766 			schedule = new Loiter_schedule(this);
1767 			break;
1768 		case Schedule::graze:   // For now.
1769 			schedule = new Graze_schedule(this);
1770 			break;
1771 		case Schedule::wander:
1772 			schedule = new Wander_schedule(this);
1773 			break;
1774 		case Schedule::blacksmith:
1775 			schedule = new Forge_schedule(this);
1776 			break;
1777 		case Schedule::sleep:
1778 			if (party_id < 0 && npc_num != 0)
1779 				empty_hands();
1780 			schedule = new Sleep_schedule(this);
1781 			break;
1782 		case Schedule::wait:
1783 			schedule = new Wait_schedule(this);
1784 			break;
1785 		case Schedule::eat:
1786 			empty_hands();
1787 			schedule = new Eat_schedule(this);
1788 			break;
1789 		case Schedule::sit:
1790 			empty_hands();
1791 			schedule = new Sit_schedule(this);
1792 			break;
1793 		case Schedule::bake:
1794 			schedule = new Bake_schedule(this);
1795 			break;
1796 		case Schedule::sew:
1797 			schedule = new Sew_schedule(this);
1798 			break;
1799 		case Schedule::shy:
1800 			empty_hands();
1801 			schedule = new Shy_schedule(this);
1802 			break;
1803 		case Schedule::lab:
1804 			schedule = new Lab_schedule(this);
1805 			break;
1806 		case Schedule::thief:
1807 			empty_hands();
1808 			schedule = new Thief_schedule(this);
1809 			break;
1810 		case Schedule::waiter:
1811 			empty_hands();
1812 			schedule = new Waiter_schedule(this);
1813 			break;
1814 		case Schedule::kid_games:
1815 			empty_hands();
1816 			schedule = new Kid_games_schedule(this);
1817 			break;
1818 		case Schedule::eat_at_inn:
1819 			empty_hands();
1820 			schedule = new Eat_at_inn_schedule(this);
1821 			break;
1822 		case Schedule::duel:
1823 			schedule = new Duel_schedule(this);
1824 			break;
1825 		case Schedule::preach:
1826 			ready_best_weapon();    // Fellowship staff.
1827 			schedule = new Preach_schedule(this);
1828 			break;
1829 		case Schedule::patrol:
1830 			ready_best_weapon();
1831 			schedule = new Patrol_schedule(this);
1832 			break;
1833 		case Schedule::desk_work:
1834 			empty_hands();
1835 			schedule = new Desk_schedule(this);
1836 			break;
1837 		case Schedule::follow_avatar:
1838 			schedule = new Follow_avatar_schedule(this);
1839 			break;
1840 		case Schedule::walk_to_schedule:
1841 			cerr << "Attempted to set a \"walk to schedule\" activity for NPC " << get_npc_num() << endl;
1842 			break;
1843 		case Schedule::arrest_avatar:
1844 			schedule = new Arrest_avatar_schedule(this);
1845 			break;
1846 		default:
1847 			if (new_schedule_type >=
1848 			        Schedule::first_scripted_schedule)
1849 				schedule = new Scripted_schedule(this,
1850 				                                 new_schedule_type);
1851 			break;
1852 		}
1853 	// Set AFTER creating new schedule.
1854 	schedule_type = new_schedule_type;
1855 
1856 	// Reset Next Schedule
1857 	schedule_loc = Tile_coord(0, 0, 0);
1858 	next_schedule = 255;
1859 
1860 	if (!gmap->is_chunk_read(get_cx(), get_cy())) {
1861 		dormant = true;     // Chunk hasn't been read in yet.
1862 		if (schedule)
1863 			schedule->im_dormant();
1864 	} else if (schedule) {  // Try to start it.
1865 		dormant = false;
1866 		schedule->now_what();
1867 	}
1868 }
1869 
1870 /*
1871  *  Cache out an actor.
1872  *  Resets the schedule, and makes the actor dormant
1873  */
cache_out()1874 void Actor::cache_out() {
1875 	// This is a bit of a hack, but it works well enough
1876 	if (get_schedule_type() != Schedule::walk_to_schedule)
1877 		set_schedule_type(get_schedule_type());
1878 }
1879 
teleport_offscreen_to_schedule(Tile_coord const & dest,int dist)1880 bool Actor::teleport_offscreen_to_schedule(Tile_coord const &dest, int dist) {
1881 	int mapnum = get_map_num();
1882 	if (mapnum < 0)
1883 		mapnum = gmap->get_num();
1884 	if ((mapnum != gmap->get_num()) ||
1885 	        (!gmap->is_chunk_read(get_cx(), get_cy()) &&
1886 	         !gmap->is_chunk_read(dest.tx / c_tiles_per_chunk,
1887 	                              dest.ty / c_tiles_per_chunk))) {
1888 		// Not on current map, or
1889 		//   src, dest. are off the screen
1890 		// Teleport if more than dist tiles from target
1891 		if (distance(dest) > dist) {
1892 			move(dest.tx, dest.ty, dest.tz, mapnum);
1893 			change_frame(get_dir_framenum(Actor::standing));
1894 		}
1895 		return true;
1896 	}
1897 	return false;
1898 }
1899 
1900 /*
1901  *  Set new schedule by type AND location.
1902  */
1903 
set_schedule_and_loc(int new_schedule_type,Tile_coord const & dest,int delay)1904 void Actor::set_schedule_and_loc(int new_schedule_type, Tile_coord const &dest,
1905                                  int delay) { // -1 for random delay.
1906 	stop();             // Stop moving.
1907 	if (schedule)           // End prev.
1908 		schedule->ending(new_schedule_type);
1909 	old_schedule_loc = dest;
1910 	if (teleport_offscreen_to_schedule(dest, 12)) {
1911 		set_schedule_type(new_schedule_type);
1912 		return;
1913 	}
1914 	// Going to walk there.
1915 	schedule_loc = dest;
1916 	next_schedule = new_schedule_type;
1917 	if (schedule_type == Schedule::walk_to_schedule)
1918 		set_action(nullptr);  // Force NPC to go to the right place.
1919 	schedule_type = Schedule::walk_to_schedule;
1920 	delete schedule;
1921 	schedule = new Walk_to_schedule(this, dest, next_schedule, delay);
1922 	dormant = false;
1923 	schedule->now_what();
1924 }
1925 
in_goblin_village(Actor const * npc)1926 static bool in_goblin_village(Actor const *npc) {
1927 	// These boundaries are exact, as far as I can tell; hack-move to the
1928 	// rescue.
1929 	static const TileRect gobvillage(576, 1200, 256, 336);
1930 	Tile_coord loc = npc->get_tile();
1931 	return GAME_SI && gobvillage.has_world_point(loc.tx, loc.ty);
1932 }
1933 
1934 /*
1935  *  Get alignment, taking into account 'charmed' flag.
1936  */
1937 
get_effective_alignment() const1938 int Actor::get_effective_alignment(
1939 ) const {
1940 	bool avatar = (this == gwin->get_main_actor());
1941 	if (!(flags & (1 << Obj_flags::charmed)) ||
1942 	        (avatar && !Combat::charmed_more_difficult)) {
1943 		// Hack warning: there are some neutral goblins in the goblin village.
1944 		// Here, we 'fix' their alignments to cause them to attack the avatar.
1945 		// The only theory I have to explain why these neutral goblins exist is
1946 		// that it *seems* that only neutral NPCs called guards in the original,
1947 		// and 'call guards in the goblin' village means 'making everyone nearby
1948 		// attack the avatar'.
1949 		// Lets not do this for non-goblins, party members (even if goblins),
1950 		// the avatar, or if in a dungeon -- the boundaries of 'goblin village'
1951 		// overlap some of the surrounding dungeons, and this behavior might not
1952 		// be desired there.
1953 		if (avatar || party_id >= 0 || !is_goblin() || gwin->is_in_dungeon())
1954 			return alignment;
1955 
1956 		if (in_goblin_village(this))
1957 			return evil;
1958 		else
1959 			return alignment;
1960 	} else
1961 		return charmalign;
1962 }
1963 
1964 /*
1965  *  Set effective alignment.
1966  */
1967 
set_effective_alignment(int newalign)1968 void Actor::set_effective_alignment(
1969     int newalign
1970 ) {
1971 	charmalign = newalign;
1972 	if (!(flags & (1 << Obj_flags::charmed)))
1973 		alignment = newalign;
1974 	else
1975 		set_charmed_combat();
1976 }
1977 
1978 /*
1979  *  Render.
1980  */
1981 
paint()1982 void Actor::paint(
1983 ) {
1984 	int flag = GAME_BG ? Obj_flags::bg_dont_render : Obj_flags::dont_render;
1985 	if (cheat.in_map_editor() || !(flags & (1L << flag))) {
1986 		int xoff;
1987 		int yoff;
1988 		gwin->get_shape_location(this, xoff, yoff);
1989 		bool invis = flags & (1L << Obj_flags::invisible);
1990 		if (invis && party_id < 0 && npc_num != 0)
1991 			return; // Don't render invisible NPCs not in party.
1992 		else if (invis)
1993 			paint_invisible(xoff, yoff);
1994 		else
1995 			paint_shape(xoff, yoff, true);
1996 
1997 		paint_weapon();
1998 		if (hit)        // Want a momentary red outline.
1999 			ShapeID::paint_outline(xoff, yoff, HIT_PIXEL);
2000 		else if (flags & ((1L << Obj_flags::protection) |
2001 		                  (1L << Obj_flags::poisoned) | (1 << Obj_flags::cursed) |
2002 		                  (1 << Obj_flags::charmed) | (1 << Obj_flags::paralyzed))) {
2003 			if (flags & (1L << Obj_flags::charmed))
2004 				ShapeID::paint_outline(xoff, yoff,
2005 				                       CHARMED_PIXEL);
2006 			else if (flags & (1L << Obj_flags::paralyzed))
2007 				ShapeID::paint_outline(xoff, yoff,
2008 				                       PARALYZE_PIXEL);
2009 			else if (flags & (1L << Obj_flags::protection))
2010 				ShapeID::paint_outline(xoff, yoff,
2011 				                       PROTECT_PIXEL);
2012 			else if (flags & (1L << Obj_flags::cursed))
2013 				ShapeID::paint_outline(xoff, yoff, CURSED_PIXEL);
2014 			else
2015 				ShapeID::paint_outline(xoff, yoff, POISON_PIXEL);
2016 		}
2017 	}
2018 }
2019 /*
2020  *  Draw the weapon in the actor's hand (if any).
2021  */
paint_weapon()2022 void Actor::paint_weapon(
2023 ) {
2024 	int weapon_x;
2025 	int weapon_y;
2026 	int weapon_frame;
2027 	if (figure_weapon_pos(weapon_x, weapon_y, weapon_frame)) {
2028 		int shnum = get_effective_weapon_shape();
2029 		ShapeID wsid(shnum, weapon_frame);
2030 		Shape_frame *wshape = wsid.get_shape();
2031 		if (!wshape) {
2032 			weapon_rect.w = 0;
2033 			return;
2034 		}
2035 		// Set dirty area rel. to NPC.
2036 		weapon_rect = gwin->get_shape_rect(wshape, weapon_x, weapon_y);
2037 		// Paint the weapon shape using the actor's coordinates
2038 		int xoff;
2039 		int yoff;
2040 		gwin->get_shape_location(this, xoff, yoff);
2041 		xoff += weapon_x;
2042 		yoff += weapon_y;
2043 
2044 		if (flags & (1L << Obj_flags::invisible))
2045 			wsid.paint_invisible(xoff, yoff);
2046 		else
2047 			wsid.paint_shape(xoff, yoff);
2048 	} else
2049 		weapon_rect.w = 0;
2050 }
2051 
2052 /*
2053  *  Figure weapon drawing info.  We need this in advance to set the dirty
2054  *  rectangle.
2055  *
2056  *  Output: false if don't need to paint weapon.
2057  */
2058 /* Weapon frames:
2059     0 - normal item
2060     1 - in hand, actor facing north/south
2061     2 - attacking (pointing north)
2062     3 - attacking (pointing east)
2063     4 - attacking (pointing south)
2064 */
2065 
figure_weapon_pos(int & weapon_x,int & weapon_y,int & weapon_frame)2066 bool Actor::figure_weapon_pos(
2067     int &weapon_x, int &weapon_y,   // Pos. rel. to NPC.
2068     int &weapon_frame
2069 ) {
2070 	unsigned char actor_x;
2071 	unsigned char actor_y;
2072 	unsigned char wx;
2073 	unsigned char wy;
2074 	if ((spots[lhand] == nullptr) && (get_casting_mode() != Actor::show_casting_frames))
2075 		return false;
2076 	// Get offsets for actor shape
2077 	int myframe = get_framenum();
2078 	get_info().get_weapon_offset(myframe & 0x1f, actor_x,
2079 	                             actor_y);
2080 	// Get weapon frames for actor frame:
2081 	switch (myframe & 0x1f) {
2082 	case 4:
2083 	case 7:
2084 	case 22:
2085 	case 25:
2086 		weapon_frame = 4;
2087 		break;
2088 	case 5:
2089 	case 8:
2090 	case 21:
2091 	case 24:
2092 		weapon_frame = 3;
2093 		break;
2094 	case 6:
2095 	case 9:
2096 	case 20:
2097 	case 23:
2098 		weapon_frame = 2;
2099 		break;
2100 		//The next cases (before the default) are here to make use of all
2101 		//the frames of the "casting frames" shape (shape 859):
2102 	case 14:
2103 	case 30:
2104 		weapon_frame = 5;
2105 		break;
2106 	case 15:
2107 		weapon_frame = 6;
2108 		break;
2109 	case 31:
2110 		weapon_frame = 7;
2111 		break;
2112 
2113 	default:
2114 		weapon_frame = 1;
2115 	}
2116 	weapon_frame |= (myframe & 32);
2117 
2118 	// Get offsets for weapon shape
2119 	int shnum = get_effective_weapon_shape();
2120 	const Shape_info &info = ShapeID::get_info(shnum);
2121 	info.get_weapon_offset(weapon_frame & 0xf, wx, wy);
2122 
2123 	// actor_x will be 255 if (for example) the actor is lying down
2124 	// wx will be 255 if the actor is not holding a proper weapon
2125 	if (actor_x != 255 && wx != 255) {
2126 		// Store offsets rel. to NPC.
2127 		weapon_x = wx - actor_x;
2128 		weapon_y = wy - actor_y;
2129 		// Need to swap offsets if actor's shape is reflected
2130 		if (myframe & 32)
2131 			swap(weapon_x, weapon_y);
2132 		// Combat frames are already done.
2133 		return true;
2134 	} else
2135 		return false;
2136 }
2137 
2138 /*
2139  *  Run usecode when double-clicked.
2140  */
activate(int event)2141 void Actor::activate(
2142     int event
2143 ) {
2144 	if (edit())
2145 		return;
2146 
2147 	bool show_party_inv = gumpman->showing_gumps(true) ||
2148 	                      gwin->in_combat();
2149 	auto sched =
2150 	    static_cast<Schedule::Schedule_types>(get_schedule_type());
2151 	if (party_id >= 0 && !can_act_charmed() &&    // if in party, charmed, and charmed more difficult
2152 	        !cheat.in_pickpocket() && event == 1) // and not pickpocket, return if double click
2153 		return;
2154 	if (!npc_num ||     // Avatar
2155 	        (show_party_inv && party_id >= 0) || // Party
2156 	        // Pickpocket cheat && double click
2157 	        (cheat.in_pickpocket() && event == 1))
2158 		show_inventory();
2159 	// Asleep (but not awakened)?
2160 	else if ((sched == Schedule::sleep &&
2161 	          (get_framenum() & 0xf) == Actor::sleep_frame) ||
2162 	         get_flag(Obj_flags::asleep))
2163 		return;
2164 	else if (sched == Schedule::combat && party_id < 0)
2165 		return;         // Too busy fighting.
2166 	// Usecode
2167 	// Failed copy-protection?
2168 	else if (gwin->failed_copy_protection())
2169 		ucmachine->call_usecode(FailCopyProtectionUsecode, this,
2170 		                        static_cast<Usecode_machine::Usecode_events>(event));
2171 	else if (usecode == -1)
2172 		ucmachine->call_usecode(get_usecode(), this,
2173 		                        static_cast<Usecode_machine::Usecode_events>(event));
2174 	else if (party_id >= 0 || !gwin->is_time_stopped())
2175 		ucmachine->call_usecode(get_usecode(), this,
2176 		                        static_cast<Usecode_machine::Usecode_events>(event));
2177 
2178 }
2179 
2180 /*
2181  *  Edit in ExultStudio.
2182  *
2183  *  Output: True if map-editing & ES is present.
2184  */
2185 
edit()2186 bool Actor::edit(
2187 ) {
2188 #ifdef USE_EXULTSTUDIO
2189 	if (client_socket >= 0 &&   // Talking to ExultStudio?
2190 	        cheat.in_map_editor()) {
2191 		editing.reset();
2192 		Tile_coord t = get_tile();
2193 		int num_schedules;  // Set up schedule-change list.
2194 		Schedule_change *changes;
2195 		get_schedules(changes, num_schedules);
2196 		Serial_schedule schedules[8];
2197 		for (int i = 0; i < num_schedules; i++) {
2198 			schedules[i].time = changes[i].get_time();
2199 			schedules[i].type = changes[i].get_type();
2200 			Tile_coord p = changes[i].get_pos();
2201 			schedules[i].tx = p.tx;
2202 			schedules[i].ty = p.ty;
2203 			schedules[i].tz = p.tz;
2204 		}
2205 		if (Npc_actor_out(client_socket, this, t.tx, t.ty, t.tz,
2206 		                  get_shapenum(), get_framenum(), get_face_shapenum(),
2207 		                  name, npc_num, ident, usecode, usecode_name, properties,
2208 		                  attack_mode, alignment, flags, flags2, type_flags,
2209 		                  num_schedules, schedules) != -1) {
2210 			cout << "Sent npc data to ExultStudio" << endl;
2211 			editing = shared_from_this();
2212 		} else
2213 			cout << "Error sending npc data to ExultStudio" << endl;
2214 		return true;
2215 	}
2216 #endif
2217 	return false;
2218 }
2219 
2220 /*
2221  *  Message to update from ExultStudio.
2222  */
2223 
update_from_studio(unsigned char * data,int datalen)2224 void Actor::update_from_studio(
2225     unsigned char *data,
2226     int datalen
2227 ) {
2228 #ifdef USE_EXULTSTUDIO
2229 	Actor *npc;
2230 	int tx;
2231 	int ty;
2232 	int tz;
2233 	int shape;
2234 	int frame;
2235 	int face;
2236 	std::string name;
2237 	short npc_num;
2238 	short ident;
2239 	int usecode;
2240 	std::string usecodefun;
2241 	int properties[12];
2242 	short attack_mode;
2243 	short alignment;
2244 	unsigned long oflags;       // Object flags.
2245 	unsigned long xflags;       // Extra object flags.
2246 	unsigned long type_flags;   // Movement flags.
2247 	short num_schedules;
2248 	Serial_schedule schedules[8];
2249 	if (!Npc_actor_in(data, datalen, npc, tx, ty, tz, shape, frame,
2250 	                  face, name, npc_num, ident, usecode, usecodefun,
2251 	                  properties, attack_mode, alignment,
2252 	                  oflags, xflags, type_flags, num_schedules, schedules)) {
2253 		cout << "Error decoding npc" << endl;
2254 		return;
2255 	}
2256 	if (npc && npc != editing.get()) {
2257 		cout << "Npc from ExultStudio is not being edited" << endl;
2258 		return;
2259 	}
2260 	// Keeps NPC alive until end of function
2261 	Game_object_shared keep = std::move(editing);
2262 	if (!npc) {         // Create a new one?
2263 		int x;
2264 		int y;
2265 		if (!Get_click(x, y, Mouse::hand, nullptr)) {
2266 			if (client_socket >= 0)
2267 				Exult_server::Send_data(client_socket, Exult_server::cancel);
2268 			return;
2269 		}
2270 		// Create.  Gets initialized below.
2271 		Actor_shared act = std::make_shared<Npc_actor>(name, shape, npc_num, usecode);
2272 		npc = act.get();
2273 		keep = std::move(act);
2274 		npc->usecode_name = usecodefun;
2275 		if (!usecodefun.empty())
2276 			npc->usecode = ucmachine->find_function(usecodefun.c_str(), true);
2277 		npc->usecode_assigned = npc_num >= 256 && npc->usecode != -1 &&
2278 
2279 		        npc->usecode != 0x400 + npc_num;
2280 
2281 		npc->set_invalid(); // Set to invalid position.
2282 		int lift;       // Try to drop at increasing hts.
2283 		for (lift = 0; lift < 12; lift++)
2284 			if (gwin->drop_at_lift(npc, x, y, lift))
2285 				break;
2286 		if (lift == 12) {
2287 			if (client_socket >= 0)
2288 				Exult_server::Send_data(client_socket, Exult_server::cancel);
2289 			delete npc;
2290 			return;
2291 		}
2292 		gwin->add_npc(npc, npc_num);
2293 		if (client_socket >= 0)
2294 			Exult_server::Send_data(client_socket, Exult_server::user_responded);
2295 	} else {            // Old.
2296 		npc->add_dirty();
2297 		npc->usecode_name = usecodefun;
2298 		if (!usecodefun.empty())
2299 			npc->usecode = ucmachine->find_function(usecodefun.c_str(), true);
2300 		else
2301 			npc->usecode = usecode;
2302 		npc->usecode_assigned = npc_num >= 256 && npc->usecode != -1 &&
2303 
2304 		        npc->usecode != 0x400 + npc_num;
2305 
2306 		npc->set_npc_name(name.c_str());
2307 	}
2308 	// Ensure proper initialization of frame #:
2309 	npc->set_shape(shape, frame);
2310 	npc->add_dirty();
2311 	npc->face_num = face;
2312 	npc->set_ident(ident);
2313 	int i;
2314 	for (i = 0; i < 12; i++)
2315 		npc->set_property(i, properties[i]);
2316 	npc->set_attack_mode(static_cast<Actor::Attack_mode>(attack_mode));
2317 	npc->set_alignment(alignment);
2318 	if (!(npc->flags & (1 << Obj_flags::charmed)))
2319 		npc->charmalign = alignment;
2320 	npc->flags = oflags;
2321 	npc->flags2 = xflags;
2322 	npc->type_flags = type_flags;
2323 	npc->set_actor_shape();
2324 	Schedule_change *scheds = num_schedules ?
2325 	                          new Schedule_change[num_schedules] : nullptr;
2326 	for (i = 0; i < num_schedules; i++)
2327 		scheds[i].set(schedules[i].tx, schedules[i].ty,
2328 		              schedules[i].tz,
2329 		              schedules[i].type, schedules[i].time);
2330 	npc->set_schedules(scheds, num_schedules);
2331 	// Force Avatar and party members to be good
2332 	if (npc_num == 0 || npc->get_flag(Obj_flags::in_party))
2333 		npc->set_alignment(good);
2334 	cout << "Npc updated" << endl;
2335 #else
2336 	ignore_unused_variable_warning(data, datalen);
2337 #endif
2338 }
2339 
2340 
show_inventory()2341 void Actor::show_inventory() {
2342 	Gump_manager *gump_man = gumpman;
2343 
2344 	int shapenum = inventory_shapenum();
2345 	if (shapenum >= 0)
2346 		gump_man->add_gump(this, shapenum, true);
2347 }
2348 
inventory_shapenum()2349 int Actor::inventory_shapenum() {
2350 	// We are serpent if we can use serpent isle paperdolls
2351 	bool serpent = (sman->can_use_paperdolls() && sman->are_paperdolls_enabled());
2352 
2353 	if (!serpent) {
2354 		// Can't display paperdolls (or they are disabled)
2355 		// Use BG gumps
2356 		int gump = get_info().get_gump_shape();
2357 		if (gump < 0)
2358 			gump = ShapeID::get_info(get_sexed_coloured_shape()).get_gump_shape();
2359 		if (gump < 0)
2360 			gump = ShapeID::get_info(get_shape_real()).get_gump_shape();
2361 		if (gump < 0) {
2362 			int shape = get_type_flag(Actor::tf_sex) ?
2363 			            Shapeinfo_lookup::GetFemaleAvShape() :
2364 			            Shapeinfo_lookup::GetMaleAvShape();
2365 			gump = ShapeID::get_info(shape).get_gump_shape();
2366 		}
2367 		if (gump < 0)
2368 			// No gump at ALL; should never happen...
2369 			return 65;  // Default to male (Pickpocket Cheat)
2370 
2371 		return gump;
2372 	} else /* if (serpent) */
2373 		return 123;     // Show paperdolls
2374 }
2375 
2376 
2377 /*
2378  *  Drop another onto this.
2379  *
2380  *  Output: false to reject, true to accept.
2381  */
2382 
drop(Game_object * obj)2383 bool Actor::drop(
2384     Game_object *obj        // MAY be deleted (if combined).
2385 ) {
2386 	if (is_in_party()) { // In party?
2387 		bool res = add(obj, false, true);// We'll take it, and combine.
2388 		int ind = find_readied(obj);
2389 		if (ind >= 0)
2390 			call_readied_usecode(ind, obj, Usecode_machine::readied);
2391 		return res;
2392 	} else
2393 		return false;
2394 }
2395 
2396 /*
2397  *  Get name.
2398  */
2399 
get_name() const2400 string Actor::get_name(
2401 ) const {
2402 	return !get_flag(Obj_flags::met) ? Game_object::get_name() : get_npc_name();
2403 }
2404 
2405 /*
2406  *  Get npc name.
2407  */
2408 
get_npc_name() const2409 string Actor::get_npc_name(
2410 ) const {
2411 	return name.empty() ? Game_object::get_name() : name;
2412 }
2413 
2414 /*
2415  *  Set npc name.
2416  */
2417 
set_npc_name(const char * n)2418 void Actor::set_npc_name(const char *n) {
2419 	name = n;
2420 }
2421 
2422 /*
2423  *  Set property.
2424  */
set_property(int prop,int val)2425 void Actor::set_property(
2426     int prop,
2427     int val
2428 ) {
2429 	if (prop == health && ((party_id != -1) || (npc_num == 0)) &&
2430 	        cheat.in_god_mode() && val < properties[prop])
2431 		return;
2432 	switch (static_cast<Item_properties>(prop)) {
2433 	case exp: {
2434 		// Experience?  Check for new level.
2435 		int old_level = get_level();
2436 		properties[static_cast<int>(exp)] = val;
2437 		int delta = get_level() - old_level;
2438 		if (delta > 0)
2439 			properties[static_cast<int>(training)] += 3 * delta;
2440 		break;
2441 	}
2442 	case food_level:
2443 		if (val > 31)       // Never seems to get above this.
2444 			val = 31;
2445 		else if (val < 0)
2446 			val = 0;
2447 		properties[prop] = val;
2448 		break;
2449 	case combat:            // limited to 30.
2450 		properties[prop] = val > 30 ? 30 : val;
2451 		break;
2452 	case magic: {
2453 		int old_val = properties[prop];
2454 		properties[prop] = val > 30 ? 30 : val; // limited to 30.
2455 		// check if magic changes to and from 0
2456 		if(is_in_party() && old_val != val && (old_val == 0 || val == 0))
2457 			Face_stats::UpdateButtons();
2458 		break;
2459 	} case training:          // Don't let this go negative.
2460 		properties[prop] = val < 0 ? 0 : val;
2461 		break;
2462 	case sex_flag:
2463 		// Doesn't seem to be settable in original BG except by hex-editing
2464 		// the save game, but there is no problem in allowing it in Exult.
2465 		if (val != 0)
2466 			set_type_flag(tf_sex);
2467 		else
2468 			clear_type_flag(tf_sex);
2469 		break;
2470 	default:
2471 		if (prop >= 0 && prop < missile_weapon)
2472 			properties[prop] = val;
2473 		break;
2474 	}
2475 	if (gumpman->showing_gumps())
2476 		gwin->set_all_dirty();
2477 }
2478 
2479 /*
2480  *  A class whose whole purpose is to stop casting mode.
2481  */
2482 class Clear_casting : public Time_sensitive {
2483     Game_object_weak actor;
2484 public:
Clear_casting(Actor * a)2485 	Clear_casting(Actor *a) : actor(weak_from_obj(a))
2486 	{  }
2487 	void handle_event(unsigned long curtime, uintptr udata) override;
2488 };
2489 
handle_event(unsigned long curtime,uintptr)2490 void Clear_casting::handle_event(unsigned long curtime, uintptr) {
2491 	ignore_unused_variable_warning(curtime);
2492 	Actor_shared a = std::static_pointer_cast<Actor>(actor.lock());
2493 	if (a) {
2494 	    a->add_dirty();
2495 	    a->hide_casting_frames();
2496 	    a->add_dirty();
2497 	}
2498 	delete this;
2499 }
2500 
end_casting_mode(int delay)2501 void Actor::end_casting_mode(int delay) {
2502 	auto *c = new Clear_casting(this);
2503 	gwin->get_tqueue()->add(Game::get_ticks() + 2 * delay, c, this);
2504 }
2505 
2506 /*
2507  *  A class whose whole purpose is to clear the 'hit' flag.
2508  */
2509 class Clear_hit : public Time_sensitive {
2510     Game_object_weak actor;
2511 public:
Clear_hit(Actor * a)2512 	Clear_hit(Actor *a) : actor(weak_from_obj(a))
2513 	{  }
2514 	void handle_event(unsigned long curtime, uintptr udata) override;
2515 };
2516 
handle_event(unsigned long curtime,uintptr)2517 void Clear_hit::handle_event(unsigned long curtime, uintptr) {
2518 	ignore_unused_variable_warning(curtime);
2519 	Actor_shared a = std::static_pointer_cast<Actor>(actor.lock());
2520 	if (a) {
2521 	    a->hit = false;
2522 	    a->add_dirty();
2523 	}
2524 	delete this;
2525 }
2526 
can_act()2527 bool Actor::can_act() {
2528 	return !(get_flag(Obj_flags::paralyzed) || get_flag(Obj_flags::asleep)
2529 	         || is_dead() || is_knocked_out());
2530 }
2531 
can_act_charmed()2532 bool Actor::can_act_charmed() {
2533 	return !(Combat::charmed_more_difficult && get_effective_alignment() != good);
2534 }
2535 
2536 /*
2537  *  Have charmed party members attack if charmed_more_difficult and party member is hostile
2538  */
2539 
set_charmed_combat()2540 void Actor::set_charmed_combat() {
2541 	if (Combat::charmed_more_difficult &&
2542 	    (is_in_party() || this == gwin->get_main_actor()) &&
2543 	    get_effective_alignment() != good) {
2544 		set_schedule_type(Schedule::combat);
2545 		if (get_attack_mode() == flee)
2546 			set_attack_mode(nearest);
2547 	}
2548 }
2549 
fight_back(Game_object * attacker)2550 void Actor::fight_back(
2551     Game_object *attacker
2552 ) {
2553 	// ++++ TODO: I think that nearby NPCs will help NPCs (or party members,
2554 	// as the case may be) of the same alignment when attacked by other NPCs,
2555 	// not just when the avatar & party attack. Although this is tricky to
2556 	// test (except, maybe, by exploiting the agressive U7 & SI duel schedule.
2557 	Actor *npc = attacker ? attacker->as_actor() : nullptr;
2558 	// No attacker, or friendly fire, should not cause a fight.
2559 	if (!npc || get_effective_alignment() == npc->get_effective_alignment())
2560 		return;
2561 	if (is_in_party() && (gwin->in_combat() || !gwin->main_actor_can_act())) {
2562 		if (!gwin->in_combat())
2563 			gwin->toggle_combat();
2564 		Actor *party[9];        // Get entire party, including Avatar.
2565 		int cnt = gwin->get_party(party, 1);
2566 		for (int i = 0; i < cnt; i++) {
2567 			int sched = party[i]->get_schedule_type();
2568 			if (sched != Schedule::combat && sched != Schedule::wait
2569 			        && sched != Schedule::loiter)
2570 				party[i]->set_schedule_type(Schedule::combat);
2571 		}
2572 	}
2573 	if (!target.lock() && !is_in_party())
2574 		set_target(npc, npc->get_schedule_type() != Schedule::duel);
2575 	// Being a bully?
2576 	if (npc->is_in_party() && !is_in_party() && is_sentient()) {
2577 		Actor *witness = this;
2578 		Actor *closest = nullptr;
2579 		int align = get_effective_alignment();
2580 		// Attack avatar if the NPC is not disabled...
2581 		if (can_act() ||
2582 		        // ... or if there is a sympathetic witness or local guard...
2583 		        (witness = gwin->find_witness(closest, align)) != nullptr ||
2584 		        // ... or if there is someone sympathetic nearby who heard it.
2585 		        ((witness = closest) != nullptr && rand() % 10 == 0)) {
2586 			static long lastcall = 0L;  // Last time yelled.
2587 			long curtime = SDL_GetTicks();
2588 			long delta = curtime - lastcall;
2589 			// Call if 10 secs. has passed or by the luck of the die.
2590 			if ((delta > 10000) || (rand() % 20 == 0)) {
2591 				int numguards = 0;
2592 				int gshape = Game_window::get_guard_shape();
2593 				// No guards in dungeons or if gshape < 0.
2594 				if (!gwin->is_in_dungeon() && gshape >= 0 &&
2595 				        // And only neutral NPCs and guards call more guards.
2596 				        (witness->get_shapenum() == gshape ||
2597 				         align == Actor::neutral))
2598 					numguards = 1 + rand() % 2;
2599 
2600 				eman->remove_text_effect(this);
2601 				if (numguards > 0) {
2602 					// Call guards.
2603 					if (witness->is_goblin())
2604 						witness->say(first_goblin_call_police, last_goblin_call_police);
2605 					else if (witness->can_speak())
2606 						witness->say(first_call_police, last_call_police);
2607 				} else {
2608 					// Cry for help.
2609 					if (witness->is_goblin())
2610 						witness->say(goblin_need_help);
2611 					else if (witness->can_speak())
2612 						witness->say(first_need_help, last_need_help);
2613 				}
2614 				// To reduce the guard pile-up.
2615 				lastcall = curtime;
2616 				gwin->attack_avatar(numguards, align);
2617 			}
2618 		}
2619 	}
2620 }
2621 
2622 /*
2623  *  This method should be called to cause damage from traps, attacks.
2624  *
2625  *  Output: Hits taken. If exp is nonzero, experience value if defeated.
2626  */
2627 
apply_damage(Game_object * attacker,int str,int wpoints,int type,int bias,int * exp)2628 int Actor::apply_damage(
2629     Game_object *attacker,  // Attacker, or null.
2630     int str,        // Attack strength.
2631     int wpoints,    // Weapon bonus.
2632     int type,       // Damage type.
2633     int bias,       // Different combat difficulty.
2634     int *exp
2635 ) {
2636 	if (exp)
2637 		*exp = 0;
2638 	int damage = bias;
2639 	str /= 3;
2640 
2641 	// In the original, wpoints == 127 does fixed 127 damage.
2642 	// Allowing for >= 127 in Exult, as the original seems to
2643 	// use only a byte for damage/health.
2644 	if (wpoints >= 127)
2645 		damage = 127;
2646 	else {
2647 		// Lightning damage ignores strength.
2648 		if (type != Weapon_data::lightning_damage && str > 0)
2649 			damage += (1 + rand() % str);
2650 		if (wpoints > 0)
2651 			damage += (1 + rand() % wpoints);
2652 	}
2653 
2654 	int armor = -bias;
2655 	const Monster_info *minf = get_info().get_monster_info();
2656 	// Monster armor protects only in UI_apply_damage.
2657 	if (minf)
2658 		armor += minf->get_armor();
2659 
2660 	// Armor defense and immunities only affect UI_apply_damage.
2661 	const int num_spots = array_size(spots);
2662 	for (int i = 0; i < num_spots; i++) {
2663 		Game_object *obj = spots[i];
2664 		if (obj) {
2665 			const Shape_info &info = obj->get_info();
2666 			armor += info.get_armor();
2667 			if ((info.get_armor_immunity() & (1 << type)) != 0) {
2668 				// Armor gives immunity.
2669 				// Metal clang.
2670 				Object_sfx::Play(this, Audio::game_sfx(5));
2671 				// Attack back anyway.
2672 				fight_back(attacker);
2673 				return 0;   // No damage == no powers.
2674 			}
2675 		}
2676 	}
2677 
2678 	// Some attacks ignore armor (unless the armor gives immunity).
2679 	if (wpoints == 127 || type == Weapon_data::lightning_damage ||
2680 	        type == Weapon_data::ethereal_damage ||
2681 	        type == Weapon_data::sonic_damage ||
2682 	        armor < 0)  // Armor should never help the attacker.
2683 		armor = 0;
2684 
2685 	if (armor)
2686 		damage -= (1 + rand() % armor);
2687 
2688 	// Paralyzed/defenseless foes may take damage even if
2689 	// the armor protects them. This code is guesswork,
2690 	// but it matches statistical tests.
2691 	if (damage <= 0 && !can_act()) {
2692 		if (str > 0)
2693 			damage = 1 + rand() % str;
2694 		else
2695 			damage = 0;
2696 	}
2697 
2698 	if (damage <= 0) {
2699 		// No damage caused.
2700 		Object_sfx::Play(this, Audio::game_sfx(5));
2701 
2702 		// Flash red outline.
2703 		hit = true;
2704 		add_dirty();
2705 		auto *c = new Clear_hit(this);
2706 		gwin->get_tqueue()->add(Game::get_ticks() + 200, c, this);
2707 		// Attack back.
2708 		fight_back(attacker);
2709 		return 0;   // No damage == no powers (usually).
2710 	}
2711 
2712 	return reduce_health(damage, type, attacker, exp);
2713 }
2714 
2715 /*
2716  *  This method should be called to decrement health directly.
2717  *
2718  *  Output: Hits taken. If exp is nonzero, experience value if defeated.
2719  */
2720 
reduce_health(int delta,int type,Game_object * attacker,int * exp)2721 int Actor::reduce_health(
2722     int delta,          // # points to lose.
2723     int type,       // Type of damage
2724     Game_object *attacker,      // Attacker, or null.
2725     int *exp
2726 ) {
2727 	if (exp)
2728 		*exp = 0;
2729 	// Cheater, cheater.
2730 	if (is_dead() || (cheat.in_god_mode() && ((party_id != -1) || (npc_num == 0))))
2731 		return 0;
2732 
2733 	const Monster_info *minf = get_info().get_monster_info_safe();
2734 	Actor *npc = attacker ? attacker->as_actor() : nullptr;
2735 
2736 	// Monster immunities DO affect UI_reduce_health, unlike
2737 	// armor immunities.
2738 	if (is_dead() || minf->cant_die() ||
2739 	        (minf->get_immune() & (1 << type)) != 0) {
2740 		// Monster data gives immunity to damage.
2741 		// Attack back.
2742 		fight_back(attacker);
2743 		return 0;
2744 	}
2745 
2746 	// Monsters vulnerable to a damage type take 2x the damage.
2747 	// The originals seem to limit damage to 127 points; we
2748 	// set a lower bound on final health below.
2749 	if ((minf->get_vulnerable() & (1 << type)) != 0)
2750 		delta *= 2;
2751 
2752 	int oldhp = properties[static_cast<int>(health)];
2753 	int maxhp = properties[static_cast<int>(strength)];
2754 	int val = oldhp - delta;
2755 	if (val < -50) {
2756 		// Limit how low it goes for safety.
2757 		val = -50;
2758 		delta = oldhp + 50;
2759 	}
2760 	// Don't set health yet!! (see tournament below for why)
2761 	// The following thresholds are exact.
2762 	if (this == gwin->get_main_actor() &&
2763 	        // Flash red if Avatar badly hurt.
2764 	        (delta >= maxhp / 3 || oldhp < maxhp / 4 ||
2765 	         // Or if lightning damage.
2766 	         type == Weapon_data::lightning_damage))
2767 		gwin->get_pal()->flash_red();
2768 	else {
2769 		hit = true;     // Flash red outline.
2770 		add_dirty();
2771 		auto *c = new Clear_hit(this);
2772 		gwin->get_tqueue()->add(Game::get_ticks() + 200, c, this);
2773 	}
2774 	if (oldhp >= maxhp / 2 && val < maxhp / 2 && rand() % 2 != 0) {
2775 		// A little oomph.
2776 		if (is_goblin())            // Goblin?
2777 			say(goblin_ouch);
2778 		else if (can_speak())
2779 			say(first_ouch, last_ouch);
2780 	}
2781 	Game_object_vector vec;     // Create blood.
2782 	const int blood = 912;      // TODO: de-hard-code this.
2783 	// Bleed only for normal damage.
2784 	if (type == Weapon_data::normal_damage && !minf->cant_bleed()
2785 	        // Trying something new. Seems to match originals better, but
2786 	        // it is hard to judge accurately (although 10 or more hits
2787 	        // *always* cause bleeding).
2788 	        && rand() % 10 < delta
2789 	        && find_nearby(vec, blood, 1, 0) < 2) {
2790 		// Create blood where actor stands.
2791 		Game_object_shared bobj = gmap->create_ireg_object(blood, 0);
2792 		bobj->set_flag(Obj_flags::is_temporary);
2793 		bobj->move(get_tile());
2794 	}
2795 	if (val <= 0 && oldhp > 0 && get_flag(Obj_flags::tournament)) {
2796 		// HPs are never reduced before tournament usecode
2797 		// (this can be checked on weapon usecode, tournament
2798 		// usecode or even UI_reduce_health directly followed
2799 		// by UI_get_npc_prop).
2800 		// THIS is why we haven't reduced health yet.
2801 		// This makes foes with tournament flag EXTREMELLY
2802 		// tough, particularly if they have high hit points
2803 		// to begin with!
2804 		// No more pushover banes!
2805 		if (npc)    // Just to be sure.
2806 			set_oppressor(npc->get_npc_num());
2807 		ucmachine->call_usecode(get_usecode(), this,
2808 		                        Usecode_machine::died);
2809 		return 0;   // If needed, NPC usecode does the killing (possibly
2810 		// by calling this function again).
2811 	}
2812 
2813 	// We do slimes here; they DO split through reduce_health intrinsic.
2814 	// They also do *not* split if hit by damage they are vulnerable to.
2815 	if (minf->splits() && val > 0 &&
2816 	        (minf->get_vulnerable() & (1 << type)) == 0 && rand() % 2 == 0)
2817 		clone();
2818 
2819 	// Doing this here simplifies the tournament code, above.
2820 	properties[static_cast<int>(health)] = val;
2821 	bool defeated = is_dying() || (val <= 0 && oldhp > 0);
2822 
2823 	if (defeated && exp) {
2824 		// Verified: No experience for killing sleeping people.
2825 		if (!get_flag(Obj_flags::asleep)) {
2826 			int expval = 0;
2827 			// Except for 2 details mentioned below, this formula
2828 			// is an exact match to what the originals give.
2829 			// We also have to do this *here*, before we kill the
2830 			// NPC, because the equipment is deleted (spells) or
2831 			// transferred to the dead body it leaves.
2832 			int combval = properties[static_cast<int>(combat)];
2833 			expval = properties[static_cast<int>(strength)] + combval +
2834 			         (properties[static_cast<int>(dexterity)] + 1) / 3 +
2835 			         properties[static_cast<int>(intelligence)] / 5;
2836 			const Monster_info *minf = get_info().get_monster_info();
2837 			int immune = minf ? minf->get_immune() : 0;
2838 			int vuln = minf ? minf->get_vulnerable() : 0;
2839 			if (minf)
2840 				expval += minf->get_base_xp_value();
2841 
2842 			if (!objects.is_empty()) {
2843 				Game_object_vector vec;     // Get list of all possessions.
2844 				vec.reserve(50);
2845 				get_objects(vec, c_any_shapenum, c_any_qual, c_any_framenum);
2846 				for (auto *obj : vec) {
2847 					// This matches the original, but maybe
2848 					// we should iterate through all items.
2849 					// After all, a death bolt in the backpack
2850 					// can still be dangerous...
2851 					if (obj->get_owner() != this)
2852 						continue;
2853 					const Shape_info &inf = obj->get_info();
2854 					expval += inf.get_armor();
2855 					// Strictly speaking, the original does not give
2856 					// XP for armor immunities; but I guess this is
2857 					// mostly because very few armors give immunities
2858 					// (ethereal ring, cadellite helm) and no monsters
2859 					// use them anyway.
2860 					// I decided to have them give a (non-cumulative)
2861 					// increase in experience.
2862 					immune |= inf.get_armor_immunity();
2863 					const Weapon_info *winf = inf.get_weapon_info();
2864 					if (!winf)
2865 						continue;
2866 					expval += winf->get_base_xp_value();
2867 					// This was tough to figure out, but figured out it was;
2868 					// it is a perfect match to what the original does.
2869 					switch (winf->get_uses()) {
2870 					case Weapon_info::melee: {
2871 						int range = winf->get_range();
2872 						expval += range > 5 ? 2 : (range > 3 ? 1 : 0);
2873 						break;
2874 					}
2875 					case Weapon_info::poor_thrown:
2876 						expval += combval / 5;
2877 						break;
2878 					case Weapon_info::good_thrown:
2879 						expval += combval / 3;
2880 						break;
2881 					case Weapon_info::ranged:
2882 						expval += winf->get_range() / 2;
2883 						break;
2884 					}
2885 				}
2886 			}
2887 			// Originals don't do this, but hey... they *should*.
2888 			// Also, being vulnerable to something you are immune
2889 			// should not matter because immunities are checked first;
2890 			// the originals don't do this check, but neither do they
2891 			// have a monster vulnerable and immune to the same thing.
2892 			vuln &= ~immune;
2893 			expval += bitcount(immune);
2894 			expval -= bitcount(vuln);
2895 			// And the final touch (verified).
2896 			expval /= 2;
2897 			*exp = expval;
2898 		}
2899 	}
2900 
2901 	// query this here because die() will reset is_in_party.
2902 	bool in_party = is_in_party();
2903 
2904 	if (is_dying())
2905 		die(attacker);
2906 	else if (val <= 0 && !get_flag(Obj_flags::asleep)) {
2907 		Combat_schedule::stop_attacking_npc(this);
2908 		set_flag(Obj_flags::asleep);
2909 	} else if (npc && !target.lock() && !in_party) {
2910 		set_target(npc, npc->get_schedule_type() != Schedule::duel);
2911 		set_oppressor(npc->get_npc_num());
2912 	}
2913 
2914 	// Dead people caused attacks on the avatar back in Actor::die, so don't do
2915 	// it again here.
2916 	if (!is_dead())
2917 		fight_back(attacker);
2918 	return delta;
2919 }
2920 
2921 /*
2922  *  Causes the actor to fall to the ground and take damage.
2923  */
2924 
fall_down()2925 void Actor::fall_down() {
2926 	if (!get_type_flag(tf_fly))
2927 		return;
2928 	int savetz = get_lift();
2929 	Tile_coord start = get_tile();
2930 	if (!Map_chunk::is_blocked(start, 1, MOVE_WALK, 100) &&
2931 	        start.tz < savetz) {
2932 		move(start.tx, start.ty, start.tz);
2933 		reduce_health(1 + rand() % 5, Weapon_data::normal_damage);
2934 	}
2935 }
2936 
2937 /*
2938  *  Causes the actor to lie down to sleep (or die).
2939  */
2940 
lay_down(bool die)2941 void Actor::lay_down(bool die) {
2942 	if (!die && get_flag(Obj_flags::asleep))
2943 		return;
2944 	// Fall to the ground.
2945 	fall_down();
2946 	bool frost_serp = GAME_SI && get_shapenum() == 832;
2947 	// Don't do it if already in sleeping frame.
2948 	if (frost_serp && (get_framenum() & 0xf) == Actor::sit_frame)
2949 		return;     // SI Frost serpents are weird.
2950 	else if ((get_framenum() & 0xf) == Actor::sleep_frame)
2951 		return;
2952 
2953 	set_action(nullptr);
2954 	auto *scr = new Usecode_script(this);
2955 	(*scr) << Ucscript::finish << (Ucscript::npc_frame + Actor::standing);
2956 	if (GAME_SI && get_shapenum() == 832) { // SI Frost serpent
2957 		// Frames are in reversed order. This results in a
2958 		// strangeanimation in the original, which we fix here.
2959 		(*scr) << (Ucscript::npc_frame + Actor::sleep_frame)
2960 		       << (Ucscript::npc_frame + Actor::kneel_frame)
2961 		       << (Ucscript::npc_frame + Actor::bow_frame)
2962 		       << (Ucscript::npc_frame + Actor::sit_frame);
2963 	} else if (get_info().has_strange_movement()) {
2964 		// BG Sea serpent; slimes are done elsewhere.
2965 		(*scr) << (Ucscript::npc_frame + Actor::bow_frame)
2966 		       << (Ucscript::npc_frame + Actor::kneel_frame)
2967 		       << (Ucscript::npc_frame + Actor::sleep_frame);
2968 	} else {
2969 		(*scr) << (Ucscript::npc_frame + Actor::kneel_frame)
2970 		       << Ucscript::sfx << Audio::game_sfx(86);
2971 		if (!die)
2972 			(*scr) << (Ucscript::npc_frame + Actor::sleep_frame);
2973 	}
2974 	if (die)    // If dying, remove.
2975 		(*scr) << Ucscript::remove;
2976 	scr->start();
2977 }
2978 
2979 /*
2980  *  Get a property.
2981  */
2982 
get_property(int prop) const2983 int Actor::get_property(int prop) const {
2984 	if (prop == Actor::sex_flag)
2985 		// Correct in BG and SI, but the flag is never normally set
2986 		// for anyone but avatar in BG.
2987 		return get_type_flag(Actor::tf_sex);
2988 	else if (prop == Actor::missile_weapon) {
2989 		// Seems to give the same results as in the originals.
2990 		Game_object *weapon = get_readied(lhand);
2991 		const Weapon_info *winf = weapon ? weapon->get_info().get_weapon_info() : nullptr;
2992 		if (!winf)
2993 			return 0;
2994 		return winf->get_uses() >= 2;
2995 	}
2996 	return (prop >= 0 && prop < Actor::sex_flag) ? properties[prop] : 0;
2997 }
2998 
2999 /*
3000  *  Get a property, modified by flags.
3001  */
3002 
get_effective_prop(int prop) const3003 int Actor::get_effective_prop(
3004     int prop                // Property #.
3005 ) const {
3006 	int val = get_property(prop);
3007 	switch (prop) {
3008 	case Actor::dexterity:
3009 	case Actor::combat:
3010 		if (get_flag(Obj_flags::paralyzed) || get_flag(Obj_flags::asleep) ||
3011 		        is_knocked_out())
3012 			return prop == Actor::dexterity ? 0 : 1;
3013 		// FALL THROUGH
3014 	case Actor::intelligence:
3015 		if (is_dead())
3016 			return prop == Actor::dexterity ? 0 : 1;
3017 		else if (get_flag(Obj_flags::charmed) || get_flag(Obj_flags::asleep))
3018 			val--;
3019 		// FALL THROUGH
3020 	case Actor::strength:
3021 		if (get_flag(Obj_flags::might))
3022 			val += (val < 15 ? val : 15);   // Add up to 15.
3023 		if (get_flag(Obj_flags::cursed))
3024 			val -= 3;   // Matches originals.
3025 		break;
3026 	}
3027 	return val;
3028 }
3029 
3030 /*
3031  *  For mods and new games:  Set generic attribute keyed by a name.
3032  */
3033 
set_attribute(const char * nm,int val)3034 void Actor::set_attribute(
3035     const char *nm,
3036     int val
3037 ) {
3038 	if (!atts)
3039 		atts = new Actor_attributes;
3040 	atts->set(nm, val);
3041 }
3042 
3043 /*
3044  *  Get generic attribute.  Returns 0 if not set.
3045  */
3046 
get_attribute(const char * nm) const3047 int Actor::get_attribute(
3048     const char *nm
3049 ) const {
3050 	return atts ? atts->get(nm) : 0;
3051 }
3052 
3053 /*
3054  *  Get them all.
3055  */
3056 
get_attributes(Atts_vector & attlist) const3057 void Actor::get_attributes(
3058     Atts_vector &attlist
3059 ) const {
3060 	attlist.resize(0);
3061 	if (atts)
3062 		atts->get_all(attlist);
3063 }
3064 
3065 /*
3066  *  Read in attributes (from savegame file).
3067  */
3068 
read_attributes(const unsigned char * buf,int len)3069 void Actor::read_attributes(
3070     const unsigned char *buf,     // Attribute/value pairs.
3071     int len
3072 ) {
3073 	const unsigned char *ptr = buf;
3074 	const unsigned char *endbuf = buf + len;
3075 	while (ptr < endbuf) {
3076 		const char *att = reinterpret_cast<const char *>(ptr);
3077 		ptr += strlen(att) + 1;
3078 		assert(ptr + 2 <= endbuf);
3079 		int val = Read2(ptr);
3080 		set_attribute(att, val);
3081 	}
3082 }
3083 
3084 /*
3085  *  Force actor to sleep.
3086  */
3087 
force_sleep()3088 void Actor::force_sleep() {
3089 	flags |= (static_cast<uint32>(1) << Obj_flags::asleep);
3090 	need_timers()->start_sleep();
3091 	set_action(nullptr);      // Stop what you're doing.
3092 	lay_down(false);    // Lie down.
3093 }
3094 
3095 // Want to avoid full include.
3096 extern bool Bg_dont_wake(Game_window *gwin, Actor *npc);
3097 
3098 /*
3099  *  Set flag.
3100  */
3101 
set_flag(int flag)3102 void Actor::set_flag(
3103     int flag
3104 ) {
3105 //	cout << "Set flag for NPC " << get_npc_num() << " = " << flag << endl;
3106 	const Monster_info *minf = get_info().get_monster_info_safe();
3107 	Actor *avatar = gwin->get_main_actor();
3108 	switch (flag) {
3109 	case Obj_flags::asleep:
3110 		if (minf->sleep_safe() || minf->power_safe() ||
3111 		        (gear_powers & (Frame_flags::power_safe | Frame_flags::sleep_safe)))
3112 			return;     // Don't do anything.
3113 		// Avoid waking Penumbra.
3114 		if (schedule_type == Schedule::sleep && Bg_dont_wake(gwin, this))
3115 			break;
3116 		// Set timer to wake in a few secs.
3117 		if (this != avatar && avatar->get_target() == this)
3118 			avatar->set_target(nullptr);
3119 		need_timers()->start_sleep();
3120 		set_action(nullptr);      // Stop what you're doing.
3121 		lay_down(false);    // Lie down.
3122 		break;
3123 	case Obj_flags::poisoned:
3124 		if (minf->poison_safe() || (gear_powers & Frame_flags::poison_safe))
3125 			return;     // Don't do anything.
3126 		need_timers()->start_poison();
3127 		break;
3128 	case Obj_flags::protection:
3129 		need_timers()->start_protection();
3130 		break;
3131 	case Obj_flags::might:
3132 		need_timers()->start_might();
3133 		break;
3134 	case Obj_flags::cursed:
3135 		if (minf->curse_safe() || minf->power_safe() ||
3136 		        (gear_powers & (Frame_flags::power_safe | Frame_flags::curse_safe)))
3137 			return;     // Don't do anything.
3138 		need_timers()->start_curse();
3139 		break;
3140 	case Obj_flags::charmed:
3141 		if (minf->charm_safe() || minf->power_safe() ||
3142 		        (gear_powers & (Frame_flags::power_safe | Frame_flags::charm_safe)))
3143 			return;     // Don't do anything.
3144 		need_timers()->start_charm();
3145 		// Actual alignment shift must be done elsewhere.
3146 		Combat_schedule::stop_attacking_npc(this);
3147 		set_target(nullptr);      // Need new opponent if in combat.
3148 		break;
3149 	case Obj_flags::paralyzed:
3150 		if (minf->paralysis_safe() || minf->power_safe() ||
3151 		        (gear_powers & (Frame_flags::power_safe | Frame_flags::paralysis_safe)))
3152 			return;     // Don't do anything.
3153 		fall_down();
3154 		need_timers()->start_paralyze();
3155 		break;
3156 	case Obj_flags::invisible:
3157 		flags |= (static_cast<uint32>(1) << flag);
3158 		need_timers()->start_invisibility();
3159 		Combat_schedule::stop_attacking_invisible(this);
3160 		gclock->set_palette();
3161 		break;
3162 	case Obj_flags::dont_move:
3163 	case Obj_flags::bg_dont_move:
3164 		stop();         // Added 7/6/03.
3165 		set_action(nullptr);  // Force actor to stop current action.
3166 		break;
3167 	case Obj_flags::naked: {
3168 		// set_polymorph needs this, and there are no problems
3169 		// in setting this twice.
3170 		flags2 |= (static_cast<uint32>(1) << (flag - 32));
3171 		if (get_npc_num() != 0) // Ignore for all but avatar.
3172 			break;
3173 		int sn;
3174 		int female = get_type_flag(tf_sex) ? 1 : 0;
3175 		Skin_data *skin = Shapeinfo_lookup::GetSkinInfoSafe(this);
3176 
3177 		if (!skin ||    // Should never happen, but hey...
3178 		        (!sman->have_si_shapes() &&
3179 		         Shapeinfo_lookup::IsSkinImported(skin->naked_shape)))
3180 			sn = Shapeinfo_lookup::GetBaseAvInfo(female != 0)->shape_num;
3181 		else
3182 			sn = skin->naked_shape;
3183 		set_polymorph(sn);
3184 		break;
3185 	}
3186 	}
3187 
3188 	// Doing it here to prevent problems with immunities.
3189 	if (flag >= 0 && flag < 32)
3190 		flags |= (static_cast<uint32>(1) << flag);
3191 	else if (flag >= 32 && flag < 64)
3192 		flags2 |= (static_cast<uint32>(1) << (flag - 32));
3193 	// Update stats if open.
3194 	if (gumpman->showing_gumps())
3195 		gwin->set_all_dirty();
3196 	set_actor_shape();
3197 }
3198 
set_type_flag(int flag)3199 void Actor::set_type_flag(
3200     int flag
3201 ) {
3202 	if (flag >= 0 && flag < 16)
3203 		type_flags |= (static_cast<uint32>(1) << flag);
3204 
3205 	set_actor_shape();
3206 }
3207 
3208 /*
3209  *  Clear flag.
3210  */
3211 
clear_flag(int flag)3212 void Actor::clear_flag(
3213     int flag
3214 ) {
3215 //	cout << "Clear flag for NPC " << get_npc_num() << " = " << flag << endl;
3216 	if (flag >= 0 && flag < 32)
3217 		flags &= ~(static_cast<uint32>(1) << flag);
3218 	else if (flag >= 32 && flag < 64)
3219 		flags2 &= ~(static_cast<uint32>(1) << (flag - 32));
3220 	if (flag == Obj_flags::invisible)   // Restore normal palette.
3221 		gclock->set_palette();
3222 	else if (flag == Obj_flags::asleep) {
3223 		if (schedule_type == Schedule::sleep)
3224 			set_schedule_type(Schedule::stand);
3225 		else if ((get_framenum() & 0xf) == Actor::sleep_frame) {
3226 			// Find spot to stand.
3227 			Tile_coord pos = get_tile();
3228 			pos.tz -= pos.tz % 5; // Want floor level.
3229 			pos = Map_chunk::find_spot(pos, 6, get_shapenum(),
3230 			                           Actor::standing, 0);
3231 			if (pos.tx >= 0)
3232 				move(pos);
3233 			change_frame(Actor::standing);
3234 		}
3235 		Usecode_script::terminate(this);
3236 	} else if (flag == Obj_flags::charmed) {
3237 		reset_effective_alignment();
3238 		Combat_schedule::stop_attacking_npc(this);
3239 		set_target(nullptr);          // Need new opponent.
3240 	} else if (flag == Obj_flags::bg_dont_move || flag == Obj_flags::dont_move)
3241 		// Start again after a little while
3242 		start_std();
3243 	else if (flag == Obj_flags::polymorph && get_flag(Obj_flags::naked))
3244 		clear_flag(Obj_flags::naked);
3245 	else if (flag == Obj_flags::naked && get_flag(Obj_flags::polymorph))
3246 		clear_flag(Obj_flags::polymorph);
3247 
3248 	set_actor_shape();
3249 }
3250 
clear_type_flag(int flag)3251 void Actor::clear_type_flag(
3252     int flag
3253 ) {
3254 	if (flag >= 0 && flag < 16)
3255 		type_flags &= ~(static_cast<uint32>(1) << flag);
3256 
3257 	set_actor_shape();
3258 }
3259 
3260 /*
3261  *  Get flags.
3262  */
3263 
get_type_flag(int flag) const3264 bool Actor::get_type_flag(
3265     int flag
3266 ) const {
3267 	return (flag >= 0 && flag < 16) ? (type_flags & (static_cast<uint32>(1) << flag))
3268 	       != 0 : false;
3269 }
3270 /*
3271  *  SetFlags
3272  */
3273 
set_type_flags(unsigned short tflags)3274 void Actor::set_type_flags(
3275     unsigned short tflags
3276 ) {
3277 	type_flags = tflags;
3278 	set_actor_shape();
3279 }
3280 
3281 /*
3282  *  Set temperature.
3283  */
3284 
set_temperature(int v)3285 void Actor::set_temperature(
3286     int v               // Should be 0-63.
3287 ) {
3288 	if (v < 0)
3289 		v = 0;
3290 	else if (v > 63)
3291 		v = 63;
3292 	temperature = v;
3293 }
3294 
3295 /*
3296  *  Figure warmth based on what's worn.  In trying to mimic the original
3297  *  SI, the base value is -75.
3298  */
3299 
figure_warmth()3300 int Actor::figure_warmth(
3301 ) {
3302 	int warmth = -75;       // Base value.
3303 
3304 	static Ready_type_Exult locs[] = {head, cloak, feet, torso, gloves, legs};
3305 	for (auto loc : locs) {
3306 		Game_object *worn = spots[static_cast<int>(loc)];
3307 		if (worn)
3308 			warmth += worn->get_info().get_object_warmth(worn->get_framenum());
3309 	}
3310 	return warmth;
3311 }
3312 
3313 /*
3314  *  Get maximum weight in stones that can be held.
3315  *
3316  *  Output: Max. allowed, or 0 if no limit (i.e., not carried by an NPC).
3317  */
3318 
get_max_weight() const3319 int Actor::get_max_weight(
3320 ) const {
3321 	return 2 * get_effective_prop(static_cast<int>(Actor::strength));
3322 }
3323 
3324 /*
3325  *  Call usecode function for an object that's readied/unreadied.
3326  */
3327 
call_readied_usecode(int index,Game_object * obj,int eventid)3328 void Actor::call_readied_usecode(
3329     int index,
3330     Game_object *obj,
3331     int eventid
3332 ) {
3333 	ignore_unused_variable_warning(index);
3334 	// Limit to certain types.
3335 	if (!obj->get_info().has_usecode_events())
3336 		return;
3337 
3338 	const Shape_info &info = obj->get_info();
3339 	if (info.get_shape_class() != Shape_info::container)
3340 		ucmachine->call_usecode(obj->get_usecode(),
3341 		                        obj, static_cast<Usecode_machine::Usecode_events>(eventid));
3342 }
3343 
3344 /*
3345  *  Returns true if NPC is in a non-no_halt usecode script or if
3346  *  dont_move flag is set.
3347  */
in_usecode_control() const3348 bool Actor::in_usecode_control() const {
3349 	if (get_flag(Obj_flags::dont_render) || get_flag(Obj_flags::dont_move))
3350 		return true;
3351 	Usecode_script *scr = nullptr;
3352 	while ((scr = Usecode_script::find_active(this, scr)) != nullptr)
3353 		// no_halt scripts seem not to prevent movement.
3354 		if (!scr->is_no_halt())
3355 			return true;
3356 	return false;
3357 }
3358 
3359 /*
3360  *  Attack preset target/tile using preset weapon shape.
3361  *
3362  *  Output: True if attack was realized and hit target (or is
3363  *  a missile flying towards target), false otherwise
3364  */
usecode_attack()3365 bool Actor::usecode_attack() {
3366     Game_object_shared tobj = target_object.lock();
3367 	return Combat_schedule::attack_target(
3368 	           this, tobj.get(), target_tile, attack_weapon);
3369 }
3370 
3371 /*
3372  *  Should be called after actors and usecode are initialized.
3373  */
3374 
init_readied()3375 void Actor::init_readied(
3376 ) {
3377 	for (size_t i = 0; i < array_size(spots); i++)
3378 		if (spots[i])
3379 			call_readied_usecode(i, spots[i],
3380 			                     Usecode_machine::readied);
3381 }
3382 
3383 /*
3384  *  Remove an object.
3385  */
3386 
remove(Game_object * obj)3387 void Actor::remove(
3388     Game_object *obj
3389 ) {
3390 	int index = Actor::find_readied(obj);   // Remove from spot.
3391 	// Note:  gwin->drop() also does this,
3392 	//   but it needs to be done before
3393 	//   removal too.
3394 	// Definitely DO NOT call if dead!
3395 	if (!is_dead()
3396 		&& !ucmachine->in_usecode_for(obj, Usecode_machine::unreadied)
3397 		&& !(GAME_SI && ucmachine->in_usecode_for(gwin->get_main_actor(), Usecode_machine::died))) // Fix for #1887 - Hang when leaving SI dream world
3398 		call_readied_usecode(index, obj, Usecode_machine::unreadied);
3399 	Container_game_object::remove(obj);
3400 	if (index >= 0) {
3401 		spots[index] = nullptr;
3402 		if (index == rhand || index == lhand)
3403 			two_handed = false;
3404 		if (index == rfinger || index == lfinger)
3405 			two_fingered = false;
3406 		if (index == belt || index == back_2h || index == back_shield)
3407 			use_scabbard = false;
3408 		if (index == amulet || index == cloak)
3409 			use_neck = false;
3410 		if (index == lhand && schedule)
3411 			schedule->set_weapon(true);
3412 		// Recheck armor immunities and frame powers.
3413 		refigure_gear();
3414 	}
3415 }
3416 
3417 /*
3418  *  Add an object.
3419  *
3420  *  Output: 1, meaning object is completely contained in this,
3421  *      0 if not enough space.
3422  */
3423 
add(Game_object * obj,bool dont_check,bool combine,bool noset)3424 bool Actor::add(
3425     Game_object *obj,
3426     bool dont_check,        // 1 to skip volume check (AND also
3427     //   to skip usecode call).
3428     bool combine,           // True to try to combine obj.  MAY
3429     //   cause obj to be deleted.
3430     bool noset      // True to prevent actors from setting sched. weapon.
3431 ) {
3432 
3433 	int index = find_best_spot(obj);// Where should it go?
3434 
3435 	if (index < 0) {        // No free spot?  Look for a bag.
3436 		if (spots[backpack] && spots[backpack]->add(obj, false, combine))
3437 			return true;
3438 		if (spots[belt] && spots[belt]->add(obj, false, combine))
3439 			return true;
3440 		if (spots[lhand] && spots[lhand]->add(obj, false, combine))
3441 			return true;
3442 		if (spots[rhand] && spots[rhand]->add(obj, false, combine))
3443 			return true;
3444 		if (!dont_check)
3445 			return false;
3446 
3447 		// try again without checking volume/weight
3448 		if (spots[backpack] && spots[backpack]->add(obj, true, combine))
3449 			return true;
3450 		if (spots[belt] && spots[belt]->add(obj, true, combine))
3451 			return true;
3452 		if (spots[lhand] && spots[lhand]->add(obj, true, combine))
3453 			return true;
3454 		if (spots[rhand] && spots[rhand]->add(obj, true, combine))
3455 			return true;
3456 
3457 		if (party_id != -1 || npc_num == 0) {
3458 			CERR("Warning: adding object (" << obj << ", sh. " << obj->get_shapenum() << ", " << obj->get_name() << ") to actor container (npc " << npc_num << ")");
3459 		}
3460 		return Container_game_object::add(obj, dont_check, combine);
3461 	}
3462 	// Add to ourself (DON'T combine).
3463 	if (!Container_game_object::add(obj, true))
3464 		return false;
3465 
3466 	if (index == both_hands) {      // Two-handed?
3467 		two_handed = true;
3468 		index = lhand;
3469 	} else if (index == lrgloves) { // BG Gloves?
3470 		two_fingered = true;
3471 		index = lfinger;
3472 	} else if (index == scabbard) { // Use scabbard?
3473 		use_scabbard = true;
3474 		index = belt;
3475 	} else if (index == neck) { // Use neck?
3476 		use_neck = true;
3477 		index = amulet;
3478 	}
3479 
3480 	spots[index] = obj;     // Store in correct spot.
3481 	if (index == lhand && schedule && !noset)
3482 		schedule->set_weapon(); // Tell combat-schedule about it.
3483 	obj->set_shape_pos(0, 0);   // Clear coords. (set by gump).
3484 	if (!dont_check)
3485 		call_readied_usecode(index, obj, Usecode_machine::readied);
3486 	// (Readied usecode now in drop().)
3487 
3488 	const Shape_info &info = obj->get_info();
3489 
3490 	if (info.is_light_source() &&
3491 	        (index == lhand || index == rhand))
3492 		add_light_source(info.get_object_light(obj->get_framenum()));
3493 
3494 	// Refigure granted immunities.
3495 	gear_immunities |= info.get_armor_immunity();
3496 	gear_powers |= info.get_object_flags(obj->get_framenum(),
3497 	                                     info.has_quality() ? obj->get_quality() : -1);
3498 	return true;
3499 }
3500 
3501 /*
3502  *  Add to given spot.
3503  *
3504  *  Output: true if successful, else false.
3505  */
3506 
add_readied(Game_object * obj,int index,bool dont_check,bool force_pos,bool noset)3507 bool Actor::add_readied(
3508     Game_object *obj,
3509     int index,          // Spot #.
3510     bool dont_check,
3511     bool force_pos,
3512     bool noset
3513 ) {
3514 	// Is Out of range?
3515 	if (index < 0 || index >= static_cast<int>(array_size(spots)))
3516 		return false;
3517 
3518 	// Already something there? Try to drop into it.
3519 	// +++++Danger:  drop() can potentially delete the object.
3520 //	if (spots[index]) return spots[index]->drop(obj);
3521 	if (spots[index]) return spots[index]->add(obj, dont_check);
3522 
3523 	int prefered;
3524 	int alt1;
3525 	int alt2;
3526 
3527 	// Get the preferences
3528 	get_prefered_slots(obj, prefered, alt1, alt2);
3529 
3530 	// Check Prefered
3531 	if (!fits_in_spot(obj, index) && !force_pos) return false;
3532 
3533 	// No room, or too heavy.
3534 	if (!Container_game_object::add(obj, true)) return false;
3535 
3536 	// Set the spot to this object
3537 	spots[index] = obj;
3538 
3539 	// Clear coords. (set by gump).
3540 	obj->set_shape_pos(0, 0);
3541 
3542 	// Must be a two-handed weapon.
3543 	if (prefered == both_hands && index == lhand)
3544 		two_handed = true;
3545 	// Must be gloves
3546 	else if (prefered == lrgloves && index == lfinger)
3547 		two_fingered = true;
3548 	// Must be in scabbard
3549 	else if ((alt1 == scabbard || alt2 == scabbard) && index == belt)
3550 		use_scabbard = true;
3551 	// Must use neck entirely
3552 	else if (prefered == neck && index == amulet)
3553 		use_neck = true;
3554 
3555 	if (!dont_check)
3556 		call_readied_usecode(index, obj, Usecode_machine::readied);
3557 
3558 	const Shape_info &info = obj->get_info();
3559 
3560 	if (info.is_light_source() &&
3561 	        (index == lhand || index == rhand))
3562 		add_light_source(info.get_object_light(obj->get_framenum()));
3563 
3564 	// Refigure granted immunities.
3565 	gear_immunities |= info.get_armor_immunity();
3566 	gear_powers |= info.get_object_flags(obj->get_framenum(),
3567 	                                     info.has_quality() ? obj->get_quality() : -1);
3568 
3569 	if (index == lhand && schedule && !noset)
3570 		schedule->set_weapon(); // Tell combat-schedule about it.
3571 	return true;
3572 }
3573 
3574 /*
3575  *  Find index of spot where an object is readied.
3576  *
3577  *  Output: Index, or -1 if not found.
3578  */
3579 
find_readied(Game_object * obj)3580 int Actor::find_readied(
3581     Game_object *obj
3582 ) {
3583 	for (size_t i = 0; i < array_size(spots); i++)
3584 		if (spots[i] == obj)
3585 			return i;
3586 	return -1;
3587 }
3588 
3589 /*
3590  *  Get object readied at given slot index.
3591  *
3592  *  Output: Object pointer, or null if invalid slot ID given.
3593  */
3594 
get_readied(int index) const3595 Game_object *Actor::get_readied(int index) const {
3596 	return index >= 0 &&
3597 	       index < static_cast<int>(array_size(spots)) ?
3598 	       spots[index] : nullptr;
3599 }
3600 
3601 /*
3602  *  Change shape of a member.
3603  */
3604 
change_member_shape(Game_object * obj,int newshape)3605 void Actor::change_member_shape(
3606     Game_object *obj,
3607     int newshape
3608 ) {
3609 	Container_game_object::change_member_shape(obj, newshape);
3610 	refigure_gear();
3611 }
3612 
3613 /*
3614  *  Step aside to a free tile, or try to swap places.
3615  *
3616  *  Output: true if successful, else false.
3617  */
3618 
move_aside(Actor * for_actor,int dir)3619 bool Actor::move_aside(
3620     Actor *for_actor,       // Moving aside for this one.
3621     int dir             // Direction to avoid (0-7).
3622 ) {
3623 	// ++++ FIXME: Ugly workaround: preventing stepping aside in combat
3624 	// also prevents some cases of double-moving aside that result in
3625 	// walking through walls or doors.
3626 	// Also, don't move if the other actor is moving, as this may break
3627 	// pathfinding.
3628 	if (get_schedule_type() == Schedule::combat || get_frame_time())
3629 		return false;
3630 	// Do not move aside if sitting, bending over, kneeling or sleeping.
3631 	int frnum = get_framenum() & 0xf;
3632 	if (frnum >= sit_frame && frnum <= sleep_frame)
3633 		return false;
3634 
3635 	Tile_coord cur = get_tile();
3636 	Tile_coord to(-1, -1, -1);
3637 	int d = 8;
3638 	// Try orthogonal directions first.
3639 	to = cur.get_neighbor((dir + 2) % 8);
3640 	if (!is_blocked(to, nullptr, get_type_flags()))
3641 		d = (dir + 2) % 8;
3642 	else {
3643 		to = cur.get_neighbor((dir + 6) % 8);
3644 		if (!is_blocked(to, nullptr, get_type_flags()))
3645 			d = (dir + 6) % 8;
3646 		else {
3647 			for (int i = 0; i < 4; i++) {   // Try diagonals now.
3648 				to = cur.get_neighbor(2 * i + 1);
3649 				if (!is_blocked(to, nullptr, get_type_flags())) {
3650 					d = 2 * i + 1;
3651 					break;
3652 				}
3653 			}
3654 		}
3655 	}
3656 
3657 	int stepdir = d;        // This is the direction.
3658 	if (d == 8 || to.tx < 0)    // Failed?  Try to swap places.
3659 		return swap_positions(for_actor);
3660 	// Step, and face direction.
3661 	step(to, get_dir_framenum(stepdir, static_cast<int>(Actor::standing)));
3662 	Tile_coord newpos = get_tile();
3663 	return newpos.tx == to.tx && newpos.ty == to.ty;
3664 }
3665 
3666 /*
3667  *  Get frame if rotated 1, 2, or 3 quadrants clockwise.
3668  */
3669 
get_rotated_frame(int quads) const3670 int Actor::get_rotated_frame(
3671     int quads           // 1=90, 2=180, 3=270.
3672 ) const {
3673 	int curframe = get_framenum();
3674 	// Bit 4=rotate180, 5=rotate-90.
3675 	int curdir = (4 + 2 * ((curframe >> 4) & 1) - ((curframe >> 5) & 1)) % 4;
3676 	int newdir = (curdir + quads) % 4;
3677 	// Convert to 8-value dir & get frame.
3678 	return get_dir_framenum(2 * newdir, curframe);
3679 }
3680 
3681 /*
3682  *  Get total value of armor being worn.
3683  */
3684 
get_armor_points() const3685 int Actor::get_armor_points(
3686 ) const {
3687 	int points = 0;
3688 	static Ready_type_Exult aspots[] = {head, amulet, torso, cloak, belt,
3689 	                                        lhand, rhand, lfinger, rfinger, legs, feet, earrings,
3690 	                                        gloves
3691 	                                        };
3692 	for (auto aspot : aspots) {
3693 		Game_object *armor = spots[static_cast<int>(aspot)];
3694 		if (armor)
3695 			points += armor->get_info().get_armor();
3696 	}
3697 	return points;
3698 }
3699 
3700 /*
3701  *  Get whether or not the actor is immune or vulnerable to a form of damage.
3702  *
3703  *  Input is damage_type for a weapon.
3704  *
3705  *  Returns 1 if the actor is immune, -1 if vulnerable or 0 otherwise.
3706  */
3707 
is_immune(int type) const3708 int Actor::is_immune(
3709     int type
3710 ) const {
3711 	if (gear_immunities & (1 << type))
3712 		return 1;
3713 	const Monster_info *minf = get_info().get_monster_info();
3714 	if (minf && minf->get_immune() & (1 << type))
3715 		return 1;
3716 	if (minf && minf->get_vulnerable() & (1 << type))
3717 		return -1;
3718 	else
3719 		return 0;
3720 }
3721 
is_goblin() const3722 bool Actor::is_goblin() const {
3723 	return get_info().is_goblin();
3724 }
3725 
can_see_invisible() const3726 bool Actor::can_see_invisible() const {
3727 	const Monster_info *minf = get_info().get_monster_info_safe();
3728 	return (minf->get_flags() & (1 << Monster_info::see_invisible)) != 0;
3729 }
3730 
can_speak() const3731 bool Actor::can_speak() const {
3732 	const Monster_info *minf = get_info().get_monster_info();
3733 	// TODO: Check for SI monks that don't speak (vows of silence, deafness).
3734 	return !minf || !minf->cant_yell();
3735 }
3736 
is_sentient() const3737 bool Actor::is_sentient() const {
3738 	// Try based on average monster intelligence (prevents some random animals
3739 	// from opening doors or assisting in battle).
3740 	const Monster_info *minf = get_info().get_monster_info_safe();
3741 	return minf->get_intelligence() >= 6;
3742 }
3743 
3744 /*
3745  *  Get weapon value.
3746  */
3747 
get_weapon(int & points,int & shape,Game_object * & obj) const3748 const Weapon_info *Actor::get_weapon(
3749     int &points,
3750     int &shape,
3751     Game_object  *&obj      // ->weapon itself returned, or nullptr.
3752 ) const {
3753 	points = 1;         // Bare hands = 1.
3754 	shape = -1;         // Bare hands.
3755 	const Weapon_info *winf = nullptr;
3756 	Game_object *weapon = spots[static_cast<int>(lhand)];
3757 	obj = weapon;
3758 	if (weapon) {
3759 		if ((winf = weapon->get_info().get_weapon_info()) != nullptr) {
3760 			points = winf->get_damage();
3761 			shape = weapon->get_shapenum();
3762 			return winf;
3763 		}
3764 	}
3765 	return winf;
3766 }
3767 
3768 /*
3769  *  Roll a 25-sided die to determine a win-lose outcome, adding a
3770  *  bias for the attacker and for the defender.
3771  */
3772 
roll_to_win(int attacker,int defender)3773 bool Actor::roll_to_win(
3774     int attacker,           // Points added.
3775     int defender            // Points subtracted.
3776 ) {
3777 	const int sides = 30;
3778 	int roll = rand() % sides;
3779 	if (roll == 0)          // Always lose.
3780 		return false;
3781 	else if (roll == sides - 1) // High?  Always win.
3782 		return true;
3783 	else
3784 		return roll + attacker - defender >= sides / 2 - 1;
3785 }
3786 
3787 /*
3788  *  Get effective property, or default value.
3789  */
3790 
Get_effective_prop(Actor * npc,Actor::Item_properties prop,int defval=0)3791 inline int Get_effective_prop(
3792     Actor *npc,         // ...or nullptr.
3793     Actor::Item_properties prop,    // Property #.
3794     int defval = 0          // Default val if npc==0.
3795 ) {
3796 	return npc ? npc->get_effective_prop(prop) : defval;
3797 }
3798 
3799 /*
3800  *  Figure hit points lost from an attack, and subtract from total.
3801  *
3802  *  Output: Hits taken or < 0 for explosion.
3803  */
3804 
figure_hit_points(Game_object * attacker,int weapon_shape,int ammo_shape,bool explosion)3805 int Actor::figure_hit_points(
3806     Game_object *attacker,
3807     int weapon_shape,       // < 0 for readied weapon.
3808     int ammo_shape,         // < 0 for no ammo shape.
3809     bool explosion          // If this is an explosion attacking.
3810 ) {
3811 	bool were_party = party_id != -1 || npc_num == 0;
3812 	// godmode effects:
3813 	if (were_party && cheat.in_god_mode())
3814 		return 0;
3815 	Actor *npc = attacker ? attacker->as_actor() : nullptr;
3816 	bool theyre_party = npc &&
3817 	                    (npc->party_id != -1 || npc->npc_num == 0);
3818 	bool instant_death = (cheat.in_god_mode() && theyre_party);
3819 	// Modify using combat difficulty.
3820 	int bias = were_party ? Combat::difficulty :
3821 	           (theyre_party ? -Combat::difficulty : 0);
3822 
3823 	const Weapon_info *winf;
3824 	const Ammo_info *ainf;
3825 
3826 	int wpoints = 0;
3827 	if (weapon_shape >= 0)
3828 		winf = ShapeID::get_info(weapon_shape).get_weapon_info();
3829 	else
3830 		winf = nullptr;
3831 	if (ammo_shape >= 0)
3832 		ainf = ShapeID::get_info(ammo_shape).get_ammo_info();
3833 	else
3834 		ainf = nullptr;
3835 	if (!winf && weapon_shape < 0)
3836 		winf = npc ? npc->get_weapon(wpoints) : nullptr;
3837 
3838 	int usefun = -1;
3839 	int powers = 0;
3840 	int type = Weapon_data::normal_damage;
3841 	bool explodes = false;
3842 
3843 	if (winf) {
3844 		wpoints = winf->get_damage();
3845 		usefun = winf->get_usecode();
3846 		type = winf->get_damage_type();
3847 		powers = winf->get_powers();
3848 		explodes = winf->explodes();
3849 	} else
3850 		wpoints = 1;    // Give at least one, but only if there's no weapon
3851 	if (ainf) {
3852 		wpoints += ainf->get_damage();
3853 		// Replace damage type.
3854 		if (ainf->get_damage_type() != Weapon_data::normal_damage)
3855 			type = ainf->get_damage_type();
3856 		powers |= ainf->get_powers();
3857 		explodes = explodes || ainf->explodes();
3858 	}
3859 
3860 	if (explodes && !explosion) { // Explosions shouldn't explode again.
3861 		// Time to explode.
3862 		Tile_coord offset(0, 0, get_info().get_3d_height() / 2);
3863 		eman->add_effect(std::make_unique<Explosion_effect>(get_tile() + offset,
3864 		                                      nullptr, 0, weapon_shape, ammo_shape, attacker));
3865 		// The explosion will handle the damage.
3866 		return -1;
3867 	}
3868 
3869 	int expval = 0;
3870 	int hits = 0;
3871 	bool nodamage = (powers & (Weapon_data::no_damage)) != 0;
3872 	if (wpoints && instant_death)
3873 		wpoints = 127;
3874 	if (wpoints && !nodamage)
3875 		// This may kill the NPC; this comes before powers because no
3876 		// damage means no powers -- except for the no_damage flag.
3877 		hits = apply_damage(attacker, Get_effective_prop(npc, Actor::strength, 0),
3878 		                    wpoints, type, bias, &expval);
3879 	// Apply weapon powers if needed.
3880 	// wpoints == 0 ==> some spells that don't hurt (but need to apply powers).
3881 	if (powers && (hits || !wpoints || nodamage)) {
3882 		// Protection prevents powers.
3883 		if (!get_flag(Obj_flags::protection)) {
3884 			int attint = Get_effective_prop(npc, Actor::intelligence, 16);
3885 			int defstr = Get_effective_prop(this, Actor::strength);
3886 			int defint = Get_effective_prop(this, Actor::intelligence);
3887 
3888 			// These rolls are bourne from statistical analisys and are,
3889 			// as far as I can tell, how the game works.
3890 			if ((powers & Weapon_data::poison) && roll_to_win(attint, defstr))
3891 				set_flag(Obj_flags::poisoned);
3892 			if ((powers & Weapon_data::curse) && roll_to_win(attint, defint))
3893 				set_flag(Obj_flags::cursed);
3894 			if ((powers & Weapon_data::charm) && roll_to_win(attint, defint)) {
3895 				set_flag(Obj_flags::charmed);
3896 				if (npc)
3897 					charmalign = npc->get_effective_alignment();
3898 				else
3899 					charmalign = chaotic;   // Verified.
3900 				set_charmed_combat();
3901 			}
3902 			if ((powers & Weapon_data::sleep) && roll_to_win(attint, defint))
3903 				set_flag(Obj_flags::asleep);
3904 			if ((powers & Weapon_data::paralyze) && roll_to_win(attint, defstr))
3905 				set_flag(Obj_flags::paralyzed);
3906 			if (powers & Weapon_data::magebane) {
3907 				// Magebane weapons (magebane sword, death scythe).
3908 				// Take away all mana.
3909 				set_property(static_cast<int>(Actor::mana), 0);
3910 				int num_spells = 0;
3911 				Game_object_vector vec;
3912 				Game_object_vector spells;
3913 				vec.reserve(50);
3914 				spells.reserve(50);
3915 				get_objects(vec, c_any_shapenum, c_any_qual, c_any_framenum);
3916 				// Gather all spells...
3917 				for (auto *obj : vec)
3918 					if (obj->get_info().is_spell())   // Seems to be right.
3919 						spells.push_back(obj);
3920 				vec.clear();
3921 				// ... and take them all away.
3922 				while (!spells.empty()) {
3923 					++num_spells;
3924 					Game_object *obj = spells.back();
3925 					spells.pop_back();
3926 					obj->remove_this();
3927 				}
3928 				if (num_spells) {
3929 					// Display magebane struck string and set
3930 					// no_spell_casting flag. This is only done
3931 					// to prevent monsters from teleporting or
3932 					// doing other such things.
3933 					set_flag(Obj_flags::no_spell_casting);
3934 					if(can_speak()) {
3935 						eman->remove_text_effect(this);
3936 						say(first_magebane_struck, last_magebane_struck);
3937 					}
3938 					// Tell schedule we need a new weapon.
3939 					if (schedule && spots[lhand] == nullptr)
3940 						schedule->set_weapon();
3941 				}
3942 			}
3943 		}
3944 		if (nodamage && ammo_shape == 568) {
3945 			// This is *only* done for SI sleep arrows, and all other
3946 			// powers have had their effect by now (as can be verified
3947 			// by using the called usecode function).
3948 			if (npc)    // Just to be sure.
3949 				set_oppressor(npc->get_npc_num());
3950 			// Allowing for BG too, as it doesn't have a function 0x7e1.
3951 			ucmachine->call_usecode(SleepArrowsUsecode, this,
3952 			                        Usecode_machine::weapon);
3953 		}
3954 	}
3955 
3956 	if (expval > 0 && npc)  // Give experience.
3957 		npc->set_property(static_cast<int>(exp),
3958 		                  npc->get_property(static_cast<int>(exp)) + expval);
3959 
3960 	// Weapon usecode comes last of all.
3961 	if (usefun > 0) {
3962 		if (npc)    // Just to be sure.
3963 			set_oppressor(npc->get_npc_num());
3964 		ucmachine->call_usecode(usefun, this,
3965 		                        Usecode_machine::weapon);
3966 	}
3967 	return hits;
3968 }
3969 
3970 /*
3971  *  Trying to hit NPC with an attack.
3972  *
3973  *  Output: true if attack hit, false otherwise.
3974  */
3975 
try_to_hit(Game_object * attacker,int attval)3976 bool Actor::try_to_hit(
3977     Game_object *attacker,
3978     int attval
3979 ) {
3980 	int defval = get_effective_prop(static_cast<int>(combat)) +
3981 	             (get_flag(Obj_flags::protection) ? 3 : 0);
3982 	if (combat_trace) {
3983 		string name = "<trap>";
3984 		if (attacker)
3985 			name = attacker->get_name();
3986 		int prob = 30 - (15 + defval - attval) + 1;
3987 		if (prob >= 30)
3988 			prob = 29;  // 1 always misses.
3989 		else if (prob <= 1)
3990 			prob = 1;   // 30 always hits.
3991 		prob *= 100;
3992 		cout << name << " is attacking " << get_name()
3993 		     << " with hit probability " << static_cast<float>(prob) / 30 << "%" << endl;
3994 	}
3995 
3996 	return Actor::roll_to_win(attval, defval);
3997 }
3998 
3999 /*
4000  *  Being attacked.
4001  *
4002  *  Output: 0 if defeated, else object itself.
4003  */
4004 
attacked(Game_object * attacker,int weapon_shape,int ammo_shape,bool explosion)4005 Game_object *Actor::attacked(
4006     Game_object *attacker,
4007     int weapon_shape,       // < 0 for readied weapon.
4008     int ammo_shape,         // < 0 for no ammo shape.
4009     bool explosion          // If this is an explosion attacking.
4010 ) {
4011 	if (is_dead() ||        // Already dead?
4012 	        // Or party member of dead Avatar?
4013 	        (party_id >= 0 && gwin->get_main_actor()->is_dead()))
4014 		return nullptr;
4015 	Actor *npc = attacker ? attacker->as_actor() : nullptr;
4016 	if (npc)
4017 		set_oppressor(npc->get_npc_num());
4018 	if (npc && npc->get_schedule_type() == Schedule::duel)
4019 		return this;    // Just play-fighting.
4020 
4021 	int oldhp = properties[static_cast<int>(health)];
4022 	int delta = figure_hit_points(attacker, weapon_shape, ammo_shape, explosion);
4023 
4024 	if (Combat::show_hits && !is_dead() && delta >= 0) {
4025 		eman->remove_text_effect(this);
4026 		char hpmsg[50];
4027 		sprintf(hpmsg, "-%d(%d)", delta, oldhp - delta);
4028 		eman->add_text(hpmsg, this);
4029 	}
4030 	if (combat_trace) {
4031 		string name = "<trap>";
4032 		if (attacker)
4033 			name = attacker->get_name();
4034 		cout << name << " hits " << get_name();
4035 		if (delta > 0) {
4036 			cout << " for " << delta << " hit points; ";
4037 			if (oldhp > 0 && oldhp < delta)
4038 				cout << get_name() << " is defeated." << endl;
4039 			else
4040 				cout << oldhp - delta << " hit points are left." << endl;
4041 		} else if (!delta)
4042 			cout << " to no damage." << endl;
4043 		else
4044 			cout << " causing an explosion." << endl;
4045 	}
4046 
4047 	if (attacker && (is_dead() || properties[static_cast<int>(health)] < 0))
4048 		return nullptr;
4049 	return this;
4050 }
4051 
4052 /*
4053  *  There's probably a smarter way to do this, but this routine checks
4054  *  for the dragon Draco.
4055  */
4056 
Is_draco(Actor * dragon)4057 static bool Is_draco(
4058     Actor *dragon
4059 ) {
4060 	Game_object_vector vec;     // Gets list.
4061 	// Should have a special scroll.
4062 	int cnt = dragon->get_objects(vec, 797, 241, 4);
4063 	return cnt > 0;
4064 }
4065 
4066 /*
4067  *  We're dead.  We're removed from the world, but not deleted.
4068  */
4069 
die(Game_object * attacker)4070 void Actor::die(
4071     Game_object *attacker
4072 ) {
4073 	// If the actor is already dead, we shouldn't do anything
4074 	//(fixes a resurrection bug).
4075 	if (is_dead())
4076 		return;
4077 	set_action(nullptr);
4078 	delete schedule;
4079 	schedule = nullptr;
4080 	gwin->get_tqueue()->remove(this);// Remove from time queue.
4081 	Actor::set_flag(Obj_flags::dead);// IMPORTANT:  Set this before moving
4082 	//   objs. so Usecode(eventid=6) isn't called.
4083 	int shnum = get_shapenum();
4084 	// Special case:  Hook, Dracothraxus.
4085 	if (((shnum == 0x1fa || (shnum == 0x1f8 && Is_draco(this))) &&
4086 	        Game::get_game_type() == BLACK_GATE)) {
4087 		// Exec. usecode before dying.
4088 		ucmachine->call_usecode(ucmachine->get_shape_fun(shnum), this,
4089 		                        Usecode_machine::internal_exec);
4090 		if (is_pos_invalid())   // Invalid now?
4091 			return;
4092 	}
4093 	// Get location.
4094 	Tile_coord pos = get_tile();
4095 	//properties[static_cast<int>(health)] = -50;
4096 	const Shape_info &info = get_info();
4097 	const Monster_info *minfo = info.get_monster_info();
4098 	bool frost_serp = GAME_SI && get_shapenum() == 832;
4099 	if ((frost_serp && (get_framenum() & 0xf) == Actor::sit_frame)
4100 	        || (get_framenum() & 0xf) == Actor::sleep_frame) {
4101 		auto *scr = new Usecode_script(this);
4102 		(*scr) << Ucscript::delay_ticks << 4 << Ucscript::remove;
4103 		scr->start();
4104 	} else  // Laying down to die.
4105 		lay_down(true);
4106 
4107 	std::shared_ptr<Dead_body> body_keep;
4108 	Dead_body *body;        // See if we need a body.
4109 	if (info.has_body_info() && (!minfo || !minfo->has_no_body())) {
4110 		// Get body shape/frame.
4111 		shnum = info.get_body_shape();      // Default 400.
4112 		int frnum = info.get_body_frame();  // Default 3.
4113 		// Reflect if NPC reflected.
4114 		frnum |= (get_framenum() & 32);
4115 		body_keep = std::make_shared<Dead_body>(shnum, frnum, 0, 0, 0,
4116 		                     npc_num > 0 ? npc_num : -1);
4117 		body = body_keep.get();
4118 		Shape_frame *shp;
4119 		bool have_body_shape = (shp = body->get_shape()) != nullptr && shp->is_empty();
4120 		if (have_body_shape) {
4121 			// Note: only do this if target shape is an actual
4122 			// body shape (frame 0 empty).
4123 			auto *scr = new Usecode_script(body);
4124 			(*scr) << Ucscript::delay_ticks << 4 << Ucscript::frame << frnum;
4125 			scr->start();
4126 		}
4127 		if (npc_num > 0) {
4128 			// Originals would use body->set_quality(2) instead
4129 			// for bodies of dead monsters. What we must do for
4130 			// backwards compatibility...
4131 			body->set_quality(1);   // Flag for dead body of NPC.
4132 			gwin->set_body(npc_num, body);
4133 		}
4134 		// Tmp. monster => tmp. body.
4135 		if (get_flag(Obj_flags::is_temporary))
4136 			body->set_flag(Obj_flags::is_temporary);
4137 		// Remove NPC from map to prevent the body
4138 		// from colliding with it.
4139 		Game_object_shared keep_this;
4140 		Game_object::remove_this(&keep_this);
4141 		const Shape_info &binf = body->get_info();
4142 		int dx = binf.get_3d_xtiles(frnum) - info.get_3d_xtiles(get_framenum());
4143 		int dy = binf.get_3d_ytiles(frnum) - info.get_3d_ytiles(get_framenum());
4144 		Tile_coord bp;
4145 		// First, try matching corners of the NPC with corners of the body.
4146 		bp = Map_chunk::find_spot(pos + Tile_coord(0,  0, 0), 0, shnum, frnum, 0);
4147 		if (bp.tx == -1)
4148 			bp = Map_chunk::find_spot(pos + Tile_coord(dx,  0, 0), 0, shnum, frnum, 0);
4149 		if (bp.tx == -1)
4150 			bp = Map_chunk::find_spot(pos + Tile_coord(0, dy, 0), 0, shnum, frnum, 0);
4151 		if (bp.tx == -1)
4152 			bp = Map_chunk::find_spot(pos + Tile_coord(dx, dy, 0), 0, shnum, frnum, 0);
4153 		// If still no spot, force to NPC pos, even if blocked.
4154 		if (bp.tx == -1)
4155 			bp = pos;
4156 		// Add NPC back.
4157 		Game_object::move(pos);
4158 		body->move(bp);
4159 		if (have_body_shape) {
4160 			body->change_frame(0); // Make body invisible
4161 		}
4162 	} else
4163 		body = nullptr;
4164 	Game_object *item;      // Move/remove all the items.
4165 	Game_object_shared_vector tooheavy;    // Some shouldn't be moved.
4166 	while ((item = objects.get_first()) != nullptr) {
4167 	    Game_object_shared item_keep = shared_from_obj(item);
4168 		remove(item);
4169 		item->set_invalid();
4170 		if (item->get_info().is_spell())
4171 		{
4172 			tooheavy.push_back(item_keep);
4173 			continue;
4174 		}
4175 		if (body) {
4176 		    item->set_shape_pos(255, 255);	// So it gets placed.
4177 			body->add(item, true);// Always succeed at adding.
4178 		} else {          // No body?  Drop on ground.
4179 			item->set_flag_recursively(Obj_flags::okay_to_take);
4180 			Tile_coord pos2 = Map_chunk::find_spot(pos, 5,
4181 			                                       item->get_shapenum(), item->get_framenum(), 1);
4182 			if (pos.tx != -1)
4183 				item->move(pos2);
4184 			else        // No room anywhere.
4185 				tooheavy.push_back(item_keep);
4186 		}
4187 	}
4188 	if (body)           // Okay to take its contents.
4189 		body->set_flag_recursively(Obj_flags::okay_to_take);
4190 
4191 	// Put the heavy ones back.
4192 	for (auto &it : tooheavy)
4193 		add(it.get(), true);
4194 	if (body)
4195 		gwin->add_dirty(body);
4196 	add_dirty();            // Want to repaint area.
4197 	delete_contents();      // remove what's left of inventory
4198 	Actor *npc = attacker ? attacker->as_actor() : nullptr;
4199 	if (npc) {
4200 		// Set oppressor and cause nearby NPCs to attack attacker.
4201 		fight_back(attacker);
4202 		set_target(nullptr, false);
4203 		set_schedule_type(Schedule::wander);
4204 
4205 		// Is this a bad guy?
4206 		// Party defeated an evil monster?
4207 		if (npc->is_in_party() && !is_in_party() && alignment >= evil)
4208 			Combat_schedule::monster_died();
4209 	}
4210 	// TODO: De-hard-code this.
4211 	if (GAME_BG && is_in_party() && !Audio::get_ptr()->is_voice_playing()
4212 		&& (rand() % 4) == 0) {
4213 		Audio::get_ptr()->start_speech(22);
4214 	}
4215 	// Move party member to 'dead' list.
4216 	partyman->update_party_status(this);
4217 }
4218 
4219 /*
4220  *  Create another monster of the same type as this, and adjacent.
4221  *
4222  *  Output: ->monster, or nullptr if failed.
4223  */
4224 
clone()4225 Game_object_shared Actor::clone(
4226 ) {
4227 	const Shape_info &info = get_info();
4228 	// Base distance on greater dim.
4229 	int frame = get_framenum();
4230 	int xs = info.get_3d_xtiles(frame);
4231 	int ys = info.get_3d_ytiles(frame);
4232 	// Find spot.
4233 	Tile_coord pos = Map_chunk::find_spot(get_tile(),
4234 	                                      xs > ys ? xs : ys, get_shapenum(), 0, 1);
4235 	if (pos.tx < 0)
4236 		return nullptr;       // Failed.
4237 	// Create, temporary & with equip.
4238 	Game_object_shared monst = Monster_actor::create(
4239 	                           get_shapenum(), pos, get_schedule_type(),
4240 	                           get_effective_alignment(), true, true);
4241 	return monst;
4242 }
4243 
4244 /*
4245  *  Restore HP's on the hour.
4246  */
4247 
mend_wounds(bool mendmana)4248 void Actor::mend_wounds(
4249     bool mendmana
4250 ) {
4251 	int hp = properties[static_cast<int>(health)];
4252 	bool starving = (get_property(static_cast<int>(food_level)) <= 9
4253 	                 && is_in_party() && !get_info().does_not_eat());
4254 	// It should be okay to leave is_cold_immune out.
4255 	// It blocks raising temperature in the first place.
4256 	bool freezing = (is_in_party() && temperature >= 50 &&
4257 	                 !(gear_powers & Frame_flags::cold_immune));
4258 	if (is_dead() || get_flag(Obj_flags::poisoned) || (starving && hp > 0) ||
4259 	        freezing)
4260 		return;
4261 	int maxhp = properties[static_cast<int>(strength)];
4262 	if (maxhp > 0 && hp < maxhp) {
4263 		// first case doesn't seem to be used in the original - will keep for npcs
4264 		if (maxhp >= 3 && !starving && get_schedule_type() == Schedule::sleep)
4265 			hp += 1 + rand() % (maxhp / 3);
4266 		else
4267 			hp += 1;
4268 		if (hp > maxhp)
4269 			hp = maxhp;
4270 		properties[static_cast<int>(health)] = hp;
4271 	}
4272 
4273 	if (!mendmana)
4274 		return;
4275 	// Restore some mana also.
4276 	int maxmana = properties[static_cast<int>(magic)];
4277 	int curmana = properties[static_cast<int>(mana)];
4278 	clear_flag(Obj_flags::no_spell_casting);
4279 
4280 	if (maxmana > 0 && curmana < maxmana) {
4281 		if (maxmana >= 3)
4282 			curmana += 1 + rand() % (maxmana / 3);
4283 		else
4284 			curmana += 1;
4285 		properties[static_cast<int>(mana)] = curmana <= maxmana ? curmana
4286 		                                     : maxmana;
4287 	}
4288 }
4289 
4290 /*
4291  *  Restore from body.  It must not be owned by anyone.
4292  *
4293  *  Output: ->actor if successful, else nullptr.
4294  */
4295 
resurrect(Dead_body * body)4296 Actor *Actor::resurrect(
4297     Dead_body *body         // Must be this actor's body.
4298 ) {
4299 	Tile_coord pos;
4300 	if (body) {
4301 		if (body->get_owner() ||    // Must be on ground.
4302 		        npc_num <= 0 || gwin->get_body(npc_num) != body)
4303 			return nullptr;
4304 		gwin->set_body(npc_num, nullptr); // Clear from gwin's list.
4305 		Game_object *item;      // Get back all the items.
4306 		while ((item = body->get_objects().get_first()) != nullptr) {
4307 		    Game_object_shared keep = item->shared_from_this();
4308 			body->remove(item);
4309 			add(item, true);       // Always succeed at adding.
4310 		}
4311 		gwin->add_dirty(body);      // Need to repaint here.
4312 		pos = body->get_tile();
4313 		body->remove_this();        // Remove and delete body.
4314 	} else
4315 		pos = Tile_coord(-1, -1, 0);
4316 	move(pos);          // Move back to life.
4317 	// Restore health to max.
4318 	properties[static_cast<int>(health)] =
4319 	    properties[static_cast<int>(strength)];
4320 	Actor::clear_flag(Obj_flags::dead);
4321 	Actor::clear_flag(Obj_flags::poisoned);
4322 	Actor::clear_flag(Obj_flags::paralyzed);
4323 	Actor::clear_flag(Obj_flags::asleep);
4324 	Actor::clear_flag(Obj_flags::protection);
4325 	Actor::clear_flag(Obj_flags::cursed);
4326 	Actor::clear_flag(Obj_flags::charmed);
4327 	// Restore to party if possible.
4328 	partyman->update_party_status(this);
4329 	// Give a reasonable schedule.
4330 	set_schedule_type(is_in_party() ? Schedule::follow_avatar
4331 	                  : Schedule::loiter);
4332 	// Stand up.
4333 	if (!body)
4334 		return this;
4335 	auto *scr = new Usecode_script(this);
4336 	(*scr) << (Ucscript::npc_frame + Actor::sleep_frame)
4337 	       << (Ucscript::npc_frame + Actor::kneel_frame)
4338 	       << (Ucscript::npc_frame + Actor::standing);
4339 	scr->start(1);
4340 	return this;
4341 }
4342 
4343 /*
4344  *  Check to see if an actor taking a step is really blocked.
4345  */
4346 
is_really_blocked(Tile_coord & t,bool force)4347 bool Actor::is_really_blocked(
4348     Tile_coord &t,
4349     bool force
4350 ) {
4351 	if (abs(t.tz - get_tile().tz) > 1)
4352 		return true;
4353 	Game_object *block = find_blocking(t, get_direction(t));
4354 	if (!block)
4355 		return true;        // IE, water.
4356 	if (block == this)
4357 		return false;
4358 	// Try to get blocker to move aside.
4359 	if (block->move_aside(this, get_direction(block)))
4360 		return false;
4361 	// (May have swapped places.)  If okay, try one last time.
4362 	return t != get_tile() && is_blocked(t, nullptr, force ? MOVE_ALL : 0);
4363 }
4364 
4365 /*
4366  *  Handle a time event (for animation).
4367  */
4368 
handle_event(unsigned long curtime,uintptr udata)4369 void Main_actor::handle_event(
4370     unsigned long curtime,      // Current time of day.
4371     uintptr udata          // Ignored.
4372 ) {
4373 	purge_deleted_actions();
4374 	if (action) {       // Doing anything?
4375 		// Do what we should.
4376 		int speed = action->get_speed();
4377 		int delay = action->handle_event(this);
4378 		if (!delay) {
4379 			// Action finished.
4380 			// This makes for a smoother scrolling and prevents the
4381 			// avatar from skipping a step when walking.
4382 			frame_time = speed;
4383 			if (!frame_time)    // Not a path. Add a delay anyway.
4384 				frame_time = gwin->get_std_delay();
4385 			delay = frame_time;
4386 			set_action(nullptr);
4387 		}
4388 
4389 		gwin->get_tqueue()->add(
4390 		    curtime + delay, this, udata);
4391 	} else if (in_usecode_control() || get_flag(Obj_flags::paralyzed)) {
4392 		frame_time = 0;
4393 		// Keep trying if we are in usecode control.
4394 		gwin->get_tqueue()->add(
4395 		    curtime + gwin->get_std_delay(), this, udata);
4396 	} else if (schedule) {
4397 		frame_time = 0;
4398 		schedule->now_what();
4399 	}
4400 }
4401 
4402 /*
4403  *  Get the party to follow.
4404  */
4405 
get_followers() const4406 void Main_actor::get_followers(
4407 ) const {
4408 	int cnt = partyman->get_count();
4409 	for (int i = 0; i < cnt; i++) {
4410 		Actor *npc = gwin->get_npc(partyman->get_member(i));
4411 		if (!npc || npc->get_flag(Obj_flags::asleep) ||
4412 		        npc->is_dead())
4413 			continue;
4414 		int sched = npc->get_schedule_type();
4415 		// Skip if in combat or set to 'wait'.
4416 		if (sched != Schedule::combat &&
4417 		        sched != Schedule::wait &&
4418 		        // Loiter added for SI.
4419 		        sched != Schedule::loiter) {
4420 			if (sched != Schedule::follow_avatar)
4421 				npc->set_schedule_type(
4422 				    Schedule::follow_avatar);
4423 			else
4424 				npc->follow(this);
4425 		}
4426 	}
4427 }
4428 
4429 /*
4430  *  Step onto an adjacent tile.
4431  *
4432  *  Output: false if blocked.
4433  */
4434 
step(Tile_coord t,int frame,bool force)4435 bool Main_actor::step(
4436     Tile_coord t,           // Tile to step onto.
4437     int frame,          // New frame #.
4438     bool force
4439 ) {
4440 	rest_time = 0;          // Reset counter.
4441 	t.fixme();
4442 	// Get chunk.
4443 	int cx = t.tx / c_tiles_per_chunk;
4444 	int cy = t.ty / c_tiles_per_chunk;
4445 	// Get rel. tile coords.
4446 	int tx = t.tx % c_tiles_per_chunk;
4447 	int ty = t.ty % c_tiles_per_chunk;
4448 	Map_chunk *nlist = gmap->get_chunk(cx, cy);
4449 	bool water;
4450 	bool poison;      // Get tile info.
4451 	get_tile_info(this, gwin, nlist, tx, ty, water, poison);
4452 	if (is_blocked(t, nullptr, force ? MOVE_ALL : 0)) {
4453 		if (is_really_blocked(t, force)) {
4454 			if (schedule)       // Tell scheduler.
4455 				schedule->set_blocked(t);
4456 			stop();
4457 			return false;
4458 		}
4459 	}
4460 	if (poison && t.tz == 0)
4461 		Actor::set_flag(static_cast<int>(Obj_flags::poisoned));
4462 	// Check for scrolling.
4463 	gwin->scroll_if_needed(this, t);
4464 	add_dirty();            // Set to update old location.
4465 	// Get old chunk, old tile.
4466 	Map_chunk *olist = get_chunk();
4467 	Tile_coord oldtile = get_tile();
4468 	// Move it.
4469 	Actor::movef(olist, nlist, tx, ty, frame, t.tz);
4470 	add_dirty(true);           // Set to update new.
4471 	// In a new chunk?
4472 	if (olist != nlist)
4473 		Main_actor::switched_chunks(olist, nlist);
4474 	int roof_height = nlist->is_roof(tx, ty, t.tz);
4475 	gwin->set_ice_dungeon(nlist->is_ice_dungeon(tx, ty));
4476 	if (gwin->set_above_main_actor(roof_height)) {
4477 		gwin->set_in_dungeon(nlist->has_dungeon() ?
4478 		                     nlist->is_dungeon(tx, ty) : 0);
4479 		gwin->set_all_dirty();
4480 	} else if (roof_height < 31 && gwin->set_in_dungeon(nlist->has_dungeon() ?
4481 	           nlist->is_dungeon(tx, ty) : 0))
4482 		gwin->set_all_dirty();
4483 	// Near an egg?  (Do this last, since
4484 	//   it may teleport.)
4485 	nlist->activate_eggs(this, t.tx, t.ty, t.tz,
4486 	                     oldtile.tx, oldtile.ty);
4487 	quake_on_walk();
4488 	return true;
4489 }
4490 
4491 /*
4492  *  Setup cache after a change in chunks.
4493  */
4494 
switched_chunks(Map_chunk * olist,Map_chunk * nlist)4495 void Main_actor::switched_chunks(
4496     Map_chunk *olist,   // Old chunk, or null.
4497     Map_chunk *nlist    // New chunk.
4498 ) {
4499 	int newcx = nlist->get_cx();
4500 	int newcy = nlist->get_cy();
4501 	int xfrom;
4502 	int xto;
4503 	int yfrom;
4504 	int yto; // Get range of chunks.
4505 	if (!olist ||           // No old, or new map?  Use all 9.
4506 	        olist->get_map() != nlist->get_map()) {
4507 		xfrom = newcx > 0 ? newcx - 1 : newcx;
4508 		xto = newcx < c_num_chunks - 1 ? newcx + 1 : newcx;
4509 		yfrom = newcy > 0 ? newcy - 1 : newcy;
4510 		yto = newcy < c_num_chunks - 1 ? newcy + 1 : newcy;
4511 	} else {
4512 		int oldcx = olist->get_cx();
4513 		int oldcy = olist->get_cy();
4514 		if (newcx == oldcx + 1) {
4515 			xfrom = newcx;
4516 			xto = newcx < c_num_chunks - 1 ? newcx + 1 : newcx;
4517 		} else if (newcx == oldcx - 1) {
4518 			xfrom = newcx > 0 ? newcx - 1 : newcx;
4519 			xto = newcx;
4520 		} else {
4521 			xfrom = newcx > 0 ? newcx - 1 : newcx;
4522 			xto = newcx < c_num_chunks - 1 ? newcx + 1 : newcx;
4523 		}
4524 		if (newcy == oldcy + 1) {
4525 			yfrom = newcy;
4526 			yto = newcy < c_num_chunks - 1 ? newcy + 1 : newcy;
4527 		} else if (newcy == oldcy - 1) {
4528 			yfrom = newcy > 0 ? newcy - 1 : newcy;
4529 			yto = newcy;
4530 		} else {
4531 			yfrom = newcy > 0 ? newcy - 1 : newcy;
4532 			yto = newcy < c_num_chunks - 1 ? newcy + 1 : newcy;
4533 		}
4534 	}
4535 	for (int y = yfrom; y <= yto; y++)
4536 		for (int x = xfrom; x <= xto; x++)
4537 			nlist->get_map()->get_chunk(FIX_COORD(x), FIX_COORD(y))->setup_cache();
4538 
4539 	// If change in Superchunk number, apply Old Style caching emulation
4540 	gwin->emulate_cache(olist, nlist);
4541 }
4542 
4543 /*
4544  *  Move (teleport) to a new spot.
4545  */
4546 
move(int newtx,int newty,int newlift,int newmap)4547 void Main_actor::move(
4548     int newtx,
4549     int newty,
4550     int newlift,
4551     int newmap
4552 ) {
4553 	// Store old chunk list.
4554 	Map_chunk *olist = get_chunk();
4555 	// Move it.
4556 	Actor::move(newtx, newty, newlift, newmap);
4557 	Map_chunk *nlist = get_chunk();
4558 	if (nlist != olist)
4559 		Main_actor::switched_chunks(olist, nlist);
4560 	int tx = get_tx();
4561 	int ty = get_ty();
4562 	gwin->set_ice_dungeon(nlist->is_ice_dungeon(tx, ty));
4563 	if (gwin->set_above_main_actor(nlist->is_roof(tx, ty, newlift)))
4564 		gwin->set_in_dungeon(nlist->has_dungeon() ?
4565 		                     nlist->is_dungeon(tx, ty) : 0);
4566 }
4567 
4568 /*
4569  *  We're dead.
4570  */
4571 
die(Game_object *)4572 void Main_actor::die(
4573     Game_object * /* attacker */
4574 ) {
4575 	if (gwin->in_combat())
4576 		gwin->toggle_combat();  // Hope this is safe....
4577 	Actor::set_flag(Obj_flags::dead);
4578 	gumpman->close_all_gumps(); // Obviously.
4579 	// Special function for dying:
4580 	Usecode_function_data *info = Shapeinfo_lookup::GetAvUsecode(0);
4581 	ucmachine->call_usecode(info->fun_id, this,
4582 	                        static_cast<Usecode_machine::Usecode_events>(info->event_id));
4583 }
4584 
4585 /*
4586  *  Set the shapenum based on skin color, sex, naked flag and petra and polymorph flag
4587  */
set_actor_shape()4588 void Actor::set_actor_shape() {
4589 	if (get_npc_num() != 0 || get_skin_color() < 0 ||
4590 	        (get_flag(Obj_flags::polymorph) && !get_flag(Obj_flags::naked)))
4591 		return;
4592 
4593 	int sn;
4594 	int female = get_type_flag(tf_sex) ? 1 : 0;
4595 	Skin_data *skin = Shapeinfo_lookup::GetSkinInfoSafe(this);
4596 
4597 	if (!skin ||    // Should never happen, but hey...
4598 	        (!sman->have_si_shapes() &&
4599 	         Shapeinfo_lookup::IsSkinImported(
4600 	             get_flag(Obj_flags::naked) ? skin->naked_shape : skin->shape_num)))
4601 		sn = Shapeinfo_lookup::GetBaseAvInfo(female != 0)->shape_num;
4602 	else
4603 		sn = get_flag(Obj_flags::naked) ? skin->naked_shape : skin->shape_num;
4604 
4605 #ifdef DEBUG
4606 	cerr << "Setting Shape to " << sn << endl;
4607 #endif
4608 	set_shape(sn, get_framenum());
4609 	set_file(SF_SHAPES_VGA);
4610 }
4611 
4612 // Sets the polymorph to shape
set_polymorph(int shape)4613 void Actor::set_polymorph(int shape) {
4614 #ifdef DEBUG
4615 	cerr << "Setting polymorph for " << get_npc_num() << endl;
4616 	cerr << "Shape " << shape << endl;
4617 	cerr << "Save shape " << shape_save << endl;
4618 #endif
4619 
4620 	// Want to set to Avatar
4621 	if (shape == Shapeinfo_lookup::GetMaleAvShape() ||
4622 	        shape == Shapeinfo_lookup::GetFemaleAvShape()) {
4623 		Actor *avatar = gwin->get_main_actor();
4624 		if (!avatar) return;
4625 
4626 		Skin_data *skin = Shapeinfo_lookup::GetSkinInfoSafe(avatar);
4627 		shape = avatar->get_flag(Obj_flags::naked) ? skin->naked_shape : skin->shape_num;
4628 		if (this == avatar)
4629 			shape_save = shape; // Revert to default un-polymorphed shape.
4630 	}
4631 	set_file(SF_SHAPES_VGA);
4632 
4633 	if (shape == shape_save) {
4634 		set_shape(shape_save);
4635 		shape_save = -1;
4636 		clear_flag(Obj_flags::polymorph);
4637 		return;
4638 	}
4639 	if (shape_save == -1) shape_save = get_shapenum();
4640 //	set_shape (shape, get_framenum());
4641 	// ++++Taking a guess for SI amulet:
4642 	set_shape(shape, get_dir_framenum(Actor::standing));
4643 	set_flag(Obj_flags::polymorph);
4644 }
4645 
4646 // Sets polymorph shape to defaults based on flags and npc num
set_polymorph_default()4647 void Actor::set_polymorph_default() {
4648 	if (!get_flag(Obj_flags::polymorph)
4649 	        || (get_npc_num() != 0 &&
4650 	            (GAME_SI && get_npc_num() != 28)))
4651 		return;
4652 
4653 	set_actor_shape();
4654 
4655 	shape_save = get_shapenum();
4656 
4657 	if (get_npc_num() == 28)        // Handle Petra First
4658 		set_polymorph(Shapeinfo_lookup::GetMaleAvShape());
4659 	else if (get_flag(Obj_flags::petra))    // Avatar as petra
4660 		set_polymorph(658);
4661 	else    // Snake
4662 		set_polymorph(530);
4663 }
4664 
4665 /*
4666  *  Get 'real' shape for Usecode.
4667  */
4668 
get_shape_real() const4669 int Actor::get_shape_real(
4670 ) const {
4671 	if (npc_num != 0)       // Not the avatar?
4672 		return shape_save != -1 ? shape_save : get_shapenum();
4673 	// Taking guess (6/18/01):
4674 	if (get_type_flag(Actor::tf_sex))
4675 		return Shapeinfo_lookup::GetFemaleAvShape();
4676 	else
4677 		return Shapeinfo_lookup::GetMaleAvShape();
4678 }
4679 
4680 /**
4681  *  Causes earthquake on step if the actor flag is set.
4682  *  @return: True if caused quake on walk, false otherwise.
4683  */
4684 
quake_on_walk()4685 bool Actor::quake_on_walk(
4686 ) {
4687 	if (get_info().quake_on_walk()) {
4688 		qsteps = (qsteps + 1) % 5;
4689 		if (!qsteps)        // Time to roll?
4690 			gwin->get_tqueue()->add(Game::get_ticks() + 10, new Earthquake(2));
4691 		return true;
4692 	}
4693 	return false;
4694 }
4695 /*
4696  *  Create NPC.
4697  */
4698 
Npc_actor(const std::string & nm,int shapenum,int num,int uc)4699 Npc_actor::Npc_actor(
4700     const std::string &nm,        // Name.  A copy is made.
4701     int shapenum,
4702     int num,
4703     int uc
4704 ) : Actor(nm, shapenum, num, uc), nearby(false),
4705 	num_schedules(0),
4706 	schedules(nullptr) {
4707 }
4708 
4709 /*
4710  *  Kill an actor.
4711  */
4712 
~Npc_actor()4713 Npc_actor::~Npc_actor(
4714 ) {
4715 	delete [] schedules;
4716 }
4717 
4718 /*
4719  *  Set schedule list.
4720  */
4721 
set_schedules(Schedule_change * sc_list,int cnt)4722 void Npc_actor::set_schedules(
4723     Schedule_change *sc_list,
4724     int cnt
4725 ) {
4726 	delete [] schedules;
4727 	schedules = sc_list;
4728 	num_schedules = cnt;
4729 }
4730 
4731 /*
4732  *  Set schedule type.
4733  */
4734 
set_schedule_time_type(int time,int type)4735 void Npc_actor::set_schedule_time_type(int time, int type) {
4736 	Tile_coord tile;
4737 	int i;
4738 
4739 	for (i = 0; i < num_schedules; i++) if (schedules[i].get_time() == time) break;
4740 
4741 	if (i == num_schedules) { // Didn't find it
4742 		auto *scheds = new Schedule_change[num_schedules + 1];
4743 
4744 		for (i = 0; i < num_schedules; i++) {
4745 			tile = schedules[i].get_pos();
4746 			scheds[i].set(tile.tx, tile.ty, tile.tz,
4747 			              schedules[i].get_type(), schedules[i].get_time());
4748 		}
4749 
4750 		scheds[num_schedules].set(0, 0, 0,
4751 		                          static_cast<unsigned char>(type),
4752 		                          static_cast<unsigned char>(time));
4753 		set_schedules(scheds, num_schedules + 1);
4754 	} else { // Did find it
4755 		tile = schedules[i].get_pos();
4756 		schedules[i].set(tile.tx, tile.ty, tile.tz,
4757 		                 static_cast<unsigned char>(type),
4758 		                 static_cast<unsigned char>(time));
4759 	}
4760 }
4761 
4762 /*
4763  *  Set schedule location.
4764  */
4765 
set_schedule_time_location(int time,int x,int y)4766 void Npc_actor::set_schedule_time_location(int time, int x, int y) {
4767 	int i;
4768 
4769 	for (i = 0; i < num_schedules; i++) if (schedules[i].get_time() == time) break;
4770 
4771 	if (i == num_schedules) { // Didn't find it
4772 		Tile_coord tile;
4773 		auto *scheds = new Schedule_change[num_schedules + 1];
4774 
4775 		for (i = 0; i < num_schedules; i++) {
4776 			tile = schedules[i].get_pos();
4777 			scheds[i].set(tile.tx, tile.ty, tile.tz,
4778 			              schedules[i].get_type(), schedules[i].get_time());
4779 		}
4780 
4781 		scheds[num_schedules].set(x, y, 0, 0,
4782 		                          static_cast<unsigned char>(time));
4783 		set_schedules(scheds, num_schedules + 1);
4784 	} else { // Did find it
4785 		schedules[i].set(x, y, 0,
4786 		                 schedules[i].get_type(), static_cast<unsigned char>(time));
4787 	}
4788 }
4789 
4790 /*
4791  *  Remove schedule
4792  */
4793 
remove_schedule(int time)4794 void Npc_actor::remove_schedule(int time) {
4795 	int i;
4796 
4797 	for (i = 0; i < num_schedules; i++)
4798 		if (schedules[i].get_time() == time) break;
4799 	if (i != num_schedules) { // Found it
4800 		int todel = i;
4801 		Tile_coord tile;
4802 		auto *scheds = new Schedule_change[num_schedules - 1];
4803 
4804 		for (i = 0; i < todel; i++) {
4805 			tile = schedules[i].get_pos();
4806 			scheds[i].set(tile.tx, tile.ty, tile.tz,
4807 			              schedules[i].get_type(), schedules[i].get_time());
4808 		}
4809 
4810 		for (; i < num_schedules - 1; i++) {
4811 			tile = schedules[i + 1].get_pos();
4812 			scheds[i].set(tile.tx, tile.ty, tile.tz,
4813 			              schedules[i + 1].get_type(),
4814 			              schedules[i + 1].get_time());
4815 		}
4816 
4817 		set_schedules(scheds, num_schedules - 1);
4818 	}
4819 }
4820 
4821 /*
4822  *  Set schedule list.
4823  */
4824 
get_schedules(Schedule_change * & sc_list,int & cnt) const4825 void Npc_actor::get_schedules(
4826     Schedule_change *&sc_list,
4827     int &cnt
4828 ) const {
4829 	sc_list = schedules;
4830 	cnt = num_schedules;
4831 }
4832 /*
4833  *  Move and change frame.
4834  */
4835 
movef(Map_chunk * old_chunk,Map_chunk * new_chunk,int new_sx,int new_sy,int new_frame,int new_lift)4836 void Npc_actor::movef(
4837     Map_chunk *old_chunk,
4838     Map_chunk *new_chunk,
4839     int new_sx, int new_sy,
4840     int new_frame,
4841     int new_lift
4842 ) {
4843 	Actor::movef(old_chunk, new_chunk,
4844 	             new_sx, new_sy, new_frame, new_lift);
4845 	if (old_chunk != new_chunk) // In new chunk?
4846 		Npc_actor::switched_chunks(old_chunk, new_chunk);
4847 }
4848 
4849 /*
4850  *  Find day's schedule for a given time-of-day.
4851  *
4852  *  Output: index of schedule change.
4853  *      -1 if not found, or if a party member.
4854  */
4855 
find_schedule_change(int hour3)4856 int Npc_actor::find_schedule_change(
4857     int hour3           // 0=midnight, 1=3am, etc.
4858 ) {
4859 	if (party_id >= 0 || is_dead())
4860 		return -1;      // Fail if a party member or dead.
4861 	for (int i = 0; i < num_schedules; i++)
4862 		if (schedules[i].get_time() == hour3)
4863 			return i;
4864 	return -1;
4865 }
4866 
find_schedule_at_time(int hour3)4867 int Npc_actor::find_schedule_at_time(
4868     int hour3           // 0=midnight, 1=3am, etc.
4869 ) {
4870 	if (party_id >= 0 || is_dead() || num_schedules == 0)
4871 		return -1;      // Fail if a party member or dead.
4872 	int closest_dist = 100;
4873 	int closest_index = 0;
4874 	for (int i = 0; i < num_schedules; i++) {
4875 		int dist = (hour3 - schedules[i].get_time() + 8) % 8;
4876 		if (dist < closest_dist) {
4877 			closest_dist = dist;
4878 			closest_index = i;
4879 		}
4880 	}
4881 	assert(closest_dist != 100);
4882 	return closest_index;
4883 }
4884 
4885 /*
4886  *  Update schedule at a 3-hour time change.
4887  */
4888 
update_schedule(int hour3,int delay,Tile_coord * pos)4889 void Npc_actor::update_schedule(
4890     int hour3,          // 0=midnight, 1=3am, etc.
4891     int delay,          // Delay in msecs, or -1 for random.
4892     Tile_coord *pos     // Were we want to return to.
4893 ) {
4894 	int i = find_schedule_change(hour3);
4895 	if (i < 0) {
4896 		// Not found?  Look at prev.
4897 		i = find_schedule_at_time(hour3);
4898 		if (i < 0)
4899 			return;
4900 		if ((schedule_type == schedules[i].get_type() ||
4901 		        restored_schedule == schedules[i].get_type()) &&
4902 		        old_schedule_loc == schedules[i].get_pos()) {
4903 			restored_schedule = -1;
4904 			return;     // Already in it.
4905 		}
4906 	}
4907 	restored_schedule = -1;
4908 	old_schedule_loc = schedules[i].get_pos();
4909 	Tile_coord newloc = pos ? *pos : schedules[i].get_pos();
4910 	set_schedule_and_loc(schedules[i].get_type(), newloc, delay);
4911 }
4912 
4913 /*
4914  *  Render.
4915  */
4916 
paint()4917 void Npc_actor::paint(
4918 ) {
4919 	Actor::paint();         // Draw on screen.
4920 	if (dormant && schedule &&  // Resume schedule.
4921 	        // FOR NOW:  Not when in formation.
4922 	        (party_id < 0 || !gwin->walk_in_formation ||
4923 	         schedule_type != Schedule::follow_avatar)) {
4924 		dormant = false;    // But clear out old entries first.??
4925 		gwin->get_tqueue()->remove(this);
4926 		// Force schedule->now_what() in .5secs
4927 		// DO NOT call now_what here!!!
4928 		uint32 curtime = Game::get_ticks();
4929 		gwin->get_tqueue()->add(curtime + 500, this, gwin);
4930 	}
4931 	if (!nearby)            // Make sure we're in 'nearby' list.
4932 		gwin->add_nearby_npc(this);
4933 }
4934 
4935 /*
4936  *  Run usecode when double-clicked.
4937  */
activate(int event)4938 void Npc_actor::activate(
4939     int event
4940 ) {
4941 	if (is_dead() && !cheat.in_map_editor())
4942 		return;
4943 	// Converse, etc.
4944 	Actor::activate(event);
4945 }
4946 
4947 /*
4948  *  Handle a time event (for animation).
4949  */
4950 
handle_event(unsigned long curtime,uintptr udata)4951 void Npc_actor::handle_event(
4952     unsigned long curtime,      // Current time of day.
4953     uintptr udata          // Ignored.
4954 ) {
4955 	purge_deleted_actions();
4956 	if ((cheat.in_map_editor() && party_id < 0) ||
4957 	        (get_flag(Obj_flags::paralyzed) || is_dead() || is_knocked_out() ||
4958 	         (get_flag(Obj_flags::asleep) && schedule_type != Schedule::sleep))) {
4959 		gwin->get_tqueue()->add(
4960 		    curtime + gwin->get_std_delay(), this, udata);
4961 		return;
4962 	}
4963 	// Prevent actor from doing anything if not in the active map.
4964 	// ... but not if the NPC is not on the map (breaks pathfinding
4965 	// from offscreen if NPC not on map).
4966 	if (get_map() && get_map() != gwin->get_map()) {
4967 		set_action(nullptr);
4968 		dormant = true;
4969 		if (schedule)
4970 			schedule->im_dormant();
4971 		return;
4972 	}
4973 
4974 	// Goblins in goblin village should be overly aggressive.
4975 	if (is_goblin() && in_goblin_village(this) && party_id < 0 && can_act() &&
4976 	        schedule &&
4977 	        (schedule_type != Schedule::combat &&   // Not if already in combat.
4978 	         // Patrol schedule already does this.
4979 	         schedule_type != Schedule::patrol &&
4980 	         schedule_type != Schedule::sleep &&
4981 	         schedule_type != Schedule::wait &&
4982 	         schedule_type != Schedule::arrest_avatar))
4983 		schedule->seek_foes();
4984 
4985 	if (!action) {          // Not doing anything?
4986 		frame_time = 0;
4987 		if (in_usecode_control() || !can_act())
4988 			// Can't move on our own. Keep trying.
4989 			gwin->get_tqueue()->add(
4990 			    curtime + gwin->get_std_delay(), this, udata);
4991 		else if (schedule) {
4992 			if (!dormant)
4993 				schedule->now_what();
4994 			else
4995 				schedule->im_dormant();
4996 		}
4997 	} else {
4998 		// Do what we should.
4999 		int delay = party_id < 0 ? gwin->is_time_stopped() : 0;
5000 		if (delay <= 0) {   // Time not stopped?
5001 			int speed = action->get_speed();
5002 			delay = action->handle_event(this);
5003 			if (!delay) {
5004 				// Action finished. Add a slight delay.
5005 				frame_time = speed;
5006 				if (!frame_time)    // Not a path. Add a delay anyway.
5007 					frame_time = gwin->get_std_delay();
5008 				delay = frame_time;
5009 				set_action(nullptr);
5010 			}
5011 		}
5012 		gwin->get_tqueue()->add(
5013 		    curtime + delay, this, udata);
5014 	}
5015 }
5016 
5017 /*
5018  *  Step onto an adjacent tile.
5019  *
5020  *  Output: false if blocked (or paralyzed).
5021  *      Dormant is set if off screen.
5022  */
5023 
step(Tile_coord t,int frame,bool force)5024 bool Npc_actor::step(
5025     Tile_coord t,           // Tile to step onto.
5026     int frame,          // New frame #.
5027     bool force
5028 ) {
5029 	if (get_flag(Obj_flags::paralyzed) || get_map() != gmap)
5030 		return false;
5031 	Tile_coord oldtile = get_tile();
5032 	// Get old chunk.
5033 	t.fixme();
5034 	// Get chunk.
5035 	int cx = t.tx / c_tiles_per_chunk;
5036 	int cy = t.ty / c_tiles_per_chunk;
5037 	// Get rel. tile coords.
5038 	int tx = t.tx % c_tiles_per_chunk;
5039 	int ty = t.ty % c_tiles_per_chunk;
5040 	// Get ->new chunk.
5041 	Map_chunk *nlist = gmap->get_chunk_safely(cx, cy);
5042 	if (!nlist) {       // Shouldn't happen!
5043 		stop();
5044 		return false;
5045 	}
5046 	bool water;
5047 	bool poison;      // Get tile info.
5048 	get_tile_info(this, gwin, nlist, tx, ty, water, poison);
5049 	if (is_blocked(t, nullptr, force ? MOVE_ALL : 0)) {
5050 		if (is_really_blocked(t, force)) {
5051 			if (schedule)       // Tell scheduler.
5052 				schedule->set_blocked(t);
5053 			stop();
5054 			// Offscreen, but not in party?
5055 			if (!gwin->add_dirty(this) && party_id < 0 &&
5056 			        // And > a screenful away?
5057 			        distance(gwin->get_camera_actor()) > 1 + c_screen_tile_size)
5058 				dormant = true; // Go dormant.
5059 			return false;       // Done.
5060 		}
5061 	}
5062 	if (poison && t.tz == 0)
5063 		Actor::set_flag(static_cast<int>(Obj_flags::poisoned));
5064 	// Check for scrolling.
5065 	gwin->scroll_if_needed(this, t);
5066 	add_dirty();            // Set to repaint old area.
5067 	// Move it.
5068 	Map_chunk *olist = get_chunk();
5069 	movef(olist, nlist, tx, ty, frame, t.tz);
5070 
5071 	// Near an egg?  (Do this last, since
5072 	//   it may teleport.)
5073 	nlist->activate_eggs(this, t.tx, t.ty, t.tz, oldtile.tx, oldtile.ty);
5074 
5075 	// Offscreen, but not in party?
5076 	if (!add_dirty(true) && party_id < 0 &&
5077 	        // And > a screenful away?
5078 	        distance(gwin->get_camera_actor()) > 1 + c_screen_tile_size &&
5079 	        //++++++++Try getting rid of the 'talk' line:
5080 	        get_schedule_type() != Schedule::talk &&
5081 	        get_schedule_type() != Schedule::street_maintenance) {
5082 		// No longer on screen.
5083 		stop();
5084 		dormant = true;
5085 		return false;
5086 	}
5087 	quake_on_walk();
5088 	return true;           // Add back to queue for next time.
5089 }
5090 
5091 /*
5092  *  Remove an object from its container, or from the world.
5093  *  The object is deleted.
5094  */
5095 
remove_this(Game_object_shared * keep)5096 void Npc_actor::remove_this(
5097     Game_object_shared *keep     // Non-null to not delete.
5098 ) {
5099 	set_action(nullptr);
5100 //	delete schedule; // Problems in SI monster creation.
5101 //	schedule = nullptr;
5102 // Messes up resurrection   num_schedules = 0;
5103 	gwin->get_tqueue()->remove(this);// Remove from time queue.
5104 	gwin->remove_nearby_npc(this);  // Remove from nearby list.
5105 	// Store old chunk list.
5106 	Map_chunk *olist = get_chunk();
5107 	Game_object_shared keep_this;
5108 	Actor::remove_this(&keep_this);  // Remove, but don't ever delete an NPC
5109 	Npc_actor::switched_chunks(olist, nullptr);
5110 	set_invalid();
5111 	if (!keep && npc_num > 0)  // Really going?
5112 		unused = true;      // Mark unused if a numbered NPC.
5113 	if (keep)
5114 		*keep = std::move(keep_this);
5115 }
5116 
5117 /*
5118  *  Update chunks' npc lists after this has moved.
5119  */
5120 
switched_chunks(Map_chunk * olist,Map_chunk * nlist)5121 void Npc_actor::switched_chunks(
5122     Map_chunk *olist,   // Old chunk, or null.
5123     Map_chunk *nlist    // New chunk, or null.
5124 ) {
5125 	ignore_unused_variable_warning(olist, nlist);
5126 	//++++++++++No longer needed.  Maybe it should go away.
5127 }
5128 
5129 /*
5130  *  Move (teleport) to a new spot.
5131  */
5132 
move(int newtx,int newty,int newlift,int newmap)5133 void Npc_actor::move(
5134     int newtx,
5135     int newty,
5136     int newlift,
5137     int newmap
5138 ) {
5139 	// Store old chunk list.
5140 	Map_chunk *olist = get_chunk();
5141 	// Move it.
5142 	Actor::move(newtx, newty, newlift, newmap);
5143 	Map_chunk *nlist = get_chunk();
5144 	if (nlist != olist) {
5145 		Npc_actor::switched_chunks(olist, nlist);
5146 		if (!olist)     // Moving back into world?
5147 			dormant = true; // Cause activation if painted.
5148 	}
5149 }
5150 
5151 /*
5152  *  Get # of NPC a body came from (or -1 if not known).
5153  */
5154 
get_live_npc_num() const5155 int Dead_body::get_live_npc_num(
5156 ) const {
5157 	return npc_num;
5158 }
5159 
5160 /*
5161  *  Get size of IREG. Returns -1 if can't write to buffer.
5162  */
5163 
get_ireg_size()5164 int Dead_body::get_ireg_size() {
5165 	int size = Container_game_object::get_ireg_size();
5166 	return size < 0 ? size : size + 1;
5167 }
5168 
5169 /*
5170  *  Write out body and its members.
5171  */
5172 
write_ireg(ODataSource * out)5173 void Dead_body::write_ireg(
5174     ODataSource *out
5175 ) {
5176 	unsigned char buf[21];      // 13-byte entry - Exult extension.
5177 	uint8 *ptr = write_common_ireg(13, buf);
5178 	Game_object *first = objects.get_first(); // Guessing: +++++
5179 	unsigned short tword = first ? first->get_prev()->get_shapenum()
5180 	                       : 0;
5181 	Write2(ptr, tword);
5182 	*ptr++ = 0;         // Unknown.
5183 	*ptr++ = get_quality();
5184 	int npc = get_live_npc_num();   // If body, get source.
5185 	// Here, store NPC # more simply.
5186 	Write2(ptr, npc);   // Allowing larger range of NPC bodies.
5187 	*ptr++ = nibble_swap(get_lift()); // Lift
5188 	*ptr++ = static_cast<unsigned char>(get_obj_hp());      // Resistance.
5189 	// Flags:  B0=invis. B3=okay_to_take.
5190 	*ptr++ = (get_flag(Obj_flags::invisible) ? 1 : 0) +
5191 	         (get_flag(Obj_flags::okay_to_take) ? (1 << 3) : 0);
5192 	out->write(reinterpret_cast<char *>(buf), ptr - buf);
5193 	write_contents(out);        // Write what's contained within.
5194 	// Write scheduled usecode.
5195 	Game_map::write_scheduled(out, this);
5196 }
5197 
5198 
5199 /*
5200  *  Create a sequence of frames.
5201  */
5202 
Frames_sequence(int cnt,unsigned char * f)5203 Frames_sequence::Frames_sequence(
5204     int cnt,            // # of frames.
5205     unsigned char *f        // List of frames.
5206 ) : num_frames(cnt) {
5207 	frames = new unsigned char[cnt];
5208 	memcpy(frames, f, cnt);     // Copy in the list.
5209 }
5210