diff --git a/include/globals.h b/include/globals.h index ac0365e..d81c8e7 100644 --- a/include/globals.h +++ b/include/globals.h @@ -55,7 +55,10 @@ extern int g_mapType; extern int g_numWaypoints; extern int g_gameVersion; extern int g_fakeArgc; -extern int g_killHistory; + +extern int g_highestDamageCT; +extern int g_highestDamageT; +extern int g_highestKills; extern int g_normalWeaponPrefs[NUM_WEAPONS]; extern int g_rusherWeaponPrefs[NUM_WEAPONS]; diff --git a/project/yapb.rc b/project/yapb.rc index 0ad7c5b..343ad66 100644 --- a/project/yapb.rc +++ b/project/yapb.rc @@ -26,7 +26,7 @@ #include <../include/resource.h> // generated by update tool -- do not edit -- -#define PRODUCT_BUILD_TOOL 3846 +#define PRODUCT_BUILD_TOOL 3850 VS_VERSION_INFO VERSIONINFO FILEVERSION PRODUCT_VERSION_DWORD, PRODUCT_BUILD_TOOL diff --git a/source/basecode.cpp b/source/basecode.cpp index 1c98767..b698c02 100644 --- a/source/basecode.cpp +++ b/source/basecode.cpp @@ -2982,7 +2982,7 @@ void Bot::ChooseAimDirection (void) TraceLine (pev->origin, dest, true, GetEntity (), &tr); if (tr.flFraction > 0.8 || tr.pHit != g_worldEdict) - m_lookAt = dest; + m_lookAt = dest + pev->view_ofs; } } else @@ -2993,7 +2993,7 @@ void Bot::ChooseAimDirection (void) TraceLine (pev->origin, dest, true, GetEntity (), &tr); if (tr.flFraction > 0.8 || tr.pHit != g_worldEdict) - m_lookAt = dest; + m_lookAt = dest + pev->view_ofs; } } } @@ -5656,6 +5656,7 @@ void Bot::TakeDamage (edict_t *inflictor, int damage, int armor, int bits) m_actualReactionTime = 0.0; m_seeEnemyTime = GetWorldTime(); m_enemy = inflictor; + m_lastEnemy = m_enemy; m_lastEnemyOrigin = m_enemy->v.origin; m_enemyOrigin = m_enemy->v.origin; @@ -5691,7 +5692,9 @@ void Bot::TakeDamage (edict_t *inflictor, int damage, int armor, int bits) // FIXME - Bot doesn't necessary sees this enemy m_seeEnemyTime = GetWorldTime (); } - CollectExperienceData (inflictor, armor + damage); + + if (yb_csdm_mode.GetInt () == 0) + CollectExperienceData (inflictor, armor + damage); } } else // hurt by unusual damage like drowning or gas @@ -5801,7 +5804,7 @@ void Bot::CollectExperienceData (edict_t *attacker, int damage) int attackerTeam = GetTeam (attacker); int victimTeam = GetTeam (GetEntity ()); - if (attackerTeam == victimTeam) + if (attackerTeam == victimTeam ) return; // if these are bots also remember damage to rank destination of the bot @@ -5841,6 +5844,9 @@ void Bot::CollectExperienceData (edict_t *attacker, int damage) if (value > MAX_DAMAGE_VALUE) value = MAX_DAMAGE_VALUE; + if (value > g_highestDamageT) + g_highestDamageT = value; + (g_experienceData + (victimIndex * g_numWaypoints) + attackerIndex)->team0Damage = static_cast (value); } else @@ -5851,6 +5857,9 @@ void Bot::CollectExperienceData (edict_t *attacker, int damage) if (value > MAX_DAMAGE_VALUE) value = MAX_DAMAGE_VALUE; + if (value > g_highestDamageCT) + g_highestDamageCT = value; + (g_experienceData + (victimIndex * g_numWaypoints) + attackerIndex)->team1Damage = static_cast (value); } } diff --git a/source/botmanager.cpp b/source/botmanager.cpp index af991b5..2059b10 100644 --- a/source/botmanager.cpp +++ b/source/botmanager.cpp @@ -953,7 +953,7 @@ int BotManager::GetHumansJoinedTeam (void) { Client *cl = &g_clients[i]; - if ((cl->flags & (CF_USED | CF_ALIVE)) && m_bots[i] == NULL && cl->team != TEAM_SPEC && !(cl->ent->v.flags & FL_FAKECLIENT)) + if ((cl->flags & (CF_USED | CF_ALIVE)) && m_bots[i] == NULL && cl->team != TEAM_SPEC && !(cl->ent->v.flags & FL_FAKECLIENT) && cl->ent->v.movetype != MOVETYPE_FLY) count++; } return count; diff --git a/source/globals.cpp b/source/globals.cpp index 0adf3bb..16e55e8 100644 --- a/source/globals.cpp +++ b/source/globals.cpp @@ -57,7 +57,10 @@ int g_fakeArgc = 0; int g_gameVersion = CSV_STEAM; int g_numWaypoints = 0; int g_mapType = 0; -int g_killHistory = 0; + +int g_highestDamageCT = 1; +int g_highestDamageT = 1; +int g_highestKills = 1; short g_modelIndexLaser = 0; short g_modelIndexArrow = 0; diff --git a/source/navigate.cpp b/source/navigate.cpp index 583e08b..d35239a 100644 --- a/source/navigate.cpp +++ b/source/navigate.cpp @@ -1029,131 +1029,161 @@ void PriorityQueue::HeapSiftUp (void) } } -float gfunctionKillsDistT (int thisIndex, int parent, int skillOffset) + +int gfunctionKillsDistT (int currentIndex, int parentIndex) { // least kills and number of nodes to goal for a team - float cost = (g_experienceData + (thisIndex * g_numWaypoints) + thisIndex)->team0Damage + g_killHistory; + int cost = (g_experienceData + (currentIndex * g_numWaypoints) + currentIndex)->team0Damage + g_highestDamageT; + + Path *current = g_waypoint->GetPath (currentIndex); + Path *parent = g_waypoint->GetPath (parentIndex); for (int i = 0; i < MAX_PATH_INDEX; i++) { - int neighbour = g_waypoint->GetPath (thisIndex)->index[i]; + int neighbour = current->index[i]; if (neighbour != -1) - cost += (g_experienceData + (neighbour * g_numWaypoints) + neighbour)->team0Damage; + cost += (g_experienceData + (neighbour * g_numWaypoints) + neighbour)->team0Damage * 0.3; } - float pathDistance = static_cast (g_waypoint->GetPathDistance (parent, thisIndex)); - if (g_waypoint->GetPath (thisIndex)->flags & FLAG_CROUCH) - cost += pathDistance * 2; + if (current->flags & FLAG_CROUCH) + cost *= 2; - return pathDistance + (cost * (yb_danger_factor.GetFloat () * 2 / skillOffset)); + if (parentIndex < 0 || parentIndex > g_numWaypoints || parentIndex == currentIndex) + return cost * ((yb_danger_factor.GetInt () * 20 / (2 * g_highestDamageT))); + + return g_waypoint->GetPathDistance (parentIndex, currentIndex) + (cost * 10 * yb_danger_factor.GetInt ()); } -float gfunctionKillsT (int thisIndex, int parent, int skillOffset) -{ - // least kills to goal for a team - float cost = (g_experienceData + (thisIndex * g_numWaypoints) + thisIndex)->team0Damage; - - for (int i = 0; i < MAX_PATH_INDEX; i++) - { - int neighbour = g_waypoint->GetPath (thisIndex)->index[i]; - - if (neighbour != -1) - cost += (g_experienceData + (neighbour * g_numWaypoints) + neighbour)->team0Damage; - } - float pathDistance = static_cast (g_waypoint->GetPathDistance (parent, thisIndex)); - - if (g_waypoint->GetPath (thisIndex)->flags & FLAG_CROUCH) - cost += pathDistance * 3; - - return pathDistance + (cost * (yb_danger_factor.GetFloat () * 2 / skillOffset)); -} - -float gfunctionKillsDistCT (int thisIndex, int parent, int skillOffset) +int gfunctionKillsDistCT (int currentIndex, int parentIndex) { // least kills and number of nodes to goal for a team - float cost = (g_experienceData + (thisIndex * g_numWaypoints) + thisIndex)->team1Damage + g_killHistory; + int cost = (g_experienceData + (currentIndex * g_numWaypoints) + currentIndex)->team1Damage + g_highestDamageCT; + + Path *current = g_waypoint->GetPath (currentIndex); + Path *parent = g_waypoint->GetPath (parentIndex); for (int i = 0; i < MAX_PATH_INDEX; i++) { - int neighbour = g_waypoint->GetPath (thisIndex)->index[i]; + int neighbour = current->index[i]; if (neighbour != -1) - cost += (g_experienceData + (neighbour * g_numWaypoints) + neighbour)->team1Damage; + cost += static_cast ((g_experienceData + (neighbour * g_numWaypoints) + neighbour)->team1Damage * 0.3); } - float pathDistance = static_cast (g_waypoint->GetPathDistance (parent, thisIndex)); - if (g_waypoint->GetPath (thisIndex)->flags & FLAG_CROUCH) - cost += pathDistance * 2; + if (current->flags & FLAG_CROUCH) + cost *= 2; - return pathDistance + (cost * (yb_danger_factor.GetFloat () * 2 / skillOffset)); + if (parentIndex < 0 || parentIndex > g_numWaypoints || parentIndex == currentIndex) + return cost * ((yb_danger_factor.GetInt () * 20 / (2 * g_highestDamageCT))); + + return g_waypoint->GetPathDistance (parentIndex, currentIndex) + (cost * 10 * yb_danger_factor.GetInt ()); } -float gfunctionKillsCT (int thisIndex, int parent, int skillOffset) +int gfunctionKillsDistCTWithHostage (int currentIndex, int parentIndex) +{ + // least kills and number of nodes to goal for a team + + Path *current = g_waypoint->GetPath (currentIndex); + + if (current->flags & FLAG_NOHOSTAGE) + return 65536; + + else if (current->flags & (FLAG_CROUCH | FLAG_LADDER)) + return gfunctionKillsDistCT (currentIndex, parentIndex) * 500; + + return gfunctionKillsDistCT (currentIndex, parentIndex); +} + +int gfunctionKillsT (int currentIndex, int parentIndex) { // least kills to goal for a team - float cost = (g_experienceData + (thisIndex * g_numWaypoints) + thisIndex)->team1Damage; + int cost = (g_experienceData + (currentIndex * g_numWaypoints) + currentIndex)->team0Damage; + + Path *current = g_waypoint->GetPath (currentIndex); for (int i = 0; i < MAX_PATH_INDEX; i++) { - int neighbour = g_waypoint->GetPath (thisIndex)->index[i]; + int neighbour = current->index[i]; if (neighbour != -1) - cost += (g_experienceData + (neighbour * g_numWaypoints) + neighbour)->team1Damage; + cost += (g_experienceData + (neighbour * g_numWaypoints) + neighbour)->team0Damage * 0.3; } - float pathDistance = static_cast (g_waypoint->GetPathDistance (parent, thisIndex)); - if (g_waypoint->GetPath (thisIndex)->flags & FLAG_CROUCH) - cost += pathDistance * 3; + if (current->flags & FLAG_CROUCH) + cost *= 2; - return pathDistance + (cost * (yb_danger_factor.GetFloat () * 2 / skillOffset)); + return cost * 10 * yb_danger_factor.GetInt (); } -float gfunctionKillsDistCTNoHostage (int thisIndex, int parent, int skillOffset) +int gfunctionKillsCT (int currentIndex, int parentIndex) { - if (g_waypoint->GetPath (thisIndex)->flags & FLAG_NOHOSTAGE) - return 65355; - else if (g_waypoint->GetPath (thisIndex)->flags & (FLAG_CROUCH | FLAG_LADDER)) - return gfunctionKillsDistCT (thisIndex, parent, skillOffset) * 500; + // least kills to goal for a team - return gfunctionKillsDistCT (thisIndex, parent, skillOffset); + int cost = (g_experienceData + (currentIndex * g_numWaypoints) + currentIndex)->team1Damage; + + Path *current = g_waypoint->GetPath (currentIndex); + + for (int i = 0; i < MAX_PATH_INDEX; i++) + { + int neighbour = current->index[i]; + + if (neighbour != -1) + cost += (g_experienceData + (neighbour * g_numWaypoints) + neighbour)->team1Damage * 0.3; + } + + if (current->flags & FLAG_CROUCH) + cost *= 2; + + return cost * 10 * yb_danger_factor.GetInt (); } -float gfunctionKillsCTNoHostage (int thisIndex, int parent, int skillOffset) +int gfunctionKillsCTWithHostage (int currentIndex, int parentIndex) { - if (g_waypoint->GetPath (thisIndex)->flags & FLAG_NOHOSTAGE) - return 65355; - else if (g_waypoint->GetPath (thisIndex)->flags & (FLAG_CROUCH | FLAG_LADDER)) - return gfunctionKillsCT (thisIndex, parent, skillOffset) * 500; + // least kills to goal for a team - return gfunctionKillsCT (thisIndex, parent, skillOffset); + Path *current = g_waypoint->GetPath (currentIndex); + + if (current->flags & FLAG_NOHOSTAGE) + return 65536; + + else if (current->flags & (FLAG_CROUCH | FLAG_LADDER)) + return gfunctionKillsDistCT (currentIndex, parentIndex) * 500; + + return gfunctionKillsCT (currentIndex, parentIndex); } -float hfunctionPathDist (int startIndex, int goalIndex, int) +int hfunctionSquareDist (int startIndex, int goalIndex) { - // using square heuristic - Path *goal = g_waypoint->GetPath (goalIndex); + // square distance heuristic + Path *start = g_waypoint->GetPath (startIndex); + Path *goal = g_waypoint->GetPath (goalIndex); float deltaX = fabsf (goal->origin.x - start->origin.x); float deltaY = fabsf (goal->origin.y - start->origin.y); float deltaZ = fabsf (goal->origin.z - start->origin.z); - return deltaX + deltaY + deltaZ; + return static_cast (deltaX + deltaY + deltaZ); } -float hfunctionNumberNodes (int startIndex, int goalIndex, int unused) +int hfunctionSquareDistWithHostage (int startIndex, int goalIndex) { - return hfunctionPathDist (startIndex, goalIndex, unused) / 128 * g_killHistory; + // square distance heuristic with hostages + + if (g_waypoint->GetPath (startIndex)->flags & FLAG_NOHOSTAGE) + return 65536; + + return hfunctionSquareDist (startIndex, goalIndex); } -float hfunctionNone (int startIndex, int goalIndex, int unused) +int hfunctionNone (int startIndex, int goalIndex) { - return hfunctionPathDist (startIndex, goalIndex, unused) / (128 * 100); + return hfunctionSquareDist (startIndex, goalIndex) / (128 * 10); } void Bot::FindPath (int srcIndex, int destIndex, unsigned char pathType) @@ -1182,10 +1212,9 @@ void Bot::FindPath (int srcIndex, int destIndex, unsigned char pathType) struct AStar_t { - double g; - double f; + int g; + int f; short parentIndex; - AStarState_t state; } astar[MAX_WAYPOINTS]; @@ -1199,52 +1228,64 @@ void Bot::FindPath (int srcIndex, int destIndex, unsigned char pathType) astar[i].state = NEW; } - float (*gcalc) (int, int, int) = NULL; - float (*hcalc) (int, int, int) = NULL; + int (*gcalc) (int, int) = NULL; + int (*hcalc) (int, int) = NULL; - int skillOffset = 1; - - if (pathType == 0) + switch (pathType) { - if (GetTeam (GetEntity ()) == TEAM_TF) - gcalc = hfunctionNone; - else if (HasHostage ()) + case 0: + if ((g_mapType & MAP_CS) && HasHostage ()) + { gcalc = hfunctionNone; + hcalc = hfunctionSquareDistWithHostage; + } else + { gcalc = hfunctionNone; + hcalc = hfunctionSquareDist; + } + break; - hcalc = hfunctionNumberNodes; - skillOffset = m_skill / 25; - } - else if (pathType == 1) - { + case 1: if (GetTeam (GetEntity ()) == TEAM_TF) + { gcalc = gfunctionKillsDistT; - else if (HasHostage ()) - gcalc = gfunctionKillsDistCTNoHostage; + hcalc = hfunctionSquareDist; + } + else if ((g_mapType & MAP_CS) && HasHostage ()) + { + gcalc = gfunctionKillsDistCTWithHostage; + hcalc = hfunctionSquareDistWithHostage; + } else + { gcalc = gfunctionKillsDistCT; + hcalc = hfunctionSquareDist; + } + break; - hcalc = hfunctionNumberNodes; - skillOffset = m_skill / 25; - } - else if (pathType == 2) - { + case 2: if (GetTeam (GetEntity ()) == TEAM_TF) + { gcalc = gfunctionKillsT; - else if (HasHostage ()) - gcalc = gfunctionKillsCTNoHostage; + hcalc = hfunctionNone; + } + else if ((g_mapType & MAP_CS) && HasHostage ()) + { + gcalc = gfunctionKillsDistCTWithHostage; + hcalc = hfunctionNone; + } else + { gcalc = gfunctionKillsCT; - - hcalc = hfunctionNone; - skillOffset = m_skill / 20; + hcalc = hfunctionNone; + } + break; } - // put start node into open list - astar[srcIndex].g = gcalc (srcIndex, -1, skillOffset); - astar[srcIndex].f = astar[srcIndex].g + hcalc (srcIndex, destIndex, skillOffset); + astar[srcIndex].g = gcalc (srcIndex, -1); + astar[srcIndex].f = astar[srcIndex].g + hcalc (srcIndex, destIndex); astar[srcIndex].state = OPEN; openList.Insert (srcIndex, astar[srcIndex].g); @@ -1285,26 +1326,26 @@ void Bot::FindPath (int srcIndex, int destIndex, unsigned char pathType) // now expand the current node for (int i = 0; i < MAX_PATH_INDEX; i++) { - int iCurChild = g_waypoint->GetPath (currentIndex)->index[i]; + int currentChild = g_waypoint->GetPath (currentIndex)->index[i]; - if (iCurChild == -1) + if (currentChild == -1) continue; // calculate the F value as F = G + H - float g = astar[currentIndex].g + gcalc (iCurChild, currentIndex, skillOffset); - float h = hcalc (srcIndex, destIndex, skillOffset); - float f = g + h; + int g = astar[currentIndex].g + gcalc (currentChild, currentIndex); + int h = hcalc (srcIndex, destIndex); + int f = g + h; - if ((astar[iCurChild].state == NEW) || (astar[iCurChild].f > f)) + if (astar[currentChild].state == NEW || astar[currentChild].f > f) { // put the current child into open list - astar[iCurChild].parentIndex = currentIndex; - astar[iCurChild].state = OPEN; + astar[currentChild].parentIndex = currentIndex; + astar[currentChild].state = OPEN; - astar[iCurChild].g = g; - astar[iCurChild].f = f; + astar[currentChild].g = g; + astar[currentChild].f = f; - openList.Insert (iCurChild, g); + openList.Insert (currentChild, g); } } } @@ -1656,7 +1697,7 @@ int Bot::FindDefendWaypoint (Vector origin) else experience = exp->team1Damage; - experience = (experience * 100) / MAX_DAMAGE_VALUE; + experience = (experience * 100) / (GetTeam (GetEntity ()) == TEAM_TF ? g_highestDamageT : g_highestDamageCT); minDistance[i] = (experience * 100) / 8192; minDistance[i] += experience; } @@ -1910,28 +1951,25 @@ bool Bot::HeadTowardWaypoint (void) int kills = 0; if (GetTeam (GetEntity ()) == TEAM_TF) - kills = (g_experienceData + (waypoint * g_numWaypoints) + waypoint)->team0Damage; + kills = (g_experienceData + (waypoint * g_numWaypoints) + waypoint)->team0Damage / g_highestDamageT; else - kills = (g_experienceData + (waypoint * g_numWaypoints) + waypoint)->team1Damage; + kills = (g_experienceData + (waypoint * g_numWaypoints) + waypoint)->team1Damage / g_highestDamageCT; // if damage done higher than one - if (kills > 1 && g_timeRoundMid > GetWorldTime () && g_killHistory > 0) + if (kills > 0.15f && g_timeRoundMid > GetWorldTime ()) { - kills = (kills * 100) / g_killHistory; - kills /= 100; - switch (m_personality) { case PERSONALITY_NORMAL: - kills /= 2; + kills *= 0.33f; break; default: - kills /= 1.2; + kills *= 0.5f; break; } - if (m_baseAgressionLevel < static_cast (kills) && (m_skill < 98 || GetTeam (GetEntity ()) == TEAM_CF)) + if (m_baseAgressionLevel < static_cast (kills) && GetTaskId () != TASK_MOVETOPOSITION && HasPrimaryWeapon ()) { StartTask (TASK_CAMP, TASKPRI_CAMP, -1, GetWorldTime () + (m_fearLevel * (g_timeRoundMid - GetWorldTime ()) * 0.5), true); // push camp task on to stack diff --git a/source/support.cpp b/source/support.cpp index 01faf26..8627497 100644 --- a/source/support.cpp +++ b/source/support.cpp @@ -637,7 +637,7 @@ void UpdateGlobalExperienceData (void) // this function called after each end of the round to update knowledge about most dangerous waypoints for each team. // no waypoints, no experience used or waypoints edited or being edited? - if ((g_numWaypoints < 1) || g_waypointsChanged) + if (g_numWaypoints < 1 || g_waypointsChanged) return; // no action unsigned short maxDamage; // maximum damage @@ -726,16 +726,30 @@ void UpdateGlobalExperienceData (void) } } } - g_killHistory++; + g_highestKills++; - if (g_killHistory == MAX_KILL_HISTORY) + int clip = g_highestDamageT - static_cast (MAX_DAMAGE_VALUE * 0.5); + + if (clip < 1) + clip = 1; + + g_highestDamageT = clip; + + clip = (int) g_highestDamageCT - static_cast (MAX_DAMAGE_VALUE * 0.5); + + if (clip < 1) + clip = 1; + + g_highestDamageCT = clip; + + if (g_highestKills == MAX_KILL_HISTORY) { for (int i = 0; i < g_numWaypoints; i++) { (g_experienceData + (i * g_numWaypoints) + i)->team0Damage /= static_cast (GetMaxClients () * 0.5); (g_experienceData + (i * g_numWaypoints) + i)->team1Damage /= static_cast (GetMaxClients () * 0.5); } - g_killHistory = 1; + g_highestKills = 1; } } diff --git a/source/waypoint.cpp b/source/waypoint.cpp index 3ecedd5..1351760 100644 --- a/source/waypoint.cpp +++ b/source/waypoint.cpp @@ -897,6 +897,9 @@ void Waypoint::InitExperienceTab (void) g_experienceData = new Experience[g_numWaypoints * g_numWaypoints]; + g_highestDamageCT = 1; + g_highestDamageT = 1; + // initialize table by hand to correct values, and NOT zero it out for (i = 0; i < g_numWaypoints; i++) { @@ -934,6 +937,12 @@ void Waypoint::InitExperienceTab (void) { (g_experienceData + (i * g_numWaypoints) + j)->team0Damage = (unsigned short) ((experienceLoad + (i * g_numWaypoints) + j)->team0Damage); (g_experienceData + (i * g_numWaypoints) + j)->team1Damage = (unsigned short) ((experienceLoad + (i * g_numWaypoints) + j)->team1Damage); + + if ((g_experienceData + (i * g_numWaypoints) + j)->team0Damage > g_highestDamageT) + g_highestDamageT = (g_experienceData + (i * g_numWaypoints) + j)->team0Damage; + + if ((g_experienceData + (i * g_numWaypoints) + j)->team1Damage > g_highestDamageCT) + g_highestDamageCT = (g_experienceData + (i * g_numWaypoints) + j)->team1Damage; } else { @@ -1168,7 +1177,7 @@ bool Waypoint::Load (void) InitTypes (); g_waypointsChanged = false; - g_killHistory = 0; + g_highestKills = 1; m_pathDisplayTime = 0.0; m_arrowDisplayTime = 0.0; @@ -1244,7 +1253,7 @@ bool Waypoint::Reachable (Bot *bot, int index) { // this function return wether bot able to reach index waypoint or not, depending on several factors. - if (index < 0 || index >= g_numWaypoints) + if (bot == NULL || index < 0 || index >= g_numWaypoints) return false; Vector src = bot->pev->origin;