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 #ifndef ASYLUM_RESOURCES_ACTOR_H 24 #define ASYLUM_RESOURCES_ACTOR_H 25 26 #include "common/array.h" 27 #include "common/rect.h" 28 #include "common/serializer.h" 29 #include "common/stream.h" 30 31 #include "asylum/shared.h" 32 33 #include "asylum/resources/inventory.h" 34 35 namespace Asylum { 36 37 class AsylumEngine; 38 class GraphicResource; 39 class Screen; 40 41 struct ActionArea; 42 struct GraphicFrame; 43 44 struct ActorData : public Common::Serializable { 45 uint32 count; 46 int32 current; 47 Common::Point points[120]; 48 ActorDirection directions[120]; 49 ActorDataActorData50 ActorData() { 51 count = 0; 52 current = 0; 53 memset(&directions, 0, sizeof(directions)); 54 } 55 ~ActorDataActorData56 virtual ~ActorData() {} 57 loadActorData58 void load(Common::SeekableReadStream *stream) { 59 count = stream->readUint32LE(); 60 61 current = stream->readUint32LE(); 62 63 for (int32 i = 0; i < 120; i++) { 64 points[i].x = stream->readSint32LE(); 65 points[i].y = stream->readSint32LE(); 66 } 67 68 for (int32 i = 0; i < 120; i++) 69 directions[i] = (ActorDirection)stream->readSint32LE(); 70 } 71 72 // Serializable saveLoadWithSerializerActorData73 void saveLoadWithSerializer(Common::Serializer &s) { 74 s.syncAsUint32LE(count); 75 s.syncAsSint32LE(current); 76 77 for (int32 i = 0; i < ARRAYSIZE(points); i++) { 78 s.syncAsSint32LE(points[i].x); 79 s.syncAsSint32LE(points[i].y); 80 } 81 82 for (int32 i = 0; i < ARRAYSIZE(directions); i++) 83 s.syncAsSint32LE(directions[i]); 84 } 85 }; 86 87 class Actor : public Common::Serializable { 88 public: 89 Actor(AsylumEngine *engine, ActorIndex index); ~Actor()90 virtual ~Actor() {}; 91 92 ////////////////////////////////////////////////////////////////////////// 93 // Public variables & accessors 94 ////////////////////////////////////////////////////////////////////////// 95 int32 flags; 96 int32 actionType; // ActionType enum value 97 Inventory inventory; 98 setActionIndex2(int32 index)99 void setActionIndex2(int32 index) { _actionIdx2 = index; } setObjectIndex(int32 index)100 void setObjectIndex(int32 index) { _objectIndex = index; } setDirection(ActorDirection dir)101 void setDirection(ActorDirection dir) { _direction = dir; } setFrameCount(int32 count)102 void setFrameCount(int32 count) { _frameCount = count; } setFrameIndex(int32 number)103 void setFrameIndex(int32 number) { _frameIndex = number; } setLastScreenUpdate(int32 tick)104 void setLastScreenUpdate(int32 tick) { _lastScreenUpdate = tick; } setNumberFlag01(int32 number)105 void setNumberFlag01(int32 number) { _numberFlag01 = number; } setPriority(int32 priority)106 void setPriority(int32 priority) { _priority = priority; } setResourceId(ResourceId id)107 void setResourceId(ResourceId id) { _resourceId = id; } setSoundResourceId(ResourceId id)108 void setSoundResourceId(ResourceId id) { _soundResourceId = id; } setStatus(ActorStatus status)109 void setStatus(ActorStatus status) { _status = status; } setTransparency(int32 val)110 void setTransparency(int32 val) { _transparency = val; } setTickCount(int32 tickCount)111 void setTickCount(int32 tickCount) { _tickCount = tickCount; } 112 setField934(int32 val)113 void setField934(int32 val) { _field_934 = val; } setField938(int32 val)114 void setField938(int32 val) { _field_938 = val; } setField944(int32 val)115 void setField944(int32 val) { _field_944 = val; } 116 getActionIndex3()117 int32 getActionIndex3() { return _actionIdx3; } getBoundingRect()118 Common::Rect *getBoundingRect() { return &_boundingRect; } getDirection()119 ActorDirection getDirection() { return _direction; } getFrameCount()120 uint32 getFrameCount() { return _frameCount; } getFrameIndex()121 uint32 getFrameIndex() { return _frameIndex; } getName()122 char *getName() { return (char *)&_name; } getNextActorIndex()123 ActorIndex getNextActorIndex() { return _nextActorIndex; } getNumberValue01()124 int32 getNumberValue01() { return _numberValue01; } getPoint()125 Common::Point *getPoint() { return &_point; } getPoint1()126 Common::Point *getPoint1() { return &_point1; } getPoint2()127 Common::Point *getPoint2() { return &_point2; } getPriority()128 int32 getPriority() { return _priority; } getResourceId()129 ResourceId getResourceId() { return _resourceId; } getResourcesId(uint32 index)130 ResourceId getResourcesId(uint32 index) { return _graphicResourceIds[index]; } getScriptIndex()131 int32 getScriptIndex() { return _scriptIndex; } shouldInvertPriority()132 bool shouldInvertPriority() { return _invertPriority; } getSoundResourceId()133 ResourceId getSoundResourceId() { return _soundResourceId; } getStatus()134 ActorStatus getStatus() { return _status; } getTickCount()135 int32 getTickCount() { return _tickCount; } 136 getField934()137 int32 getField934() { return _field_934; } getField944()138 int32 getField944() { return _field_944; } getField948()139 int32 getField948() { return _field_948; } getField94C()140 int32 getField94C() { return _field_94C; } 141 142 // For saving getData()143 ActorData *getData() { return &_data; } 144 145 ///////////////////////////////////////////////////////////////////////// 146 // Data 147 ///////////////////////////////////////////////////////////////////////// 148 149 /** 150 * Loads the actor 151 * 152 * @param stream If non-null, the Common::SeekableReadStream to load from 153 */ 154 void load(Common::SeekableReadStream *stream); 155 156 ///////////////////////////////////////////////////////////////////////// 157 // Visibility 158 ///////////////////////////////////////////////////////////////////////// 159 160 /** 161 * Query if this actor is visible. 162 * 163 * @return true if visible, false if not. 164 */ isVisible()165 bool isVisible() { return flags & kActorFlagVisible; } 166 167 /** 168 * Query if this actor is on screen. 169 * 170 * @return true if on screen, false if not. 171 */ 172 bool isOnScreen(); 173 174 /** 175 * Shows this actor. 176 */ show()177 void show() { setVisible(true); } 178 179 /** 180 * Hides this actor. 181 */ hide()182 void hide() { setVisible(false); } 183 184 ///////////////////////////////////////////////////////////////////////// 185 // Drawing & update 186 ////////////////////////////////////////////////////////////////////////// 187 188 /** 189 * Draws the actor 190 */ 191 void draw(); 192 193 /** 194 * Draw number text (called on scene drawing) 195 */ 196 void drawNumber(); 197 198 /** 199 * Updates the actor. 200 */ 201 void update(); 202 203 /** 204 * Enables the actor 205 */ enable()206 void enable() { changeStatus(kActorStatusEnabled); } 207 208 /** 209 * Changes the actor status. 210 * 211 * @param status The status. 212 */ 213 void changeStatus(ActorStatus status); 214 215 ///////////////////////////////////////////////////////////////////////// 216 // Direction & position 217 ///////////////////////////////////////////////////////////////////////// 218 219 /** 220 * Updates the actor's mirror image. 221 */ 222 void updateReflectionData(); 223 224 /** 225 * Updates resource Id using the actor direction. 226 * 227 * @param direction The direction. 228 */ 229 void changeDirection(ActorDirection direction); 230 231 /** 232 * Face a target from a certain direction 233 * 234 * @param target Identifier for the target. 235 * @param from direction to face from. 236 */ 237 void faceTarget(uint32 target, DirectionFrom from); 238 239 /** 240 * Initialize the x1/y1 values of the actor, update the active animation frame and, if the current direction isn't 8, update the actor's direction. 241 * 242 * @param newX The new x coordinate. 243 * @param newY The new y coordinate. 244 * @param newDirection The new direction. 245 * @param frame The frame. 246 */ 247 void setPosition(int16 newX, int16 newY, ActorDirection newDirection, uint32 frame); 248 249 /** 250 * Query if a graphic resource is present. 251 * 252 * @param index Zero-based index of the graphic resource. 253 * 254 * @return true if the graphic resource is present. 255 */ 256 bool canChangeStatus(int index) const; 257 258 /** 259 * Adjust coordinates. 260 * 261 * @param point The point. 262 */ 263 void adjustCoordinates(Common::Point *point); 264 265 ///////////////////////////////////////////////////////////////////////// 266 // Misc 267 ///////////////////////////////////////////////////////////////////////// 268 269 /** 270 * Stop the actor related sounds 271 */ 272 void stopSound(); 273 274 /** 275 * Convert this object into a string representation. 276 * 277 * @param shortString toggle whether to output a summary or 278 * detailed view of the actor object 279 * @return A string representation of this object. 280 */ 281 Common::String toString(bool shortString = true); 282 283 /** 284 * Clears actor data fields 285 */ 286 void clearFields(); 287 288 bool canReach(const Common::Point &point); 289 void forceTo(int16 actorX, int16 actorY, bool doSpeech); 290 void setupReflectionData(ActorIndex nextActor, int32 actionAreaId, ActorDirection nextDirection, const Common::Point &nextPosition, bool invertPriority, const Common::Point &nextPositionOffset); 291 bool aNicePlaceToTalk(Common::Point *point, int32* param); 292 bool canMove(Common::Point *point, ActorDirection direction, uint32 count, bool hasDelta); 293 void move(ActorDirection dir, uint32 distance); 294 bool testActorCollision(Common::Point *point, ActorDirection direction); 295 void drawInventory(); 296 void stopWalking(); 297 298 /** 299 * Query if the object resource is present in the resource table between indices 10 & 20 300 * 301 * @return true if resource present between 15 & 20, false if not. 302 */ 303 bool checkBoredStatus() const; 304 305 ////////////////////////////////////////////////////////////////////////// 306 // Static update methods 307 ////////////////////////////////////////////////////////////////////////// 308 static void crowsReturn(AsylumEngine *engine); 309 310 /** 311 * Updates the player appearance in chapter 9. 312 * 313 * @param [in,out] engine If non-null, the engine. 314 * @param nextPlayer The next player index 315 */ 316 static void morphInto(AsylumEngine *engine, int nextPlayer); 317 318 /** 319 * Gets a direction using the angle between the two vectors. 320 * 321 * @param vec1 The first vector. 322 * @param vec2 The second vector. 323 * 324 * @return The direction 325 */ 326 static ActorDirection getAngle(const Common::Point &vec1, const Common::Point &vec2); 327 328 /** 329 * Gets the euclidean distance between two points. 330 * 331 * @param point1 The first point. 332 * @param point2 The second point. 333 * 334 * @return the distance. 335 */ 336 static uint32 euclidianDistance(const Common::Point &point1, const Common::Point &point2); 337 338 // Serializable 339 void saveLoadWithSerializer(Common::Serializer &s); 340 341 private: 342 AsylumEngine *_vm; 343 344 // Our current index 345 ActorIndex _index; 346 347 ////////////////////////////////////////////////////////////////////////// 348 // Data 349 ////////////////////////////////////////////////////////////////////////// 350 Common::Point _point; 351 ResourceId _resourceId; 352 int32 _objectIndex; 353 uint32 _frameIndex; 354 uint32 _frameCount; 355 Common::Point _point1; 356 Common::Point _point2; 357 Common::Rect _boundingRect; 358 ActorDirection _direction; 359 int32 _field_3C; 360 ActorStatus _status; 361 int32 _field_44; 362 int32 _priority; 363 //flags 364 int32 _field_50; 365 int32 _field_54; 366 int32 _field_58; 367 int32 _field_5C; 368 int32 _field_60; 369 int32 _actionIdx3; 370 // TODO field_68 till field_617 371 ResourceId _walkingSound1; 372 ResourceId _walkingSound2; 373 ResourceId _walkingSound3; 374 ResourceId _walkingSound4; 375 uint32 _field_64C; 376 uint32 _field_650; 377 ResourceId _graphicResourceIds[55]; 378 char _name[256]; 379 int32 _distancesEO[20]; 380 int32 _distancesNS[20]; 381 int32 _distancesNSEO[20]; 382 int32 _actionIdx2; 383 int32 _field_924; 384 uint32 _lastScreenUpdate; 385 int32 _scriptIndex; 386 //actionType 387 int32 _field_934; 388 int32 _field_938; 389 ResourceId _soundResourceId; // field_93C 390 int32 _numberValue01; 391 int32 _field_944; // has collision ?! 392 int32 _field_948; 393 int32 _field_94C; 394 int32 _numberFlag01; 395 int16 _numberStringWidth; 396 Common::Point _numberPoint; 397 char _numberString01[8]; 398 int32 _field_968; 399 int32 _transparency; 400 bool _processNewDirection; 401 bool _invertPriority; 402 ActorDirection _nextDirection; 403 int32 _nextActionIndex; 404 ActorIndex _nextActorIndex; 405 Common::Point _nextPositionOffset; 406 Common::Point _nextPosition; 407 int32 _field_994; 408 int32 _field_998; 409 int32 _field_99C; 410 int32 _field_9A0; 411 412 ////////////////////////////////////////////////////////////////////////// 413 // Actor data 414 ////////////////////////////////////////////////////////////////////////// 415 ActorData _data; 416 417 int32 _tickCount; 418 419 uint32 _updateCounter; 420 421 ////////////////////////////////////////////////////////////////////////// 422 // Update methods 423 ////////////////////////////////////////////////////////////////////////// 424 void updateStatusInteracting(); 425 void checkPumpkinDeath(); 426 void updatePumpkin(GameFlag flagToCheck, GameFlag flagToSet, ObjectId objectToUpdate, ObjectId objectToDisable); 427 428 void updateStatusEnabled(); 429 void updateStatusEnabledProcessStatus(int16 testX, int16 testY, uint32 counter, int16 setX, int16 setY); 430 431 void updateStatusBored(); 432 433 void CrowClosesIn(); 434 void ScareCrowClosesIn(); 435 void TentacleRises(); 436 437 void updateStatusEnabled2(); 438 void CrowHoveringBeforeKill(); 439 void CrowStatusQuo(); 440 void TentacleWigglesForSarah(); 441 442 void CrowDives(); 443 void MaxGetsHit(); 444 void MaxAttacks(); 445 void checkScareCrowDeath(); 446 bool checkCrowDeath(); 447 void ScareCrowAttacks(); 448 bool actorsIntersect(ActorIndex actorIndex1, ActorIndex actorIndex2); 449 void TentacleWhips(); 450 void SarahAttacks(); 451 452 void MaxGetsSome(); 453 void SarahGetsSome(); 454 455 void TentacleDies(); 456 457 void CrowSwoops(); 458 void ScareCrowRetreats(); 459 460 void updateStatusMorphing(); 461 462 void actionAreaCheck(); 463 464 ////////////////////////////////////////////////////////////////////////// 465 // Path finding functions 466 ////////////////////////////////////////////////////////////////////////// 467 uint32 _frameNumber; 468 bool findLeftPath(Common::Point source, const Common::Point &destination, Common::Array<int> *actions); 469 bool findRightPath(Common::Point source, const Common::Point &destination, Common::Array<int> *actions); 470 bool findUpPath(Common::Point source, const Common::Point &destination, Common::Array<int> *actions); 471 bool findDownPath(Common::Point source, const Common::Point &destination, Common::Array<int> *actions); 472 bool tryDirection(const Common::Point &source, Common::Array<int> *actions, Common::Point *point, ActorDirection direction, const Common::Point &destination, bool *flag); 473 bool canGetToDest(Common::Array<int> *actions, const Common::Point &point, ActorDirection direction, int16 loopcount); 474 bool testPolyInLink(const Common::Point &pt, Common::Array<int> *actions); 475 476 ////////////////////////////////////////////////////////////////////////// 477 // Misc 478 ////////////////////////////////////////////////////////////////////////// 479 480 /** 481 * Sets actor visibility 482 * 483 * @param value true to set to visible, false to set to hidden. 484 */ 485 void setVisible(bool value); 486 487 /** 488 * Sets the volume. 489 */ 490 void setVolume(); 491 492 void TentacleBlocksSarah(const Common::Point &vec1, Common::Point vec2); 493 void SarahDies(); 494 495 /** 496 * Updates the actor "number" data if the item is "1". 497 * 498 * @param item The item. 499 * @param point The coordinates 500 */ 501 void updateNumbers(uint item, const Common::Point &point); 502 503 /** 504 * Determine if the supplied point is in the action area 505 * 506 * @param pt The point. 507 * @param [in,out] area If non-null, the area. 508 * 509 * @return true if in the action area, false otherwise 510 */ 511 bool isInActionArea(const Common::Point &pt, ActionArea *area); 512 513 ////////////////////////////////////////////////////////////////////////// 514 // Helper methods 515 ////////////////////////////////////////////////////////////////////////// 516 517 /** 518 * Updates the actor graphic information 519 * 520 * @param offset The offset used to get the id from the _graphicResourceIds table 521 */ 522 void updateGraphicData(uint32 offset); 523 524 /** 525 * Gets the graphics flag for queuing the actor graphics (mirrored or normal) 526 * 527 * @return The graphics flag. 528 */ 529 DrawFlags getGraphicsFlags(); 530 531 /** 532 * Gets the absolute value of the walk increment for a frame. 533 * 534 * @param direction The direction. 535 * @param frameIndex Zero-based index of the frame. 536 * 537 * @return The absolute value of the walk increment. 538 */ 539 int32 getStride(ActorDirection direction, uint32 frameIndex) const; 540 541 /** 542 * Gets the walk increment for a frame. 543 * 544 * @param direction The direction. 545 * @param frameIndex Zero-based index of the frame. 546 * 547 * @return The walk increment. 548 */ 549 int32 getWalkIncrement(ActorDirection direction, uint32 frameIndex) const; 550 551 /** 552 * Updates the coordinates depending on the direction. 553 * 554 * @param direction The direction. 555 * @param delta The delta. 556 * @param [in,out] point If non-null, the point. 557 */ 558 static void incPosition(ActorDirection direction, int16 delta, Common::Point *point); 559 560 /** 561 * Get the angle between the two vectors 562 * 563 * @param p1 The first vector. 564 * @param p2 The second vector. 565 * 566 * @return the angle 567 */ 568 static int32 getAngleOfVector(const Common::Point &vec1, const Common::Point &vec2); 569 570 /** 571 * Computes the Scare Crow's strike zone. 572 * 573 * @param rect The strike zone. 574 * @param direction The direction. 575 * @param point The point. 576 */ 577 static void getCrowStrikeZone(Common::Rect *rect, ActorDirection direction, const Common::Point &point); 578 579 /** 580 * Determines the direction of the shortest rotation between two vectors. 581 * 582 * @param vec1 The first vector. 583 * @param vec2 The second vector. 584 * 585 * @return true if CCW, false if CW. 586 */ 587 static bool determineLeftOrRight(const Common::Point &vec1, const Common::Point &vec2); 588 589 /** 590 * Gets the adjustment for the X-coordinate of the supplied point. 591 * 592 * @param rect The rectangle. 593 * @param point The test point. 594 * 595 * @return value depending on the horizontal position of the point relative to the rectangle. 596 */ 597 static int16 pointInRectXAdjust(const Common::Rect &rect, const Common::Point &point); 598 599 /** 600 * Gets the adjustment for the Y-coordinate of the supplied point. 601 * 602 * @param rect The rectangle. 603 * @param point The test point. 604 * 605 * @return value depending on the vertical position of the point relative to the rectangle. 606 */ 607 static int16 pointInRectYAdjust(const Common::Rect &rect, const Common::Point &point); 608 609 }; // end of class MainActor 610 611 } // end of namespace Asylum 612 613 #endif // ASYLUM_RESOURCES_ACTOR_H 614