/** * Save current scene. * @param sd Pointer to the scene data */ void DoSaveScene(SAVED_DATA *sd) { sd->SavedSceneHandle = GetSceneHandle(); sd->SavedBgroundHandle = GetBgroundHandle(); SaveMovers(sd->SavedMoverInfo); sd->NumSavedActors = SaveActors(sd->SavedActorInfo); PlayfieldGetPos(FIELD_WORLD, &sd->SavedLoffset, &sd->SavedToffset); SaveInterpretContexts(sd->SavedICInfo); sd->SavedControl = ControlIsOn(); sd->SavedNoBlocking = GetNoBlocking(); GetNoScrollData(&sd->SavedNoScrollData); if (TinselV2) { // Tinsel 2 specific data save SaveActorZ(sd->savedActorZ); SaveZpositions(sd->zPositions); SavePolygonStuff(sd->SavedPolygonStuff); _vm->_pcmMusic->getTunePlaying(sd->SavedTune, sizeof(sd->SavedTune)); sd->bTinselDim = _vm->_pcmMusic->getMusicTinselDimmed(); sd->SavedScrollFocus = GetScrollFocus(); SaveSysVars(sd->SavedSystemVars); SaveSoundReels(sd->SavedSoundReels); } else { // Tinsel 1 specific data save SaveDeadPolys(sd->SavedDeadPolys); CurrentMidiFacts(&sd->SavedMidi, &sd->SavedLoop); } ASceneIsSaved = true; }
/** * Scroll to abslote position. */ void ScrollTo(int x, int y, int xIter, int yIter) { int Loffset, Toffset; // for background offsets g_scrollPixelsX = xIter != 0 ? xIter : (TinselV2 ? g_sd.xSpeed : SCROLLPIXELS); g_scrollPixelsY = yIter != 0 ? yIter : (TinselV2 ? g_sd.ySpeed : SCROLLPIXELS); PlayfieldGetPos(FIELD_WORLD, &Loffset, &Toffset); // get background offsets g_LeftScroll = x - Loffset; g_DownScroll = y - Toffset; }
/** * See if the actor on whom the camera is is approaching an edge. * Request a scroll if he is. */ static void MonitorScroll() { int newx, newy; int Loffset, Toffset; /* * Only do it if the actor is there and is visible */ if (!g_pScrollMover || MoverHidden(g_pScrollMover) || !MoverIs(g_pScrollMover)) return; GetActorPos(g_scrollActor, &newx, &newy); if (g_oldx == newx && g_oldy == newy) return; PlayfieldGetPos(FIELD_WORLD, &Loffset, &Toffset); /* * Approaching right side or left side of the screen? */ if (newx > Loffset+SCREEN_WIDTH - RLDISTANCE && Loffset < g_ImageW - SCREEN_WIDTH) { if (newx > g_oldx) NeedScroll(LEFT); } else if (newx < Loffset + RLDISTANCE && Loffset) { if (newx < g_oldx) NeedScroll(RIGHT); } /* * Approaching bottom or top of the screen? */ if (newy > Toffset+SCREEN_HEIGHT-DDISTANCE && Toffset < g_ImageH-SCREEN_HEIGHT) { if (newy > g_oldy) NeedScroll(UP); } else if (Toffset && newy < Toffset + UDISTANCE + GetActorBottom(g_scrollActor) - GetActorTop(g_scrollActor)) { if (newy < g_oldy) NeedScroll(DOWN); } g_oldx = newx; g_oldy = newy; }
/** * GetActorTagPos */ void GetActorTagPos(int actor, int *pTagX, int *pTagY, bool bAbsolute) { unsigned topEighth, botEighth; int aTop; // Top and bottom limits } int aHeight; // Height } of active area int Loffset, Toffset; GetActorTagPortion(actor, &topEighth, &botEighth, (unsigned *)&Loffset, (unsigned *)&Toffset); aTop = GetActorTop(actor); aHeight = GetActorBottom(actor) - aTop; aTop += ((topEighth - 1) * aHeight) / 8; *pTagX = ((GetActorLeft(actor) + GetActorRight(actor)) / 2); *pTagY = aTop; if (!bAbsolute) { PlayfieldGetPos(FIELD_WORLD, &Loffset, &Toffset); *pTagX -= Loffset; *pTagY -= Toffset; } }
/** * Called from scroll process - Scrolls the image as appropriate. */ static void ScrollImage() { int OldLoffset = 0, OldToffset = 0; // Used when keeping cursor on a tag int Loffset, Toffset; int curX, curY; // get background offsets PlayfieldGetPos(FIELD_WORLD, &Loffset, &Toffset); /* * Keeping cursor on a tag? */ if (g_ScrollCursor) { GetCursorXYNoWait(&curX, &curY, true); if (InPolygon(curX, curY, TAG) != NOPOLY || InPolygon(curX, curY, EXIT) != NOPOLY) { OldLoffset = Loffset; OldToffset = Toffset; } else g_ScrollCursor = false; } /* * Horizontal scrolling */ if (g_LeftScroll > 0) { g_LeftScroll -= g_scrollPixelsX; if (g_LeftScroll < 0) { Loffset += g_LeftScroll; g_LeftScroll = 0; } Loffset += g_scrollPixelsX; // Move right if (Loffset > g_ImageW - SCREEN_WIDTH) Loffset = g_ImageW - SCREEN_WIDTH;// Now at extreme right /*** New feature to prop up rickety scroll boundaries ***/ if (TinselV2 && SysVar(SV_MaximumXoffset) && (Loffset > SysVar(SV_MaximumXoffset))) Loffset = SysVar(SV_MaximumXoffset); } else if (g_LeftScroll < 0) { g_LeftScroll += g_scrollPixelsX; if (g_LeftScroll > 0) { Loffset += g_LeftScroll; g_LeftScroll = 0; } Loffset -= g_scrollPixelsX; // Move left if (Loffset < 0) Loffset = 0; // Now at extreme left /*** New feature to prop up rickety scroll boundaries ***/ if (TinselV2 && SysVar(SV_MinimumXoffset) && (Loffset < SysVar(SV_MinimumXoffset))) Loffset = SysVar(SV_MinimumXoffset); } /* * Vertical scrolling */ if (g_DownScroll > 0) { g_DownScroll -= g_scrollPixelsY; if (g_DownScroll < 0) { Toffset += g_DownScroll; g_DownScroll = 0; } Toffset += g_scrollPixelsY; // Move down if (Toffset > g_ImageH - SCREEN_HEIGHT) Toffset = g_ImageH - SCREEN_HEIGHT;// Now at extreme bottom /*** New feature to prop up rickety scroll boundaries ***/ if (TinselV2 && SysVar(SV_MaximumYoffset) && Toffset > SysVar(SV_MaximumYoffset)) Toffset = SysVar(SV_MaximumYoffset); } else if (g_DownScroll < 0) { g_DownScroll += g_scrollPixelsY; if (g_DownScroll > 0) { Toffset += g_DownScroll; g_DownScroll = 0; } Toffset -= g_scrollPixelsY; // Move up if (Toffset < 0) Toffset = 0; // Now at extreme top /*** New feature to prop up rickety scroll boundaries ***/ if (TinselV2 && SysVar(SV_MinimumYoffset) && Toffset < SysVar(SV_MinimumYoffset)) Toffset = SysVar(SV_MinimumYoffset); } /* * Move cursor if keeping cursor on a tag. */ if (g_ScrollCursor) AdjustCursorXY(OldLoffset - Loffset, OldToffset - Toffset); PlayfieldSetPos(FIELD_WORLD, Loffset, Toffset); }
/** * Called from scroll process when it thinks that a scroll is in order. * Checks for no-scroll boundaries and sets off a scroll if allowed. */ static void NeedScroll(int direction) { uint i; int BottomLine, RightCol; int Loffset, Toffset; // get background offsets PlayfieldGetPos(FIELD_WORLD, &Loffset, &Toffset); switch (direction) { case LEFT: /* Picture will go left, 'camera' right */ BottomLine = Toffset + (SCREEN_HEIGHT - 1); RightCol = Loffset + (SCREEN_WIDTH - 1); for (i = 0; i < g_sd.NumNoH; i++) { if (RightCol >= g_sd.NoHScroll[i].ln - 1 && RightCol <= g_sd.NoHScroll[i].ln + 1 && ((g_sd.NoHScroll[i].c1 >= Toffset && g_sd.NoHScroll[i].c1 <= BottomLine) || (g_sd.NoHScroll[i].c2 >= Toffset && g_sd.NoHScroll[i].c2 <= BottomLine) || (g_sd.NoHScroll[i].c1 < Toffset && g_sd.NoHScroll[i].c2 > BottomLine))) return; } if (g_LeftScroll <= 0) { if (TinselV2) { g_scrollPixelsX = g_sd.xSpeed; g_LeftScroll += g_sd.xDistance; } else { g_scrollPixelsX = SCROLLPIXELS; g_LeftScroll = RLSCROLL; } } break; case RIGHT: /* Picture will go right, 'camera' left */ BottomLine = Toffset + (SCREEN_HEIGHT - 1); for (i = 0; i < g_sd.NumNoH; i++) { if (Loffset >= g_sd.NoHScroll[i].ln - 1 && Loffset <= g_sd.NoHScroll[i].ln + 1 && ((g_sd.NoHScroll[i].c1 >= Toffset && g_sd.NoHScroll[i].c1 <= BottomLine) || (g_sd.NoHScroll[i].c2 >= Toffset && g_sd.NoHScroll[i].c2 <= BottomLine) || (g_sd.NoHScroll[i].c1 < Toffset && g_sd.NoHScroll[i].c2 > BottomLine))) return; } if (g_LeftScroll >= 0) { if (TinselV2) { g_scrollPixelsX = g_sd.xSpeed; g_LeftScroll -= g_sd.xDistance; } else { g_scrollPixelsX = SCROLLPIXELS; g_LeftScroll = -RLSCROLL; } } break; case UP: /* Picture will go upwards, 'camera' downwards */ BottomLine = Toffset + (SCREEN_HEIGHT - 1); RightCol = Loffset + (SCREEN_WIDTH - 1); for (i = 0; i < g_sd.NumNoV; i++) { if ((BottomLine >= g_sd.NoVScroll[i].ln - 1 && BottomLine <= g_sd.NoVScroll[i].ln + 1) && ((g_sd.NoVScroll[i].c1 >= Loffset && g_sd.NoVScroll[i].c1 <= RightCol) || (g_sd.NoVScroll[i].c2 >= Loffset && g_sd.NoVScroll[i].c2 <= RightCol) || (g_sd.NoVScroll[i].c1 < Loffset && g_sd.NoVScroll[i].c2 > RightCol))) return; } if (g_DownScroll <= 0) { if (TinselV2) { g_scrollPixelsY = g_sd.ySpeed; g_DownScroll += g_sd.yDistance; } else { g_scrollPixelsY = SCROLLPIXELS; g_DownScroll = UDSCROLL; } } break; case DOWN: /* Picture will go downwards, 'camera' upwards */ RightCol = Loffset + (SCREEN_WIDTH - 1); for (i = 0; i < g_sd.NumNoV; i++) { if (Toffset >= g_sd.NoVScroll[i].ln - 1 && Toffset <= g_sd.NoVScroll[i].ln + 1 && ((g_sd.NoVScroll[i].c1 >= Loffset && g_sd.NoVScroll[i].c1 <= RightCol) || (g_sd.NoVScroll[i].c2 >= Loffset && g_sd.NoVScroll[i].c2 <= RightCol) || (g_sd.NoVScroll[i].c1 < Loffset && g_sd.NoVScroll[i].c2 > RightCol))) return; } if (g_DownScroll >= 0) { if (TinselV2) { g_scrollPixelsY = g_sd.ySpeed; g_DownScroll -= g_sd.yDistance; } else { g_scrollPixelsY = SCROLLPIXELS; g_DownScroll = -UDSCROLL; } } break; } }
/** * Main interface point for specifying player atcions */ void PlayerEvent(PLR_EVENT pEvent, const Common::Point &coOrds) { // Logging of player actions const char *actionList[] = { "PLR_PROV_WALKTO", "PLR_WALKTO", "PLR_LOOK", "PLR_ACTION", "PLR_ESCAPE", "PLR_MENU", "PLR_QUIT", "PLR_PGUP", "PLR_PGDN", "PLR_HOME", "PLR_END", "PLR_DRAG1_START", "PLR_DRAG1_END", "PLR_DRAG2_START", "PLR_DRAG2_END", "PLR_JUMP", "PLR_NOEVENT", "PLR_SAVE", "PLR_LOAD", "PLR_WHEEL_UP", "PLR_WHEEL_DOWN"}; debugC(DEBUG_BASIC, kTinselDebugActions, "%s - (%d,%d)", actionList[pEvent], coOrds.x, coOrds.y); static uint32 lastRealAction = 0; // FIXME: Avoid non-const global vars // This stuff to allow F1 key during startup. if (g_bEnableMenu && pEvent == PLR_MENU) Control(CONTROL_ON); else IncUserEvents(); if (pEvent == PLR_ESCAPE) { ++g_escEvents; ++g_leftEvents; // Yes, I do mean this } else if ((pEvent == PLR_PROV_WALKTO) || (pEvent == PLR_WALKTO) || (pEvent == PLR_LOOK) || (pEvent == PLR_ACTION)) { ++g_leftEvents; } // Only allow events if player control is on if (!ControlIsOn() && (pEvent != PLR_DRAG1_END)) return; if (TinselV2 && InventoryActive()) { int x, y; PlayfieldGetPos(FIELD_WORLD, &x, &y); EventToInventory(pEvent, Common::Point(coOrds.x - x, coOrds.y - y)); return; } switch (pEvent) { case PLR_QUIT: OpenMenu(QUIT_MENU); break; case PLR_MENU: OpenMenu(MAIN_MENU); break; case PLR_JUMP: OpenMenu(HOPPER_MENU1); break; case PLR_SAVE: OpenMenu(SAVE_MENU); break; case PLR_LOAD: OpenMenu(LOAD_MENU); break; case PLR_PROV_WALKTO: // Provisional WALKTO ! ProcessUserEvent(PROV_WALKTO, coOrds); break; case PLR_WALKTO: REAL_ACTION_CHECK; if (TinselV2 || !InventoryActive()) ProcessUserEvent(WALKTO, coOrds, PLR_SLEFT); else EventToInventory(PLR_SLEFT, coOrds); break; case PLR_ACTION: REAL_ACTION_CHECK; if (TinselV2 || !InventoryActive()) ProcessUserEvent(ACTION, coOrds, PLR_DLEFT); else EventToInventory(PLR_DLEFT, coOrds); break; case PLR_LOOK: REAL_ACTION_CHECK; if (TinselV2 || !InventoryActive()) ProcessUserEvent(LOOK, coOrds, PLR_SRIGHT); else EventToInventory(PLR_SRIGHT, coOrds); break; default: if (InventoryActive()) EventToInventory(pEvent, coOrds); break; } }