aboutsummaryrefslogtreecommitdiff
path: root/engines/parallaction/parallaction.cpp
diff options
context:
space:
mode:
authorNicola Mettifogo2008-08-31 09:30:16 +0000
committerNicola Mettifogo2008-08-31 09:30:16 +0000
commit6db501d61220e39dde691d82599f6aa9ab277d56 (patch)
tree7087505404d2f0fc1f00b6c6cccbdf0318ed244b /engines/parallaction/parallaction.cpp
parentfc518efe08aef3813e5bb1b24111d32a03631b2a (diff)
downloadscummvm-rg350-6db501d61220e39dde691d82599f6aa9ab277d56.tar.gz
scummvm-rg350-6db501d61220e39dde691d82599f6aa9ab277d56.tar.bz2
scummvm-rg350-6db501d61220e39dde691d82599f6aa9ab277d56.zip
Cleanup.
svn-id: r34222
Diffstat (limited to 'engines/parallaction/parallaction.cpp')
-rw-r--r--engines/parallaction/parallaction.cpp381
1 files changed, 381 insertions, 0 deletions
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index c02c9b7ce6..78df9c24a8 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -428,6 +428,387 @@ uint32 Parallaction::getLocationFlags() {
+void Parallaction::drawAnimations() {
+ debugC(9, kDebugExec, "Parallaction_ns::drawAnimations()\n");
+
+ uint16 layer = 0, scale = 100;
+
+ for (AnimationList::iterator it = _location._animations.begin(); it != _location._animations.end(); it++) {
+
+ AnimationPtr anim = *it;
+ GfxObj *obj = anim->gfxobj;
+
+ // Validation is performed here, so that every animation is affected, instead that only the ones
+ // who *own* a script. In fact, some scripts can change values in other animations.
+ // The right way to do this would be to enforce validation when any variable is modified from
+ // a script.
+ anim->validateScriptVars();
+
+ if ((anim->_flags & kFlagsActive) && ((anim->_flags & kFlagsRemove) == 0)) {
+
+ if (anim->_flags & kFlagsNoMasked)
+ layer = LAYER_FOREGROUND;
+ else {
+ if (getGameType() == GType_Nippon) {
+ // Layer in NS depends on where the animation is on the screen, for each animation.
+ layer = _gfx->_backgroundInfo->getLayer(anim->getFrameY() + anim->height());
+ } else {
+ // Layer in BRA is calculated from Z value. For characters it is the same as NS,
+ // but other animations can have Z set from scripts independently from their
+ // position on the screen.
+ layer = _gfx->_backgroundInfo->getLayer(anim->getZ());
+ }
+ }
+
+ if (getGameType() == GType_BRA) {
+ if (anim->_flags & (kFlagsScaled | kFlagsCharacter)) {
+ if (anim->getZ() <= _location._zeta0) {
+ if (anim->getZ() >= _location._zeta1) {
+ scale = ((anim->getZ() - _location._zeta1) * (100 - _location._zeta2)) / (_location._zeta0 - _location._zeta1) + _location._zeta2;
+ } else {
+ scale = _location._zeta2;
+ }
+ }
+ }
+ }
+
+ if (obj) {
+ _gfx->showGfxObj(obj, true);
+ obj->frame = anim->getF();
+ obj->x = anim->getX();
+ obj->y = anim->getY();
+ obj->z = anim->getZ();
+ obj->layer = layer;
+ obj->scale = scale;
+ }
+ }
+
+ if (((anim->_flags & kFlagsActive) == 0) && (anim->_flags & kFlagsRemove)) {
+ anim->_flags &= ~kFlagsRemove;
+ }
+
+ if ((anim->_flags & kFlagsActive) && (anim->_flags & kFlagsRemove)) {
+ anim->_flags &= ~kFlagsActive;
+ anim->_flags |= kFlagsRemove;
+ if (obj) {
+ _gfx->showGfxObj(obj, false);
+ }
+ }
+ }
+
+ debugC(9, kDebugExec, "Parallaction_ns::drawAnimations done()\n");
+
+ return;
+}
+
+
+void Parallaction::showZone(ZonePtr z, bool visible) {
+ if (!z) {
+ return;
+ }
+
+ if (visible) {
+ z->_flags &= ~kFlagsRemove;
+ z->_flags |= kFlagsActive;
+ } else {
+ z->_flags |= kFlagsRemove;
+ }
+
+ if ((z->_type & 0xFFFF) == kZoneGet) {
+ _gfx->showGfxObj(z->u.get->gfxobj, visible);
+
+ GetData *data = z->u.get;
+ if (data->hasMask && _gfx->_backgroundInfo->hasMask) {
+ if (visible) {
+ _gfx->_backgroundInfo->mask.bltOr(data->gfxobj->x, data->gfxobj->y, data->_mask[0], 0, 0, data->_mask->w, data->_mask->h);
+ } else {
+ _gfx->_backgroundInfo->mask.bltCopy(data->gfxobj->x, data->gfxobj->y, data->_mask[1], 0, 0, data->_mask->w, data->_mask->h);
+ }
+ }
+ }
+}
+
+
+//
+// ZONE TYPE: EXAMINE
+//
+
+void Parallaction::enterCommentMode(ZonePtr z) {
+ if (!z) {
+ return;
+ }
+
+ _commentZone = z;
+
+ ExamineData *data = _commentZone->u.examine;
+
+ if (!data->_description) {
+ return;
+ }
+
+ // TODO: move this balloons stuff into DialogueManager and BalloonManager
+ if (getGameType() == GType_Nippon) {
+ int id;
+ if (data->_filename) {
+ if (data->_cnv == 0) {
+ data->_cnv = _disk->loadStatic(data->_filename);
+ }
+
+ _gfx->setHalfbriteMode(true);
+ _balloonMan->setSingleBalloon(data->_description, 0, 90, 0, BalloonManager::kNormalColor);
+ Common::Rect r;
+ data->_cnv->getRect(0, r);
+ id = _gfx->setItem(data->_cnv, 140, (_screenHeight - r.height())/2);
+ _gfx->setItemFrame(id, 0);
+ id = _gfx->setItem(_char._head, 100, 152);
+ _gfx->setItemFrame(id, 0);
+ } else {
+ _balloonMan->setSingleBalloon(data->_description, 140, 10, 0, BalloonManager::kNormalColor);
+ id = _gfx->setItem(_char._talk, 190, 80);
+ _gfx->setItemFrame(id, 0);
+ }
+ } else
+ if (getGameType() == GType_BRA) {
+ _balloonMan->setSingleBalloon(data->_description, 0, 0, 1, BalloonManager::kNormalColor);
+ int id = _gfx->setItem(_char._talk, 10, 80);
+ _gfx->setItemFrame(id, 0);
+ }
+
+ _input->_inputMode = Input::kInputModeComment;
+}
+
+void Parallaction::exitCommentMode() {
+ _input->_inputMode = Input::kInputModeGame;
+
+ hideDialogueStuff();
+ _gfx->setHalfbriteMode(false);
+
+ _cmdExec->run(_commentZone->_commands, _commentZone);
+ _commentZone = nullZonePtr;
+}
+
+void Parallaction::runCommentFrame() {
+ if (_input->_inputMode != Input::kInputModeComment) {
+ return;
+ }
+
+ if (_input->getLastButtonEvent() == kMouseLeftUp) {
+ exitCommentMode();
+ }
+}
+
+
+void Parallaction::runZone(ZonePtr z) {
+ debugC(3, kDebugExec, "runZone (%s)", z->_name);
+
+ uint16 subtype = z->_type & 0xFFFF;
+
+ debugC(3, kDebugExec, "type = %x, object = %x", subtype, (z->_type & 0xFFFF0000) >> 16);
+ switch(subtype) {
+
+ case kZoneExamine:
+ enterCommentMode(z);
+ return;
+
+ case kZoneGet:
+ pickupItem(z);
+ break;
+
+ case kZoneDoor:
+ if (z->_flags & kFlagsLocked) break;
+ updateDoor(z, !(z->_flags & kFlagsClosed));
+ break;
+
+ case kZoneHear:
+ _soundMan->playSfx(z->u.hear->_name, z->u.hear->_channel, (z->_flags & kFlagsLooping) == kFlagsLooping, 60);
+ break;
+
+ case kZoneSpeak:
+ enterDialogueMode(z);
+ return;
+ }
+
+ debugC(3, kDebugExec, "runZone completed");
+
+ _cmdExec->run(z->_commands, z);
+
+ return;
+}
+
+//
+// ZONE TYPE: DOOR
+//
+void Parallaction::updateDoor(ZonePtr z, bool close) {
+ z->_flags = close ? (z->_flags |= kFlagsClosed) : (z->_flags &= ~kFlagsClosed);
+
+ if (z->u.door->gfxobj) {
+ uint frame = (close ? 0 : 1);
+// z->u.door->gfxobj->setFrame(frame);
+ z->u.door->gfxobj->frame = frame;
+ }
+
+ return;
+}
+
+
+
+//
+// ZONE TYPE: GET
+//
+
+bool Parallaction::pickupItem(ZonePtr z) {
+ if (z->_flags & kFlagsFixed) {
+ return false;
+ }
+
+ int slot = addInventoryItem(z->u.get->_icon);
+ if (slot != -1) {
+ showZone(z, false);
+ }
+
+ return (slot != -1);
+}
+
+// FIXME: input coordinates must be offseted to handle scrolling!
+bool Parallaction::checkSpecialZoneBox(ZonePtr z, uint32 type, uint x, uint y) {
+ // not a special zone
+ if ((z->getX() != -2) && (z->getX() != -3)) {
+ return false;
+ }
+
+ // WORKAROUND: this huge condition is needed because we made TypeData a collection of structs
+ // instead of an union. So, merge->_obj1 and get->_icon were just aliases in the original engine,
+ // but we need to check it separately here. The same workaround is applied in freeZones.
+ if ((((z->_type & 0xFFFF) == kZoneMerge) && (((x == z->u.merge->_obj1) && (y == z->u.merge->_obj2)) || ((x == z->u.merge->_obj2) && (y == z->u.merge->_obj1)))) ||
+ (((z->_type & 0xFFFF) == kZoneGet) && ((x == z->u.get->_icon) || (y == z->u.get->_icon)))) {
+
+ // WORKAROUND for bug 2070751: special zones are only used in NS, to allow the
+ // the EXAMINE/USE action to be applied on some particular item in the inventory.
+ // The usage a verb requires at least an item match, so type can't be 0, as it
+ // was in the original code. This bug has been here since the beginning, and was
+ // hidden by label code, which filtered the bogus matches produced here.
+
+ // look for action + item match
+ if (z->_type == type)
+ return true;
+ // look for item match, but don't accept 0 types
+ if (((z->_type & 0xFFFF0000) == type) && (type))
+ return true;
+ }
+
+ return false;
+}
+
+// FIXME: input coordinates must be offseted to handle scrolling!
+bool Parallaction::checkZoneBox(ZonePtr z, uint32 type, uint x, uint y) {
+ if (z->_flags & kFlagsRemove)
+ return false;
+
+ debugC(5, kDebugExec, "checkZoneBox for %s (type = %x, x = %i, y = %i)", z->_name, type, x, y);
+
+ Common::Rect r;
+ z->getBox(r);
+ r.right++; // adjust border because Common::Rect doesn't include bottom-right edge
+ r.bottom++;
+
+ r.grow(-1); // allows some tolerance for mouse click
+
+ if (!r.contains(x, y)) {
+
+ // check for special zones (items defined in common.loc)
+ if (checkSpecialZoneBox(z, type, x, y))
+ return true;
+
+ if (z->getX() != -1)
+ return false;
+ if ((int)x < _char._ani->getFrameX())
+ return false;
+ if ((int)x > (_char._ani->getFrameX() + _char._ani->width()))
+ return false;
+ if ((int)y < _char._ani->getFrameY())
+ return false;
+ if ((int)y > (_char._ani->getFrameY() + _char._ani->height()))
+ return false;
+ }
+
+ // normal Zone
+ if ((type == 0) && ((z->_type & 0xFFFF0000) == 0))
+ return true;
+ if (z->_type == type)
+ return true;
+ if ((z->_type & 0xFFFF0000) == type)
+ return true;
+
+ return false;
+}
+
+// FIXME: input coordinates must be offseted to handle scrolling!
+bool Parallaction::checkLinkedAnimBox(ZonePtr z, uint32 type, uint x, uint y) {
+ if (z->_flags & kFlagsRemove)
+ return false;
+
+ if ((z->_flags & kFlagsAnimLinked) == 0)
+ return false;
+
+ debugC(5, kDebugExec, "checkLinkedAnimBox for %s (type = %x, x = %i, y = %i)", z->_name, type, x, y);
+
+ AnimationPtr anim = z->_linkedAnim;
+ Common::Rect r(anim->getFrameX(), anim->getFrameY(), anim->getFrameX() + anim->width() + 1, anim->getFrameY() + anim->height() + 1);
+
+ if (!r.contains(x, y)) {
+ return false;
+ }
+
+ // NOTE: the implementation of the following lines is a different in the
+ // original... it is working so far, though
+ if ((type == 0) && ((z->_type & 0xFFFF0000) == 0))
+ return true;
+ if (z->_type == type)
+ return true;
+ if ((z->_type & 0xFFFF0000) == type)
+ return true;
+
+ return false;
+}
+
+ZonePtr Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
+ uint16 _di = y;
+ uint16 _si = x;
+
+ for (ZoneList::iterator it = _location._zones.begin(); it != _location._zones.end(); it++) {
+ if (checkLinkedAnimBox(*it, type, x, y)) {
+ return *it;
+ }
+ if (checkZoneBox(*it, type, x, y)) {
+ return *it;
+ }
+ }
+
+
+ int16 _a, _b, _c, _d, _e, _f;
+ for (AnimationList::iterator ait = _location._animations.begin(); ait != _location._animations.end(); ait++) {
+
+ AnimationPtr a = *ait;
+
+ _a = (a->_flags & kFlagsActive) ? 1 : 0; // _a: active Animation
+ _e = ((_si >= a->getFrameX() + a->width()) || (_si <= a->getFrameX())) ? 0 : 1; // _e: horizontal range
+ _f = ((_di >= a->getFrameY() + a->height()) || (_di <= a->getFrameY())) ? 0 : 1; // _f: vertical range
+
+ _b = ((type != 0) || (a->_type == kZoneYou)) ? 0 : 1; // _b: (no type specified) AND (Animation is not the character)
+ _c = (a->_type & 0xFFFF0000) ? 0 : 1; // _c: Animation is not an object
+ _d = ((a->_type & 0xFFFF0000) != type) ? 0 : 1; // _d: Animation is an object of the same type
+
+ if ((_a != 0 && _e != 0 && _f != 0) && ((_b != 0 && _c != 0) || (a->_type == type) || (_d != 0))) {
+
+ return a;
+
+ }
+
+ }
+
+ return nullZonePtr;
+}
+
ZonePtr Parallaction::findZone(const char *name) {