int Game_Character::GetRealY() const { int y = GetY() * SCREEN_TILE_WIDTH; if (IsMoving()) { int d = GetDirection(); if (d == Down || d == DownRight || d == DownLeft) y -= remaining_step; else if (d == Up || d == UpRight || d == UpLeft) y += remaining_step; } else if (IsJumping()) y -= (GetY() - jump_y) * remaining_step; return y; }
int Game_Character::GetRealX() const { int x = GetX() * SCREEN_TILE_WIDTH; if (IsMoving()) { int d = GetDirection(); if (d == Right || d == UpRight || d == DownRight) x -= remaining_step; else if (d == Left || d == UpLeft || d == DownLeft) x += remaining_step; } else if (IsJumping()) x -= ((GetX() - jump_x) * remaining_step); return x; }
bool Game_Event::CheckEventTriggerTouch(int x, int y) { if (Game_Map::GetInterpreter().IsRunning()) return false; if ((trigger == RPG::EventPage::Trigger_collision) && (Main_Data::game_player->IsInPosition(x, y))) { // TODO check over trigger VX differs from XP here if (!IsJumping()) { Start(); } } return true; }
int Game_Character::GetScreenY() const { int y = GetRealY() / TILE_SIZE - Game_Map::GetDisplayY() / TILE_SIZE + TILE_SIZE; if (Game_Map::LoopVertical()) { int map_height = Game_Map::GetHeight() * TILE_SIZE; y = (y + map_height) % map_height; } if (IsJumping()) { int jump_height = (remaining_step > SCREEN_TILE_WIDTH / 2 ? SCREEN_TILE_WIDTH - remaining_step : remaining_step) / 8; y -= (jump_height < 5 ? jump_height * 2 : jump_height < 13 ? jump_height + 4 : 16); } return y; }
bool Game_Player::IsMovable() const { if (IsMoving() || IsJumping()) return false; if (Graphics::IsTransitionPending()) return false; if (IsMoveRouteOverwritten()) return false; if (location.boarding || location.unboarding) return false; if (Game_Message::message_waiting) return false; if (InAirship() && !GetVehicle()->IsMovable()) return false; return true; }
void Game_Vehicle::SyncWithPlayer() { SetX(Main_Data::game_player->GetX()); SetY(Main_Data::game_player->GetY()); SetRemainingStep(Main_Data::game_player->GetRemainingStep()); SetJumping(Main_Data::game_player->IsJumping()); SetBeginJumpX(Main_Data::game_player->GetBeginJumpX()); SetBeginJumpY(Main_Data::game_player->GetBeginJumpY()); if (!IsAscendingOrDescending()) { SetDirection(Main_Data::game_player->GetDirection()); SetSpriteDirection(Main_Data::game_player->GetSpriteDirection()); } else { if (!IsMoving() && !IsJumping()) { SetDirection(Left); SetSpriteDirection(Left); } } }
void Game_Player::UpdateScroll() { int center_x = DisplayUi->GetWidth() / 2 - TILE_SIZE / 2 - Game_Map::GetPanX() / (SCREEN_TILE_WIDTH / TILE_SIZE); int center_y = DisplayUi->GetHeight() / 2 + TILE_SIZE / 2 - Game_Map::GetPanY() / (SCREEN_TILE_WIDTH / TILE_SIZE); int dx = 0; int dy = 0; if (!Game_Map::IsPanLocked()) { if (IsMoving()) { int d = GetDirection(); if ((d == Right || d == UpRight || d == DownRight) && GetScreenX() >= center_x) dx = 1; else if ((d == Left || d == UpLeft || d == DownLeft) && GetScreenX() <= center_x) dx = -1; dx <<= 1 + GetMoveSpeed(); if ((d == Down || d == DownRight || d == DownLeft) && GetScreenY() >= center_y) dy = 1; else if ((d == Up || d == UpRight || d == UpLeft) && GetScreenY() <= center_y) dy = -1; dy <<= 1 + GetMoveSpeed(); } else if (IsJumping()) { int move_speed = GetMoveSpeed(); int diff = move_speed < 5 ? 48 / (2 + pow(2.0, 3 - move_speed)) : 64 / (7 - move_speed); dx += (GetX() - jump_x) * diff; dy += (GetY() - jump_y) * diff; } } if (Game_Map::GetPanX() != last_pan_x || Game_Map::GetPanY() != last_pan_y) { dx += Game_Map::GetPanX() - last_pan_x; dy += Game_Map::GetPanY() - last_pan_y; last_pan_x = Game_Map::GetPanX(); last_pan_y = Game_Map::GetPanY(); } if (dx > 0) Game_Map::ScrollRight(dx); else if (dx < 0) Game_Map::ScrollLeft(-dx); if (dy > 0) Game_Map::ScrollDown(dy); else if (dy < 0) Game_Map::ScrollUp(-dy); }
void CHostageImprov::SetKnownGoodPosition(const Vector &pos) { if (IsJumping() || IsCrouching()) return; if (m_hasKnownGoodPos) { if (m_priorKnownGoodPosTimer.IsElapsed()) { m_hasPriorKnownGoodPos = true; m_priorKnownGoodPos = m_knownGoodPos; m_priorKnownGoodPosTimer.Start(1); } } m_hasKnownGoodPos = true; m_knownGoodPos = pos; }
void Game_Character::UpdateSprite() { if (IsJumping()) { UpdateJump(); if (IsSpinning()) anime_count++; } else if (IsMoving()) { remaining_step -= min(1 << (1 + GetMoveSpeed()), remaining_step); if (IsSpinning() || (animation_type != RPG::EventPage::AnimType_fixed_graphic && walk_animation)) anime_count++; } else { stop_count++; if ((walk_animation && (IsSpinning() || IsContinuous())) || pattern != original_pattern) anime_count++; } if (anime_count >= GetSteppingSpeed()) { if (IsSpinning()) { SetSpriteDirection((GetSpriteDirection() + 1) % 4); } else if (!IsContinuous() && IsStopping()) { pattern = original_pattern; last_pattern = last_pattern == RPG::EventPage::Frame_left ? RPG::EventPage::Frame_right : RPG::EventPage::Frame_left; } else { if (last_pattern == RPG::EventPage::Frame_left) { if (pattern == RPG::EventPage::Frame_right) { pattern = RPG::EventPage::Frame_middle; last_pattern = RPG::EventPage::Frame_right; } else { pattern = RPG::EventPage::Frame_right; } } else { if (pattern == RPG::EventPage::Frame_left) { pattern = RPG::EventPage::Frame_middle; last_pattern = RPG::EventPage::Frame_left; } else { pattern = RPG::EventPage::Frame_left; } } } anime_count = 0; } }
// Check if we need to jump due to height change bool CHostageImprov::DiscontinuityJump(float ground, bool onlyJumpDown, bool mustJump) { // Don't try to jump if in the air or crouching. if (IsJumping() || IsCrouching() || IsUsingLadder()) return false; float dz = ground - GetFeet().z; if (dz > StepHeight && !onlyJumpDown) { Jump(); return true; } else if (dz < -JumpHeight) { Jump(); return true; } return false; }
bool Game_Event::CheckEventTriggerTouch(int x, int y) { if (Game_Map::GetInterpreter().IsRunning()) return false; if (trigger == RPG::EventPage::Trigger_collision && !IsJumping()) { if (Main_Data::game_player->IsInPosition(GetX(), GetY()) && GetLayer() == RPG::EventPage::Layers_same) { return false; } if (Main_Data::game_player->IsInPosition(x, y) && !Main_Data::game_player->IsBlockedByMoveRoute()) { if (Main_Data::game_player->InAirship() && GetLayer() == RPG::EventPage::Layers_same) { return false; } Start(); return true; } } return false; }
bool Game_Character::IsStopping() const { return !(IsMoving() || IsJumping()); }
bool Game_Character::IsMoving() const { return !IsJumping() && remaining_step > 0; }
// Move along the path. Return false if end of path reached. CCSBot::PathResult CCSBot::UpdatePathMovement(bool allowSpeedChange) { if (m_pathLength == 0) return PATH_FAILURE; if (cv_bot_walk.value != 0.0f) Walk(); // If we are navigating a ladder, it overrides all other path movement until complete if (UpdateLadderMovement()) return PROGRESSING; // ladder failure can destroy the path if (m_pathLength == 0) return PATH_FAILURE; // we are not supposed to be on a ladder - if we are, jump off if (IsOnLadder()) Jump(MUST_JUMP); assert(m_pathIndex < m_pathLength); // Check if reached the end of the path bool nearEndOfPath = false; if (m_pathIndex >= m_pathLength - 1) { Vector toEnd(pev->origin.x, pev->origin.y, GetFeetZ()); Vector d = GetPathEndpoint() - toEnd; // can't use 2D because path end may be below us (jump down) const float walkRange = 200.0f; // walk as we get close to the goal position to ensure we hit it if (d.IsLengthLessThan(walkRange)) { // don't walk if crouching - too slow if (allowSpeedChange && !IsCrouching()) Walk(); // note if we are near the end of the path const float nearEndRange = 50.0f; if (d.IsLengthLessThan(nearEndRange)) nearEndOfPath = true; const float closeEpsilon = 20.0f; if (d.IsLengthLessThan(closeEpsilon)) { // reached goal position - path complete DestroyPath(); // TODO: We should push and pop walk state here, in case we want to continue walking after reaching goal if (allowSpeedChange) Run(); return END_OF_PATH; } } } // To keep us moving smoothly, we will move towards // a point farther ahead of us down our path. int prevIndex = 0; // closest index on path just prior to where we are now const float aheadRange = 300.0f; int newIndex = FindPathPoint(aheadRange, &m_goalPosition, &prevIndex); // BOTPORT: Why is prevIndex sometimes -1? if (prevIndex < 0) prevIndex = 0; // if goal position is near to us, we must be about to go around a corner - so look ahead! const float nearCornerRange = 100.0f; if (m_pathIndex < m_pathLength - 1 && (m_goalPosition - pev->origin).IsLengthLessThan(nearCornerRange)) { ClearLookAt(); InhibitLookAround(0.5f); } // if we moved to a new node on the path, setup movement if (newIndex > m_pathIndex) { SetPathIndex(newIndex); } if (!IsUsingLadder()) { // Crouching // if we are approaching a crouch area, crouch // if there are no crouch areas coming up, stand const float crouchRange = 50.0f; bool didCrouch = false; for (int i = prevIndex; i < m_pathLength; i++) { const CNavArea *to = m_path[i].area; // if there is a jump area on the way to the crouch area, don't crouch as it messes up the jump // unless we are already higher than the jump area - we must've jumped already but not moved into next area if ((to->GetAttributes() & NAV_JUMP)/* && to->GetCenter()->z > GetFeetZ()*/) break; Vector close; to->GetClosestPointOnArea(&pev->origin, &close); if ((close - pev->origin).Make2D().IsLengthGreaterThan(crouchRange)) break; if (to->GetAttributes() & NAV_CROUCH) { Crouch(); didCrouch = true; break; } } if (!didCrouch && !IsJumping()) { // no crouch areas coming up StandUp(); } // end crouching logic } // compute our forward facing angle m_forwardAngle = UTIL_VecToYaw(m_goalPosition - pev->origin); // Look farther down the path to "lead" our view around corners Vector toGoal; if (m_pathIndex == 0) { toGoal = m_path[1].pos; } else if (m_pathIndex < m_pathLength) { toGoal = m_path[m_pathIndex].pos - pev->origin; // actually aim our view farther down the path const float lookAheadRange = 500.0f; if (!m_path[m_pathIndex].ladder && !IsNearJump() && toGoal.Make2D().IsLengthLessThan(lookAheadRange)) { float along = toGoal.Length2D(); int i; for (i = m_pathIndex + 1; i < m_pathLength; i++) { Vector delta = m_path[i].pos - m_path[i - 1].pos; float segmentLength = delta.Length2D(); if (along + segmentLength >= lookAheadRange) { // interpolate between points to keep look ahead point at fixed distance float t = (lookAheadRange - along) / (segmentLength + along); Vector target; if (t <= 0.0f) target = m_path[i - 1].pos; else if (t >= 1.0f) target = m_path[i].pos; else target = m_path[i - 1].pos + t * delta; toGoal = target - pev->origin; break; } // if we are coming up to a ladder or a jump, look at it if (m_path[i].ladder || (m_path[i].area->GetAttributes() & NAV_JUMP)) { toGoal = m_path[i].pos - pev->origin; break; } along += segmentLength; } if (i == m_pathLength) { toGoal = GetPathEndpoint() - pev->origin; } } } else { toGoal = GetPathEndpoint() - pev->origin; } m_lookAheadAngle = UTIL_VecToYaw(toGoal); // initialize "adjusted" goal to current goal Vector adjustedGoal = m_goalPosition; // Use short "feelers" to veer away from close-range obstacles // Feelers come from our ankles, just above StepHeight, so we avoid short walls, too // Don't use feelers if very near the end of the path, or about to jump // TODO: Consider having feelers at several heights to deal with overhangs, etc. if (!nearEndOfPath && !IsNearJump() && !IsJumping()) { FeelerReflexAdjustment(&adjustedGoal); } // draw debug visualization if ((cv_bot_traceview.value == 1.0f && IsLocalPlayerWatchingMe()) || cv_bot_traceview.value == 10.0f) { DrawPath(); const Vector *pos = &m_path[m_pathIndex].pos; UTIL_DrawBeamPoints(*pos, *pos + Vector(0, 0, 50), 1, 255, 255, 0); UTIL_DrawBeamPoints(adjustedGoal, adjustedGoal + Vector(0, 0, 50), 1, 255, 0, 255); UTIL_DrawBeamPoints(pev->origin, adjustedGoal + Vector(0, 0, 50), 1, 255, 0, 255); } // dont use adjustedGoal, as it can vary wildly from the feeler adjustment if (!IsAttacking() && IsFriendInTheWay(&m_goalPosition)) { if (!m_isWaitingBehindFriend) { m_isWaitingBehindFriend = true; const float politeDuration = 5.0f - 3.0f * GetProfile()->GetAggression(); m_politeTimer.Start(politeDuration); } else if (m_politeTimer.IsElapsed()) { // we have run out of patience m_isWaitingBehindFriend = false; ResetStuckMonitor(); // repath to avoid clump of friends in the way DestroyPath(); } } else if (m_isWaitingBehindFriend) { // we're done waiting for our friend to move m_isWaitingBehindFriend = false; ResetStuckMonitor(); } // Move along our path if there are no friends blocking our way, // or we have run out of patience if (!m_isWaitingBehindFriend || m_politeTimer.IsElapsed()) { // Move along path MoveTowardsPosition(&adjustedGoal); // Stuck check if (m_isStuck && !IsJumping()) { Wiggle(); } } // if our goal is high above us, we must have fallen bool didFall = false; if (m_goalPosition.z - GetFeetZ() > JumpCrouchHeight) { const float closeRange = 75.0f; Vector2D to(pev->origin.x - m_goalPosition.x, pev->origin.y - m_goalPosition.y); if (to.IsLengthLessThan(closeRange)) { // we can't reach the goal position // check if we can reach the next node, in case this was a "jump down" situation if (m_pathIndex < m_pathLength - 1) { if (m_path[m_pathIndex + 1].pos.z - GetFeetZ() > JumpCrouchHeight) { // the next node is too high, too - we really did fall of the path didFall = true; } } else { // fell trying to get to the last node in the path didFall = true; } } } // This timeout check is needed if the bot somehow slips way off // of its path and cannot progress, but also moves around // enough that it never becomes "stuck" const float giveUpDuration = 5.0f; // 4.0f if (didFall || gpGlobals->time - m_areaEnteredTimestamp > giveUpDuration) { if (didFall) { PrintIfWatched("I fell off!\n"); } // if we havent made any progress in a long time, give up if (m_pathIndex < m_pathLength - 1) { PrintIfWatched("Giving up trying to get to area #%d\n", m_path[m_pathIndex].area->GetID()); } else { PrintIfWatched("Giving up trying to get to end of path\n"); } Run(); StandUp(); DestroyPath(); return PATH_FAILURE; } return PROGRESSING; }
bool ANimModCharacter::IsInAir() const { return IsFalling() || IsJumping(); }
void CHostageImprov::MoveTowards(const Vector &pos, float deltaT) { Vector move; float_precision accelRate; const float crouchWalkRate = 250.0f; // Jump up on ledges // Because we may not be able to get to our goal position and enter the next // area because our extent collides with a nearby vertical ledge, make sure // we look far enough ahead to avoid this situation. // Can't look too far ahead, or bots will try to jump up slopes. // // NOTE: We need to do this frequently to catch edges at the right time // TODO: Look ahead *along path* instead of straight line ClearPath(); if ((m_lastKnownArea == NULL || !(m_lastKnownArea->GetAttributes() & NAV_NO_JUMP)) && !IsUsingLadder() && !IsJumping() && IsOnGround() && !IsCrouching()) { float ground; Vector aheadRay(pos.x - GetFeet().x, pos.y - GetFeet().y, 0); aheadRay.NormalizeInPlace(); bool jumped = false; if (IsRunning()) { const float farLookAheadRange = 80.0f; Vector normal; Vector stepAhead = GetFeet() + farLookAheadRange * aheadRay; stepAhead.z += HumanHeight; if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground, &normal )) { if (normal.z > 0.9f) jumped = DiscontinuityJump(ground, HOSTAGE_ONLY_JUMP_DOWN); } } if (!jumped) { // close up jumping // cant be less or will miss jumps over low walls const float lookAheadRange = 30.0f; Vector stepAhead = GetFeet() + lookAheadRange * aheadRay; stepAhead.z += HumanHeight; if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground)) { jumped = DiscontinuityJump(ground); } } if (!jumped) { // about to fall gap-jumping const float lookAheadRange = 10.0f; Vector stepAhead = GetFeet() + lookAheadRange * aheadRay; stepAhead.z += HumanHeight; if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground)) { jumped = DiscontinuityJump(ground, HOSTAGE_ONLY_JUMP_DOWN, HOSTAGE_MUST_JUMP); } } } move = (pos - GetFeet()); move.z = 0; if (!move.IsZero()) { move.NormalizeInPlace(); } switch (m_moveType) { case Stopped: accelRate = 0; break; case Walking: if (IsCrouching()) accelRate = crouchWalkRate; else accelRate = 400; break; case Running: if (IsCrouching()) accelRate = crouchWalkRate; else accelRate = 1000; break; } m_vel.x = move.x * accelRate * deltaT + m_vel.x; m_vel.y = move.y * accelRate * deltaT + m_vel.y; }
void Game_Player::Update() { int cur_frame_count = Player::GetFrames(); // Only update the event once per frame if (cur_frame_count == frame_count_at_last_update_parallel) { return; } frame_count_at_last_update_parallel = cur_frame_count; bool last_moving = IsMoving() || IsJumping(); // Workaround: If a blocking move route ends in this frame, Game_Player::CancelMoveRoute decides // which events to start. was_blocked is used to avoid triggering events the usual way. bool was_blocked = IsBlockedByMoveRoute(); Game_Character::Update(); if (!Game_Map::GetInterpreter().IsRunning() && !Game_Map::IsAnyEventStarting()) { if (IsMovable()) { switch (Input::dir4) { case 2: Move(Down); break; case 4: Move(Left); break; case 6: Move(Right); break; case 8: Move(Up); } } // ESC-Menu calling if (Game_System::GetAllowMenu() && !Game_Message::message_waiting && Input::IsTriggered(Input::CANCEL)) { Game_Temp::menu_calling = true; } } Game_Character::UpdateSprite(); UpdateScroll(); if (location.aboard) GetVehicle()->SyncWithPlayer(); if (IsMoving() || was_blocked) return; if (last_moving && location.boarding) { // Boarding completed location.aboard = true; location.boarding = false; SetMoveSpeed(GetVehicle()->GetMoveSpeed()); SetDirection(GetVehicle()->GetDirection()); return; } if (last_moving && location.unboarding) { // Unboarding completed location.unboarding = false; location.vehicle = Game_Vehicle::None; CheckTouchEvent(); return; } if (InAirship() && !GetVehicle()->IsInUse()) { // Airship has landed Unboard(); location.vehicle = Game_Vehicle::None; SetDirection(RPG::EventPage::Direction_down); } if (last_moving && CheckTouchEvent()) return; if (!Game_Map::GetInterpreter().IsRunning() && !Game_Map::IsAnyEventStarting()) { if (!Game_Message::visible && Input::IsTriggered(Input::DECISION)) { if ( GetOnOffVehicle() ) return; if ( CheckActionEvent() ) return; } } if (last_moving) Game_Map::UpdateEncounterSteps(); }
void CCSBot::StuckCheck() { if (m_isStuck) { // we are stuck - see if we have moved far enough to be considered unstuck Vector delta = pev->origin - m_stuckSpot; const float unstuckRange = 75.0f; if (delta.IsLengthGreaterThan(unstuckRange)) { // we are no longer stuck ResetStuckMonitor(); PrintIfWatched("UN-STUCK\n"); } } else { // check if we are stuck // compute average velocity over a short period (for stuck check) Vector vel = pev->origin - m_lastOrigin; // if we are jumping, ignore Z if (IsJumping()) vel.z = 0.0f; // cannot be Length2D, or will break ladder movement (they are only Z) float moveDist = vel.Length(); float deltaT = g_flBotFullThinkInterval; m_avgVel[ m_avgVelIndex++ ] = moveDist / deltaT; if (m_avgVelIndex == MAX_VEL_SAMPLES) m_avgVelIndex = 0; if (m_avgVelCount < MAX_VEL_SAMPLES) { m_avgVelCount++; } else { // we have enough samples to know if we're stuck float avgVel = 0.0f; for (int t = 0; t < m_avgVelCount; ++t) avgVel += m_avgVel[t]; avgVel /= m_avgVelCount; // cannot make this velocity too high, or bots will get "stuck" when going down ladders float stuckVel = (IsUsingLadder()) ? 10.0f : 20.0f; if (avgVel < stuckVel) { // we are stuck - note when and where we initially become stuck m_stuckTimestamp = gpGlobals->time; m_stuckSpot = pev->origin; m_stuckJumpTimestamp = gpGlobals->time + RANDOM_FLOAT(0.0f, 0.5f); PrintIfWatched("STUCK\n"); if (IsLocalPlayerWatchingMe() && cv_bot_debug.value > 0.0f) { EMIT_SOUND(ENT(pev), CHAN_ITEM, "buttons/button11.wav", VOL_NORM, ATTN_NORM); } m_isStuck = true; } } } // always need to track this m_lastOrigin = pev->origin; }
void CHostageImprov::UpdatePosition(float deltaT) { CNavArea *area = TheNavAreaGrid.GetNavArea(&m_hostage->pev->origin); if (area != NULL) { m_lastKnownArea = area; } DrawAxes(m_moveGoal, 255, 255, 0); if (IsJumping()) { Vector dir; const float pushSpeed = 100.0f; if (!m_hasJumped) { m_hasJumped = true; m_hasJumpedIntoAir = false; m_hostage->pev->velocity.z += 300.0f; } else ResetJump(); dir = m_jumpTarget - GetFeet(); dir.z = 0; #ifndef PLAY_GAMEDLL // TODO: fix test demo dir.NormalizeInPlace(); m_hostage->pev->velocity.x = dir.x * pushSpeed; m_hostage->pev->velocity.y = dir.y * pushSpeed; #else Vector vecRet = NormalizeMulScalar<float_precision, float_precision, float_precision, float>(dir, pushSpeed); m_hostage->pev->velocity.x = vecRet.x; m_hostage->pev->velocity.y = vecRet.y; #endif m_hostage->SetBoneController(0); m_hostage->SetBoneController(1); FaceTowards(m_jumpTarget, deltaT); return; } if (m_isLookingAt) { Vector angles = UTIL_VecToAngles(m_viewGoal - GetEyes()); float_precision pitch = angles.x - m_hostage->pev->angles.x; float_precision yaw = angles.y - m_hostage->pev->angles.y; while (yaw > 180.0f) yaw -= 360.0f; while (yaw < -180.0f) yaw += 360.0f; while (pitch > 180.0f) pitch -= 360.0f; while (pitch < -180.0f) pitch += 360.0f; m_hostage->SetBoneController(0, yaw); m_hostage->SetBoneController(1, -pitch); if (IsAtMoveGoal() && !HasFaceTo()) { if (yaw < -45.0f || yaw > 45.0f) { FaceTowards(m_viewGoal, deltaT); } } } else { m_hostage->SetBoneController(0); m_hostage->SetBoneController(1); } if (HasFaceTo() && FaceTowards(m_faceGoal, deltaT)) ClearFaceTo(); if (!IsAtMoveGoal() || m_path.GetSegmentCount() > 0) { if (m_path.GetSegmentCount() <= 0) { HostagePathCost pathCost; if (m_path.Compute(&GetFeet(), &m_moveGoal, pathCost)) { m_follower.SetPath(&m_path); m_follower.SetImprov(this); m_follower.Reset(); m_follower.Debug(cv_hostage_debug.value > 0.0); } } m_follower.Update(deltaT, m_inhibitObstacleAvoidance.IsElapsed()); if (m_moveType == Stopped) { m_follower.ResetStuck(); } if (m_follower.IsStuck()) { Wiggle(); } } const float friction = 3.0f; m_vel.x += m_vel.x * -friction * deltaT; m_vel.y += m_vel.y * -friction * deltaT; float_precision speed = m_vel.NormalizeInPlace(); const float maxSpeed = 285.0f; if (speed > maxSpeed) { speed = maxSpeed; } m_vel.x = m_vel.x * speed; m_vel.y = m_vel.y * speed; KeepPersonalSpace spacer(this); ForEachPlayer(spacer); if (g_pHostages != NULL) { g_pHostages->ForEachHostage(spacer); } m_hostage->pev->velocity.x = m_vel.x; m_hostage->pev->velocity.y = m_vel.y; m_moveFlags = 0; }
void Game_Player::UpdateScroll() { // First, update for the player's movement... int center_x = DisplayUi->GetWidth() / 2 - TILE_SIZE / 2 - actual_pan_x / (SCREEN_TILE_WIDTH / TILE_SIZE); int center_y = DisplayUi->GetHeight() / 2 + TILE_SIZE / 2 - actual_pan_y / (SCREEN_TILE_WIDTH / TILE_SIZE); int dx = 0; int dy = 0; if (!Game_Map::IsPanLocked()) { if (IsMoving() || last_remaining_move > 0) { if (last_remaining_move == 0) last_remaining_move = SCREEN_TILE_WIDTH; int d = GetDirection(); if ((d == Right || d == UpRight || d == DownRight) && GetScreenX() > center_x) dx = 1; else if ((d == Left || d == UpLeft || d == DownLeft) && GetScreenX() < center_x) dx = -1; dx *= last_remaining_move - remaining_step; if ((d == Down || d == DownRight || d == DownLeft) && GetScreenY() > center_y) dy = 1; else if ((d == Up || d == UpRight || d == UpLeft) && GetScreenY() < center_y) dy = -1; dy *= last_remaining_move - remaining_step; last_remaining_move = remaining_step; } else if (IsJumping() || last_remaining_jump > 0) { if (last_remaining_jump == 0) last_remaining_jump = SCREEN_TILE_WIDTH; if ((GetX() > jump_x && GetScreenX() > center_x) || (GetX() < jump_x && GetScreenX() < center_x)) dx = (GetX() - jump_x) * (last_remaining_jump - remaining_step); if ((GetY() > jump_y && GetScreenY() > center_y) || (GetY() < jump_y && GetScreenY() < center_y)) dy = (GetY() - jump_y) * (last_remaining_jump - remaining_step); last_remaining_jump = remaining_step; } } Game_Map::ScrollRight(dx); Game_Map::ScrollDown(dy); // Second, update for the change in pan... int pan_x = Game_Map::GetPanX(); int pan_y = Game_Map::GetPanY(); int pan_dx = pan_x - last_pan_x; int pan_dy = pan_y - last_pan_y; last_pan_x = pan_x; last_pan_y = pan_y; // Change pan_dx/pan_dy to account for hitting the edges int screen_x = Game_Map::GetPositionX(); int screen_y = Game_Map::GetPositionY(); Game_Map::AddScreenX(screen_x, pan_dx); Game_Map::AddScreenY(screen_y, pan_dy); // Only move for the pan if we're closer to the target pan than we were before. if (std::abs(actual_pan_x + pan_dx - Game_Map::GetTargetPanX()) < std::abs(actual_pan_x - Game_Map::GetTargetPanX())) { Game_Map::ScrollRight(pan_dx); actual_pan_x += pan_dx; } if (std::abs(actual_pan_y + pan_dy - Game_Map::GetTargetPanY()) < std::abs(actual_pan_y - Game_Map::GetTargetPanY())) { Game_Map::ScrollDown(pan_dy); actual_pan_y += pan_dy; } }