NOXREF void CCSBot::MoveAwayFromPosition(const Vector *pos) { // compute our current forward and lateral vectors float angle = pev->v_angle[ YAW ]; Vector2D dir(BotCOS(angle), BotSIN(angle)); Vector2D lat(-dir.y, dir.x); // compute unit vector to goal position Vector2D to(pos->x - pev->origin.x, pos->y - pev->origin.y); to.NormalizeInPlace(); // move away from the position independant of our view direction float toProj = to.x * dir.x + to.y * dir.y; float latProj = to.x * lat.x + to.y * lat.y; const float c = 0.5f; if (toProj > c) MoveBackward(); else if (toProj < -c) MoveForward(); if (latProj >= c) StrafeRight(); else if (latProj <= -c) StrafeLeft(); }
void CFreeCameraController::Update() { if(Global::InputManager().KeyDown('W')) { MoveForward(); } else if(Global::InputManager().KeyDown('S')) { MoveBackward(); } if (Global::InputManager().KeyDown('A')) { StrafeLeft(); } else if (Global::InputManager().KeyDown('D')) { StrafeRight(); } if (Global::InputManager().RightMouseDown()) { MouseView(); } }
void PlayerCamera::UpdateCamera(float inTimeDelta) { D3DXMatrixRotationY(&tmpMat, (_pInput->_mouseState).lX / 300.0f); D3DXVec3TransformCoord(&_right, &_right, &tmpMat); D3DXVec3TransformCoord(&_look3, &_look3, &tmpMat); D3DXMatrixRotationAxis(&tmpMat, &_right, (_pInput->_mouseState).lY / 300.0f); D3DXVec3TransformCoord(&_up, &_up, &tmpMat); D3DXVec3TransformCoord(&_look3, &_look3, &tmpMat); if( _pInput->IsWPressed() ) { MoveForwards(inTimeDelta); } if( _pInput->IsSPressed() ) { MoveBackwards(inTimeDelta); } if( _pInput->IsAPressed() ) { StrafeLeft(inTimeDelta); } if( _pInput->IsDPressed() ) { StrafeRight(inTimeDelta); } _position4.x = _position3.x; _position4.y = _position3.y; _position4.z = _position3.z; _position4.w = 1.0f; _look4.x = _look3.x; _look4.y = _look3.y; _look4.z = _look3.z; _look4.w = 1.0f; UpdateViewMatrix(); D3DXMatrixMultiply(&_viewProjectionMatrix , &_viewMatrix, &_projectionMatrix); }
void CCSBot::StrafeAwayFromPosition(const Vector *pos) { // compute our current forward and lateral vectors float angle = pev->v_angle[ YAW ]; Vector2D dir(BotCOS(angle), BotSIN(angle)); Vector2D lat(-dir.y, dir.x); // compute unit vector to goal position Vector2D to(pos->x - pev->origin.x, pos->y - pev->origin.y); to.NormalizeInPlace(); float latProj = to.x * lat.x + to.y * lat.y; if (latProj >= 0.0f) StrafeRight(); else StrafeLeft(); }
void CCSBot::Wiggle() { if (IsCrouching()) { ResetStuckMonitor(); return; } // for wiggling if (gpGlobals->time >= m_wiggleTimestamp) { m_wiggleDirection = (NavRelativeDirType)RANDOM_LONG(0, 3); m_wiggleTimestamp = RANDOM_FLOAT(0.5, 1.5) + gpGlobals->time; } // TODO: implement checking of the movement to fall down switch (m_wiggleDirection) { case LEFT: StrafeLeft(); break; case RIGHT: StrafeRight(); break; case FORWARD: MoveForward(); break; case BACKWARD: MoveBackward(); break; default: break; } if (gpGlobals->time >= m_stuckJumpTimestamp) { if (Jump()) { m_stuckJumpTimestamp = RANDOM_FLOAT(1.0, 2.0) + gpGlobals->time; } } }
void CCSBot::MoveTowardsPosition(const Vector *pos) { // 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 if ((m_lastKnownArea == NULL || !(m_lastKnownArea->GetAttributes() & NAV_NO_JUMP)) && !IsOnLadder() && !m_isJumpCrouching) { float ground; Vector aheadRay(pos->x - pev->origin.x, pos->y - pev->origin.y, 0); aheadRay.NormalizeInPlace(); // look far ahead to allow us to smoothly jump over gaps, ledges, etc // only jump if ground is flat at lookahead spot to avoid jumping up slopes bool jumped = false; if (IsRunning()) { const float farLookAheadRange = 80.0f; Vector normal; Vector stepAhead = pev->origin + farLookAheadRange * aheadRay; stepAhead.z += HalfHumanHeight; if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground, &normal)) { if (normal.z > 0.9f) jumped = DiscontinuityJump(ground, 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 = pev->origin + lookAheadRange * aheadRay; stepAhead.z += HalfHumanHeight; if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground)) { jumped = DiscontinuityJump(ground); } } if (!jumped) { // about to fall gap-jumping const float lookAheadRange = 10.0f; Vector stepAhead = pev->origin + lookAheadRange * aheadRay; stepAhead.z += HalfHumanHeight; if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground)) { jumped = DiscontinuityJump(ground, ONLY_JUMP_DOWN, MUST_JUMP); } } } // compute our current forward and lateral vectors float angle = pev->v_angle.y; Vector2D dir(BotCOS(angle), BotSIN(angle)); Vector2D lat(-dir.y, dir.x); // compute unit vector to goal position Vector2D to(pos->x - pev->origin.x, pos->y - pev->origin.y); to.NormalizeInPlace(); // move towards the position independant of our view direction float toProj = to.x * dir.x + to.y * dir.y; float latProj = to.x * lat.x + to.y * lat.y; const float c = 0.25f; if (toProj > c) MoveForward(); else if (toProj < -c) MoveBackward(); // if we are avoiding someone via strafing, don't override if (m_avoid != NULL) return; if (latProj >= c) StrafeLeft(); else if (latProj <= -c) StrafeRight(); }
void CFullScreenFrame::SetupInput() { INPUTENGPARAMS inputParams; KEYBIND binding; CHashString kbName(_T("GDS_kb")); CHashString inputManager(_T("CInputManager")); CHashString StopMessage(_T("StopPlaying")); CHashString MoveForward(_T("CamMoveForward")); CHashString MoveBackward(_T("CamMoveBackward")); CHashString StrafeLeft(_T("CamStrafeLeft")); CHashString StrafeRight(_T("CamStrafeRight")); // create the input manager m_ToolBox->CreateComponent(&CHashString(_T("CInputManager")), 0); // start the input manager HMODULE mod = GetModuleHandle(NULL); inputParams.hMod = mod; inputParams.hWnd = GetSafeHwnd(); inputParams.mouseImmediate = true; inputParams.mouseExclusive = false; inputParams.mouseFG = true; inputParams.kbImmediate = true; inputParams.kbExclusive = false; inputParams.kbFG = true; static DWORD msgHash_Begin = CHashString(_T("Begin")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_Begin, sizeof(INPUTENGPARAMS), &inputParams, NULL, &inputManager); static DWORD msgHash_Start = CHashString(_T("Start")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_Start, 0, NULL, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_ESC;//0x1; binding.m_MessageID = StopMessage.GetUniqueID(); binding.m_bHitOnce = true; static DWORD msgHash_SetKeyBinding = CHashString(_T("SetKeyBinding")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_LEFT; binding.m_MessageID = StrafeLeft.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_RIGHT; binding.m_MessageID = StrafeRight.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_UP; binding.m_MessageID = MoveForward.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_DOWN; binding.m_MessageID = MoveBackward.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_A; binding.m_MessageID = StrafeLeft.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_D; binding.m_MessageID = StrafeRight.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_W; binding.m_MessageID = MoveForward.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); CHashString reloadshaders(_T("ReloadAllShaders")); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_S; binding.m_MessageID = MoveBackward.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_Q; binding.m_MessageID = reloadshaders.GetUniqueID(); binding.m_bHitOnce = true; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); static DWORD msgHash_SetActiveKeyBinding = CHashString(_T("SetActiveKeyBinding")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SetActiveKeyBinding, sizeof(DWORD*), &binding.m_kbNameID, &inputManager); }
// Navigate our current ladder. Return true if we are doing ladder navigation. // TODO: Need Push() and Pop() for run/walk context to keep ladder speed contained. bool CCSBot::UpdateLadderMovement() { if (!m_pathLadder) return false; bool giveUp = false; // check for timeout const float ladderTimeoutDuration = 10.0f; if (gpGlobals->time - m_pathLadderTimestamp > ladderTimeoutDuration) { PrintIfWatched("Ladder timeout!\n"); giveUp = true; } else if (m_pathLadderState == APPROACH_ASCENDING_LADDER || m_pathLadderState == APPROACH_DESCENDING_LADDER || m_pathLadderState == ASCEND_LADDER || m_pathLadderState == DESCEND_LADDER || m_pathLadderState == DISMOUNT_ASCENDING_LADDER || m_pathLadderState == MOVE_TO_DESTINATION) { if (m_isStuck) { PrintIfWatched("Giving up ladder - stuck\n"); giveUp = true; } } if (giveUp) { // jump off ladder and give up Jump(MUST_JUMP); Wiggle(); ResetStuckMonitor(); DestroyPath(); Run(); return false; } ResetStuckMonitor(); // check if somehow we totally missed the ladder switch (m_pathLadderState) { case MOUNT_ASCENDING_LADDER: case MOUNT_DESCENDING_LADDER: case ASCEND_LADDER: case DESCEND_LADDER: { const float farAway = 200.0f; Vector2D d = (m_pathLadder->m_top - pev->origin).Make2D(); if (d.IsLengthGreaterThan(farAway)) { PrintIfWatched("Missed ladder\n"); Jump(MUST_JUMP); DestroyPath(); Run(); return false; } break; } } m_areaEnteredTimestamp = gpGlobals->time; const float tolerance = 10.0f; const float closeToGoal = 25.0f; switch (m_pathLadderState) { case APPROACH_ASCENDING_LADDER: { bool approached = false; Vector2D d(pev->origin.x - m_goalPosition.x, pev->origin.y - m_goalPosition.y); if (d.x * m_pathLadder->m_dirVector.x + d.y * m_pathLadder->m_dirVector.y < 0.0f) { Vector2D perp(-m_pathLadder->m_dirVector.y, m_pathLadder->m_dirVector.x); #ifdef REGAMEDLL_FIXES if (Q_abs(d.x * perp.x + d.y * perp.y) < tolerance && d.Length() < closeToGoal) #else if (Q_abs(int64(d.x * perp.x + d.y * perp.y)) < tolerance && d.Length() < closeToGoal) #endif approached = true; } // small radius will just slow them down a little for more accuracy in hitting their spot const float walkRange = 50.0f; if (d.IsLengthLessThan(walkRange)) { Walk(); StandUp(); } // TODO: Check that we are on the ladder we think we are if (IsOnLadder()) { m_pathLadderState = ASCEND_LADDER; PrintIfWatched("ASCEND_LADDER\n"); // find actual top in case m_pathLadder penetrates the ceiling ComputeLadderEndpoint(true); } else if (approached) { // face the m_pathLadder m_pathLadderState = FACE_ASCENDING_LADDER; PrintIfWatched("FACE_ASCENDING_LADDER\n"); } else { // move toward ladder mount point MoveTowardsPosition(&m_goalPosition); } break; } case APPROACH_DESCENDING_LADDER: { // fall check if (GetFeetZ() <= m_pathLadder->m_bottom.z + HalfHumanHeight) { PrintIfWatched("Fell from ladder.\n"); m_pathLadderState = MOVE_TO_DESTINATION; m_path[m_pathIndex].area->GetClosestPointOnArea(&m_pathLadder->m_bottom, &m_goalPosition); AddDirectionVector(&m_goalPosition, m_pathLadder->m_dir, HalfHumanWidth); PrintIfWatched("MOVE_TO_DESTINATION\n"); } else { bool approached = false; Vector2D d(pev->origin.x - m_goalPosition.x, pev->origin.y - m_goalPosition.y); if (d.x * m_pathLadder->m_dirVector.x + d.y * m_pathLadder->m_dirVector.y > 0.0f) { Vector2D perp(-m_pathLadder->m_dirVector.y, m_pathLadder->m_dirVector.x); if (Q_abs(int64(d.x * perp.x + d.y * perp.y)) < tolerance && d.Length() < closeToGoal) approached = true; } // if approaching ladder from the side or "ahead", walk if (m_pathLadder->m_topBehindArea != m_lastKnownArea) { const float walkRange = 150.0f; if (!IsCrouching() && d.IsLengthLessThan(walkRange)) Walk(); } // TODO: Check that we are on the ladder we think we are if (IsOnLadder()) { // we slipped onto the ladder - climb it m_pathLadderState = DESCEND_LADDER; Run(); PrintIfWatched("DESCEND_LADDER\n"); // find actual bottom in case m_pathLadder penetrates the floor ComputeLadderEndpoint(false); } else if (approached) { // face the ladder m_pathLadderState = FACE_DESCENDING_LADDER; PrintIfWatched("FACE_DESCENDING_LADDER\n"); } else { // move toward ladder mount point MoveTowardsPosition(&m_goalPosition); } } break; } case FACE_ASCENDING_LADDER: { // find yaw to directly aim at ladder Vector to = m_pathLadder->m_bottom - pev->origin; Vector idealAngle = UTIL_VecToAngles(to); const float angleTolerance = 5.0f; if (AnglesAreEqual(pev->v_angle.y, idealAngle.y, angleTolerance)) { // move toward ladder until we become "on" it Run(); ResetStuckMonitor(); m_pathLadderState = MOUNT_ASCENDING_LADDER; PrintIfWatched("MOUNT_ASCENDING_LADDER\n"); } break; } case FACE_DESCENDING_LADDER: { // find yaw to directly aim at ladder Vector to = m_pathLadder->m_top - pev->origin; Vector idealAngle = UTIL_VecToAngles(to); const float angleTolerance = 5.0f; if (AnglesAreEqual(pev->v_angle.y, idealAngle.y, angleTolerance)) { // move toward ladder until we become "on" it m_pathLadderState = MOUNT_DESCENDING_LADDER; ResetStuckMonitor(); PrintIfWatched("MOUNT_DESCENDING_LADDER\n"); } break; } case MOUNT_ASCENDING_LADDER: { if (IsOnLadder()) { m_pathLadderState = ASCEND_LADDER; PrintIfWatched("ASCEND_LADDER\n"); // find actual top in case m_pathLadder penetrates the ceiling ComputeLadderEndpoint(true); } MoveForward(); break; } case MOUNT_DESCENDING_LADDER: { // fall check if (GetFeetZ() <= m_pathLadder->m_bottom.z + HalfHumanHeight) { PrintIfWatched("Fell from ladder.\n"); m_pathLadderState = MOVE_TO_DESTINATION; m_path[m_pathIndex].area->GetClosestPointOnArea(&m_pathLadder->m_bottom, &m_goalPosition); AddDirectionVector(&m_goalPosition, m_pathLadder->m_dir, HalfHumanWidth); PrintIfWatched("MOVE_TO_DESTINATION\n"); } else { if (IsOnLadder()) { m_pathLadderState = DESCEND_LADDER; PrintIfWatched("DESCEND_LADDER\n"); // find actual bottom in case m_pathLadder penetrates the floor ComputeLadderEndpoint(false); } // move toward ladder mount point MoveForward(); } break; } case ASCEND_LADDER: { // run, so we can make our dismount jump to the side, if necessary Run(); // if our destination area requires us to crouch, do it if (m_path[m_pathIndex].area->GetAttributes() & NAV_CROUCH) Crouch(); // did we reach the top? if (GetFeetZ() >= m_pathLadderEnd) { // we reached the top - dismount m_pathLadderState = DISMOUNT_ASCENDING_LADDER; PrintIfWatched("DISMOUNT_ASCENDING_LADDER\n"); if (m_path[m_pathIndex].area == m_pathLadder->m_topForwardArea) m_pathLadderDismountDir = FORWARD; else if (m_path[m_pathIndex].area == m_pathLadder->m_topLeftArea) m_pathLadderDismountDir = LEFT; else if (m_path[m_pathIndex].area == m_pathLadder->m_topRightArea) m_pathLadderDismountDir = RIGHT; m_pathLadderDismountTimestamp = gpGlobals->time; } else if (!IsOnLadder()) { // we fall off the ladder, repath DestroyPath(); return false; } // move up ladder MoveForward(); break; } case DESCEND_LADDER: { Run(); float destHeight = m_pathLadderEnd + HalfHumanHeight; if (!IsOnLadder() || GetFeetZ() <= destHeight) { // we reached the bottom, or we fell off - dismount m_pathLadderState = MOVE_TO_DESTINATION; m_path[m_pathIndex].area->GetClosestPointOnArea(&m_pathLadder->m_bottom, &m_goalPosition); AddDirectionVector(&m_goalPosition, m_pathLadder->m_dir, HalfHumanWidth); PrintIfWatched("MOVE_TO_DESTINATION\n"); } // Move down ladder MoveForward(); break; } case DISMOUNT_ASCENDING_LADDER: { if (gpGlobals->time - m_pathLadderDismountTimestamp >= 0.4f) { m_pathLadderState = MOVE_TO_DESTINATION; m_path[m_pathIndex].area->GetClosestPointOnArea(&pev->origin, &m_goalPosition); PrintIfWatched("MOVE_TO_DESTINATION\n"); } // We should already be facing the dismount point if (m_pathLadderFaceIn) { switch (m_pathLadderDismountDir) { case LEFT: StrafeLeft(); break; case RIGHT: StrafeRight(); break; case FORWARD: MoveForward(); break; } } else { switch (m_pathLadderDismountDir) { case LEFT: StrafeRight(); break; case RIGHT: StrafeLeft(); break; case FORWARD: MoveBackward(); break; } } break; } case MOVE_TO_DESTINATION: { if (m_path[m_pathIndex].area->Contains(&pev->origin)) { // successfully traversed ladder and reached destination area // exit ladder state machine PrintIfWatched("Ladder traversed.\n"); m_pathLadder = nullptr; // incrememnt path index to next step beyond this ladder SetPathIndex(m_pathIndex + 1); return false; } MoveTowardsPosition(&m_goalPosition); break; } } return true; }