nav: fixed lift usage as much as possible without full rewrite
mgr: end round with ``endround`` regamedll command if available (menus only) aim: prevent look angles overflows in some situations
This commit is contained in:
parent
b790e7a4bb
commit
0de53173f0
5 changed files with 67 additions and 45 deletions
|
|
@ -519,7 +519,7 @@ private:
|
||||||
void pickupItem_ ();
|
void pickupItem_ ();
|
||||||
void shootBreakable_ ();
|
void shootBreakable_ ();
|
||||||
|
|
||||||
edict_t *lookupButton (StringRef target);
|
edict_t *lookupButton (StringRef target, bool blindTest = false);
|
||||||
edict_t *lookupBreakable ();
|
edict_t *lookupBreakable ();
|
||||||
edict_t *setCorrectGrenadeVelocity (StringRef model);
|
edict_t *setCorrectGrenadeVelocity (StringRef model);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1025,7 +1025,12 @@ int BotControl::menuMain (int item) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
|
if (game.is (GameFlags::ReGameDLL)) {
|
||||||
|
game.serverCommand ("endround");
|
||||||
|
}
|
||||||
|
else {
|
||||||
bots.killAllBots ();
|
bots.killAllBots ();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 10:
|
case 10:
|
||||||
|
|
|
||||||
|
|
@ -1070,7 +1070,7 @@ bool Bot::updateNavigation () {
|
||||||
|
|
||||||
// delay task
|
// delay task
|
||||||
if (m_buttonPushTime < game.time ()) {
|
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
|
// check if we got valid button
|
||||||
if (!game.isNullEntity (button)) {
|
if (!game.isNullEntity (button)) {
|
||||||
|
|
@ -1241,6 +1241,7 @@ bool Bot::updateLiftHandling () {
|
||||||
auto wait = [&] () {
|
auto wait = [&] () {
|
||||||
m_moveSpeed = 0.0f;
|
m_moveSpeed = 0.0f;
|
||||||
m_strafeSpeed = 0.0f;
|
m_strafeSpeed = 0.0f;
|
||||||
|
m_checkTerrain = false;
|
||||||
|
|
||||||
m_navTimeset = game.time ();
|
m_navTimeset = game.time ();
|
||||||
m_aimFlags |= AimFlags::Nav;
|
m_aimFlags |= AimFlags::Nav;
|
||||||
|
|
@ -1250,6 +1251,13 @@ bool Bot::updateLiftHandling () {
|
||||||
ignoreCollision ();
|
ignoreCollision ();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// need to wait?
|
||||||
|
auto checkNeedToWait = [&] (float limitSq = 22.0f) {
|
||||||
|
if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (limitSq)) {
|
||||||
|
wait ();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// trace line to door
|
// trace line to door
|
||||||
game.testLine (pev->origin, m_pathOrigin, TraceIgnore::Everything, ent (), &tr);
|
game.testLine (pev->origin, m_pathOrigin, TraceIgnore::Everything, ent (), &tr);
|
||||||
|
|
||||||
|
|
@ -1291,8 +1299,7 @@ bool Bot::updateLiftHandling () {
|
||||||
m_liftUsageTime = game.time () + 7.0f;
|
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 ()) {
|
if ((m_liftState == LiftState::None || m_liftState == LiftState::WaitingFor) && m_pathWalk.hasNext ()) {
|
||||||
int nextNode = m_pathWalk.next ();
|
int nextNode = m_pathWalk.next ();
|
||||||
|
|
||||||
|
|
@ -1313,7 +1320,7 @@ bool Bot::updateLiftHandling () {
|
||||||
m_destOrigin = m_liftTravelPos;
|
m_destOrigin = m_liftTravelPos;
|
||||||
|
|
||||||
// check if we enough to destination
|
// 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 ();
|
wait ();
|
||||||
|
|
||||||
// need to wait our following teammate ?
|
// need to wait our following teammate ?
|
||||||
|
|
@ -1371,10 +1378,7 @@ bool Bot::updateLiftHandling () {
|
||||||
// need to wait for teammate
|
// need to wait for teammate
|
||||||
if (needWaitForTeammate) {
|
if (needWaitForTeammate) {
|
||||||
m_destOrigin = m_liftTravelPos;
|
m_destOrigin = m_liftTravelPos;
|
||||||
|
checkNeedToWait ();
|
||||||
if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (20.0f)) {
|
|
||||||
wait ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// else we need to look for button
|
// else we need to look for button
|
||||||
|
|
@ -1386,7 +1390,9 @@ bool Bot::updateLiftHandling () {
|
||||||
|
|
||||||
// bot is trying to find button inside a lift
|
// bot is trying to find button inside a lift
|
||||||
if (m_liftState == LiftState::LookingButtonInside) {
|
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 ?
|
// got a valid button entity ?
|
||||||
if (!game.isNullEntity (button)
|
if (!game.isNullEntity (button)
|
||||||
|
|
@ -1395,11 +1401,21 @@ bool Bot::updateLiftHandling () {
|
||||||
&& cr::fzero (m_liftEntity->v.velocity.z)
|
&& cr::fzero (m_liftEntity->v.velocity.z)
|
||||||
&& isOnFloor ()) {
|
&& isOnFloor ()) {
|
||||||
|
|
||||||
m_pickupItem = button;
|
auto buttonWithLineOfSight = lookupButton (m_liftEntity->v.targetname.str (), false);
|
||||||
m_pickupType = Pickup::Button;
|
|
||||||
|
|
||||||
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 ?
|
// 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_liftState = LiftState::TravelingBy;
|
||||||
m_liftUsageTime = game.time () + 14.0f;
|
m_liftUsageTime = game.time () + 14.0f;
|
||||||
|
|
||||||
if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (20.0f)) {
|
checkNeedToWait ();
|
||||||
wait ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1426,9 +1440,7 @@ bool Bot::updateLiftHandling () {
|
||||||
if (m_liftState == LiftState::TravelingBy) {
|
if (m_liftState == LiftState::TravelingBy) {
|
||||||
m_destOrigin = Vector (m_liftTravelPos.x, m_liftTravelPos.y, pev->origin.z);
|
m_destOrigin = Vector (m_liftTravelPos.x, m_liftTravelPos.y, pev->origin.z);
|
||||||
|
|
||||||
if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (20.0f)) {
|
checkNeedToWait ();
|
||||||
wait ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to find a button outside the lift
|
// need to find a button outside the lift
|
||||||
|
|
@ -1442,13 +1454,10 @@ bool Bot::updateLiftHandling () {
|
||||||
else {
|
else {
|
||||||
m_destOrigin = pev->origin;
|
m_destOrigin = pev->origin;
|
||||||
}
|
}
|
||||||
|
checkNeedToWait (64.0f);
|
||||||
if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (20.0f)) {
|
|
||||||
wait ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (!game.isNullEntity (m_liftEntity)) {
|
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 we got a valid button entity
|
||||||
if (!game.isNullEntity (button)) {
|
if (!game.isNullEntity (button)) {
|
||||||
|
|
@ -1457,7 +1466,11 @@ bool Bot::updateLiftHandling () {
|
||||||
|
|
||||||
// iterate though clients, and find if lift already used
|
// iterate though clients, and find if lift already used
|
||||||
for (const auto &client : util.getClients ()) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1475,14 +1488,12 @@ bool Bot::updateLiftHandling () {
|
||||||
else {
|
else {
|
||||||
m_destOrigin = button->v.origin;
|
m_destOrigin = button->v.origin;
|
||||||
}
|
}
|
||||||
|
checkNeedToWait (64.0f);
|
||||||
if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (20.0f)) {
|
|
||||||
wait ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_pickupItem = button;
|
m_pickupItem = button;
|
||||||
m_pickupType = Pickup::Button;
|
m_pickupType = Pickup::Button;
|
||||||
|
|
||||||
m_liftState = LiftState::WaitingFor;
|
m_liftState = LiftState::WaitingFor;
|
||||||
|
|
||||||
m_navTimeset = game.time ();
|
m_navTimeset = game.time ();
|
||||||
|
|
@ -1506,10 +1517,7 @@ bool Bot::updateLiftHandling () {
|
||||||
m_destOrigin = graph[m_previousNodes[1]].origin;
|
m_destOrigin = graph[m_previousNodes[1]].origin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
checkNeedToWait (64.0f);
|
||||||
if (pev->origin.distanceSq (m_destOrigin) < cr::sqrf (20.0f)) {
|
|
||||||
wait ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if bot is waiting for lift, or going to it
|
// 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
|
// get ladder nodes used by other (first moving) bots
|
||||||
for (const auto &other : bots) {
|
for (const auto &other : bots) {
|
||||||
// if another bot uses this ladder, wait 3 secs
|
// 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);
|
startTask (Task::Pause, TaskPri::Pause, kInvalidNodeIndex, game.time () + 3.0f, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -3074,7 +3082,7 @@ bool Bot::isOccupiedNode (int index, bool needZeroVelocity) {
|
||||||
return false;
|
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
|
// 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.
|
// 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) {
|
game.searchEntities ("target", target, [&] (edict_t *ent) {
|
||||||
const Vector &pos = game.getEntityOrigin (ent);
|
const Vector &pos = game.getEntityOrigin (ent);
|
||||||
|
|
||||||
|
if (!blindTest) {
|
||||||
game.testLine (pev->origin, pos, TraceIgnore::Monsters, pev->pContainingEntity, &tr);
|
game.testLine (pev->origin, pos, TraceIgnore::Monsters, pev->pContainingEntity, &tr);
|
||||||
|
}
|
||||||
|
|
||||||
// check if this place safe
|
// 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);
|
const float distanceSq = pev->origin.distanceSq (pos);
|
||||||
|
|
||||||
// check if we got more close button
|
// check if we got more close button
|
||||||
|
|
|
||||||
|
|
@ -1687,9 +1687,15 @@ void Bot::pickupItem_ () {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
float distanceToButtonSq = cr::sqrf (90.0f);
|
||||||
|
|
||||||
|
// reduce on lifts
|
||||||
|
if (!game.isNullEntity (m_liftEntity)) {
|
||||||
|
distanceToButtonSq = cr::sqrf (24.0f);
|
||||||
|
}
|
||||||
|
|
||||||
// near to the button?
|
// near to the button?
|
||||||
if (itemDistanceSq < cr::sqrf (90.0f)) {
|
if (itemDistanceSq < distanceToButtonSq) {
|
||||||
m_moveSpeed = 0.0f;
|
m_moveSpeed = 0.0f;
|
||||||
m_strafeSpeed = 0.0f;
|
m_strafeSpeed = 0.0f;
|
||||||
m_moveToGoal = false;
|
m_moveToGoal = false;
|
||||||
|
|
|
||||||
|
|
@ -201,9 +201,9 @@ void Bot::setAimDirection () {
|
||||||
else {
|
else {
|
||||||
m_lookAt = m_destOrigin;
|
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);
|
const auto dangerIndex = practice.getIndex (m_team, m_currentNodeIndex, m_currentNodeIndex);
|
||||||
|
|
||||||
if (graph.exists (dangerIndex)
|
if (graph.exists (dangerIndex)
|
||||||
|
|
@ -223,7 +223,7 @@ void Bot::setAimDirection () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// try look at next node if on ladder
|
// 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 ()];
|
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) {
|
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
|
// 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;
|
m_lookAt.z = getEyesPos ().z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -402,7 +402,7 @@ void Bot::updateLookAngles () {
|
||||||
updateBodyAngles ();
|
updateBodyAngles ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float aimSkill = cr::clamp (static_cast <float> (m_difficulty), 1.0f, 4.0f) * 25.0f;
|
float aimSkill = cr::clamp (static_cast <float> (m_difficulty), 3.0f, 4.0f) * 25.0f;
|
||||||
|
|
||||||
// do not slowdown while on ladder
|
// do not slowdown while on ladder
|
||||||
if (isOnLadderPath () || isOnLadder ()) {
|
if (isOnLadderPath () || isOnLadder ()) {
|
||||||
|
|
@ -462,7 +462,8 @@ void Bot::updateLookAngles () {
|
||||||
m_lookPitchVel += delta * accel;
|
m_lookPitchVel += delta * accel;
|
||||||
m_idealAngles.x += cr::clamp (delta * m_lookPitchVel, -89.0f, 89.0f);
|
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 ();
|
updateBodyAngles ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue