/** * Check if given entry is at destination point. * This function is used to updated the flags of an object with move.obj * type motion that * has reached its final destination coordinates. * @param v Pointer to view table entry */ void AgiEngine::inDestination(ScreenObjEntry *screenObj) { if (screenObj->motionType == kMotionMoveObj) { screenObj->stepSize = screenObj->move_stepSize; setFlag(screenObj->move_flag, true); } screenObj->motionType = kMotionNormal; if (isEgoView(screenObj)) _game.playerControl = true; }
/** * Check if given entry is at destination point. * This function is used to updated the flags of an object with move.obj * type motion that * has reached its final destination coordinates. * @param v Pointer to view table entry */ void AgiEngine::inDestination(VtEntry *v) { if (v->motion == MOTION_MOVE_OBJ) { v->stepSize = v->parm3; setflag(v->parm4, true); } v->motion = MOTION_NORMAL; if (isEgoView(v)) _game.playerControl = true; }
void AgiEngine::motionMoveObj(VtEntry *v) { v->direction = getDirection(v->xPos, v->yPos, v->parm1, v->parm2, v->stepSize); // Update V6 if ego if (isEgoView(v)) _game.vars[vEgoDir] = v->direction; if (v->direction == 0) inDestination(v); }
void AgiEngine::motionMoveObj(ScreenObjEntry *screenObj) { screenObj->direction = getDirection(screenObj->xPos, screenObj->yPos, screenObj->move_x, screenObj->move_y, screenObj->stepSize); // Update V6 if ego if (isEgoView(screenObj)) setVar(VM_VAR_EGO_DIRECTION, screenObj->direction); if (screenObj->direction == 0) motionMoveObjStop(screenObj); }
void AgiEngine::motionWander(VtEntry *v) { if (v->parm1--) { if (~v->flags & DIDNT_MOVE) return; } v->direction = _rnd->getRandomNumber(8); if (isEgoView(v)) { _game.vars[vEgoDir] = v->direction; while (v->parm1 < 6) { v->parm1 = _rnd->getRandomNumber(50); // huh? } } }
void AgiEngine::motionMoveObjStop(ScreenObjEntry *screenObj) { screenObj->stepSize = screenObj->move_stepSize; // This check for motionType was only done in AGI3. // But we use this motion type for mouse movement, so we need to check in any case, otherwise it will cause glitches. if (screenObj->motionType != kMotionEgo) { setFlag(screenObj->move_flag, true); } screenObj->motionType = kMotionNormal; if (isEgoView(screenObj)) { _game.playerControl = true; setVar(VM_VAR_EGO_DIRECTION, 0); } }
void AgiEngine::motionWander(ScreenObjEntry *screenObj) { uint8 originalWanderCount = screenObj->wander_count; screenObj->wander_count--; if ((originalWanderCount == 0) || (screenObj->flags & fDidntMove)) { screenObj->direction = _rnd->getRandomNumber(8); if (isEgoView(screenObj)) { setVar(VM_VAR_EGO_DIRECTION, screenObj->direction); } while (screenObj->wander_count < 6) { screenObj->wander_count = _rnd->getRandomNumber(50); // huh? } } }
void AgiEngine::changePos(VtEntry *v) { int b, x, y; int dx[9] = { 0, 0, 1, 1, 1, 0, -1, -1, -1 }; int dy[9] = { 0, -1, -1, 0, 1, 1, 1, 0, -1 }; x = v->xPos; y = v->yPos; b = checkBlock(x, y); x += v->stepSize * dx[v->direction]; y += v->stepSize * dy[v->direction]; if (checkBlock(x, y) == b) { v->flags &= ~MOTION; } else { v->flags |= MOTION; v->direction = 0; if (isEgoView(v)) _game.vars[vEgoDir] = 0; } }
void AgiEngine::changePos(ScreenObjEntry *screenObj) { bool insideBlock; int16 x, y; int dx[9] = { 0, 0, 1, 1, 1, 0, -1, -1, -1 }; int dy[9] = { 0, -1, -1, 0, 1, 1, 1, 0, -1 }; x = screenObj->xPos; y = screenObj->yPos; insideBlock = checkBlock(x, y); x += screenObj->stepSize * dx[screenObj->direction]; y += screenObj->stepSize * dy[screenObj->direction]; if (checkBlock(x, y) == insideBlock) { screenObj->flags &= ~fMotion; } else { screenObj->flags |= fMotion; screenObj->direction = 0; if (isEgoView(screenObj)) setVar(VM_VAR_EGO_DIRECTION, 0); } }
/** * Update position of objects * This function updates the position of all animated, updating view * table entries according to its motion type, step size, etc. The * new position must be valid according to the sprite positioning * rules, otherwise the previous position will be kept. */ void AgiEngine::updatePosition() { ScreenObjEntry *screenObj; int x, y, oldX, oldY, border; setVar(VM_VAR_BORDER_CODE, 0); setVar(VM_VAR_BORDER_TOUCH_EGO, 0); setVar(VM_VAR_BORDER_TOUCH_OBJECT, 0); for (screenObj = _game.screenObjTable; screenObj < &_game.screenObjTable[SCREENOBJECTS_MAX]; screenObj++) { if ((screenObj->flags & (fAnimated | fUpdate | fDrawn)) != (fAnimated | fUpdate | fDrawn)) { continue; } if (screenObj->stepTimeCount > 1) { screenObj->stepTimeCount--; continue; } screenObj->stepTimeCount = screenObj->stepTime; x = oldX = screenObj->xPos; y = oldY = screenObj->yPos; // If object has moved, update its position if (!(screenObj->flags & fUpdatePos)) { int dx[9] = { 0, 0, 1, 1, 1, 0, -1, -1, -1 }; int dy[9] = { 0, -1, -1, 0, 1, 1, 1, 0, -1 }; x += screenObj->stepSize * dx[screenObj->direction]; y += screenObj->stepSize * dy[screenObj->direction]; } // Now check if it touched the borders border = 0; // Check left/right borders if (getVersion() == 0x3086) { // KQ4 interpreter does a different comparison on x // The interpreter before (2.917) and after that (3.098) don't do them that way // This difference is required for at least Sarien bug #192 // KQ4: room 135, hen moves from the center of the screen to the left border, // but it doesn't disappear. if (x <= 0) { x = 0; border = 4; } } else { // regular comparison if (x < 0) { x = 0; border = 4; } } // } else if (v->entry == 0 && x == 0 && v->flags & fAdjEgoXY) { // should not be required // // Extra test to walk west clicking the mouse // x = 0; // border = 4; if (!border) { if (x + screenObj->xSize > SCRIPT_WIDTH) { x = SCRIPT_WIDTH - screenObj->xSize; border = 2; } } // Check top/bottom borders. if (y - screenObj->ySize < -1) { y = screenObj->ySize - 1; border = 1; } else if (y > SCRIPT_HEIGHT - 1) { y = SCRIPT_HEIGHT - 1; border = 3; } else if ((!(screenObj->flags & fIgnoreHorizon)) && y <= _game.horizon) { debugC(4, kDebugLevelSprites, "y = %d, horizon = %d", y, _game.horizon); y = _game.horizon + 1; border = 1; } // Test new position. rollback if test fails screenObj->xPos = x; screenObj->yPos = y; if (checkCollision(screenObj) || !checkPriority(screenObj)) { screenObj->xPos = oldX; screenObj->yPos = oldY; border = 0; fixPosition(screenObj->objectNr); } if (border) { if (isEgoView(screenObj)) { setVar(VM_VAR_BORDER_TOUCH_EGO, border); } else { setVar(VM_VAR_BORDER_CODE, screenObj->objectNr); setVar(VM_VAR_BORDER_TOUCH_OBJECT, border); } if (screenObj->motionType == kMotionMoveObj) { motionMoveObjStop(screenObj); } } screenObj->flags &= ~fUpdatePos; } }
/** * Update position of objects * This function updates the position of all animated, updating view * table entries according to its motion type, step size, etc. The * new position must be valid according to the sprite positioning * rules, otherwise the previous position will be kept. */ void AgiEngine::updatePosition() { VtEntry *v; int x, y, oldX, oldY, border; _game.vars[vBorderCode] = 0; _game.vars[vBorderTouchEgo] = 0; _game.vars[vBorderTouchObj] = 0; for (v = _game.viewTable; v < &_game.viewTable[MAX_VIEWTABLE]; v++) { if ((v->flags & (ANIMATED | UPDATE | DRAWN)) != (ANIMATED | UPDATE | DRAWN)) { continue; } if (v->stepTimeCount != 0) { if (--v->stepTimeCount != 0) continue; } v->stepTimeCount = v->stepTime; x = oldX = v->xPos; y = oldY = v->yPos; // If object has moved, update its position if (~v->flags & UPDATE_POS) { int dx[9] = { 0, 0, 1, 1, 1, 0, -1, -1, -1 }; int dy[9] = { 0, -1, -1, 0, 1, 1, 1, 0, -1 }; x += v->stepSize * dx[v->direction]; y += v->stepSize * dy[v->direction]; } // Now check if it touched the borders border = 0; // Check left/right borders if (x < 0) { x = 0; border = 4; } else if (x <= 0 && getVersion() == 0x3086) { // KQ4 x = 0; // See Sarien bug #590462 border = 4; } else if (v->entry == 0 && x == 0 && v->flags & ADJ_EGO_XY) { // Extra test to walk west clicking the mouse x = 0; border = 4; } else if (x + v->xSize > _WIDTH) { x = _WIDTH - v->xSize; border = 2; } // Check top/bottom borders. if (y - v->ySize + 1 < 0) { y = v->ySize - 1; border = 1; } else if (y > _HEIGHT - 1) { y = _HEIGHT - 1; border = 3; } else if ((~v->flags & IGNORE_HORIZON) && y <= _game.horizon) { debugC(4, kDebugLevelSprites, "y = %d, horizon = %d", y, _game.horizon); y = _game.horizon + 1; border = 1; } // Test new position. rollback if test fails v->xPos = x; v->yPos = y; if (checkCollision(v) || !checkPriority(v)) { v->xPos = oldX; v->yPos = oldY; border = 0; fixPosition(v->entry); } if (border != 0) { if (isEgoView(v)) { _game.vars[vBorderTouchEgo] = border; } else { _game.vars[vBorderCode] = v->entry; _game.vars[vBorderTouchObj] = border; } if (v->motion == MOTION_MOVE_OBJ) { inDestination(v); } } v->flags &= ~UPDATE_POS; } }