diff --git a/inc/yapb.h b/inc/yapb.h index eeb84cc..8f4f67b 100644 --- a/inc/yapb.h +++ b/inc/yapb.h @@ -519,7 +519,7 @@ private: void pickupItem_ (); void shootBreakable_ (); - edict_t *lookupButton (StringRef target); + edict_t *lookupButton (StringRef target, bool blindTest = false); edict_t *lookupBreakable (); edict_t *setCorrectGrenadeVelocity (StringRef model); diff --git a/src/control.cpp b/src/control.cpp index b276cee..97b0f9c 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -1025,7 +1025,12 @@ int BotControl::menuMain (int item) { break; case 4: - bots.killAllBots (); + if (game.is (GameFlags::ReGameDLL)) { + game.serverCommand ("endround"); + } + else { + bots.killAllBots (); + } break; case 10: diff --git a/src/navigate.cpp b/src/navigate.cpp index 585fa2c..beaefa8 100644 --- a/src/navigate.cpp +++ b/src/navigate.cpp @@ -1070,7 +1070,7 @@ bool Bot::updateNavigation () { // delay task if (m_buttonPushTime < game.time ()) { - auto button = lookupButton (tr.pHit->v.targetname.chars ()); + auto button = lookupButton (tr.pHit->v.targetname.chars (), true); // check if we got valid button if (!game.isNullEntity (button)) { @@ -1241,6 +1241,7 @@ bool Bot::updateLiftHandling () { auto wait = [&] () { m_moveSpeed = 0.0f; m_strafeSpeed = 0.0f; + m_checkTerrain = false; m_navTimeset = game.time (); m_aimFlags |= AimFlags::Nav; @@ -1250,6 +1251,13 @@ bool Bot::updateLiftHandling () { ignoreCollision (); }; + // need to wait? + auto checkNeedToWait = [&] (float limitSq = 22.0f) { + if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (limitSq)) { + wait (); + } + }; + // trace line to door game.testLine (pev->origin, m_pathOrigin, TraceIgnore::Everything, ent (), &tr); @@ -1291,8 +1299,7 @@ bool Bot::updateLiftHandling () { m_liftUsageTime = game.time () + 7.0f; } } - else if (!m_pathWalk.empty ()) // no lift found at node - { + else if (!m_pathWalk.empty ()) { // no lift found at node if ((m_liftState == LiftState::None || m_liftState == LiftState::WaitingFor) && m_pathWalk.hasNext ()) { int nextNode = m_pathWalk.next (); @@ -1313,7 +1320,7 @@ bool Bot::updateLiftHandling () { m_destOrigin = m_liftTravelPos; // check if we enough to destination - if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (20.0f)) { + if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (22.0f)) { wait (); // need to wait our following teammate ? @@ -1371,10 +1378,7 @@ bool Bot::updateLiftHandling () { // need to wait for teammate if (needWaitForTeammate) { m_destOrigin = m_liftTravelPos; - - if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (20.0f)) { - wait (); - } + checkNeedToWait (); } // else we need to look for button @@ -1386,7 +1390,9 @@ bool Bot::updateLiftHandling () { // bot is trying to find button inside a lift if (m_liftState == LiftState::LookingButtonInside) { - auto button = lookupButton (m_liftEntity->v.targetname.str ()); + m_checkTerrain = false; + + auto button = lookupButton (m_liftEntity->v.targetname.str (), true); // got a valid button entity ? if (!game.isNullEntity (button) @@ -1395,11 +1401,21 @@ bool Bot::updateLiftHandling () { && cr::fzero (m_liftEntity->v.velocity.z) && isOnFloor ()) { - m_pickupItem = button; - m_pickupType = Pickup::Button; + auto buttonWithLineOfSight = lookupButton (m_liftEntity->v.targetname.str (), false); - m_navTimeset = game.time (); + if (!game.isNullEntity (buttonWithLineOfSight)) { + m_pickupItem = buttonWithLineOfSight; + m_pickupType = Pickup::Button; + } + else { + MDLL_Use (button, ent ()); + } + + if (pev->origin.distanceSq2d (graph[m_previousNodes[0]].origin) < cr::sqrf (64.0f)) { + wait (); + } } + ignoreCollision (); } // is lift activated and bot is standing on it and lift is moving ? @@ -1416,9 +1432,7 @@ bool Bot::updateLiftHandling () { m_liftState = LiftState::TravelingBy; m_liftUsageTime = game.time () + 14.0f; - if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (20.0f)) { - wait (); - } + checkNeedToWait (); } } @@ -1426,9 +1440,7 @@ bool Bot::updateLiftHandling () { if (m_liftState == LiftState::TravelingBy) { m_destOrigin = Vector (m_liftTravelPos.x, m_liftTravelPos.y, pev->origin.z); - if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (20.0f)) { - wait (); - } + checkNeedToWait (); } // need to find a button outside the lift @@ -1442,13 +1454,10 @@ bool Bot::updateLiftHandling () { else { m_destOrigin = pev->origin; } - - if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (20.0f)) { - wait (); - } + checkNeedToWait (64.0f); } else if (!game.isNullEntity (m_liftEntity)) { - auto button = lookupButton (m_liftEntity->v.targetname.str ()); + auto button = lookupButton (m_liftEntity->v.targetname.str (), true); // if we got a valid button entity if (!game.isNullEntity (button)) { @@ -1457,7 +1466,11 @@ bool Bot::updateLiftHandling () { // iterate though clients, and find if lift already used for (const auto &client : util.getClients ()) { - if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.team != m_team || client.ent == ent () || game.isNullEntity (client.ent->v.groundentity)) { + if (!(client.flags & ClientFlags::Used) + || !(client.flags & ClientFlags::Alive) + || client.team != m_team + || client.ent == ent () + || game.isNullEntity (client.ent->v.groundentity)) { continue; } @@ -1475,14 +1488,12 @@ bool Bot::updateLiftHandling () { else { m_destOrigin = button->v.origin; } - - if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (20.0f)) { - wait (); - } + checkNeedToWait (64.0f); } else { m_pickupItem = button; m_pickupType = Pickup::Button; + m_liftState = LiftState::WaitingFor; m_navTimeset = game.time (); @@ -1506,10 +1517,7 @@ bool Bot::updateLiftHandling () { m_destOrigin = graph[m_previousNodes[1]].origin; } } - - if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (20.0f)) { - wait (); - } + checkNeedToWait (64.0f); } // if bot is waiting for lift, or going to it @@ -2409,7 +2417,7 @@ bool Bot::advanceMovement () { // get ladder nodes used by other (first moving) bots for (const auto &other : bots) { // if another bot uses this ladder, wait 3 secs - if (other.get () != this && other->m_isAlive && other->m_currentNodeIndex == destIndex) { + if (other.get () != this && other->m_isAlive && other->m_currentNodeIndex == destIndex && other->isOnLadder ()) { startTask (Task::Pause, TaskPri::Pause, kInvalidNodeIndex, game.time () + 3.0f, false); return true; } @@ -3074,7 +3082,7 @@ bool Bot::isOccupiedNode (int index, bool needZeroVelocity) { return false; } -edict_t *Bot::lookupButton (StringRef target) { +edict_t *Bot::lookupButton (StringRef target, bool blindTest) { // this function tries to find nearest to current bot button, and returns pointer to // it's entity, also here must be specified the target, that button must open. @@ -3090,10 +3098,12 @@ edict_t *Bot::lookupButton (StringRef target) { game.searchEntities ("target", target, [&] (edict_t *ent) { const Vector &pos = game.getEntityOrigin (ent); - game.testLine (pev->origin, pos, TraceIgnore::Monsters, pev->pContainingEntity, &tr); + if (!blindTest) { + game.testLine (pev->origin, pos, TraceIgnore::Monsters, pev->pContainingEntity, &tr); + } // check if this place safe - if (tr.pHit == ent && tr.flFraction > 0.95f && !isDeadlyMove (pos)) { + if (blindTest || (tr.pHit == ent || tr.flFraction > 0.95f)) { const float distanceSq = pev->origin.distanceSq (pos); // check if we got more close button diff --git a/src/tasks.cpp b/src/tasks.cpp index 51845b0..454a742 100644 --- a/src/tasks.cpp +++ b/src/tasks.cpp @@ -1687,9 +1687,15 @@ void Bot::pickupItem_ () { break; } + float distanceToButtonSq = cr::sqrf (90.0f); + + // reduce on lifts + if (!game.isNullEntity (m_liftEntity)) { + distanceToButtonSq = cr::sqrf (24.0f); + } // near to the button? - if (itemDistanceSq < cr::sqrf (90.0f)) { + if (itemDistanceSq < distanceToButtonSq) { m_moveSpeed = 0.0f; m_strafeSpeed = 0.0f; m_moveToGoal = false; diff --git a/src/vision.cpp b/src/vision.cpp index bab41d2..f4b251c 100644 --- a/src/vision.cpp +++ b/src/vision.cpp @@ -201,9 +201,9 @@ void Bot::setAimDirection () { else { m_lookAt = m_destOrigin; } - const bool onLadder = (m_pathFlags & NodeFlag::Ladder); + const bool horizontalMovement = (m_pathFlags & NodeFlag::Ladder) || isOnLadder () || !cr::fzero (pev->velocity.z); - if (m_canChooseAimDirection && m_seeEnemyTime + 4.0f < game.time () && m_currentNodeIndex != kInvalidNodeIndex && !onLadder) { + if (m_canChooseAimDirection && m_seeEnemyTime + 4.0f < game.time () && m_currentNodeIndex != kInvalidNodeIndex && !horizontalMovement) { const auto dangerIndex = practice.getIndex (m_team, m_currentNodeIndex, m_currentNodeIndex); if (graph.exists (dangerIndex) @@ -223,7 +223,7 @@ void Bot::setAimDirection () { } // try look at next node if on ladder - if (onLadder && m_pathWalk.hasNext ()) { + if (horizontalMovement && m_pathWalk.hasNext ()) { const auto &nextPath = graph[m_pathWalk.next ()]; if ((nextPath.flags & NodeFlag::Ladder) && m_destOrigin.distanceSq (pev->origin) < cr::sqrf (128.0f) && nextPath.origin.z > m_pathOrigin.z + 26.0f) { @@ -240,7 +240,7 @@ void Bot::setAimDirection () { } // don't look at bottom of node, if reached it - if (m_lookAt == m_destOrigin && !onLadder) { + if (m_lookAt == m_destOrigin && !horizontalMovement) { m_lookAt.z = getEyesPos ().z; } } @@ -402,7 +402,7 @@ void Bot::updateLookAngles () { updateBodyAngles (); return; } - float aimSkill = cr::clamp (static_cast (m_difficulty), 1.0f, 4.0f) * 25.0f; + float aimSkill = cr::clamp (static_cast (m_difficulty), 3.0f, 4.0f) * 25.0f; // do not slowdown while on ladder if (isOnLadderPath () || isOnLadder ()) { @@ -462,7 +462,8 @@ void Bot::updateLookAngles () { m_lookPitchVel += delta * accel; m_idealAngles.x += cr::clamp (delta * m_lookPitchVel, -89.0f, 89.0f); - pev->v_angle = m_idealAngles; + pev->v_angle = m_idealAngles.clampAngles (); + pev->v_angle.z = 0.0f; updateBodyAngles (); }