1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "ultima/nuvie/core/nuvie_defs.h"
24 #include "ultima/nuvie/misc/u6_misc.h"
25 #include "ultima/nuvie/files/nuvie_io.h"
26 #include "ultima/nuvie/core/game.h"
27 #include "ultima/nuvie/core/converse.h"
28 #include "ultima/nuvie/core/timed_event.h"
29 #include "ultima/nuvie/conf/configuration.h"
30 #include "ultima/nuvie/actors/actor_manager.h"
31 #include "ultima/nuvie/sound/sound_manager.h"
32 #include "ultima/nuvie/views/view_manager.h"
33 #include "ultima/nuvie/core/player.h"
34 #include "ultima/nuvie/core/map.h"
35 #include "ultima/nuvie/gui/widgets/map_window.h"
36 #include "ultima/nuvie/usecode/u6_usecode.h"
37 #include "ultima/nuvie/gui/widgets/command_bar.h"
38 #include "ultima/nuvie/pathfinder/party_path_finder.h"
39 #include "ultima/nuvie/core/party.h"
40 #include "ultima/nuvie/views/view.h"
41 #include "ultima/nuvie/save/obj_list.h"
42 #include "ultima/nuvie/core/events.h"
43 
44 namespace Ultima {
45 namespace Nuvie {
46 
Party(Configuration * cfg)47 Party::Party(Configuration *cfg) {
48 	config = cfg;
49 	game = NULL;
50 	actor_manager = NULL;
51 	map = NULL;
52 	pathfinder = NULL;
53 	rest_campfire = NULL;
54 
55 	formation = PARTY_FORM_STANDARD;
56 	num_in_party = 0;
57 	prev_leader_x = prev_leader_y = 0;
58 	defer_removing_dead_members = false;
59 	autowalk = false;
60 	in_vehicle = false;
61 	in_combat_mode = false;
62 	lightsources = 0;
63 
64 	memset(&member, 0, sizeof member);
65 }
66 
~Party()67 Party::~Party() {
68 	if (pathfinder)
69 		delete pathfinder;
70 }
71 
init(Game * g,ActorManager * am)72 bool Party::init(Game *g, ActorManager *am) {
73 	Std::string formation_string;
74 
75 	game = g;
76 	actor_manager = am;
77 	map = g->get_game_map();
78 	if (!pathfinder)
79 		pathfinder = new PartyPathFinder(this);
80 
81 	autowalk = false;
82 	in_vehicle = false;
83 
84 	config->value("config/general/party_formation", formation_string, "");
85 	if (formation_string == "row")
86 		formation = PARTY_FORM_ROW;
87 	else if (formation_string == "column")
88 		formation = PARTY_FORM_COLUMN;
89 	else if (formation_string == "delta")
90 		formation = PARTY_FORM_DELTA;
91 	else
92 		formation = PARTY_FORM_STANDARD;
93 
94 	config->value("config/audio/combat_changes_music", combat_changes_music, true);
95 	config->value("config/audio/vehicles_change_music", vehicles_change_music, true);
96 
97 	return true;
98 }
99 
load(NuvieIO * objlist)100 bool Party::load(NuvieIO *objlist) {
101 	uint8 actor_num;
102 	uint16 i;
103 
104 	autowalk = false;
105 	in_vehicle = false;
106 
107 	objlist->seek(OBJLIST_OFFSET_NUM_IN_PARTY);
108 	num_in_party = objlist->read1();
109 
110 
111 	objlist->seek(OBJLIST_OFFSET_PARTY_NAMES);
112 	for (i = 0; i < num_in_party; i++) {
113 		objlist->readToBuf((unsigned char *)member[i].name, PARTY_NAME_MAX_LENGTH + 1); // read in Player name.
114 	}
115 	objlist->seek(OBJLIST_OFFSET_PARTY_ROSTER);
116 	for (i = 0; i < num_in_party; i++) {
117 		actor_num = objlist->read1();
118 		member[i].actor = actor_manager->get_actor(actor_num);
119 		member[i].actor->set_in_party(true);
120 		//member[i].inactive = false; // false unless actor is asleep, or paralyzed (is_immobile)
121 	}
122 
123 	objlist->seek(OBJLIST_OFFSET_U6_COMBAT_MODE); // combat mode flag. NOTE! this offset is probably U6 specifix FIXME
124 	in_combat_mode = (bool)objlist->read1();
125 
126 	MapCoord leader_loc = get_leader_location(); // previous leader location
127 	prev_leader_x = leader_loc.x;
128 	prev_leader_y = leader_loc.y;
129 
130 	reform_party();
131 
132 	autowalk = false;
133 
134 	if (actor_manager->get_actor(ACTOR_VEHICLE_ID_N)->get_worktype() == ACTOR_WT_PLAYER) { // WT_U6_PLAYER
135 		set_in_vehicle(true);
136 		hide();
137 	}
138 
139 	for (i = 0; i < PARTY_MAX_MEMBERS; i++) {
140 		clear_combat_target(i);
141 	}
142 
143 	update_light_sources();
144 	update_music();
145 
146 	return true;
147 }
148 
save(NuvieIO * objlist)149 bool Party::save(NuvieIO *objlist) {
150 	uint16 i;
151 
152 	objlist->seek(OBJLIST_OFFSET_NUM_IN_PARTY);
153 	objlist->write1(num_in_party);
154 
155 
156 	objlist->seek(OBJLIST_OFFSET_PARTY_NAMES);
157 	for (i = 0; i < num_in_party; i++) {
158 		objlist->writeBuf((unsigned char *)member[i].name, PARTY_NAME_MAX_LENGTH + 1);
159 	}
160 
161 	objlist->seek(OBJLIST_OFFSET_PARTY_ROSTER);
162 	for (i = 0; i < num_in_party; i++) {
163 		objlist->write1(member[i].actor->get_actor_num());
164 	}
165 
166 	objlist->seek(OBJLIST_OFFSET_U6_COMBAT_MODE); // combat mode flag. NOTE! this offset is probably U6 specifix FIXME
167 	objlist->write1((uint8)in_combat_mode);
168 
169 	return true;
170 }
171 
add_actor(Actor * actor)172 bool Party::add_actor(Actor *actor) {
173 	Converse *converse = game->get_converse();
174 
175 	if (num_in_party < PARTY_MAX_MEMBERS) {
176 		actor->set_in_party(true);
177 		member[num_in_party].actor = actor;
178 		//member[num_in_party].inactive = false;
179 		strncpy(member[num_in_party].name, converse->npc_name(actor->id_n), PARTY_NAME_MAX_LENGTH + 1);
180 		member[num_in_party].name[PARTY_NAME_MAX_LENGTH] = '\0'; // make sure name is terminated
181 		member[num_in_party].combat_position = 0;
182 //    member[num_in_party].leader_x = member[0].actor->get_location().x;
183 //    member[num_in_party].leader_y = member[0].actor->get_location().y;
184 
185 		num_in_party++;
186 		reform_party();
187 		return true;
188 	}
189 
190 	return false;
191 }
192 
193 
194 // remove actor from member array shuffle remaining actors down if required.
remove_actor(Actor * actor,bool keep_party_flag)195 bool Party::remove_actor(Actor *actor, bool keep_party_flag) {
196 	if (defer_removing_dead_members) //we don't want to remove member while inside the Party::follow() method.
197 		return true;
198 	Game::get_game()->get_event()->set_control_cheat(false);
199 	uint8 i;
200 
201 	for (i = 0; i < num_in_party; i++) {
202 		if (member[i].actor->id_n == actor->id_n) {
203 			if (keep_party_flag == false) {
204 				for (int j = 0; j < member[i].actor->get_num_light_sources(); j++)
205 					subtract_light_source();
206 				member[i].actor->set_in_party(false);
207 			}
208 			if (i != (num_in_party - 1)) {
209 				for (; i + 1 < num_in_party; i++)
210 					member[i] = member[i + 1];
211 			}
212 			num_in_party--;
213 
214 			reform_party();
215 			if (game->is_new_style()) {
216 				Game::get_game()->get_event()->close_gumps();
217 				return true;
218 			}
219 			//FIXME this is a bit hacky we need a better way to refresh views when things change
220 			//maybe using callbacks.
221 			//If the last actor dies and was being displayed in a view then we need to set the
222 			//view to the new last party member.
223 			View *cur_view = Game::get_game()->get_view_manager()->get_current_view();
224 			if (cur_view && cur_view->get_party_member_num() >= num_in_party)
225 				cur_view->set_party_member(num_in_party - 1);
226 			else if (cur_view)
227 				cur_view->set_party_member(cur_view->get_party_member_num()); // needed if a middle party member dies
228 			return true;
229 		}
230 	}
231 
232 	return false;
233 }
234 
remove_dead_actor(Actor * actor)235 bool Party::remove_dead_actor(Actor *actor) {
236 	return remove_actor(actor, PARTY_KEEP_PARTY_FLAG);
237 }
238 
resurrect_dead_members()239 bool Party::resurrect_dead_members() {
240 	uint16 i;
241 	Actor *actor;
242 	MapCoord new_pos = get_leader_location();
243 	if (Game::get_game()->get_event()->using_control_cheat()) {
244 		Game::get_game()->get_event()->set_control_cheat(false);
245 		if (!Game::get_game()->is_new_style()) {
246 			Game::get_game()->get_view_manager()->set_inventory_mode();
247 			Game::get_game()->get_view_manager()->get_current_view()->set_party_member(0);
248 		}
249 	}
250 
251 	for (i = 0; i < ACTORMANAGER_MAX_ACTORS; i++) {
252 		actor = actor_manager->get_actor(i);
253 		if (actor->is_in_party() && actor->is_alive() == false)
254 			actor->resurrect(new_pos);
255 	}
256 	update_light_sources(); // should only be needed for control cheat but it won't hurt to recheck
257 	return true;
258 }
259 
260 
split_gold()261 void Party::split_gold() {
262 }
263 
gather_gold()264 void Party::gather_gold() {
265 }
266 
get_party_size()267 uint8 Party::get_party_size() {
268 	return num_in_party;
269 }
270 
get_leader_actor()271 Actor *Party::get_leader_actor() {
272 	sint8 leader = get_leader();
273 	if (leader < 0) {
274 		return NULL;
275 	}
276 
277 	return get_actor(leader);
278 }
279 
get_actor(uint8 member_num)280 Actor *Party::get_actor(uint8 member_num) {
281 	if (num_in_party <= member_num)
282 		return NULL;
283 
284 	return member[member_num].actor;
285 }
286 
get_actor_name(uint8 member_num)287 char *Party::get_actor_name(uint8 member_num) {
288 	if (num_in_party <= member_num)
289 		return NULL;
290 
291 	return member[member_num].name;
292 }
293 
294 
295 /* Returns position of actor in party or -1.
296  */
get_member_num(Actor * actor)297 sint8 Party::get_member_num(Actor *actor) {
298 	for (int i = 0; i < num_in_party; i++) {
299 		if (member[i].actor->id_n == actor->id_n)
300 			return (i);
301 	}
302 	return (-1);
303 }
304 
get_member_num(uint8 a)305 sint8 Party::get_member_num(uint8 a) {
306 	return (get_member_num(actor_manager->get_actor(a)));
307 }
308 
get_actor_num(uint8 member_num)309 uint8 Party::get_actor_num(uint8 member_num) {
310 	if (num_in_party <= member_num)
311 		return 0; // hmm how should we handle this error.
312 
313 	return member[member_num].actor->id_n;
314 }
315 
316 /* Rearrange member slot positions based on the number of members and the
317  * selected formation. Used only when adding or removing actors.
318  */
reform_party()319 void Party::reform_party() {
320 	uint32 n;
321 	sint32 x, y, max_x;
322 	bool even_row;
323 	sint8 leader = get_leader();
324 	if (leader < 0 || num_in_party == 1)
325 		return;
326 	member[leader].form_x = 0;
327 	member[leader].form_y = 0;
328 	switch (formation) {
329 	case PARTY_FORM_COLUMN: // line up behind Avatar
330 		x = 0;
331 		y = 1;
332 		for (n = leader + 1; n < num_in_party; n++) {
333 			member[n].form_x = x;
334 			member[n].form_y = y++;
335 			if (y == 5) {
336 				x += 1;
337 				y = 0;
338 			}
339 		}
340 		break;
341 	case PARTY_FORM_ROW: // line up left of Avatar
342 		x = -1;
343 		y = 0;
344 		for (n = leader + 1; n < num_in_party; n++) {
345 			member[n].form_x = x--;
346 			member[n].form_y = y;
347 			if (x == -5) {
348 				y += 1;
349 				x = 0;
350 			}
351 		}
352 		break;
353 	case PARTY_FORM_DELTA: // open triangle formation with Avatar at front
354 		x = -1;
355 		y = 1;
356 		for (n = leader + 1; n < num_in_party; n++) {
357 			member[n].form_x = x;
358 			member[n].form_y = y;
359 			// alternate X once, then move down
360 			x = -x;
361 			if (x == 0 || x < 0) {
362 				x -= 1;
363 				++y;
364 			}
365 			if (y == 5) { // start at top of triangle
366 				y -= ((-x) - 1);
367 				x = 0;
368 			}
369 		}
370 		break;
371 //        case PARTY_FORM_COMBAT: // positions determined by COMBAT mode
372 //            break;
373 	case PARTY_FORM_REST: // special formation used while Resting
374 		member[1].form_x = 0;
375 		member[1].form_y = -2;
376 		member[2].form_x = 1;
377 		member[2].form_y = -1;
378 		member[3].form_x = -1;
379 		member[3].form_y = -1;
380 		member[4].form_x = 1;
381 		member[4].form_y = 0;
382 		member[5].form_x = -1;
383 		member[5].form_y = -2;
384 		member[6].form_x = 1;
385 		member[6].form_y = -2;
386 		member[7].form_x = -1;
387 		member[7].form_y = 0;
388 		break;
389 	case PARTY_FORM_STANDARD: // U6
390 	default:
391 		// put first follower behind or behind and to the left of Avatar
392 		member[leader + 1].form_x = (num_in_party >= 3) ? -1 : 0;
393 		member[leader + 1].form_y = 1;
394 		x = y = 1;
395 		even_row = false;
396 		for (n = leader + 2, max_x = 1; n < num_in_party; n++) {
397 			member[n].form_x = x;
398 			member[n].form_y = y;
399 			// alternate & move X left/right by 2
400 			x = (x == 0) ? x - 2 : (x < 0) ? -x : -x - 2;
401 			if (x > max_x || (x < 0 && -x > max_x)) { // reached row max.
402 				++y;
403 				even_row = !even_row; // next row
404 				++max_x; // increase row max.
405 				x = even_row ? 0 : -1; // next guy starts at center or left by 2
406 			}
407 		}
408 	}
409 }
410 
411 /* Returns number of person leading the party (the first active member), or -1
412  * if the party has no leader and can't move. */
get_leader()413 sint8 Party::get_leader() {
414 	for (int m = 0; m < num_in_party; m++)
415 		if (member[m].actor->is_immobile() == false && member[m].actor->is_charmed() == false)
416 			return m;
417 	return -1;
418 }
419 
420 /* Get map location of a party member. */
get_location(uint8 m)421 MapCoord Party::get_location(uint8 m) {
422 	return (member[m].actor->get_location());
423 }
424 
425 /* Get map location of the first active party member. */
get_leader_location()426 MapCoord Party::get_leader_location() {
427 	sint8 m = get_leader();
428 	MapCoord loc;
429 	if (m >= 0)
430 		loc = member[m].actor->get_location();
431 	return (loc);
432 }
433 
434 /* Returns absolute location where party member `m' SHOULD be (based on party
435  * formation and leader location.
436  */
get_formation_coords(uint8 m)437 MapCoord Party::get_formation_coords(uint8 m) {
438 	MapCoord a = get_location(m); // my location
439 	MapCoord l = get_leader_location(); // leader location
440 	sint8 leader = get_leader();
441 	if (leader < 0)
442 		return (a);
443 	uint8 ldir = member[leader].actor->get_direction(); // leader direction
444 	// intended location
445 	uint16 x = (ldir == NUVIE_DIR_N) ? l.x + member[m].form_x : // X
446 	           (ldir == NUVIE_DIR_E) ? l.x - member[m].form_y :
447 	           (ldir == NUVIE_DIR_S) ? l.x - member[m].form_x :
448 	           (ldir == NUVIE_DIR_W) ? l.x + member[m].form_y : a.x;
449 	uint16 y = (ldir == NUVIE_DIR_N) ? l.y + member[m].form_y : // Y
450 	           (ldir == NUVIE_DIR_E) ? l.y + member[m].form_x :
451 	           (ldir == NUVIE_DIR_S) ? l.y - member[m].form_y :
452 	           (ldir == NUVIE_DIR_W) ? l.y - member[m].form_x : a.y;
453 	return (MapCoord(WRAPPED_COORD(x, a.z),
454 	                 WRAPPED_COORD(y, a.z),
455 	                 a.z // Z
456 	                ));
457 }
458 
459 
460 /* Update the actual locations of the party actors on the map, so that they are
461  * in the proper formation. */
follow(sint8 rel_x,sint8 rel_y)462 void Party::follow(sint8 rel_x, sint8 rel_y) {
463 	Common::Array<bool> try_again;
464 	try_again.resize(get_party_max());
465 
466 	sint8 leader = get_leader();
467 	if (leader <= -1)
468 		return;
469 
470 	if (is_in_combat_mode()) { // just update everyone's combat mode
471 		for (int p = 0; p < get_party_size(); p++)
472 			get_actor(p)->set_worktype(get_actor(p)->get_combat_mode());
473 		return;
474 	}
475 
476 	defer_removing_dead_members = true;
477 
478 	// set previous leader location first, just in case the leader changed
479 	prev_leader_x = WRAPPED_COORD(member[leader].actor->x - rel_x, member[leader].actor->z);
480 	prev_leader_y = member[leader].actor->y - rel_y;
481 	// PASS 1: Keep actors chained together.
482 	for (uint32 p = (leader + 1); p < num_in_party; p++) {
483 		if (member[p].actor->is_immobile()) continue;
484 
485 		try_again[p] = false;
486 		if (!pathfinder->follow_passA(p))
487 			try_again[p] = true;
488 	}
489 	// PASS 2: Catch up to party.
490 	for (uint32 p = (leader + 1); p < num_in_party; p++) {
491 		if (member[p].actor->is_immobile()) continue;
492 
493 		if (try_again[p])
494 			pathfinder->follow_passA(p);
495 		pathfinder->follow_passB(p);
496 		if (!pathfinder->is_contiguous(p)) {
497 			sint8 l = get_leader();
498 			if (l >= 0) {
499 				DEBUG(0, LEVEL_DEBUGGING, "%s is looking for %s.\n", get_actor_name(p), get_actor_name(l));
500 			}
501 			pathfinder->seek_leader(p); // enter/update seek mode
502 		} else if (member[p].actor->get_pathfinder())
503 			pathfinder->end_seek(p);
504 
505 		get_actor(p)->set_moves_left(get_actor(p)->get_moves_left() - 10);
506 		get_actor(p)->set_worktype(0x01); // revert to normal worktype
507 	}
508 
509 	defer_removing_dead_members = false;
510 
511 	//remove party members that died during follow routine.
512 	for (int p = get_party_size() - 1; p >= 0; p--) {
513 		Actor *a = get_actor(p);
514 		if (a->is_alive() == false)
515 			remove_actor(a, PARTY_KEEP_PARTY_FLAG);
516 	}
517 }
518 
519 // Returns true if anyone in the party has a matching object.
has_obj(uint16 obj_n,uint8 quality,bool match_zero_qual)520 bool Party::has_obj(uint16 obj_n, uint8 quality, bool match_zero_qual) {
521 	uint16 i;
522 
523 	for (i = 0; i < num_in_party; i++) {
524 		if (member[i].actor->inventory_get_object(obj_n, quality, match_zero_qual) != NULL) // we got a match
525 			return true;
526 	}
527 
528 	return false;
529 }
530 
531 // Removes the first occurence of an object in the party.
remove_obj(uint16 obj_n,uint8 quality)532 bool Party::remove_obj(uint16 obj_n, uint8 quality) {
533 	uint16 i;
534 	Obj *obj;
535 
536 	for (i = 0; i < num_in_party; i++) {
537 		obj = member[i].actor->inventory_get_object(obj_n, quality);
538 		if (obj != NULL) {
539 			if (member[i].actor->inventory_remove_obj(obj)) {
540 				delete_obj(obj);
541 				return true;
542 			}
543 		}
544 	}
545 
546 	return false;
547 }
548 
549 // Returns the actor id of the first person in the party to have a matching object.
who_has_obj(uint16 obj_n,uint8 quality,bool match_qual_zero)550 Actor *Party::who_has_obj(uint16 obj_n, uint8 quality, bool match_qual_zero) {
551 	uint16 i;
552 	for (i = 0; i < num_in_party; i++) {
553 		if (member[i].actor->inventory_get_object(obj_n, quality, match_qual_zero) != NULL)
554 			return (member[i].actor);
555 	}
556 	return NULL;
557 }
558 
get_obj(uint16 obj_n,uint8 quality,bool match_qual_zero,uint8 frame_n,bool match_frame_n)559 Obj *Party::get_obj(uint16 obj_n, uint8 quality, bool match_qual_zero, uint8 frame_n, bool match_frame_n) {
560 	Obj *obj;
561 	for (uint16 i = 0; i < num_in_party; i++) {
562 		obj = member[i].actor->inventory_get_object(obj_n, quality, match_qual_zero, frame_n, match_frame_n);
563 		if (obj)
564 			return obj;
565 	}
566 	return NULL;
567 }
568 
569 /* Is EVERYONE in the party at or near the coordinates?
570  */
is_at(uint16 x,uint16 y,uint8 z,uint32 threshold)571 bool Party::is_at(uint16 x, uint16 y, uint8 z, uint32 threshold) {
572 	for (uint32 p = 0; p < num_in_party; p++) {
573 		MapCoord loc(x, y, z);
574 		if (!member[p].actor->is_nearby(loc, threshold))
575 			return (false);
576 	}
577 	return (true);
578 }
579 
is_at(MapCoord & xyz,uint32 threshold)580 bool Party::is_at(MapCoord &xyz, uint32 threshold) {
581 	return (is_at(xyz.x, xyz.y, xyz.z, threshold));
582 }
583 
584 /* Is ANYONE in the party at or near the coordinates? */
is_anyone_at(uint16 x,uint16 y,uint8 z,uint32 threshold)585 bool Party::is_anyone_at(uint16 x, uint16 y, uint8 z, uint32 threshold) {
586 	for (uint32 p = 0; p < num_in_party; p++) {
587 		MapCoord loc(x, y, z);
588 		if (member[p].actor->is_nearby(loc, threshold))
589 			return (true);
590 	}
591 	return (false);
592 }
593 
is_anyone_at(MapCoord & xyz,uint32 threshold)594 bool Party::is_anyone_at(MapCoord &xyz, uint32 threshold) {
595 	return (is_anyone_at(xyz.x, xyz.y, xyz.z, threshold));
596 }
597 
contains_actor(Actor * actor)598 bool Party::contains_actor(Actor *actor) {
599 	if (get_member_num(actor) >= 0)
600 		return (true);
601 
602 	return (false);
603 }
604 
contains_actor(uint8 actor_num)605 bool Party::contains_actor(uint8 actor_num) {
606 	return (contains_actor(actor_manager->get_actor(actor_num)));
607 }
608 
set_in_combat_mode(bool value)609 void Party::set_in_combat_mode(bool value) {
610 	in_combat_mode = value;
611 	actor_manager->set_combat_movement(value);
612 
613 	if (in_combat_mode) {
614 		for (int p = 0; p < get_party_size(); p++)
615 			get_actor(p)->set_worktype(get_actor(p)->get_combat_mode()); //set combat worktype
616 	} else {
617 		for (int p = 0; p < get_party_size(); p++)
618 			get_actor(p)->set_worktype(ACTOR_WT_FOLLOW); //set back to follow party leader.
619 	}
620 //  if(combat_changes_music)
621 	update_music();
622 	if (game->get_command_bar() != NULL) {
623 		game->get_command_bar()->set_combat_mode(in_combat_mode);
624 	}
625 }
626 
update_music()627 void Party::update_music() {
628 	SoundManager *s = Game::get_game()->get_sound_manager();
629 	MapCoord pos;
630 
631 	if (in_vehicle && vehicles_change_music) {
632 		s->musicPlayFrom("boat");
633 		return;
634 	} else if (in_combat_mode && combat_changes_music) {
635 		s->musicPlayFrom("combat");
636 		return;
637 	}
638 
639 	pos = get_leader_location();
640 
641 	switch (pos.z) {
642 	case 0 :
643 		s->musicPlayFrom("random");
644 		break;
645 	case 5 :
646 		s->musicPlayFrom("gargoyle");
647 		break;
648 	default :
649 		s->musicPlayFrom("dungeon");
650 		break;
651 	}
652 
653 	return;
654 }
655 
heal()656 void Party::heal() {
657 	uint16 i;
658 
659 	for (i = 0; i < num_in_party; i++) {
660 		member[i].actor->heal();
661 	}
662 
663 	return;
664 
665 }
666 
cure()667 void Party::cure() {
668 	for (uint16 i = 0; i < num_in_party; i++) {
669 		member[i].actor->cure();
670 	}
671 }
672 
set_ethereal(bool ethereal)673 void Party::set_ethereal(bool ethereal) {
674 	for (uint16 i = 0; i < num_in_party; i++) {
675 		member[i].actor->set_ethereal(ethereal);
676 	}
677 }
678 
show()679 void Party::show() {
680 	uint16 i;
681 
682 	for (i = 0; i < num_in_party; i++) {
683 		member[i].actor->show();
684 	}
685 
686 	return;
687 }
688 
hide()689 void Party::hide() {
690 	uint16 i;
691 
692 	for (i = 0; i < num_in_party; i++) {
693 		member[i].actor->hide();
694 	}
695 
696 	return;
697 }
698 
699 /* Move and center everyone in the party to one location.
700  */
move(uint16 dx,uint16 dy,uint8 dz)701 bool Party::move(uint16 dx, uint16 dy, uint8 dz) {
702 	for (sint32 m = 0; m < num_in_party; m++)
703 		if (!member[m].actor->move(dx, dy, dz, ACTOR_FORCE_MOVE))
704 			return (false);
705 	return (true);
706 }
707 
708 
709 /* Automatically walk (timed) to a destination, and then teleport to new
710  * location (optional). Used to enter/exit dungeons.
711  * (step_delay 0 = default speed)
712  */
walk(MapCoord * walkto,MapCoord * teleport,uint32 step_delay)713 void Party::walk(MapCoord *walkto, MapCoord *teleport, uint32 step_delay) {
714 	if (step_delay)
715 		new TimedPartyMove(walkto, teleport, step_delay);
716 	else
717 		new TimedPartyMove(walkto, teleport);
718 
719 	game->pause_world(); // other actors won't move
720 	game->pause_user(); // don't allow input
721 	// view will snap back to player after everyone has moved
722 	game->get_player()->set_mapwindow_centered(false);
723 	autowalk = true;
724 }
725 
726 
727 /* Enter a moongate and teleport to a new location.
728  * (step_delay 0 = default speed)
729  */
walk(Obj * moongate,MapCoord * teleport,uint32 step_delay)730 void Party::walk(Obj *moongate, MapCoord *teleport, uint32 step_delay) {
731 	MapCoord walkto(moongate->x, moongate->y, moongate->z);
732 	if (step_delay)
733 		new TimedPartyMove(&walkto, teleport, moongate, step_delay);
734 	else
735 		new TimedPartyMove(&walkto, teleport, moongate);
736 
737 	game->pause_world(); // other actors won't move
738 	game->pause_user(); // don't allow input
739 	// view will snap back to player after everyone has moved
740 	game->get_player()->set_mapwindow_centered(false);
741 	autowalk = true;
742 }
743 
744 
745 
746 /* Automatically walk (timed) to vehicle. (step_delay 0 = default speed)
747  */
enter_vehicle(Obj * ship_obj,uint32 step_delay)748 void Party::enter_vehicle(Obj *ship_obj, uint32 step_delay) {
749 	MapCoord walkto(ship_obj->x, ship_obj->y, ship_obj->z);
750 
751 	dismount_from_horses();
752 
753 	if (step_delay)
754 		new TimedPartyMoveToVehicle(&walkto, ship_obj, step_delay);
755 	else
756 		new TimedPartyMoveToVehicle(&walkto, ship_obj);
757 
758 	game->pause_world(); // other actors won't move
759 	game->pause_user(); // don't allow input
760 	// view will snap back to player after everyone has moved
761 	game->get_player()->set_mapwindow_centered(false);
762 	autowalk = true;
763 }
764 
exit_vehicle(uint16 x,uint16 y,uint16 z)765 void Party::exit_vehicle(uint16 x, uint16 y, uint16 z) {
766 	if (is_in_vehicle() == false)
767 		return;
768 
769 	Actor *vehicle_actor = actor_manager->get_actor(0);
770 
771 	show();
772 	vehicle_actor->unlink_surrounding_objects();
773 	vehicle_actor->hide();
774 	vehicle_actor->set_worktype(0);
775 
776 	Player *player = game->get_player();
777 
778 	player->set_actor(get_actor(0));
779 	player->move(x, y, z, false);
780 	vehicle_actor->obj_n = 0;//OBJ_U6_NO_VEHICLE;
781 	vehicle_actor->frame_n = 0;
782 	vehicle_actor->init();
783 	vehicle_actor->move(0, 0, 0, ACTOR_FORCE_MOVE);
784 
785 	set_in_vehicle(false);
786 }
787 
set_in_vehicle(bool value)788 void Party::set_in_vehicle(bool value) {
789 	in_vehicle = value;
790 	if (vehicles_change_music)
791 		update_music();
792 	if (value) {
793 		if (in_combat_mode == true)
794 			set_in_combat_mode(false); // break off combat when boarding a vehicle
795 	}
796 
797 	return;
798 }
799 
800 /* Done automatically walking, return view to player character.
801  */
stop_walking(bool force_music_change)802 void Party::stop_walking(bool force_music_change) {
803 	game->get_player()->set_mapwindow_centered(true);
804 	game->unpause_world(); // allow user input, unfreeze actors
805 	game->unpause_user();
806 	autowalk = false;
807 	if (force_music_change || vehicles_change_music)
808 		update_music();
809 }
810 
dismount_from_horses()811 void Party::dismount_from_horses() {
812 	UseCode *usecode = Game::get_game()->get_usecode();
813 
814 	for (uint32 m = 0; m < num_in_party; m++) {
815 		if (member[m].actor->obj_n == OBJ_U6_HORSE_WITH_RIDER) {
816 			Obj *my_obj = member[m].actor->make_obj();
817 			usecode->use_obj(my_obj, member[m].actor);
818 			delete_obj(my_obj);
819 		}
820 	}
821 
822 	return;
823 }
824 
get_slowest_actor()825 Actor *Party::get_slowest_actor() {
826 	Actor *actor = 0;
827 	sint8 begin = get_leader();
828 	if (begin >= 0) {
829 		actor = member[begin].actor;
830 		sint8 moves = actor->get_moves_left();
831 		for (uint32 m = begin + 1; m < num_in_party; m++) {
832 			sint8 select_moves = member[m].actor->get_moves_left();
833 			if (member[m].actor->is_immobile() == false && (select_moves < moves)) {
834 				moves = select_moves;
835 				actor = member[m].actor;
836 			}
837 		}
838 	}
839 	return actor;
840 }
841 
842 /* Gather everyone around a campfire to Rest. */
rest_gather()843 void Party::rest_gather() {
844 	Actor *player_actor = get_leader_actor();
845 	if (player_actor) {
846 		MapCoord player_loc = player_actor->get_location();
847 		rest_campfire = new_obj(OBJ_U6_CAMPFIRE, 1, player_loc.x, player_loc.y, player_loc.z);
848 		rest_campfire->set_temporary();
849 		rest_campfire->qty = 1; //this is set so the campfire may be destroyed by being attacked.
850 		game->get_obj_manager()->add_obj(rest_campfire, true); // addOnTop
851 
852 		game->get_player()->set_mapwindow_centered(false);
853 		game->pause_user();
854 		new TimedRestGather(player_loc.x, player_loc.y);
855 	}
856 }
857 
858 /* Start Resting for the specified number of hours, optionally with a party
859  * member standing guard. */
rest_sleep(uint8 hours,sint16 guard)860 void Party::rest_sleep(uint8 hours, sint16 guard) {
861 	// FIXME: change music to Stones when asking "How many hours?", change to
862 	// a random song when finished camping (or if cancelled)
863 	new TimedRest(hours, guard >= 0 ? member[guard].actor : 0, rest_campfire);
864 }
865 
can_rest(Std::string & err_str)866 bool Party::can_rest(Std::string &err_str) {
867 	Map *map_ = game->get_game_map();
868 	Player *player = game->get_player();
869 	Actor *pActor = player->get_actor();
870 	MapCoord loc = pActor->get_location();
871 
872 	ActorList *enemies = 0;
873 	ActorList *all_actors = 0;
874 
875 	if (is_in_combat_mode()) {
876 		if (Game::get_game()->get_game_type() == NUVIE_GAME_SE)
877 			err_str = "\nNot while in Combat mode!";
878 		else if (Game::get_game()->get_game_type() == NUVIE_GAME_MD)
879 			err_str = "- Not while in Combat!";
880 		else
881 			err_str = "-Not while in Combat!";
882 	} else if (is_in_vehicle()
883 	           && pActor->get_obj_n() != OBJ_U6_SHIP) // player is a vehicle
884 		err_str = "-Can not be repaired!";
885 	else if (Game::get_game()->get_game_type() == NUVIE_GAME_U6
886 	         && game->get_map_window()->in_town())
887 		err_str = "-Only in the wilderness!";
888 	else if ((enemies = pActor->find_enemies())) {
889 		if (Game::get_game()->get_game_type() == NUVIE_GAME_MD)
890 			err_str = "\nNot while foes are near!";
891 		if (Game::get_game()->get_game_type() == NUVIE_GAME_SE)
892 			err_str = "- Not while foes are near!";
893 		else
894 			err_str = "-Not while foes are near!";
895 	} else if ((all_actors = actor_manager->filter_party(actor_manager->filter_distance(actor_manager->get_actor_list(),
896 	                         loc.x, loc.y, loc.z, 5)))
897 	           && !all_actors->empty() && !is_in_vehicle()) {
898 		if (Game::get_game()->get_game_type() == NUVIE_GAME_U6)
899 			err_str = "-Not while others are near!";
900 		else
901 			err_str = "\nIt's too noisy to sleep here!";
902 		delete all_actors;
903 	} else if (!player->in_party_mode())
904 		err_str = "-Not in solo mode!";
905 	else if (!is_in_vehicle() && !map_->is_passable(loc.x - 1, loc.y - 1, loc.x + 1, loc.y + 1, loc.z)
906 	         && Game::get_game()->get_game_type() != NUVIE_GAME_SE)
907 		err_str = "-Not enough room!"; // FIXME: for ships the original checks all squares around the ship. Do we really need this?
908 	else if (is_horsed())
909 		err_str = "-Dismount first!";
910 	else
911 		return true;
912 	delete enemies;
913 	return false;
914 }
915 
is_horsed()916 bool Party::is_horsed() {
917 	for (int p = 0; p < num_in_party; p++)
918 		if (member[p].actor->get_obj_n() == OBJ_U6_HORSE_WITH_RIDER)
919 			return true;
920 	return false;
921 }
922 
is_everyone_horsed()923 bool Party::is_everyone_horsed() {
924 	for (int p = 0; p < num_in_party; p++)
925 		if (member[p].actor->get_obj_n() != OBJ_U6_HORSE_WITH_RIDER)
926 			return false;
927 	return true;
928 }
929 
get_food()930 Obj *Party::get_food() {
931 	for (int p = 0; p < num_in_party; p++) {
932 		Obj *food = member[p].actor->inventory_get_food();
933 		if (food)
934 			return food;
935 	}
936 	return 0;
937 }
938 
set_combat_target(uint8 member_num,Actor * target)939 void Party::set_combat_target(uint8 member_num, Actor *target) {
940 	if (num_in_party <= member_num)
941 		return;
942 
943 	member[member_num].target.type = TARGET_ACTOR;
944 	member[member_num].target.actor_num = target->get_actor_num();
945 }
946 
set_combat_target(uint8 member_num,MapCoord target)947 void Party::set_combat_target(uint8 member_num, MapCoord target) {
948 	if (num_in_party <= member_num)
949 		return;
950 
951 	member[member_num].target.type = TARGET_LOCATION;
952 	member[member_num].target.loc = target;
953 }
954 
clear_combat_target(uint8 member_num)955 void Party::clear_combat_target(uint8 member_num) {
956 	if (member_num >= PARTY_MAX_MEMBERS)
957 		return;
958 
959 	member[member_num].target.type = TARGET_NONE;
960 	member[member_num].target.loc = MapCoord();
961 	member[member_num].target.actor_num = 0;
962 }
963 
get_combat_target(uint8 member_num)964 CombatTarget Party::get_combat_target(uint8 member_num) {
965 	if (num_in_party <= member_num) {
966 		CombatTarget noTarget;
967 		noTarget.type = TARGET_NONE;
968 		noTarget.loc = MapCoord();
969 		noTarget.actor_num = 0;
970 		return noTarget;
971 	}
972 
973 	return member[member_num].target;
974 }
975 
update_light_sources()976 void Party::update_light_sources() {
977 	lightsources = 0;
978 	for (int i = 0; i < num_in_party; i++) {
979 		for (int j = 0; j < member[i].actor->get_num_light_sources(); j++)
980 			add_light_source();
981 	}
982 	if (game->get_event()->using_control_cheat()) {
983 		for (int i = 0; i < game->get_player()->get_actor()->get_num_light_sources(); i++)
984 			add_light_source();
985 	}
986 	game->get_map_window()->updateAmbience();
987 }
988 
has_light_source()989 bool Party::has_light_source() {
990 	if (!game->get_player()->get_actor())
991 		return false;
992 	if (lightsources > 0) { // the original engine didn't care about distance
993 		if (game->get_event()->using_control_cheat()) {
994 			if (game->get_player()->get_actor()->get_num_light_sources() > 0)
995 				return true;
996 			else
997 				return false;
998 		}
999 		for (int i = 0; i < num_in_party; i++) {
1000 			if (member[i].actor->get_num_light_sources() > 0) {
1001 				if (!game->get_map_window()->tile_is_black(member[i].actor->x, member[i].actor->y)
1002 				        && member[i].actor->is_nearby(game->get_player()->get_actor())) // within 5 tiles of player
1003 					return true;
1004 			}
1005 		}
1006 	}
1007 	return false;
1008 }
1009 
1010 } // End of namespace Nuvie
1011 } // End of namespace Ultima
1012