bool Parallaction::checkZoneType(ZonePtr z, uint32 type) { if (_gameType == GType_Nippon) { if ((type == 0) && (ITEMTYPE(z) == 0)) return true; } if (_gameType == GType_BRA) { if (type == 0) { if (ITEMTYPE(z) == 0) { if (ACTIONTYPE(z) != kZonePath) { return true; } } if (ACTIONTYPE(z) == kZoneDoor) { return true; } } } if (z->_type == type) return true; if (ITEMTYPE(z) == type) return true; return false; }
void Parallaction_br::runPendingZones() { ZonePtr z; _cmdExec->runSuspended(); if (_activeZone) { z = _activeZone; // speak Zone or sound _activeZone.reset(); if (ACTIONTYPE(z) == kZoneSpeak && z->u._speakDialogue) { enterDialogueMode(z); } else { runZone(z); // FIXME: BRA doesn't handle sound yet } } if (_activeZone2) { z = _activeZone2; // speak Zone or sound _activeZone2.reset(); if (ACTIONTYPE(z) == kZoneSpeak && z->u._speakDialogue) { enterDialogueMode(z); } else { runZone(z); // FIXME: BRA doesn't handle sound yet } } }
void Parallaction::drawZone(ZonePtr zone) { if (!zone) { return; } GfxObj *obj = 0; if (ACTIONTYPE(zone) == kZoneGet) { obj = zone->u._gfxobj; } else if (ACTIONTYPE(zone) == kZoneDoor) { obj = zone->u._gfxobj; } if (!obj) { return; } obj->x = zone->getX(); obj->y = zone->getY(); _gfx->addObjectToScene(obj); }
void LocationParser_ns::parseZoneTypeBlock(ZonePtr z) { debugC(7, kDebugParser, "parseZoneTypeBlock(name: %s, type: %x)", z->_name, z->_type); ZoneTypeParser p = parsers[ACTIONTYPE(z)]; do { if (p) { (this->*p)(z); } _script->readLineToken(true); } while (scumm_stricmp(_tokens[0], "endzone") && scumm_stricmp(_tokens[0], "endanimation")); debugC(7, kDebugParser, "parseZoneTypeBlock() done"); }
bool Parallaction::checkSpecialZoneBox(ZonePtr z, uint32 type, uint x, uint y) { // check if really a special zone if (_gameType == GType_Nippon) { // so-called special zones in NS have special x coordinates if ((z->getX() != -2) && (z->getX() != -3)) { return false; } } if (_gameType == GType_BRA) { // so far, special zones in BRA are only merge zones if (ACTIONTYPE(z) != kZoneMerge) { 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 (((ACTIONTYPE(z) == kZoneMerge) && (((x == z->u._mergeObj1) && (y == z->u._mergeObj2)) || ((x == z->u._mergeObj2) && (y == z->u._mergeObj1)))) || ((ACTIONTYPE(z) == kZoneGet) && ((x == z->u._getIcon) || (y == z->u._getIcon)))) { // 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 ((ITEMTYPE(z) == type) && (type)) return true; } return false; }
void Parallaction::showZone(ZonePtr z, bool visible) { if (!z) { return; } if (visible) { z->_flags &= ~kFlagsRemove; z->_flags |= kFlagsActive; } else { z->_flags |= kFlagsRemove; } if (ACTIONTYPE(z) == kZoneGet) { _gfx->showGfxObj(z->u._gfxobj, visible); } }
void Parallaction::runZone(ZonePtr z) { debugC(3, kDebugExec, "runZone (%s)", z->_name); uint16 actionType = ACTIONTYPE(z); debugC(3, kDebugExec, "actionType = %x, itemType = %x", actionType, ITEMTYPE(z)); switch (actionType) { 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: if (z->u._hearChannel == MUSIC_HEAR_CHANNEL) { _soundMan->execute(SC_SETMUSICFILE, z->u._filename.c_str()); _soundMan->execute(SC_PLAYMUSIC); } else { _soundMan->execute(SC_SETSFXCHANNEL, z->u._hearChannel); _soundMan->execute(SC_SETSFXLOOPING, (int)((z->_flags & kFlagsLooping) == kFlagsLooping)); _soundMan->execute(SC_SETSFXVOLUME, 60); _soundMan->execute(SC_PLAYSFX, z->u._filename.c_str()); } break; case kZoneSpeak: if (z->u._speakDialogue) { enterDialogueMode(z); return; } break; } debugC(3, kDebugExec, "runZone completed"); _cmdExec->run(z->_commands, z); return; }
// NOTE: hitZone needs to be passed absolute game coordinates to work. // // When type is kZoneMerge, then x and y are the identifiers of the objects to merge, // and the above requirement does not apply. 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; bool _ef; for (AnimationList::iterator ait = _location._animations.begin(); ait != _location._animations.end(); ++ait) { AnimationPtr a = *ait; _a = (a->_flags & kFlagsActive) ? 1 : 0; // _a: active Animation if (!_a) { if (_gameType == GType_BRA && ACTIONTYPE(a) != kZoneTrap) { continue; } } _ef = a->hitFrameRect(_si, _di); _b = ((type != 0) || (a->_type == kZoneYou)) ? 0 : 1; // _b: (no type specified) AND (Animation is not the character) _c = ITEMTYPE(a) ? 0 : 1; // _c: Animation is not an object _d = (ITEMTYPE(a) != type) ? 0 : 1; // _d: Animation is an object of the same type if ((_a != 0 && _ef) && ((_b != 0 && _c != 0) || (a->_type == type) || (_d != 0))) { return a; } } return ZonePtr(); }
bool Location::keepZone_br(ZonePtr z) { return (z->_flags & kFlagsSelfuse) || (ACTIONTYPE(z) == kZoneMerge); }
bool Input::translateGameInput() { if (_engineFlags & kEnginePauseJobs) { return false; } if (_hasDelayedAction) { // if walking is over, then take programmed action takeAction(_delayedActionZone); _hasDelayedAction = false; _delayedActionZone.reset(); return true; } if (_mouseButtons == kMouseRightDown) { // right button down shows inventory enterInventoryMode(); return true; } Common::Point mousePos; getAbsoluteCursorPos(mousePos); // test if mouse is hovering on an interactive zone for the currently selected inventory item ZonePtr z = _vm->hitZone(_activeItem._id, mousePos.x, mousePos.y); if (((_mouseButtons == kMouseLeftUp) && (_activeItem._id == 0) && ((_engineFlags & kEngineWalking) == 0)) && ((!z) || (ACTIONTYPE(z) != kZoneCommand))) { walkTo(mousePos); return true; } trackMouse(z); if (!z) { return true; } if ((_mouseButtons == kMouseLeftUp) && ((_activeItem._id != 0) || (ACTIONTYPE(z) == kZoneCommand))) { bool noWalk = z->_flags & kFlagsNoWalk; // check the explicit no-walk flag if (_gameType == GType_BRA) { // action performed on object marked for self-use do not need walk in BRA noWalk |= ((z->_flags & kFlagsYourself) != 0); } if (noWalk) { takeAction(z); } else { // action delayed: if Zone defined a moveto position the character is programmed to move there, // else it will move to the mouse position _delayedActionZone = z; _hasDelayedAction = true; if (z->_moveTo.y != 0) { mousePos = z->_moveTo; } walkTo(mousePos); } _vm->beep(); setArrowCursor(); return true; } return true; }