misc: refactored weapon type recognition.
fix: reverted body offsets from 2.7 version. fix: do not destroy breakable around if closer than 100 units. (#156 possible can be fixed). fix: minimum supported hl & cs version display. fix: csdm respawn outside of waypointed area causing pathfinder errors.
This commit is contained in:
parent
8acd84fdc8
commit
a675c40927
10 changed files with 205 additions and 174 deletions
10
inc/config.h
10
inc/config.h
|
|
@ -185,6 +185,16 @@ public:
|
||||||
return m_weaponProps[id];
|
return m_weaponProps[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get's weapons type by id
|
||||||
|
int32 getWeaponType (int id) const {
|
||||||
|
for (const auto &weapon : m_weapons) {
|
||||||
|
if (weapon.id == id) {
|
||||||
|
return weapon.type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return WeaponType::None;
|
||||||
|
}
|
||||||
|
|
||||||
// get's weapon preferences for personality
|
// get's weapon preferences for personality
|
||||||
int32 *getWeaponPrefs (int personality) const {
|
int32 *getWeaponPrefs (int personality) const {
|
||||||
switch (personality) {
|
switch (personality) {
|
||||||
|
|
|
||||||
22
inc/yapb.h
22
inc/yapb.h
|
|
@ -239,6 +239,19 @@ CR_DECLARE_SCOPED_ENUM (Chatter,
|
||||||
Count
|
Count
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// counter strike weapon classes (types)
|
||||||
|
CR_DECLARE_SCOPED_ENUM (WeaponType,
|
||||||
|
None,
|
||||||
|
Melee,
|
||||||
|
Pistol,
|
||||||
|
Shotgun,
|
||||||
|
ZoomRifle,
|
||||||
|
Rifle,
|
||||||
|
SMG,
|
||||||
|
Sniper,
|
||||||
|
Heavy
|
||||||
|
)
|
||||||
|
|
||||||
// counter-strike weapon id's
|
// counter-strike weapon id's
|
||||||
CR_DECLARE_SCOPED_ENUM (Weapon,
|
CR_DECLARE_SCOPED_ENUM (Weapon,
|
||||||
P228 = 1,
|
P228 = 1,
|
||||||
|
|
@ -524,6 +537,7 @@ struct WeaponInfo {
|
||||||
int buySelectCT; // for counter-strike v1.6
|
int buySelectCT; // for counter-strike v1.6
|
||||||
int penetratePower; // penetrate power
|
int penetratePower; // penetrate power
|
||||||
int maxClip; // max ammo in clip
|
int maxClip; // max ammo in clip
|
||||||
|
int type; // weapon class
|
||||||
bool primaryFireHold; // hold down primary fire button to use?
|
bool primaryFireHold; // hold down primary fire button to use?
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -540,9 +554,10 @@ public:
|
||||||
int buySelectCT,
|
int buySelectCT,
|
||||||
int penetratePower,
|
int penetratePower,
|
||||||
int maxClip,
|
int maxClip,
|
||||||
|
int type,
|
||||||
bool fireHold) : id (id), name (name), model (model), price (price), minPrimaryAmmo (minPriAmmo), teamStandard (teamStd),
|
bool fireHold) : id (id), name (name), model (model), price (price), minPrimaryAmmo (minPriAmmo), teamStandard (teamStd),
|
||||||
teamAS (teamAs), buyGroup (buyGroup), buySelect (buySelect), buySelectT (buySelectT), buySelectCT (buySelectCT),
|
teamAS (teamAs), buyGroup (buyGroup), buySelect (buySelect), buySelectT (buySelectT), buySelectCT (buySelectCT),
|
||||||
penetratePower (penetratePower), maxClip (maxClip), primaryFireHold (fireHold)
|
penetratePower (penetratePower), maxClip (maxClip), type (type), primaryFireHold (fireHold)
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -980,6 +995,7 @@ public:
|
||||||
int m_lastDamageType; // stores last damage
|
int m_lastDamageType; // stores last damage
|
||||||
int m_team; // bot team
|
int m_team; // bot team
|
||||||
int m_currentWeapon; // one current weapon for each bot
|
int m_currentWeapon; // one current weapon for each bot
|
||||||
|
int m_weaponType; // current weapon type
|
||||||
int m_ammoInClip[kMaxWeapons]; // ammo in clip for each weapons
|
int m_ammoInClip[kMaxWeapons]; // ammo in clip for each weapons
|
||||||
int m_ammo[MAX_AMMO_SLOTS]; // total ammo amounts
|
int m_ammo[MAX_AMMO_SLOTS]; // total ammo amounts
|
||||||
|
|
||||||
|
|
@ -1025,6 +1041,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void logic (); /// the things that can be executed while skipping frames
|
void logic (); /// the things that can be executed while skipping frames
|
||||||
|
void spawned ();
|
||||||
void takeBlind (int alpha);
|
void takeBlind (int alpha);
|
||||||
void takeDamage (edict_t *inflictor, int damage, int armor, int bits);
|
void takeDamage (edict_t *inflictor, int damage, int armor, int bits);
|
||||||
void showDebugOverlay ();
|
void showDebugOverlay ();
|
||||||
|
|
@ -1057,9 +1074,12 @@ public:
|
||||||
bool usesPistol ();
|
bool usesPistol ();
|
||||||
bool usesSniper ();
|
bool usesSniper ();
|
||||||
bool usesSubmachine ();
|
bool usesSubmachine ();
|
||||||
|
bool usesShotgun ();
|
||||||
|
bool usesHeavy ();
|
||||||
bool usesZoomableRifle ();
|
bool usesZoomableRifle ();
|
||||||
bool usesBadWeapon ();
|
bool usesBadWeapon ();
|
||||||
bool usesCampGun ();
|
bool usesCampGun ();
|
||||||
|
bool usesKnife ();
|
||||||
bool hasPrimaryWeapon ();
|
bool hasPrimaryWeapon ();
|
||||||
bool hasSecondaryWeapon ();
|
bool hasSecondaryWeapon ();
|
||||||
bool hasShield ();
|
bool hasShield ();
|
||||||
|
|
|
||||||
|
|
@ -409,18 +409,25 @@ void Bot::checkBreakable (edict_t *touch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::checkBreakablesAround () {
|
void Bot::checkBreakablesAround () {
|
||||||
if (!cv_destroy_breakables_around.bool_ () || m_currentWeapon == Weapon::Knife || rg.chance (25) || !game.hasBreakables () || m_seeEnemyTime + 4.0f > game.time () || !game.isNullEntity (m_enemy) || !hasPrimaryWeapon ()) {
|
if (!cv_destroy_breakables_around.bool_ () || usesKnife () || rg.chance (25) || !game.hasBreakables () || m_seeEnemyTime + 4.0f > game.time () || !game.isNullEntity (m_enemy) || !hasPrimaryWeapon ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we're have some breakbles in 450 units range
|
// check if we're have some breakbles in 400 units range
|
||||||
for (const auto &breakable : game.getBreakables ()) {
|
for (const auto &breakable : game.getBreakables ()) {
|
||||||
if (!game.isShootableBreakable (breakable)) {
|
if (!game.isShootableBreakable (breakable)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto &origin = game.getEntityWorldOrigin (breakable);
|
const auto &origin = game.getEntityWorldOrigin (breakable);
|
||||||
|
const auto lengthToObstacle = (origin - pev->origin).lengthSq ();
|
||||||
|
|
||||||
if ((origin - pev->origin).lengthSq () > cr::square (450.0f)) {
|
// too far, skip it
|
||||||
|
if (lengthToObstacle > cr::square (400.0f)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// too close, skip it
|
||||||
|
if (lengthToObstacle < cr::square (100.0f)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -605,11 +612,12 @@ void Bot::updatePickups () {
|
||||||
allowPickup = false;
|
allowPickup = false;
|
||||||
}
|
}
|
||||||
else if (!m_isVIP && primaryWeaponCarried >= 7 && (m_ammo[primary.id] > 0.3 * primaryProp.ammo1Max) && strncmp (model, "w_", 2) == 0) {
|
else if (!m_isVIP && primaryWeaponCarried >= 7 && (m_ammo[primary.id] > 0.3 * primaryProp.ammo1Max) && strncmp (model, "w_", 2) == 0) {
|
||||||
|
auto weaponType = conf.getWeaponType (primaryWeaponCarried);
|
||||||
|
|
||||||
const bool isSniperRifle = primaryWeaponCarried == Weapon::AWP || primaryWeaponCarried == Weapon::G3SG1 || primaryWeaponCarried == Weapon::SG550;
|
const bool isSniperRifle = weaponType == WeaponType::Sniper;
|
||||||
const bool isSubmachine = primaryWeaponCarried == Weapon::MP5 || primaryWeaponCarried == Weapon::TMP || primaryWeaponCarried == Weapon::P90 || primaryWeaponCarried == Weapon::MAC10 || primaryWeaponCarried == Weapon::UMP45;
|
const bool isSubmachine = weaponType == WeaponType::SMG;
|
||||||
const bool isShotgun = primaryWeaponCarried == Weapon::M3;
|
const bool isShotgun = weaponType == WeaponType::Shotgun;
|
||||||
const bool isRifle = primaryWeaponCarried == Weapon::Famas || primaryWeaponCarried == Weapon::AK47 || primaryWeaponCarried == Weapon::M4A1 || primaryWeaponCarried == Weapon::Galil || primaryWeaponCarried == Weapon::AUG || primaryWeaponCarried == Weapon::SG552;
|
const bool isRifle = weaponType == WeaponType::Rifle || weaponType == WeaponType::ZoomRifle;
|
||||||
|
|
||||||
if (strcmp (model, "w_9mmarclip.mdl") == 0 && !isRifle) {
|
if (strcmp (model, "w_9mmarclip.mdl") == 0 && !isRifle) {
|
||||||
allowPickup = false;
|
allowPickup = false;
|
||||||
|
|
@ -762,7 +770,7 @@ void Bot::updatePickups () {
|
||||||
m_defendedBomb = true;
|
m_defendedBomb = true;
|
||||||
|
|
||||||
int index = findDefendNode (origin);
|
int index = findDefendNode (origin);
|
||||||
const Path &path = graph[index];
|
const auto &path = graph[index];
|
||||||
|
|
||||||
float timeToExplode = bots.getTimeBombPlanted () + mp_c4timer.float_ () - graph.calculateTravelTime (pev->maxspeed, pev->origin, path.origin);
|
float timeToExplode = bots.getTimeBombPlanted () + mp_c4timer.float_ () - graph.calculateTravelTime (pev->maxspeed, pev->origin, path.origin);
|
||||||
|
|
||||||
|
|
@ -1232,7 +1240,7 @@ bool Bot::canReplaceWeapon () {
|
||||||
else if (m_currentWeapon == Weapon::MP5 && m_moneyAmount > 6000) {
|
else if (m_currentWeapon == Weapon::MP5 && m_moneyAmount > 6000) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if ((m_currentWeapon == Weapon::M3 || m_currentWeapon == Weapon::XM1014) && m_moneyAmount > 4000) {
|
else if (usesShotgun () && m_moneyAmount > 4000) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return isWeaponRestricted (m_currentWeapon);
|
return isWeaponRestricted (m_currentWeapon);
|
||||||
|
|
@ -1689,7 +1697,7 @@ void Bot::updateEmotions () {
|
||||||
|
|
||||||
void Bot::overrideConditions () {
|
void Bot::overrideConditions () {
|
||||||
|
|
||||||
if (m_currentWeapon != Weapon::Knife && m_difficulty > Difficulty::Normal && ((m_aimFlags & AimFlags::Enemy) || (m_states & Sense::SeeingEnemy)) && !cv_jasonmode.bool_ () && getCurrentTaskId () != Task::Camp && getCurrentTaskId () != Task::SeekCover && !isOnLadder ()) {
|
if (!usesKnife () && m_difficulty > Difficulty::Normal && ((m_aimFlags & AimFlags::Enemy) || (m_states & Sense::SeeingEnemy)) && !cv_jasonmode.bool_ () && getCurrentTaskId () != Task::Camp && getCurrentTaskId () != Task::SeekCover && !isOnLadder ()) {
|
||||||
m_moveToGoal = false; // don't move to goal
|
m_moveToGoal = false; // don't move to goal
|
||||||
m_navTimeset = game.time ();
|
m_navTimeset = game.time ();
|
||||||
|
|
||||||
|
|
@ -1707,7 +1715,7 @@ void Bot::overrideConditions () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// special handling, if we have a knife in our hands
|
// special handling, if we have a knife in our hands
|
||||||
if ((bots.getRoundStartTime () + 6.0f > game.time () || !hasAnyWeapons ()) && m_currentWeapon == Weapon::Knife && util.isPlayer (m_enemy)) {
|
if ((bots.getRoundStartTime () + 6.0f > game.time () || !hasAnyWeapons ()) && usesKnife () && util.isPlayer (m_enemy)) {
|
||||||
float length = (pev->origin - m_enemy->v.origin).length2d ();
|
float length = (pev->origin - m_enemy->v.origin).length2d ();
|
||||||
|
|
||||||
// do waypoint movement if enemy is not reachable with a knife
|
// do waypoint movement if enemy is not reachable with a knife
|
||||||
|
|
@ -1808,7 +1816,7 @@ void Bot::setConditions () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if no more enemies found AND bomb planted, switch to knife to get to bombplace faster
|
// if no more enemies found AND bomb planted, switch to knife to get to bombplace faster
|
||||||
if (m_team == Team::CT && m_currentWeapon != Weapon::Knife && m_numEnemiesLeft == 0 && bots.isBombPlanted ()) {
|
if (m_team == Team::CT && !usesKnife () && m_numEnemiesLeft == 0 && bots.isBombPlanted ()) {
|
||||||
selectWeaponByName ("weapon_knife");
|
selectWeaponByName ("weapon_knife");
|
||||||
m_plantedBombNodeIndex = getNearestToPlantedBomb ();
|
m_plantedBombNodeIndex = getNearestToPlantedBomb ();
|
||||||
|
|
||||||
|
|
@ -1945,7 +1953,7 @@ void Bot::filterTasks () {
|
||||||
}
|
}
|
||||||
bool lowAmmo = m_ammoInClip[m_currentWeapon] < conf.findWeaponById (m_currentWeapon).maxClip * 0.18f;
|
bool lowAmmo = m_ammoInClip[m_currentWeapon] < conf.findWeaponById (m_currentWeapon).maxClip * 0.18f;
|
||||||
|
|
||||||
if (bots.isBombPlanted () || m_isStuck || m_currentWeapon == Weapon::Knife) {
|
if (bots.isBombPlanted () || m_isStuck || usesKnife ()) {
|
||||||
ratio /= 3.0f; // reduce the seek cover desire if bomb is planted
|
ratio /= 3.0f; // reduce the seek cover desire if bomb is planted
|
||||||
}
|
}
|
||||||
else if (m_isVIP || m_isReloading || (lowAmmo && usesSniper ())) {
|
else if (m_isVIP || m_isReloading || (lowAmmo && usesSniper ())) {
|
||||||
|
|
@ -2427,7 +2435,7 @@ void Bot::checkRadioQueue () {
|
||||||
|
|
||||||
case Radio::RegroupTeam:
|
case Radio::RegroupTeam:
|
||||||
// if no more enemies found AND bomb planted, switch to knife to get to bombplace faster
|
// if no more enemies found AND bomb planted, switch to knife to get to bombplace faster
|
||||||
if (m_team == Team::CT && m_currentWeapon != Weapon::Knife && m_numEnemiesLeft == 0 && bots.isBombPlanted () && getCurrentTaskId () != Task::DefuseBomb) {
|
if (m_team == Team::CT && !usesKnife () && m_numEnemiesLeft == 0 && bots.isBombPlanted () && getCurrentTaskId () != Task::DefuseBomb) {
|
||||||
selectWeaponByName ("weapon_knife");
|
selectWeaponByName ("weapon_knife");
|
||||||
|
|
||||||
clearSearchNodes ();
|
clearSearchNodes ();
|
||||||
|
|
@ -3055,7 +3063,7 @@ void Bot::normal_ () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// bots rushing with knife, when have no enemy (thanks for idea to nicebot project)
|
// bots rushing with knife, when have no enemy (thanks for idea to nicebot project)
|
||||||
if (m_currentWeapon == Weapon::Knife && (game.isNullEntity (m_lastEnemy) || !util.isAlive (m_lastEnemy)) && game.isNullEntity (m_enemy) && m_knifeAttackTime < game.time () && !hasShield () && numFriendsNear (pev->origin, 96.0f) == 0) {
|
if (usesKnife () && (game.isNullEntity (m_lastEnemy) || !util.isAlive (m_lastEnemy)) && game.isNullEntity (m_enemy) && m_knifeAttackTime < game.time () && !hasShield () && numFriendsNear (pev->origin, 96.0f) == 0) {
|
||||||
if (rg.chance (40)) {
|
if (rg.chance (40)) {
|
||||||
pev->button |= IN_ATTACK;
|
pev->button |= IN_ATTACK;
|
||||||
}
|
}
|
||||||
|
|
@ -3233,7 +3241,12 @@ void Bot::normal_ () {
|
||||||
ignoreCollision ();
|
ignoreCollision ();
|
||||||
|
|
||||||
// did we already decide about a goal before?
|
// did we already decide about a goal before?
|
||||||
int destIndex = getTask ()->data != kInvalidNodeIndex ? getTask ()->data : findBestGoal ();
|
auto destIndex = graph.exists (getTask ()->data) ? getTask ()->data : findBestGoal ();
|
||||||
|
|
||||||
|
// check for existance (this is failover, for i.e. csdm, this should be not true with normal gameplay, only when spawned outside of waypointed area)
|
||||||
|
if (!graph.exists (destIndex)) {
|
||||||
|
destIndex = graph.getFarest (pev->origin, 512.0f);
|
||||||
|
}
|
||||||
|
|
||||||
m_prevGoalIndex = destIndex;
|
m_prevGoalIndex = destIndex;
|
||||||
|
|
||||||
|
|
@ -3483,7 +3496,7 @@ void Bot::attackEnemy_ () {
|
||||||
ignoreCollision ();
|
ignoreCollision ();
|
||||||
attackMovement ();
|
attackMovement ();
|
||||||
|
|
||||||
if (m_currentWeapon == Weapon::Knife && !m_lastEnemyOrigin.empty ()) {
|
if (usesKnife () && !m_lastEnemyOrigin.empty ()) {
|
||||||
m_destOrigin = m_lastEnemyOrigin;
|
m_destOrigin = m_lastEnemyOrigin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4348,7 +4361,7 @@ void Bot::escapeFromBomb_ () {
|
||||||
pev->button |= IN_ATTACK2;
|
pev->button |= IN_ATTACK2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_currentWeapon != Weapon::Knife && m_numEnemiesLeft == 0) {
|
if (!usesKnife () && m_numEnemiesLeft == 0) {
|
||||||
selectWeaponByName ("weapon_knife");
|
selectWeaponByName ("weapon_knife");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4423,7 +4436,7 @@ void Bot::shootBreakable_ () {
|
||||||
m_moveSpeed = 0.0f;
|
m_moveSpeed = 0.0f;
|
||||||
m_strafeSpeed = 0.0f;
|
m_strafeSpeed = 0.0f;
|
||||||
|
|
||||||
if (m_currentWeapon == Weapon::Knife) {
|
if (usesKnife ()) {
|
||||||
selectBestWeapon ();
|
selectBestWeapon ();
|
||||||
}
|
}
|
||||||
m_wantsToFire = true;
|
m_wantsToFire = true;
|
||||||
|
|
@ -4919,6 +4932,12 @@ void Bot::logic () {
|
||||||
m_lastDamageType = -1; // reset damage
|
m_lastDamageType = -1; // reset damage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bot::spawned () {
|
||||||
|
if (game.is (GameFlags::CSDM)) {
|
||||||
|
newRound ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Bot::showDebugOverlay () {
|
void Bot::showDebugOverlay () {
|
||||||
bool displayDebugOverlay = false;
|
bool displayDebugOverlay = false;
|
||||||
|
|
||||||
|
|
@ -5050,7 +5069,6 @@ void Bot::showDebugOverlay () {
|
||||||
for (size_t i = 0; i < m_pathWalk.length () && i + 1 < m_pathWalk.length (); ++i) {
|
for (size_t i = 0; i < m_pathWalk.length () && i + 1 < m_pathWalk.length (); ++i) {
|
||||||
game.drawLine (game.getLocalEntity (), graph[m_pathWalk.at (i)].origin, graph[m_pathWalk.at (i + 1)].origin, 15, 0, { 255, 100, 55 }, 200, 5, 1, DrawLine::Arrow);
|
game.drawLine (game.getLocalEntity (), graph[m_pathWalk.at (i)].origin, graph[m_pathWalk.at (i + 1)].origin, 15, 0, { 255, 100, 55 }, 200, 5, 1, DrawLine::Arrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bot::hasHostage () {
|
bool Bot::hasHostage () {
|
||||||
|
|
|
||||||
171
src/combat.cpp
171
src/combat.cpp
|
|
@ -462,26 +462,19 @@ const Vector &Bot::getEnemyBodyOffset () {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
|
||||||
// now take in account different parts of enemy body
|
// now take in account different parts of enemy body
|
||||||
if (m_enemyParts & (Visibility::Head | Visibility::Body)) {
|
if (m_enemyParts & (Visibility::Head | Visibility::Body)) {
|
||||||
// forced to use body?
|
|
||||||
bool useBody = !usesPistol () && distance >= kSprayDistance && distance < 3072.0f;
|
|
||||||
|
|
||||||
// now check is our skill match to aim at head, else aim at enemy body
|
// now check is our skill match to aim at head, else aim at enemy body
|
||||||
if (rg.chance (conf.getDifficultyTweaks (m_difficulty)->headshotPct) && !useBody) {
|
if (rg.chance (conf.getDifficultyTweaks (m_difficulty)->headshotPct)) {
|
||||||
aimPos.z = headOffset (m_enemy) + getEnemyBodyOffsetCorrection (distance);
|
aimPos.z = headOffset (m_enemy) + getEnemyBodyOffsetCorrection (distance);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
aimPos.z += getEnemyBodyOffsetCorrection (distance);
|
aimPos.z += 3.5f;
|
||||||
|
|
||||||
if (useBody) {
|
|
||||||
aimPos.z += 4.5f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_enemyParts & Visibility::Body) {
|
else if (m_enemyParts & Visibility::Body) {
|
||||||
aimPos.z += getEnemyBodyOffsetCorrection (distance);
|
aimPos.z += 3.5f;
|
||||||
}
|
}
|
||||||
else if (m_enemyParts & Visibility::Other) {
|
else if (m_enemyParts & Visibility::Other) {
|
||||||
aimPos = m_enemyOrigin;
|
aimPos = m_enemyOrigin;
|
||||||
|
|
@ -502,44 +495,41 @@ const Vector &Bot::getEnemyBodyOffset () {
|
||||||
}
|
}
|
||||||
|
|
||||||
float Bot::getEnemyBodyOffsetCorrection (float distance) {
|
float Bot::getEnemyBodyOffsetCorrection (float distance) {
|
||||||
bool sniper = usesSniper ();
|
enum DistanceIndex {
|
||||||
bool pistol = usesPistol ();
|
Long, Middle, Short
|
||||||
bool rifle = usesRifle ();
|
};
|
||||||
|
|
||||||
bool zoomableRifle = usesZoomableRifle ();
|
static float offsetRanges[9][3] = {
|
||||||
bool submachine = usesSubmachine ();
|
{ 0.0f, 0.0f, 0.0f }, // none
|
||||||
bool shotgun = (m_currentWeapon == Weapon::XM1014 || m_currentWeapon == Weapon::M3);
|
{ 0.0f, 0.0f, 0.0f }, // melee
|
||||||
bool m249 = m_currentWeapon == Weapon::M249;
|
{ 6.5f, 6.5f, 4.5f }, // pistol
|
||||||
|
{ 9.5f, 9.0f, -5.0f }, // shotgun
|
||||||
|
{ 4.5f, 3.5f, -5.0f }, // zoomrifle
|
||||||
|
{ 5.5f, 1.0f, -4.5f }, // rifle
|
||||||
|
{ 5.5f, 3.5f, -4.5f }, // smg
|
||||||
|
{ 3.5f, 3.5f, 4.5f }, // sniper
|
||||||
|
{ 2.5f, -2.0f, -6.0f } // heavy
|
||||||
|
};
|
||||||
|
|
||||||
float result = -2.0f;
|
// only highskilled bots do that
|
||||||
|
if (m_difficulty < Difficulty::Normal) {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
if (distance >= kDoubleSprayDistance) {
|
// default distance index is short
|
||||||
if (sniper) {
|
int32 distanceIndex = DistanceIndex::Short;
|
||||||
result = 0.18f;
|
|
||||||
|
// set distance index appropriate to distance
|
||||||
|
if (distance < 3072.0f && distance > kDoubleSprayDistance) {
|
||||||
|
distanceIndex = DistanceIndex::Long;
|
||||||
}
|
}
|
||||||
else if (zoomableRifle) {
|
else if (distance > kSprayDistance && distance <= kDoubleSprayDistance) {
|
||||||
result = 1.5f;
|
distanceIndex = DistanceIndex::Middle;
|
||||||
}
|
}
|
||||||
else if (pistol) {
|
else if (distance < kSprayDistance) {
|
||||||
result = 2.5f;
|
distanceIndex = DistanceIndex::Short;
|
||||||
}
|
}
|
||||||
else if (submachine) {
|
return offsetRanges[m_weaponType][distanceIndex];
|
||||||
result = 1.5f;
|
|
||||||
}
|
|
||||||
else if (rifle) {
|
|
||||||
result = -1.0f;
|
|
||||||
}
|
|
||||||
else if (m249) {
|
|
||||||
result = -5.5f;
|
|
||||||
}
|
|
||||||
else if (shotgun) {
|
|
||||||
result = -4.5f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = -5.6f;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bot::isFriendInLineOfFire (float distance) {
|
bool Bot::isFriendInLineOfFire (float distance) {
|
||||||
|
|
@ -967,12 +957,12 @@ bool Bot::isWeaponBadAtDistance (int weaponIndex, float distance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// better use pistol in short range distances, when using sniper weapons
|
// better use pistol in short range distances, when using sniper weapons
|
||||||
if ((wid == Weapon::Scout || wid == Weapon::AWP || wid == Weapon::G3SG1 || wid == Weapon::SG550) && distance < 450.0f) {
|
if (m_weaponType == WeaponType::Sniper && distance < 450.0f) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// shotguns is too inaccurate at long distances, so weapon is bad
|
// shotguns is too inaccurate at long distances, so weapon is bad
|
||||||
if ((wid == Weapon::M3 || wid == Weapon::XM1014) && distance > 750.0f) {
|
if (m_weaponType == WeaponType::Shotgun && distance > 750.0f) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -992,7 +982,7 @@ void Bot::focusEnemy () {
|
||||||
float distance = (m_lookAt - getEyesPos ()).length2d (); // how far away is the enemy scum?
|
float distance = (m_lookAt - getEyesPos ()).length2d (); // how far away is the enemy scum?
|
||||||
|
|
||||||
if (distance < 128.0f && !usesSniper ()) {
|
if (distance < 128.0f && !usesSniper ()) {
|
||||||
if (m_currentWeapon == Weapon::Knife) {
|
if (usesKnife ()) {
|
||||||
if (distance < 80.0f) {
|
if (distance < 80.0f) {
|
||||||
m_wantsToFire = true;
|
m_wantsToFire = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1039,7 +1029,7 @@ void Bot::attackMovement () {
|
||||||
if (m_lastUsedNodesTime + getFrameInterval () + 0.5f < game.time ()) {
|
if (m_lastUsedNodesTime + getFrameInterval () + 0.5f < game.time ()) {
|
||||||
int approach;
|
int approach;
|
||||||
|
|
||||||
if (m_currentWeapon == Weapon::Knife) {
|
if (usesKnife ()) {
|
||||||
approach = 100;
|
approach = 100;
|
||||||
}
|
}
|
||||||
else if ((m_states & Sense::SuspectEnemy) && !(m_states & Sense::SeeingEnemy)) {
|
else if ((m_states & Sense::SuspectEnemy) && !(m_states & Sense::SeeingEnemy)) {
|
||||||
|
|
@ -1068,7 +1058,7 @@ void Bot::attackMovement () {
|
||||||
m_moveSpeed = pev->maxspeed;
|
m_moveSpeed = pev->maxspeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (distance < 96.0f && m_currentWeapon != Weapon::Knife) {
|
if (distance < 96.0f && !usesKnife ()) {
|
||||||
m_moveSpeed = -pev->maxspeed;
|
m_moveSpeed = -pev->maxspeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1106,7 +1096,7 @@ void Bot::attackMovement () {
|
||||||
m_fightStyle = Fight::Strafe;
|
m_fightStyle = Fight::Strafe;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_fightStyle == Fight::Strafe || ((pev->button & IN_RELOAD) || m_isReloading) || (usesPistol () && distance < 400.0f) || m_currentWeapon == Weapon::Knife) {
|
if (m_fightStyle == Fight::Strafe || ((pev->button & IN_RELOAD) || m_isReloading) || (usesPistol () && distance < 400.0f) || usesKnife ()) {
|
||||||
if (m_strafeSetTime < game.time ()) {
|
if (m_strafeSetTime < game.time ()) {
|
||||||
|
|
||||||
// to start strafing, we have to first figure out if the target is on the left side or right side
|
// to start strafing, we have to first figure out if the target is on the left side or right side
|
||||||
|
|
@ -1149,11 +1139,11 @@ void Bot::attackMovement () {
|
||||||
pev->button |= IN_JUMP;
|
pev->button |= IN_JUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_moveSpeed > 0.0f && distance > 100.0f && m_currentWeapon != Weapon::Knife) {
|
if (m_moveSpeed > 0.0f && distance > 100.0f && !usesKnife ()) {
|
||||||
m_moveSpeed = 0.0f;
|
m_moveSpeed = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_currentWeapon == Weapon::Knife) {
|
if (usesKnife ()) {
|
||||||
m_strafeSpeed = 0.0f;
|
m_strafeSpeed = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1172,7 +1162,7 @@ void Bot::attackMovement () {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_fightStyle == Fight::Stay || (m_duckTime > game.time () || m_sniperStopTime > game.time ())) {
|
if (m_fightStyle == Fight::Stay || (m_duckTime > game.time () || m_sniperStopTime > game.time ())) {
|
||||||
if (m_moveSpeed > 0.0f && m_currentWeapon != Weapon::Knife) {
|
if (m_moveSpeed > 0.0f && !usesKnife ()) {
|
||||||
m_moveSpeed = 0.0f;
|
m_moveSpeed = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1237,60 +1227,43 @@ bool Bot::isEnemyBehindShield (edict_t *enemy) {
|
||||||
bool Bot::usesSniper () {
|
bool Bot::usesSniper () {
|
||||||
// this function returns true, if returns if bot is using a sniper rifle
|
// this function returns true, if returns if bot is using a sniper rifle
|
||||||
|
|
||||||
return m_currentWeapon == Weapon::AWP || m_currentWeapon == Weapon::G3SG1 || m_currentWeapon == Weapon::Scout || m_currentWeapon == Weapon::SG550;
|
return m_weaponType == WeaponType::Sniper;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bot::usesRifle () {
|
bool Bot::usesRifle () {
|
||||||
auto tab = conf.getRawWeapons ();
|
return usesZoomableRifle () || m_weaponType == WeaponType::Rifle;
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
while (tab->id) {
|
|
||||||
if (m_currentWeapon == tab->id) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tab++;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tab->id && count > 13) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Bot::usesPistol () {
|
|
||||||
auto tab = conf.getRawWeapons ();
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
// loop through all the weapons until terminator is found
|
|
||||||
while (tab->id) {
|
|
||||||
if (m_currentWeapon == tab->id) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tab++;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tab->id && count < 7) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Bot::usesCampGun () {
|
|
||||||
return usesSubmachine () || usesRifle () || usesSniper ();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Bot::usesSubmachine () {
|
|
||||||
return m_currentWeapon == Weapon::MP5 || m_currentWeapon == Weapon::TMP || m_currentWeapon == Weapon::P90 || m_currentWeapon == Weapon::MAC10 || m_currentWeapon == Weapon::UMP45;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bot::usesZoomableRifle () {
|
bool Bot::usesZoomableRifle () {
|
||||||
return m_currentWeapon == Weapon::AUG || m_currentWeapon == Weapon::SG552;
|
return m_weaponType == WeaponType::ZoomRifle;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::usesPistol () {
|
||||||
|
return m_weaponType == WeaponType::Pistol;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::usesSubmachine () {
|
||||||
|
return m_weaponType == WeaponType::SMG;;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::usesShotgun () {
|
||||||
|
return m_weaponType == WeaponType::Shotgun;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::usesHeavy () {
|
||||||
|
return m_weaponType == WeaponType::Heavy;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bot::usesBadWeapon () {
|
bool Bot::usesBadWeapon () {
|
||||||
return m_currentWeapon == Weapon::XM1014 || m_currentWeapon == Weapon::M3 || m_currentWeapon == Weapon::UMP45 || m_currentWeapon == Weapon::MAC10 || m_currentWeapon == Weapon::TMP || m_currentWeapon == Weapon::P90;
|
return usesShotgun () || m_currentWeapon == Weapon::UMP45 || m_currentWeapon == Weapon::MAC10 || m_currentWeapon == Weapon::TMP;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::usesCampGun () {
|
||||||
|
return usesSubmachine () || usesRifle () || usesSniper () || usesHeavy ();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::usesKnife (){
|
||||||
|
return m_weaponType == WeaponType::Melee;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Bot::bestPrimaryCarried () {
|
int Bot::bestPrimaryCarried () {
|
||||||
|
|
@ -1301,7 +1274,7 @@ int Bot::bestPrimaryCarried () {
|
||||||
int weaponIndex = 0;
|
int weaponIndex = 0;
|
||||||
int weapons = pev->weapons;
|
int weapons = pev->weapons;
|
||||||
|
|
||||||
auto &weaponTab = conf.getWeapons ();
|
const auto &tab = conf.getWeapons ();
|
||||||
|
|
||||||
// take the shield in account
|
// take the shield in account
|
||||||
if (hasShield ()) {
|
if (hasShield ()) {
|
||||||
|
|
@ -1309,7 +1282,7 @@ int Bot::bestPrimaryCarried () {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < kNumWeapons; ++i) {
|
for (int i = 0; i < kNumWeapons; ++i) {
|
||||||
if (weapons & cr::bit (weaponTab[*pref].id)) {
|
if (weapons & cr::bit (tab[*pref].id)) {
|
||||||
weaponIndex = i;
|
weaponIndex = i;
|
||||||
}
|
}
|
||||||
pref++;
|
pref++;
|
||||||
|
|
@ -1329,7 +1302,7 @@ int Bot::bestSecondaryCarried () {
|
||||||
if (hasShield ()) {
|
if (hasShield ()) {
|
||||||
weapons |= cr::bit (Weapon::Shield);
|
weapons |= cr::bit (Weapon::Shield);
|
||||||
}
|
}
|
||||||
auto tab = conf.getRawWeapons ();
|
const auto tab = conf.getRawWeapons ();
|
||||||
|
|
||||||
for (int i = 0; i < kNumWeapons; ++i) {
|
for (int i = 0; i < kNumWeapons; ++i) {
|
||||||
int id = tab[*pref].id;
|
int id = tab[*pref].id;
|
||||||
|
|
|
||||||
|
|
@ -696,35 +696,35 @@ void BotConfig::initWeapons () {
|
||||||
m_weapons.clear ();
|
m_weapons.clear ();
|
||||||
|
|
||||||
// fill array with available weapons
|
// fill array with available weapons
|
||||||
m_weapons.emplace (Weapon::Knife, "weapon_knife", "knife.mdl", 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, true);
|
m_weapons.emplace (Weapon::Knife, "weapon_knife", "knife.mdl", 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, WeaponType::Melee, true);
|
||||||
m_weapons.emplace (Weapon::USP, "weapon_usp", "usp.mdl", 500, 1, -1, -1, 1, 1, 2, 2, 0, 12, false);
|
m_weapons.emplace (Weapon::USP, "weapon_usp", "usp.mdl", 500, 1, -1, -1, 1, 1, 2, 2, 0, 12, WeaponType::Pistol, false);
|
||||||
m_weapons.emplace (Weapon::Glock18, "weapon_glock18", "glock18.mdl", 400, 1, -1, -1, 1, 2, 1, 1, 0, 20, false);
|
m_weapons.emplace (Weapon::Glock18, "weapon_glock18", "glock18.mdl", 400, 1, -1, -1, 1, 2, 1, 1, 0, 20, WeaponType::Pistol, false);
|
||||||
m_weapons.emplace (Weapon::Deagle, "weapon_deagle", "deagle.mdl", 650, 1, 2, 2, 1, 3, 4, 4, 2, 7, false);
|
m_weapons.emplace (Weapon::Deagle, "weapon_deagle", "deagle.mdl", 650, 1, 2, 2, 1, 3, 4, 4, 2, 7, WeaponType::Pistol, false);
|
||||||
m_weapons.emplace (Weapon::P228, "weapon_p228", "p228.mdl", 600, 1, 2, 2, 1, 4, 3, 3, 0, 13, false);
|
m_weapons.emplace (Weapon::P228, "weapon_p228", "p228.mdl", 600, 1, 2, 2, 1, 4, 3, 3, 0, 13, WeaponType::Pistol, false);
|
||||||
m_weapons.emplace (Weapon::Elite, "weapon_elite", "elite.mdl", 800, 1, 0, 0, 1, 5, 5, 5, 0, 30, false);
|
m_weapons.emplace (Weapon::Elite, "weapon_elite", "elite.mdl", 800, 1, 0, 0, 1, 5, 5, 5, 0, 30, WeaponType::Pistol, false);
|
||||||
m_weapons.emplace (Weapon::FiveSeven, "weapon_fiveseven", "fiveseven.mdl", 750, 1, 1, 1, 1, 6, 5, 5, 0, 20, false);
|
m_weapons.emplace (Weapon::FiveSeven, "weapon_fiveseven", "fiveseven.mdl", 750, 1, 1, 1, 1, 6, 5, 5, 0, 20, WeaponType::Pistol, false);
|
||||||
m_weapons.emplace (Weapon::M3, "weapon_m3", "m3.mdl", 1700, 1, 2, -1, 2, 1, 1, 1, 0, 8, false);
|
m_weapons.emplace (Weapon::M3, "weapon_m3", "m3.mdl", 1700, 1, 2, -1, 2, 1, 1, 1, 0, 8, WeaponType::Shotgun, false);
|
||||||
m_weapons.emplace (Weapon::XM1014, "weapon_xm1014", "xm1014.mdl", 3000, 1, 2, -1, 2, 2, 2, 2, 0, 7, false);
|
m_weapons.emplace (Weapon::XM1014, "weapon_xm1014", "xm1014.mdl", 3000, 1, 2, -1, 2, 2, 2, 2, 0, 7, WeaponType::Shotgun, false);
|
||||||
m_weapons.emplace (Weapon::MP5, "weapon_mp5navy", "mp5.mdl", 1500, 1, 2, 1, 3, 1, 2, 2, 0, 30, true);
|
m_weapons.emplace (Weapon::MP5, "weapon_mp5navy", "mp5.mdl", 1500, 1, 2, 1, 3, 1, 2, 2, 0, 30, WeaponType::SMG, true);
|
||||||
m_weapons.emplace (Weapon::TMP, "weapon_tmp", "tmp.mdl", 1250, 1, 1, 1, 3, 2, 1, 1, 0, 30, true);
|
m_weapons.emplace (Weapon::TMP, "weapon_tmp", "tmp.mdl", 1250, 1, 1, 1, 3, 2, 1, 1, 0, 30, WeaponType::SMG, true);
|
||||||
m_weapons.emplace (Weapon::P90, "weapon_p90", "p90.mdl", 2350, 1, 2, 1, 3, 3, 4, 4, 0, 50, true);
|
m_weapons.emplace (Weapon::P90, "weapon_p90", "p90.mdl", 2350, 1, 2, 1, 3, 3, 4, 4, 0, 50, WeaponType::SMG, true);
|
||||||
m_weapons.emplace (Weapon::MAC10, "weapon_mac10", "mac10.mdl", 1400, 1, 0, 0, 3, 4, 1, 1, 0, 30, true);
|
m_weapons.emplace (Weapon::MAC10, "weapon_mac10", "mac10.mdl", 1400, 1, 0, 0, 3, 4, 1, 1, 0, 30, WeaponType::SMG, true);
|
||||||
m_weapons.emplace (Weapon::UMP45, "weapon_ump45", "ump45.mdl", 1700, 1, 2, 2, 3, 5, 3, 3, 0, 25, true);
|
m_weapons.emplace (Weapon::UMP45, "weapon_ump45", "ump45.mdl", 1700, 1, 2, 2, 3, 5, 3, 3, 0, 25, WeaponType::SMG, true);
|
||||||
m_weapons.emplace (Weapon::AK47, "weapon_ak47", "ak47.mdl", 2500, 1, 0, 0, 4, 1, 2, 2, 2, 30, true);
|
m_weapons.emplace (Weapon::AK47, "weapon_ak47", "ak47.mdl", 2500, 1, 0, 0, 4, 1, 2, 2, 2, 30, WeaponType::Rifle, true);
|
||||||
m_weapons.emplace (Weapon::SG552, "weapon_sg552", "sg552.mdl", 3500, 1, 0, -1, 4, 2, 4, 4, 2, 30, true);
|
m_weapons.emplace (Weapon::SG552, "weapon_sg552", "sg552.mdl", 3500, 1, 0, -1, 4, 2, 4, 4, 2, 30, WeaponType::ZoomRifle, true);
|
||||||
m_weapons.emplace (Weapon::M4A1, "weapon_m4a1", "m4a1.mdl", 3100, 1, 1, 1, 4, 3, 3, 3, 2, 30, true);
|
m_weapons.emplace (Weapon::M4A1, "weapon_m4a1", "m4a1.mdl", 3100, 1, 1, 1, 4, 3, 3, 3, 2, 30, WeaponType::Rifle, true);
|
||||||
m_weapons.emplace (Weapon::Galil, "weapon_galil", "galil.mdl", 2000, 1, 0, 0, 4, -1, 1, 1, 2, 35, true);
|
m_weapons.emplace (Weapon::Galil, "weapon_galil", "galil.mdl", 2000, 1, 0, 0, 4, -1, 1, 1, 2, 35, WeaponType::Rifle, true);
|
||||||
m_weapons.emplace (Weapon::Famas, "weapon_famas", "famas.mdl", 2250, 1, 1, 1, 4, -1, 1, 1, 2, 25, true);
|
m_weapons.emplace (Weapon::Famas, "weapon_famas", "famas.mdl", 2250, 1, 1, 1, 4, -1, 1, 1, 2, 25, WeaponType::Rifle, true);
|
||||||
m_weapons.emplace (Weapon::AUG, "weapon_aug", "aug.mdl", 3500, 1, 1, 1, 4, 4, 4, 4, 2, 30, true);
|
m_weapons.emplace (Weapon::AUG, "weapon_aug", "aug.mdl", 3500, 1, 1, 1, 4, 4, 4, 4, 2, 30, WeaponType::ZoomRifle, true);
|
||||||
m_weapons.emplace (Weapon::Scout, "weapon_scout", "scout.mdl", 2750, 1, 2, 0, 4, 5, 3, 2, 3, 10, false);
|
m_weapons.emplace (Weapon::Scout, "weapon_scout", "scout.mdl", 2750, 1, 2, 0, 4, 5, 3, 2, 3, 10, WeaponType::Sniper, false);
|
||||||
m_weapons.emplace (Weapon::AWP, "weapon_awp", "awp.mdl", 4750, 1, 2, 0, 4, 6, 5, 6, 3, 10, false);
|
m_weapons.emplace (Weapon::AWP, "weapon_awp", "awp.mdl", 4750, 1, 2, 0, 4, 6, 5, 6, 3, 10, WeaponType::Sniper, false);
|
||||||
m_weapons.emplace (Weapon::G3SG1, "weapon_g3sg1", "g3sg1.mdl", 5000, 1, 0, 2, 4, 7, 6, 6, 3, 20, false);
|
m_weapons.emplace (Weapon::G3SG1, "weapon_g3sg1", "g3sg1.mdl", 5000, 1, 0, 2, 4, 7, 6, 6, 3, 20, WeaponType::Sniper, false);
|
||||||
m_weapons.emplace (Weapon::SG550, "weapon_sg550", "sg550.mdl", 4200, 1, 1, 1, 4, 8, 5, 5, 3, 30, false);
|
m_weapons.emplace (Weapon::SG550, "weapon_sg550", "sg550.mdl", 4200, 1, 1, 1, 4, 8, 5, 5, 3, 30, WeaponType::Sniper, false);
|
||||||
m_weapons.emplace (Weapon::M249, "weapon_m249", "m249.mdl", 5750, 1, 2, 1, 5, 1, 1, 1, 2, 100, true);
|
m_weapons.emplace (Weapon::M249, "weapon_m249", "m249.mdl", 5750, 1, 2, 1, 5, 1, 1, 1, 2, 100, WeaponType::Heavy, true);
|
||||||
m_weapons.emplace (Weapon::Shield, "weapon_shield", "shield.mdl", 2200, 0, 1, 1, 8, -1, 8, 8, 0, 0, false);
|
m_weapons.emplace (Weapon::Shield, "weapon_shield", "shield.mdl", 2200, 0, 1, 1, 8, -1, 8, 8, 0, 0, WeaponType::Pistol, false);
|
||||||
|
|
||||||
// not needed actually, but cause too much refactoring for now. todo
|
// not needed actually, but cause too much refactoring for now. todo
|
||||||
m_weapons.emplace (0, "", "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false);
|
m_weapons.emplace (0, "", "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WeaponType::None, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotConfig::adjustWeaponPrices () {
|
void BotConfig::adjustWeaponPrices () {
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,11 @@ void Game::levelInitialize (edict_t *entities, int max) {
|
||||||
}
|
}
|
||||||
else if (strcmp (classname, "func_escapezone") == 0) {
|
else if (strcmp (classname, "func_escapezone") == 0) {
|
||||||
m_mapFlags |= MapFlags::Escape;
|
m_mapFlags |= MapFlags::Escape;
|
||||||
|
|
||||||
|
// strange thing on some ES maps, where hostage entity present there
|
||||||
|
if (m_mapFlags & MapFlags::HostageRescue) {
|
||||||
|
m_mapFlags &= ~MapFlags::HostageRescue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (strncmp (classname, "func_door", 9) == 0) {
|
else if (strncmp (classname, "func_door", 9) == 0) {
|
||||||
m_mapFlags |= MapFlags::HasDoors;
|
m_mapFlags |= MapFlags::HasDoors;
|
||||||
|
|
@ -366,7 +371,7 @@ void Game::registerEngineCommand (const char *command, void func ()) {
|
||||||
|
|
||||||
// check for hl pre 1.1.0.4, as it's doesn't have pfnAddServerCommand
|
// check for hl pre 1.1.0.4, as it's doesn't have pfnAddServerCommand
|
||||||
if (!plat.checkPointer (engfuncs.pfnAddServerCommand)) {
|
if (!plat.checkPointer (engfuncs.pfnAddServerCommand)) {
|
||||||
logger.fatal ("%s's minimum HL engine version is 1.1.0.6 and minimum Counter-Strike is Beta 7.1. Please update your engine / game version.", product.name);
|
logger.fatal ("%s's minimum HL engine version is 1.1.0.4 and minimum Counter-Strike is Beta 6.5. Please update your engine / game version.", product.name);
|
||||||
}
|
}
|
||||||
engfuncs.pfnAddServerCommand (const_cast <char *> (command), func);
|
engfuncs.pfnAddServerCommand (const_cast <char *> (command), func);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,12 @@ CR_EXPORT int GetEntityAPI (gamefuncs_t *table, int) {
|
||||||
// Spawn() function is one of the functions any entity is supposed to have in the game DLL,
|
// Spawn() function is one of the functions any entity is supposed to have in the game DLL,
|
||||||
// and any MOD is supposed to implement one for each of its entities.
|
// and any MOD is supposed to implement one for each of its entities.
|
||||||
|
|
||||||
|
auto bot = bots[ent];
|
||||||
|
|
||||||
|
if (bot) {
|
||||||
|
bot->spawned ();
|
||||||
|
}
|
||||||
|
|
||||||
if (game.is (GameFlags::Metamod)) {
|
if (game.is (GameFlags::Metamod)) {
|
||||||
RETURN_META_VALUE (MRES_IGNORED, 0);
|
RETURN_META_VALUE (MRES_IGNORED, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -954,3 +960,4 @@ DLL_GIVEFNPTRSTODLL GiveFnptrsToDll (enginefuncs_t *functionTable, globalvars_t
|
||||||
|
|
||||||
// add linkents for android
|
// add linkents for android
|
||||||
#include "android.cpp"
|
#include "android.cpp"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -958,6 +958,8 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int member) {
|
||||||
plat.bzero (&m_ammo, sizeof (m_ammo));
|
plat.bzero (&m_ammo, sizeof (m_ammo));
|
||||||
|
|
||||||
m_currentWeapon = 0; // current weapon is not assigned at start
|
m_currentWeapon = 0; // current weapon is not assigned at start
|
||||||
|
m_weaponType = WeaponType::None; // current weapon type is not assigned at start
|
||||||
|
|
||||||
m_voicePitch = rg.int_ (80, 115); // assign voice pitch
|
m_voicePitch = rg.int_ (80, 115); // assign voice pitch
|
||||||
|
|
||||||
// copy them over to the temp level variables
|
// copy them over to the temp level variables
|
||||||
|
|
@ -1255,6 +1257,7 @@ void Bot::newRound () {
|
||||||
plat.bzero (&m_ammo, sizeof (m_ammo));
|
plat.bzero (&m_ammo, sizeof (m_ammo));
|
||||||
|
|
||||||
m_currentWeapon = 0;
|
m_currentWeapon = 0;
|
||||||
|
m_weaponType = 0;
|
||||||
}
|
}
|
||||||
m_flashLevel = 100.0f;
|
m_flashLevel = 100.0f;
|
||||||
m_checkDarkTime = game.time ();
|
m_checkDarkTime = game.time ();
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,7 @@ void MessageDispatcher::netMsgCurWeapon () {
|
||||||
if (m_args[id].long_ < kMaxWeapons) {
|
if (m_args[id].long_ < kMaxWeapons) {
|
||||||
if (m_args[state].long_ != 0) {
|
if (m_args[state].long_ != 0) {
|
||||||
m_bot->m_currentWeapon = m_args[id].long_;
|
m_bot->m_currentWeapon = m_args[id].long_;
|
||||||
|
m_bot->m_weaponType = conf.getWeaponType (m_args[id].long_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ammo amount decreased ? must have fired a bullet...
|
// ammo amount decreased ? must have fired a bullet...
|
||||||
|
|
@ -329,13 +330,6 @@ void MessageDispatcher::netMsgTeamInfo () {
|
||||||
// update player team
|
// update player team
|
||||||
client.team2 = m_teamInfoCache[m_args[team].chars_]; // update real team
|
client.team2 = m_teamInfoCache[m_args[team].chars_]; // update real team
|
||||||
client.team = game.is (GameFlags::FreeForAll) ? m_args[index].long_ : client.team2;
|
client.team = game.is (GameFlags::FreeForAll) ? m_args[index].long_ : client.team2;
|
||||||
|
|
||||||
auto bot = bots[client.ent];
|
|
||||||
|
|
||||||
// clear the routes so we're have no error in pathfinding in case team info update (respawn/change team)
|
|
||||||
if (bot) {
|
|
||||||
bot->clearSearchNodes ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageDispatcher::netMsgBarTime () {
|
void MessageDispatcher::netMsgBarTime () {
|
||||||
|
|
|
||||||
|
|
@ -676,7 +676,7 @@ bool Bot::updateNavigation () {
|
||||||
m_desiredVelocity = nullptr;
|
m_desiredVelocity = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!cv_jasonmode.bool_ () && m_currentWeapon == Weapon::Knife && isOnFloor ()) {
|
else if (!cv_jasonmode.bool_ () && usesKnife () && isOnFloor ()) {
|
||||||
selectBestWeapon ();
|
selectBestWeapon ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1176,11 +1176,11 @@ void Bot::findShortestPath (int srcIndex, int destIndex) {
|
||||||
// this function finds the shortest path from source index to destination index
|
// this function finds the shortest path from source index to destination index
|
||||||
|
|
||||||
if (!graph.exists (srcIndex)){
|
if (!graph.exists (srcIndex)){
|
||||||
logger.error ("Pathfinder source path index not valid (%d).", srcIndex);
|
logger.error ("%s source path index not valid (%d).", __FUNCTION__, srcIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!graph.exists (destIndex)) {
|
else if (!graph.exists (destIndex)) {
|
||||||
logger.error ("Pathfinder destination path index not valid (%d).", destIndex);
|
logger.error ("%s destination path index not valid (%d).", __FUNCTION__, destIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clearSearchNodes ();
|
clearSearchNodes ();
|
||||||
|
|
@ -1329,7 +1329,7 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
||||||
float euclidean = cr::powf (cr::powf (x, 2.0f) + cr::powf (y, 2.0f) + cr::powf (z, 2.0f), 0.5f);
|
float euclidean = cr::powf (cr::powf (x, 2.0f) + cr::powf (y, 2.0f) + cr::powf (z, 2.0f), 0.5f);
|
||||||
|
|
||||||
if (cv_debug_heuristic_type.int_ () == 4) {
|
if (cv_debug_heuristic_type.int_ () == 4) {
|
||||||
return 1000.0f *(cr::ceilf (euclidean) - euclidean);
|
return 1000.0f * (cr::ceilf (euclidean) - euclidean);
|
||||||
}
|
}
|
||||||
return euclidean;
|
return euclidean;
|
||||||
}
|
}
|
||||||
|
|
@ -1348,8 +1348,18 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
||||||
return hfunctionPathDist (index, startIndex, goalIndex) / 128.0f * 10.0f;
|
return hfunctionPathDist (index, startIndex, goalIndex) / 128.0f * 10.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!graph.exists (srcIndex)) {
|
||||||
|
logger.error ("%s source path index not valid (%d).", __FUNCTION__, srcIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!graph.exists (destIndex)) {
|
||||||
|
|
||||||
|
logger.error ("%s destination path index not valid (%d).", __FUNCTION__, destIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// holders for heuristic functions
|
// holders for heuristic functions
|
||||||
Lambda <float (int, int, int)> gcalc, hcalc;
|
static Lambda <float (int, int, int)> gcalc, hcalc;
|
||||||
|
|
||||||
// get correct calculation for heuristic
|
// get correct calculation for heuristic
|
||||||
if (pathType == FindPath::Optimal) {
|
if (pathType == FindPath::Optimal) {
|
||||||
|
|
@ -1382,15 +1392,6 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
||||||
gcalc = gfunctionPathDist;
|
gcalc = gfunctionPathDist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!graph.exists (srcIndex)) {
|
|
||||||
logger.error ("Pathfinder source path index not valid (%d).", srcIndex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (!graph.exists (destIndex)) {
|
|
||||||
logger.error ("Pathfinder destination path index not valid (%d).", destIndex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
clearSearchNodes ();
|
clearSearchNodes ();
|
||||||
|
|
||||||
m_chosenGoalIndex = srcIndex;
|
m_chosenGoalIndex = srcIndex;
|
||||||
|
|
@ -2182,7 +2183,7 @@ bool Bot::advanceMovement () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// is there a jump node right ahead and do we need to draw out the light weapon ?
|
// is there a jump node right ahead and do we need to draw out the light weapon ?
|
||||||
if (willJump && m_currentWeapon != Weapon::Knife && m_currentWeapon != Weapon::Scout && !m_isReloading && !usesPistol () && (jumpDistance > 200.0f || (dst.z - 32.0f > src.z && jumpDistance > 150.0f)) && !(m_states & (Sense::SeeingEnemy | Sense::SuspectEnemy))) {
|
if (willJump && !usesKnife () && m_currentWeapon != Weapon::Scout && !m_isReloading && !usesPistol () && (jumpDistance > 200.0f || (dst.z - 32.0f > src.z && jumpDistance > 150.0f)) && !(m_states & (Sense::SeeingEnemy | Sense::SuspectEnemy))) {
|
||||||
selectWeaponByName ("weapon_knife"); // draw out the knife if we needed
|
selectWeaponByName ("weapon_knife"); // draw out the knife if we needed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2206,7 +2207,7 @@ bool Bot::advanceMovement () {
|
||||||
|
|
||||||
// if wayzone radius non zero vary origin a bit depending on the body angles
|
// if wayzone radius non zero vary origin a bit depending on the body angles
|
||||||
if (m_path->radius > 0.0f) {
|
if (m_path->radius > 0.0f) {
|
||||||
m_pathOrigin = m_pathOrigin + Vector (pev->angles.x, cr::normalizeAngles (pev->angles.y + rg.float_ (-90.0f, 90.0f)), 0.0f).forward () * rg.float_ (0.0f, m_path->radius);
|
m_pathOrigin += Vector (pev->angles.x, cr::normalizeAngles (pev->angles.y + rg.float_ (-90.0f, 90.0f)), 0.0f).forward () * rg.float_ (0.0f, m_path->radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOnLadder ()) {
|
if (isOnLadder ()) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue