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  * Based on the original sources
23  *   Faery Tale II -- The Halls of the Dead
24  *   (c) 1993-1996 The Wyrmkeep Entertainment Co.
25  */
26 
27 #include "saga2/saga2.h"
28 #include "saga2/actor.h"
29 #include "saga2/assign.h"
30 #include "saga2/calender.h"
31 #include "saga2/task.h"
32 #include "saga2/tile.h"
33 
34 namespace Saga2 {
35 
36 const uint16 kIndefiniteTime = CalenderTime::kFramesPerDay;
37 
38 /* ===================================================================== *
39    ActorAssignment member functions
40  * ===================================================================== */
41 
42 //  Constructor
ActorAssignment(Actor * a,uint16 until)43 ActorAssignment::ActorAssignment(Actor *a, uint16 until) :
44 	_startFrame(g_vm->_calender->frameInDay()),
45 	_endFrame(until) {
46 	_actor = a;
47 	debugC(2, kDebugActors, "New assignment for %p (%s) from %d until %d: %p",
48 	      (void *)a, a->objName(), _startFrame, _endFrame, (void *)this);
49 	a->_assignment = this;
50 	a->_flags |= hasAssignment;
51 }
52 
ActorAssignment(Actor * ac,Common::SeekableReadStream * stream)53 ActorAssignment::ActorAssignment(Actor *ac, Common::SeekableReadStream *stream) {
54 	_startFrame = stream->readUint16LE();
55 	_endFrame = stream->readUint16LE();
56 
57 	_actor = ac;
58 	ac->_assignment = this;
59 	ac->_flags |= hasAssignment;
60 }
61 
62 //----------------------------------------------------------------------
63 //	ActorAssignment destructor
64 
~ActorAssignment(void)65 ActorAssignment::~ActorAssignment(void) {
66 	Actor *a = getActor();
67 	debugC(2, kDebugActors, "Ending assignment for %p (%s): %p",
68 	      (void *)a, a->objName(), (void *)this);
69 
70 	//  Determine if the actor has a task initiated by this assignment
71 	if (a->_currentGoal == actorGoalFollowAssignment
72 	        &&  a->_curTask != NULL) {
73 		//  If so, abort it
74 		a->_curTask->abortTask();
75 		delete a->_curTask;
76 		a->_curTask = NULL;
77 	}
78 
79 	a->_flags &= ~hasAssignment;
80 }
81 
82 //----------------------------------------------------------------------
83 //	Return the number of bytes need to archive the data in this
84 //	assignment
85 
archiveSize(void) const86 inline int32 ActorAssignment::archiveSize(void) const {
87 	return sizeof(_startFrame) + sizeof(_endFrame);
88 }
89 
write(Common::MemoryWriteStreamDynamic * out) const90 void ActorAssignment::write(Common::MemoryWriteStreamDynamic *out) const {
91 	out->writeUint16LE(_startFrame);
92 	out->writeUint16LE(_endFrame);
93 }
94 
95 //----------------------------------------------------------------------
96 //	Determine if the time limit for this assignment has been exceeded
97 
isValid(void)98 bool ActorAssignment::isValid(void) {
99 	uint16  frame = g_vm->_calender->frameInDay();
100 
101 	return      frame < _endFrame
102 	            || (_startFrame >= _endFrame && frame >= _startFrame);
103 }
104 
105 //----------------------------------------------------------------------
106 //	Create a TaskStack for this actor and plug in the assignment's Task.
107 
createTask(void)108 TaskStack *ActorAssignment::createTask(void) {
109 	if (!taskNeeded()) return NULL;
110 
111 	Actor       *a = getActor();
112 	TaskStack   *ts = NULL;
113 
114 	if ((ts = newTaskStack(a)) != NULL) {
115 		Task    *task = getTask(ts);
116 
117 		if (task != NULL)
118 			ts->setTask(task);
119 		else {
120 			delete ts;
121 			ts = NULL;
122 		}
123 	}
124 
125 	return ts;
126 }
127 
getActor(void) const128 Actor *ActorAssignment::getActor(void) const {
129 	return _actor;
130 }
131 
132 
133 //----------------------------------------------------------------------
134 //	This function is called to notify the assignment of the completion
135 //	of a task which the assignment had created.
136 
handleTaskCompletion(TaskResult)137 void ActorAssignment::handleTaskCompletion(TaskResult) {
138 	//  Do nothing
139 }
140 
141 //----------------------------------------------------------------------
142 //	Plug a new task into the actor, if the actor is currently following
143 //	his assignment
144 
startTask(void)145 void ActorAssignment::startTask(void) {
146 	Actor   *a = getActor();
147 
148 	if (a->_currentGoal == actorGoalFollowAssignment)
149 		a->_curTask = createTask();
150 }
151 
152 //----------------------------------------------------------------------
153 //	Determine if this assignment needs to create a task at this time
154 
taskNeeded(void)155 bool ActorAssignment::taskNeeded(void) {
156 	return true;
157 }
158 
159 /* ===================================================================== *
160    PatrolRouteAssignment member functions
161  * ===================================================================== */
162 
163 //----------------------------------------------------------------------
164 //	Constructor -- initial object construction
165 
PatrolRouteAssignment(Actor * a,uint16 until,int16 rteNo,uint8 patrolFlags,int16 start,int16 end)166 PatrolRouteAssignment::PatrolRouteAssignment(
167 	Actor *a,
168     uint16  until,
169     int16   rteNo,
170     uint8   patrolFlags,
171     int16   start,
172     int16   end) :
173 	ActorAssignment(a, until),
174 	_routeNo(rteNo),
175 	_startingWayPoint(start),
176 	_endingWayPoint(end),
177 	_routeFlags(patrolFlags),
178 	_flags(0) {
179 }
180 
PatrolRouteAssignment(Actor * a,Common::SeekableReadStream * stream)181 PatrolRouteAssignment::PatrolRouteAssignment(Actor *a, Common::SeekableReadStream *stream) :
182 	ActorAssignment(a, stream) {
183 	debugC(4, kDebugSaveload, "... Loading PatrolRouteAssignment");
184 
185 	//  Restore route number
186 	_routeNo = stream->readSint16LE();
187 	//  Restore the starting way point
188 	_startingWayPoint = stream->readSint16LE();
189 	//  Restore the ending way point
190 	_endingWayPoint = stream->readSint16LE();
191 
192 	//  Restore the route flags
193 	_routeFlags = stream->readByte();
194 	//  Restore the assignment flags
195 	_flags = stream->readByte();
196 }
197 
198 //----------------------------------------------------------------------
199 //	Return the number of bytes need to archive the data in this
200 //	assignment
201 
archiveSize(void) const202 inline int32 PatrolRouteAssignment::archiveSize(void) const {
203 	return      ActorAssignment::archiveSize()
204 	            +   sizeof(_routeNo)
205 	            +   sizeof(_startingWayPoint)
206 	            +   sizeof(_endingWayPoint)
207 	            +   sizeof(_routeFlags)
208 	            +   sizeof(_flags);
209 }
210 
write(Common::MemoryWriteStreamDynamic * out) const211 void PatrolRouteAssignment::write(Common::MemoryWriteStreamDynamic *out) const {
212 	debugC(3, kDebugSaveload, "... Saving PatrolRouteAssignment");
213 
214 	//  Let the base class write its data to the buffer
215 	ActorAssignment::write(out);
216 
217 	//  Store the route number
218 	out->writeSint16LE(_routeNo);
219 	out->writeSint16LE(_startingWayPoint);
220 	out->writeSint16LE(_endingWayPoint);
221 
222 	//  Store the route flags
223 	out->writeByte(_routeFlags);
224 	//  Store the assignment flags
225 	out->writeByte(_flags);
226 }
227 
228 //----------------------------------------------------------------------
229 //	Return an integer representing the class of this object for archival
230 //	reasons.
231 
type(void) const232 int16 PatrolRouteAssignment::type(void) const {
233 	return patrolRouteAssignment;
234 }
235 
236 //----------------------------------------------------------------------
237 //	This function is called to notify the assignment of the completion
238 //	of a task which the assignment had created.
239 
handleTaskCompletion(TaskResult result)240 void PatrolRouteAssignment::handleTaskCompletion(TaskResult result) {
241 	if (result == taskSucceeded) _flags |= routeCompleted;
242 }
243 
244 //----------------------------------------------------------------------
245 //	Determine if assignment is still valid
246 
isValid(void)247 bool PatrolRouteAssignment::isValid(void) {
248 	//  If the route has already been completed, then the assignment is
249 	//  no longer valid
250 	if (_flags & routeCompleted) return false;
251 
252 	return ActorAssignment::isValid();
253 }
254 
255 //----------------------------------------------------------------------
256 //	Determine if this assignment needs to create a task at this time
257 
taskNeeded(void)258 bool PatrolRouteAssignment::taskNeeded(void) {
259 	//  If the route has already been completed, then no task is needed
260 	return !(_flags & routeCompleted);
261 }
262 
263 //----------------------------------------------------------------------
264 //	Construct a Task for this assignment
265 
getTask(TaskStack * ts)266 Task *PatrolRouteAssignment::getTask(TaskStack *ts) {
267 	int16       startPoint = _startingWayPoint;
268 	uint8       mapNum = getActor()->getMapNum();
269 
270 	_startingWayPoint = -1;
271 
272 	if (startPoint == -1) {
273 		int16               i;
274 		uint16              bestDist = maxuint16;
275 		const PatrolRoute   &route = patrolRouteList[mapNum]->getRoute(_routeNo);
276 		TilePoint           actorLoc = getActor()->getLocation();
277 
278 		for (i = 0; i < route.vertices(); i++) {
279 			uint16  dist = lineDist(route[i], route[(i + 1) % route.vertices()], actorLoc);
280 
281 			if (dist < bestDist) {
282 				bestDist = dist;
283 				startPoint = (_routeFlags & patrolRouteReverse) ? i : (i + 1) % route.vertices();
284 			}
285 		}
286 	}
287 
288 	//  Construct a patrol route iterator.
289 	PatrolRouteIterator
290 	iter =  PatrolRouteIterator(
291 	            mapNum,
292 	            _routeNo,
293 	            _routeFlags,
294 	            startPoint);
295 
296 	//  Construct a FollowPatrolRouteTask
297 	return  _endingWayPoint != -1
298 	        ?   new FollowPatrolRouteTask(ts, iter, _endingWayPoint)
299 	        :   new FollowPatrolRouteTask(ts, iter);
300 }
301 
302 /* ===================================================================== *
303    HuntToBeNearLocationAssignment member functions
304  * ===================================================================== */
305 
HuntToBeNearLocationAssignment(Actor * a,const TilePoint & tp,uint16 r)306 HuntToBeNearLocationAssignment::HuntToBeNearLocationAssignment(Actor *a, const TilePoint &tp, uint16 r) :
307 	ActorAssignment(a, kIndefiniteTime) {
308 	initialize(LocationTarget(tp), r);
309 }
310 
311 //  Construct with no time limit and an abstract target
HuntToBeNearLocationAssignment(Actor * a,const Target & targ,uint16 r)312 HuntToBeNearLocationAssignment::HuntToBeNearLocationAssignment(Actor *a, const Target &targ, uint16 r) :
313 	ActorAssignment(a, kIndefiniteTime) {
314 	initialize(targ, r);
315 }
316 
317 //----------------------------------------------------------------------
318 //	An initialization function which provides a common ground for
319 //	the initial constructors.
320 
initialize(const Target & targ,uint16 r)321 void HuntToBeNearLocationAssignment::initialize(
322     const Target    &targ,
323     uint16          r) {
324 	assert(targ.size() <= sizeof(_targetMem));
325 	//  Make a copy of the target
326 	targ.clone(_targetMem);
327 
328 	_range = r;
329 }
330 
HuntToBeNearLocationAssignment(Actor * a,Common::SeekableReadStream * stream)331 HuntToBeNearLocationAssignment::HuntToBeNearLocationAssignment(Actor *a, Common::SeekableReadStream *stream) :
332 	ActorAssignment(a, stream) {
333 	debugC(4, kDebugSaveload, "... Loading HuntToBeNearLocationAssignment");
334 
335 	//  Restore the target
336 	readTarget(_targetMem, stream);
337 
338 	//  Restore the range
339 	_range = stream->readUint16LE();
340 }
341 
342 //----------------------------------------------------------------------
343 //	Return the number of bytes need to archive the data in this
344 //	assignment
345 
archiveSize(void) const346 inline int32 HuntToBeNearLocationAssignment::archiveSize(void) const {
347 	return      ActorAssignment::archiveSize()
348 	            +   targetArchiveSize(getTarget())
349 	            +   sizeof(_range);
350 }
351 
write(Common::MemoryWriteStreamDynamic * out) const352 void HuntToBeNearLocationAssignment::write(Common::MemoryWriteStreamDynamic *out) const {
353 	debugC(3, kDebugSaveload, "... Saving HuntToBeNearLocationAssignment");
354 
355 	//  Let the base class archive its data
356 	ActorAssignment::write(out);
357 
358 	//  Store the target
359 	writeTarget(getTarget(), out);
360 
361 	//  Store the range
362 	out->writeUint16LE(_range);
363 }
364 
365 //----------------------------------------------------------------------
366 //	Return an integer representing the class of this object for archival
367 //	reasons.
368 
type(void) const369 int16 HuntToBeNearLocationAssignment::type(void) const {
370 	return huntToBeNearLocationAssignment;
371 }
372 
373 //----------------------------------------------------------------------
374 //	Determine if this assignment needs to create a task at this time
375 
taskNeeded(void)376 bool HuntToBeNearLocationAssignment::taskNeeded(void) {
377 	Actor       *a  = getActor();
378 	TilePoint   actorLoc = a->getLocation();
379 
380 	return !a->inRange(getTarget()->where(a->world(), actorLoc), _range);
381 }
382 
383 //----------------------------------------------------------------------
384 //	Construct a Task for this assignment
385 
getTask(TaskStack * ts)386 Task *HuntToBeNearLocationAssignment::getTask(TaskStack *ts) {
387 	return new HuntToBeNearLocationTask(ts, *getTarget(), _range);
388 }
389 
390 /* ===================================================================== *
391    HuntToBeNearActorAssignment member functions
392  * ===================================================================== */
393 
394 //  Construct with no time limit and specific actor
HuntToBeNearActorAssignment(Actor * a,uint16 r,bool trackFlag)395 HuntToBeNearActorAssignment::HuntToBeNearActorAssignment(
396 	Actor               *a,
397 	uint16              r,
398 	bool                trackFlag) :
399 	ActorAssignment(a, kIndefiniteTime) {
400 	assert(isActor(a) && a != getActor());
401 	initialize(SpecificActorTarget(a), r, trackFlag);
402 }
403 
404 //  Construct with no time limit and abstract actor target
HuntToBeNearActorAssignment(Actor * a,const ActorTarget & at,uint16 r,bool trackFlag)405 HuntToBeNearActorAssignment::HuntToBeNearActorAssignment(
406 	Actor *a,
407 	const ActorTarget   &at,
408 	uint16              r,
409 	bool                trackFlag) :
410 	ActorAssignment(a, kIndefiniteTime) {
411 	initialize(at, r, trackFlag);
412 }
413 
414 //----------------------------------------------------------------------
415 //	An initialization function which provides a common ground for the
416 //	initial constructors.
417 
initialize(const ActorTarget & at,uint16 r,bool trackFlag)418 void HuntToBeNearActorAssignment::initialize(
419     const ActorTarget   &at,
420     uint16              r,
421     bool                trackFlag) {
422 	assert(at.size() <= sizeof(_targetMem));
423 
424 	//  Copy the target
425 	at.clone(_targetMem);
426 
427 	_range = r;
428 	_flags = trackFlag ? track : 0;
429 }
430 
HuntToBeNearActorAssignment(Actor * a,Common::SeekableReadStream * stream)431 HuntToBeNearActorAssignment::HuntToBeNearActorAssignment(Actor *a, Common::SeekableReadStream *stream) :
432 	ActorAssignment(a, stream) {
433 	debugC(4, kDebugSaveload, "... Loading HuntToBeNearActorAssignment");
434 
435 	readTarget(_targetMem, stream);
436 
437 	//  Restore the range
438 	_range = stream->readUint16LE();
439 
440 	//  Restore the flags
441 	_flags = stream->readByte();
442 }
443 
444 //----------------------------------------------------------------------
445 //	Return the number of bytes need to archive the data in this
446 //	assignment
447 
archiveSize(void) const448 inline int32 HuntToBeNearActorAssignment::archiveSize(void) const {
449 	return      ActorAssignment::archiveSize()
450 	            +   targetArchiveSize(getTarget())
451 	            +   sizeof(_range)
452 	            +   sizeof(_flags);
453 }
454 
write(Common::MemoryWriteStreamDynamic * out) const455 void HuntToBeNearActorAssignment::write(Common::MemoryWriteStreamDynamic *out) const {
456 	debugC(3, kDebugSaveload, "... Saving HuntToBeNearActorAssignment");
457 
458 	//  Let the base class archive its data
459 	ActorAssignment::write(out);
460 
461 	//  Store the target
462 	writeTarget(getTarget(), out);
463 
464 	//  Store the range
465 	out->writeUint16LE(_range);
466 
467 	//  Store the flags
468 	out->writeByte(_flags);
469 }
470 
471 //----------------------------------------------------------------------
472 //	Return an integer representing the class of this object for archival
473 //	reasons.
474 
type(void) const475 int16 HuntToBeNearActorAssignment::type(void) const {
476 	return huntToBeNearActorAssignment;
477 }
478 
479 //----------------------------------------------------------------------
480 //	Determine if this assignment needs to create a task at this time
481 
taskNeeded(void)482 bool HuntToBeNearActorAssignment::taskNeeded(void) {
483 	Actor       *a  = getActor();
484 	TilePoint   actorLoc = a->getLocation(),
485 	            targetLoc = getTarget()->where(a->world(), actorLoc);
486 
487 	return      !a->inRange(targetLoc, _range)
488 	            ||  a->inRange(targetLoc, HuntToBeNearActorTask::tooClose);
489 }
490 
491 //----------------------------------------------------------------------
492 //	Construct a Task for this assignment
493 
getTask(TaskStack * ts)494 Task *HuntToBeNearActorAssignment::getTask(TaskStack *ts) {
495 	return new HuntToBeNearActorTask(
496 	           ts,
497 	           *getTarget(),
498 	           _range,
499 	           (_flags & track) != false);
500 }
501 
502 /* ===================================================================== *
503    HuntToKillAssignment member functions
504  * ===================================================================== */
505 
506 //  Construct with no time limit and specific actor
HuntToKillAssignment(Actor * a,bool trackFlag)507 HuntToKillAssignment::HuntToKillAssignment(Actor *a, bool trackFlag) :
508 	ActorAssignment(a, kIndefiniteTime) {
509 	assert(isActor(a) && a != getActor());
510 	initialize(SpecificActorTarget(a), trackFlag, true);
511 }
512 
513 //  Construct with no time limit and abstract actor target
HuntToKillAssignment(Actor * a,const ActorTarget & at,bool trackFlag)514 HuntToKillAssignment::HuntToKillAssignment(
515 	Actor *a,
516 	const ActorTarget   &at,
517 	bool                trackFlag) :
518 	ActorAssignment(a, kIndefiniteTime) {
519 	initialize(at, trackFlag, false);
520 }
521 
522 
523 //----------------------------------------------------------------------
524 //	An initialization function which provides a common ground for the
525 //	initial constructors.
526 
initialize(const ActorTarget & at,bool trackFlag,bool specificActorFlag)527 void HuntToKillAssignment::initialize(
528     const ActorTarget   &at,
529     bool                trackFlag,
530     bool                specificActorFlag) {
531 	assert(at.size() <= sizeof(_targetMem));
532 
533 	//  Copy the target
534 	at.clone(_targetMem);
535 
536 	_flags = (trackFlag ? track : 0)
537 	        | (specificActorFlag ? specificActor : 0);
538 }
539 
540 //----------------------------------------------------------------------
541 //	Return the number of bytes need to archive the data in this
542 //	assignment
543 
archiveSize(void) const544 inline int32 HuntToKillAssignment::archiveSize(void) const {
545 	return      ActorAssignment::archiveSize()
546 	            +   targetArchiveSize(getTarget())
547 	            +   sizeof(_flags);
548 }
549 
write(Common::MemoryWriteStreamDynamic * out) const550 void HuntToKillAssignment::write(Common::MemoryWriteStreamDynamic *out) const {
551 	debugC(3, kDebugSaveload, "... Saving HuntToKillAssignment");
552 
553 	//  Let the base class archive its data
554 	ActorAssignment::write(out);
555 
556 	//  Store the target
557 	writeTarget(getTarget(), out);
558 
559 	//  Store the flags
560 	out->writeByte(_flags);
561 }
562 
563 //----------------------------------------------------------------------
564 //	Determine if this assignment is still valid
565 
isValid(void)566 bool HuntToKillAssignment::isValid(void) {
567 	//  If the target actor is already dead, then this is not a valid
568 	//  assignment
569 	if (_flags & specificActor) {
570 		const SpecificActorTarget *sat = (const SpecificActorTarget *)getTarget();
571 
572 		if (sat->getTargetActor()->isDead()) return false;
573 	}
574 
575 	//  Otherwise, determine if the base class thinks this is a valid
576 	//  assignment
577 	return ActorAssignment::isValid();
578 }
579 
580 //----------------------------------------------------------------------
581 //	Return an integer representing the class of this object for archival
582 //	reasons.
583 
type(void) const584 int16 HuntToKillAssignment::type(void) const {
585 	return huntToKillAssignment;
586 }
587 
588 //----------------------------------------------------------------------
589 //	Determine if this assignment needs to create a task at this time
590 
taskNeeded(void)591 bool HuntToKillAssignment::taskNeeded(void) {
592 	//  If we're hunting a specific actor, we only need a task if that
593 	//  actor is still alive.
594 	if (_flags & specificActor) {
595 		const SpecificActorTarget *sat = (const SpecificActorTarget *)getTarget();
596 
597 		return !sat->getTargetActor()->isDead();
598 	}
599 
600 	//  Otherwise, we'll always want to create a task
601 	return true;
602 }
603 
604 //----------------------------------------------------------------------
605 //	Construct a Task for this assignment
606 
getTask(TaskStack * ts)607 Task *HuntToKillAssignment::getTask(TaskStack *ts) {
608 	return new HuntToKillTask(
609 	           ts,
610 	           *getTarget(),
611 	           (_flags & track) != false);
612 }
613 
614 /* ===================================================================== *
615    TetheredAssignment member functions
616  * ===================================================================== */
617 
TetheredAssignment(Actor * ac,Common::SeekableReadStream * stream)618 TetheredAssignment::TetheredAssignment(Actor *ac, Common::SeekableReadStream *stream) : ActorAssignment(ac, stream) {
619 	debugC(4, kDebugSaveload, "... Loading TetheredAssignment");
620 
621 	//  Read data from buffer
622 	_minU = stream->readSint16LE();
623 	_minV = stream->readSint16LE();
624 	_maxU = stream->readSint16LE();
625 	_maxV = stream->readSint16LE();
626 }
627 
628 //----------------------------------------------------------------------
629 //	Return the number of bytes need to archive the data in this
630 //	assignment
631 
archiveSize(void) const632 inline int32 TetheredAssignment::archiveSize(void) const {
633 	return      ActorAssignment::archiveSize()
634 	            +   sizeof(_minU)
635 	            +   sizeof(_minV)
636 	            +   sizeof(_maxU)
637 	            +   sizeof(_maxV);
638 }
639 
write(Common::MemoryWriteStreamDynamic * out) const640 void TetheredAssignment::write(Common::MemoryWriteStreamDynamic *out) const {
641 	debugC(3, kDebugSaveload, "... Saving TetheredAssignment");
642 
643 	//  Let the base class archive its data
644 	ActorAssignment::write(out);
645 
646 	//  Copy data to buffer
647 	out->writeSint16LE(_minU);
648 	out->writeSint16LE(_minV);
649 	out->writeSint16LE(_maxU);
650 	out->writeSint16LE(_maxV);
651 }
652 
653 /* ===================================================================== *
654    TetheredWanderAssignment member functions
655  * ===================================================================== */
656 
657 //----------------------------------------------------------------------
658 //	Constructor -- initial assignment construction
659 
TetheredWanderAssignment(Actor * a,uint16 until,const TileRegion & reg)660 TetheredWanderAssignment::TetheredWanderAssignment(
661 	Actor *a,
662     uint16 until,
663     const TileRegion &reg) :
664 	TetheredAssignment(a, until, reg) {
665 }
666 
667 //----------------------------------------------------------------------
668 //	Return an integer representing the class of this object for archival
669 //	reasons.
670 
type(void) const671 int16 TetheredWanderAssignment::type(void) const {
672 	return tetheredWanderAssignment;
673 }
674 
675 //----------------------------------------------------------------------
676 //	Construct a Task for this assignment
677 
getTask(TaskStack * ts)678 Task *TetheredWanderAssignment::getTask(TaskStack *ts) {
679 	return new TetheredWanderTask(ts, _minU, _minV, _maxU, _maxV);
680 }
681 
682 /* ===================================================================== *
683    AttendAssignment member functions
684  * ===================================================================== */
685 
686 //----------------------------------------------------------------------
687 //	Constructor -- initial assignment construction
688 
AttendAssignment(Actor * a,uint16 until,GameObject * o)689 AttendAssignment::AttendAssignment(Actor *a, uint16 until, GameObject *o) :
690 	ActorAssignment(a, until),
691 	_obj(o) {
692 }
693 
AttendAssignment(Actor * a,Common::SeekableReadStream * stream)694 AttendAssignment::AttendAssignment(Actor *a, Common::SeekableReadStream *stream) : ActorAssignment(a, stream) {
695 	debugC(4, kDebugSaveload, "... Loading AttendAssignment");
696 
697 	ObjectID    objID;
698 
699 	//  Get the object ID
700 	objID = stream->readUint16LE();
701 
702 	//  Convert the object ID to an object pointer
703 	_obj = objID != Nothing ? GameObject::objectAddress(objID) : NULL;
704 }
705 
706 //----------------------------------------------------------------------
707 //	Return the number of bytes need to archive the data in this
708 //	assignment
709 
archiveSize(void) const710 inline int32 AttendAssignment::archiveSize(void) const {
711 	return      ActorAssignment::archiveSize()
712 	            +   sizeof(ObjectID);
713 }
714 
write(Common::MemoryWriteStreamDynamic * out) const715 void AttendAssignment::write(Common::MemoryWriteStreamDynamic *out) const {
716 	debugC(3, kDebugSaveload, "... Saving AttendAssignment");
717 
718 	//  Let the base class write its data to the buffer
719 	ActorAssignment::write(out);
720 
721 	ObjectID    objID;
722 
723 	//  Convert the object pointer to an object ID
724 	objID = _obj != NULL ? _obj->thisID() : Nothing;
725 
726 	//  Store the object ID
727 	out->writeUint16LE(objID);
728 }
729 
730 //----------------------------------------------------------------------
731 //	Return an integer representing the class of this object for archival
732 //	reasons.
733 
type(void) const734 int16 AttendAssignment::type(void) const {
735 	return attendAssignment;
736 }
737 
738 //----------------------------------------------------------------------
739 //	Construct a Task for this assignment
740 
getTask(TaskStack * ts)741 Task *AttendAssignment::getTask(TaskStack *ts) {
742 	return new AttendTask(ts, _obj);
743 }
744 
745 /* ===================================================================== *
746    Misc functions
747  * ===================================================================== */
748 
readAssignment(Actor * a,Common::InSaveFile * in)749 void readAssignment(Actor *a, Common::InSaveFile *in) {
750 	//  Get the type which is the first word in the archive buffer
751 	int16 type = in->readSint16LE();
752 
753 	//  Based upon the type, call the correct constructor
754 	switch (type) {
755 	case patrolRouteAssignment:
756 		new PatrolRouteAssignment(a, in);
757 		break;
758 
759 	case huntToBeNearActorAssignment:
760 		new HuntToBeNearActorAssignment(a, in);
761 		break;
762 
763 	case huntToBeNearLocationAssignment:
764 		new HuntToBeNearLocationAssignment(a, in);
765 		break;
766 
767 	case tetheredWanderAssignment:
768 		new TetheredWanderAssignment(a, in);
769 		break;
770 
771 	case attendAssignment:
772 		new AttendAssignment(a, in);
773 		break;
774 	}
775 }
776 
777 //----------------------------------------------------------------------
778 //	Return the number of bytes necessary to archive this actor's
779 //	assignment in an archive buffer
780 
assignmentArchiveSize(Actor * a)781 int32 assignmentArchiveSize(Actor *a) {
782 	ActorAssignment     *assign = a->getAssignment();
783 
784 	return assign != NULL ? sizeof(int16) + assign->archiveSize() : 0;
785 }
786 
writeAssignment(Actor * a,Common::MemoryWriteStreamDynamic * out)787 void writeAssignment(Actor *a, Common::MemoryWriteStreamDynamic *out) {
788 	ActorAssignment *assign = a->getAssignment();
789 
790 	if (assign != NULL) {
791 		out->writeSint16LE(assign->type());
792 
793 		assign->write(out);
794 	}
795 }
796 
797 }
798