Implemented flashligr and nightvision goggles usage.

Credits for this mostly goes to Immortal_BLG and KWo.
This commit is contained in:
Dmitry 2019-05-10 21:12:12 +03:00 committed by jeefo
commit 61b2566373
7 changed files with 149 additions and 29 deletions

View file

@ -361,8 +361,7 @@ public:
} }
}; };
class SimpleColor final : private NonCopyable class SimpleColor final : private NonCopyable {
{
public: public:
int red, green, blue; int red, green, blue;

View file

@ -54,7 +54,11 @@ enum NetMsgId {
NETMSG_SENDAUDIO = 17, NETMSG_SENDAUDIO = 17,
NETMSG_SAYTEXT = 18, NETMSG_SAYTEXT = 18,
NETMSG_BOTVOICE = 19, NETMSG_BOTVOICE = 19,
NETMSG_NUM = 21 NETMSG_NVGTOGGLE = 20,
NETMSG_FLASHBAT = 21,
NETMSG_FLASHLIGHT = 22,
NETMSG_ITEMSTATUS = 23,
NETMSG_NUM = 25
}; };
// variable reg pair // variable reg pair
@ -418,7 +422,7 @@ public:
void animateLight (void); void animateLight (void);
float getLightLevel (const Vector &point); float getLightLevel (const Vector &point);
float getSkiesColor (void); float getSkyColor (void);
private: private:
template <typename S, typename M> bool recursiveLightPoint (const M *node, const Vector &start, const Vector &end); template <typename S, typename M> bool recursiveLightPoint (const M *node, const Vector &start, const Vector &end);

View file

@ -287,6 +287,7 @@ enum BuyState {
BUYSTATE_GRENADES, BUYSTATE_GRENADES,
BUYSTATE_DEFUSER, BUYSTATE_DEFUSER,
BUYSTATE_AMMO, BUYSTATE_AMMO,
BUYSTATE_NIGHTVISION,
BUYSTATE_FINISHED BUYSTATE_FINISHED
}; };
@ -947,6 +948,7 @@ private:
void filterGoals (const IntArray &goals, int *result); void filterGoals (const IntArray &goals, int *result);
void processPickups (void); void processPickups (void);
void checkTerrain (float movedDistance, const Vector &dirNormal); void checkTerrain (float movedDistance, const Vector &dirNormal);
void checkDarkness (void);
bool doPlayerAvoidance (const Vector &normal); bool doPlayerAvoidance (const Vector &normal);
void getCampDir (Vector *dest); void getCampDir (Vector *dest);
@ -1109,20 +1111,24 @@ public:
bool m_ignoreBuyDelay; // when reaching buyzone in the middle of the round don't do pauses bool m_ignoreBuyDelay; // when reaching buyzone in the middle of the round don't do pauses
bool m_inBombZone; // bot in the bomb zone or not bool m_inBombZone; // bot in the bomb zone or not
int m_buyState; // current Count in Buying int m_buyState; // current count in buying
float m_nextBuyTime; // next buy time float m_nextBuyTime; // next buy time
float m_checkDarkTime; // check for darkness time
bool m_inBuyZone; // bot currently in buy zone bool m_inBuyZone; // bot currently in buy zone
bool m_inVIPZone; // bot in the vip satefy zone bool m_inVIPZone; // bot in the vip satefy zone
bool m_buyingFinished; // done with buying bool m_buyingFinished; // done with buying
bool m_buyPending; // bot buy is pending bool m_buyPending; // bot buy is pending
bool m_hasDefuser; // does bot has defuser bool m_hasDefuser; // does bot has defuser
bool m_hasNVG; // does bot has nightvision goggles
bool m_usesNVG; // does nightvision goggles turned on
bool m_hasC4; // does bot has c4 bomb bool m_hasC4; // does bot has c4 bomb
bool m_hasProgressBar; // has progress bar on a HUD bool m_hasProgressBar; // has progress bar on a HUD
bool m_jumpReady; // is double jump ready bool m_jumpReady; // is double jump ready
bool m_canChooseAimDirection; // can choose aiming direction bool m_canChooseAimDirection; // can choose aiming direction
float m_turnAwayFromFlashbang; // bot turned away from flashbang float m_turnAwayFromFlashbang; // bot turned away from flashbang
float m_flashLevel; // flashlight level
float m_blindTime; // time when bot is blinded float m_blindTime; // time when bot is blinded
float m_blindMoveSpeed; // mad speeds when bot is blind float m_blindMoveSpeed; // mad speeds when bot is blind
float m_blindSidemoveSpeed; // mad side move speeds when bot is blind float m_blindSidemoveSpeed; // mad side move speeds when bot is blind

View file

@ -31,8 +31,10 @@ ConVar yb_best_weapon_picker_type ("yb_best_weapon_picker_type", "1");
// game console variables // game console variables
ConVar mp_c4timer ("mp_c4timer", nullptr, VT_NOREGISTER); ConVar mp_c4timer ("mp_c4timer", nullptr, VT_NOREGISTER);
ConVar mp_flashlight ("mp_flashlight", nullptr, VT_NOREGISTER);
ConVar mp_buytime ("mp_buytime", nullptr, VT_NOREGISTER, true, "1"); ConVar mp_buytime ("mp_buytime", nullptr, VT_NOREGISTER, true, "1");
ConVar mp_footsteps ("mp_footsteps", nullptr, VT_NOREGISTER); ConVar mp_footsteps ("mp_footsteps", nullptr, VT_NOREGISTER);
ConVar sv_gravity ("sv_gravity", nullptr, VT_NOREGISTER); ConVar sv_gravity ("sv_gravity", nullptr, VT_NOREGISTER);
int Bot::getMsgQueue (void) { int Bot::getMsgQueue (void) {
@ -1710,6 +1712,24 @@ void Bot::buyStuff (void) {
} }
break; break;
case BUYSTATE_NIGHTVISION:
if (m_moneyAmount > 2500 && !m_hasNVG && rng.getInt (1, 100) < 30) {
float skyColor = illum.getSkyColor ();
float lightLevel = waypoints.getLightLevel (m_currentWaypointIndex);
// if it's somewhat darkm do buy nightvision goggles
if ((skyColor >= 50.0f && lightLevel <= 15.0f) || (skyColor < 50.0f && lightLevel < 40.0f)) {
if (isOldGame) {
engine.execBotCmd (ent (), "buyequip;menuselect 7");
}
else {
engine.execBotCmd (ent (), "nvgs"); // use alias in steamcs
}
engine.print ("%s bought googles", STRING (pev->netname));
}
}
break;
case BUYSTATE_AMMO: // buy enough primary & secondary ammo (do not check for money here) case BUYSTATE_AMMO: // buy enough primary & secondary ammo (do not check for money here)
for (int i = 0; i <= 5; i++) { for (int i = 0; i <= 5; i++) {
engine.execBotCmd (ent (), "buyammo%d", rng.getInt (1, 2)); // simulate human engine.execBotCmd (ent (), "buyammo%d", rng.getInt (1, 2)); // simulate human
@ -2828,6 +2848,46 @@ void Bot::updateAimDir (void) {
} }
} }
void Bot::checkDarkness (void) {
// do not check for darkness at the start of the round
if (m_spawnTime + 5.0f > engine.timebase () || !waypoints.exists (m_currentWaypointIndex)) {
return;
}
// do not check every frame
if (m_checkDarkTime + 2.5f > engine.timebase ()) {
return;
}
float lightLevel = waypoints.getLightLevel (m_currentWaypointIndex);
float skyColor = illum.getSkyColor ();
if (mp_flashlight.boolean () && !m_hasNVG) {
auto task = TaskID ();
if (!(pev->effects & EF_DIMLIGHT) && task != TASK_CAMP && task != TASK_ATTACK && m_heardSoundTime + 3.0f < engine.timebase () && m_flashLevel > 30.0f && ((skyColor > 50.0f && lightLevel < 10.0f) || (skyColor <= 50.0f && lightLevel < 40.0f))) {
pev->impulse = 100;
}
else if ((pev->effects & EF_DIMLIGHT) && (((lightLevel > 15.0f && skyColor > 50.0f) || (lightLevel > 45.0f && skyColor <= 50.0f)) || task == TASK_CAMP || task == TASK_ATTACK || m_flashLevel <= 0 || m_heardSoundTime + 3.0f >= engine.timebase ()))
{
pev->impulse = 100;
}
}
else if (m_hasNVG) {
if (pev->effects & EF_DIMLIGHT) {
pev->impulse = 100;
}
else if (!m_usesNVG && ((skyColor > 50.0f && lightLevel < 15.0f) || (skyColor <= 50.0f && lightLevel < 40.0f))) {
engine.execBotCmd (ent (), "nightvision");
}
else if (m_usesNVG && ((lightLevel > 20.0f && skyColor > 50.0f) || (lightLevel > 45.0f && skyColor <= 50.0f))) {
engine.execBotCmd (ent (), "nightvision");
}
}
m_checkDarkTime = engine.timebase ();
}
void Bot::framePeriodic (void) { void Bot::framePeriodic (void) {
if (m_thinkFps <= engine.timebase ()) { if (m_thinkFps <= engine.timebase ()) {
// execute delayed think // execute delayed think
@ -4860,6 +4920,9 @@ void Bot::ai (void) {
checkTerrain (movedDistance, dirNormal); checkTerrain (movedDistance, dirNormal);
} }
// check the darkness
checkDarkness ();
// must avoid a grenade? // must avoid a grenade?
if (m_needAvoidGrenade != 0) { if (m_needAvoidGrenade != 0) {
// don't duck to get away faster // don't duck to get away faster

View file

@ -849,10 +849,7 @@ void Engine::processMessages (void *ptr) {
case 1: case 1:
if (bot != nullptr) { if (bot != nullptr) {
if (strcmp (strVal, "defuser") == 0) { if (strcmp (strVal, "buyzone") == 0) {
bot->m_hasDefuser = (enabled != 0);
}
else if (strcmp (strVal, "buyzone") == 0) {
bot->m_inBuyZone = (enabled != 0); bot->m_inBuyZone = (enabled != 0);
// try to equip in buyzone // try to equip in buyzone
@ -1102,6 +1099,31 @@ void Engine::processMessages (void *ptr) {
} }
break; break;
case NETMSG_ITEMSTATUS:
if (bot != nullptr && m_msgBlock.state == 0) {
enum ItemStatus {
IS_NIGHTVISION = (1 << 0),
IS_DEFUSEKIT = (1 << 1)
};
bot->m_hasNVG = (intVal & IS_NIGHTVISION) ? true : false;
bot->m_hasDefuser = (intVal & IS_DEFUSEKIT) ? true : false;
}
break;
case NETMSG_FLASHBAT:
if (bot != nullptr && m_msgBlock.state == 0) {
bot->m_flashLevel = static_cast <float> (intVal);
}
break;
case NETMSG_NVGTOGGLE:
if (bot != nullptr && m_msgBlock.state == 0) {
bot->m_usesNVG = intVal > 0;
}
break;
default: default:
logEntry (true, LL_FATAL, "Network message handler error. Call to unrecognized message id (%d).\n", m_msgBlock.msg); logEntry (true, LL_FATAL, "Network message handler error. Call to unrecognized message id (%d).\n", m_msgBlock.msg);
} }
@ -1257,6 +1279,6 @@ float LightMeasure::getLightLevel (const Vector &point) {
return !recursiveCheck () ? 0.0f : 100 * cr::sqrtf (cr::min (75.0f, static_cast <float> (m_point.avg ())) / 75.0f); return !recursiveCheck () ? 0.0f : 100 * cr::sqrtf (cr::min (75.0f, static_cast <float> (m_point.avg ())) / 75.0f);
} }
float LightMeasure::getSkiesColor (void) { float LightMeasure::getSkyColor (void) {
return sv_skycolor_r.flt () + sv_skycolor_g.flt () + sv_skycolor_b.flt (); return (sv_skycolor_r.flt () + sv_skycolor_g.flt () + sv_skycolor_b.flt ()) / 3;
} }

View file

@ -203,7 +203,7 @@ int handleBotCommands (edict_t *ent, const char *arg0, const char *arg1, const c
} }
else if (stricmp (arg0, "glp") == 0) { else if (stricmp (arg0, "glp") == 0) {
for (int i = 0; i < waypoints.length (); i++) { for (int i = 0; i < waypoints.length (); i++) {
engine.print ("%d - %f - %f", i, waypoints.getLightLevel (i), illum.getSkiesColor ()); engine.print ("%d - %f - %f", i, waypoints.getLightLevel (i), illum.getSkyColor ());
} }
} }
@ -2428,23 +2428,32 @@ void pfnMessageBegin (int msgDest, int msgType, const float *origin, edict_t *ed
// store the message type in our own variables, since the GET_USER_MSG_ID () will just do a lot of strcmp()'s... // store the message type in our own variables, since the GET_USER_MSG_ID () will just do a lot of strcmp()'s...
if ((g_gameFlags & GAME_METAMOD) && engine.getMessageId (NETMSG_MONEY) == -1) { if ((g_gameFlags & GAME_METAMOD) && engine.getMessageId (NETMSG_MONEY) == -1) {
engine.setMessageId (NETMSG_VGUI, GET_USER_MSG_ID (PLID, "VGUIMenu", nullptr));
engine.setMessageId (NETMSG_SHOWMENU, GET_USER_MSG_ID (PLID, "ShowMenu", nullptr)); auto setMsgId = [&] (const char *name, NetMsgId id) {
engine.setMessageId (NETMSG_WEAPONLIST, GET_USER_MSG_ID (PLID, "WeaponList", nullptr)); engine.setMessageId (id, GET_USER_MSG_ID (PLID, name, nullptr));
engine.setMessageId (NETMSG_CURWEAPON, GET_USER_MSG_ID (PLID, "CurWeapon", nullptr)); };
engine.setMessageId (NETMSG_AMMOX, GET_USER_MSG_ID (PLID, "AmmoX", nullptr));
engine.setMessageId (NETMSG_AMMOPICKUP, GET_USER_MSG_ID (PLID, "AmmoPickup", nullptr)); setMsgId ("VGUIMenu", NETMSG_VGUI);
engine.setMessageId (NETMSG_DAMAGE, GET_USER_MSG_ID (PLID, "Damage", nullptr)); setMsgId ("ShowMenu", NETMSG_SHOWMENU);
engine.setMessageId (NETMSG_MONEY, GET_USER_MSG_ID (PLID, "Money", nullptr)); setMsgId ("WeaponList", NETMSG_WEAPONLIST);
engine.setMessageId (NETMSG_STATUSICON, GET_USER_MSG_ID (PLID, "StatusIcon", nullptr)); setMsgId ("CurWeapon", NETMSG_CURWEAPON);
engine.setMessageId (NETMSG_DEATH, GET_USER_MSG_ID (PLID, "DeathMsg", nullptr)); setMsgId ("AmmoX", NETMSG_AMMOX);
engine.setMessageId (NETMSG_SCREENFADE, GET_USER_MSG_ID (PLID, "ScreenFade", nullptr)); setMsgId ("AmmoPickup", NETMSG_AMMOPICKUP);
engine.setMessageId (NETMSG_HLTV, GET_USER_MSG_ID (PLID, "HLTV", nullptr)); setMsgId ("Damage", NETMSG_DAMAGE);
engine.setMessageId (NETMSG_TEXTMSG, GET_USER_MSG_ID (PLID, "TextMsg", nullptr)); setMsgId ("Money", NETMSG_MONEY);
engine.setMessageId (NETMSG_TEAMINFO, GET_USER_MSG_ID (PLID, "TeamInfo", nullptr)); setMsgId ("StatusIcon", NETMSG_STATUSICON);
engine.setMessageId (NETMSG_BARTIME, GET_USER_MSG_ID (PLID, "BarTime", nullptr)); setMsgId ("DeathMsg", NETMSG_DEATH);
engine.setMessageId (NETMSG_SENDAUDIO, GET_USER_MSG_ID (PLID, "SendAudio", nullptr)); setMsgId ("ScreenFade", NETMSG_SCREENFADE);
engine.setMessageId (NETMSG_SAYTEXT, GET_USER_MSG_ID (PLID, "SayText", nullptr)); setMsgId ("HLTV", NETMSG_HLTV);
setMsgId ("TextMsg", NETMSG_TEXTMSG);
setMsgId ("TeamInfo", NETMSG_TEAMINFO);
setMsgId ("BarTime", NETMSG_BARTIME);
setMsgId ("SendAudio", NETMSG_SENDAUDIO);
setMsgId ("SayText", NETMSG_SAYTEXT);
setMsgId ("FlashBat", NETMSG_FLASHBAT);
setMsgId ("Flashlight", NETMSG_FLASHLIGHT);
setMsgId ("NVGToggle", NETMSG_NVGTOGGLE);
setMsgId ("ItemStatus", NETMSG_ITEMSTATUS);
if (g_gameFlags & GAME_SUPPORT_BOT_VOICE) { if (g_gameFlags & GAME_SUPPORT_BOT_VOICE) {
engine.setMessageId (NETMSG_BOTVOICE, GET_USER_MSG_ID (PLID, "BotVoice", nullptr)); engine.setMessageId (NETMSG_BOTVOICE, GET_USER_MSG_ID (PLID, "BotVoice", nullptr));
@ -2476,6 +2485,9 @@ void pfnMessageBegin (int msgDest, int msgType, const float *origin, edict_t *ed
engine.captureMessage (msgType, NETMSG_BARTIME); engine.captureMessage (msgType, NETMSG_BARTIME);
engine.captureMessage (msgType, NETMSG_TEXTMSG); engine.captureMessage (msgType, NETMSG_TEXTMSG);
engine.captureMessage (msgType, NETMSG_SHOWMENU); engine.captureMessage (msgType, NETMSG_SHOWMENU);
engine.captureMessage (msgType, NETMSG_FLASHBAT);
engine.captureMessage (msgType, NETMSG_NVGTOGGLE);
engine.captureMessage (msgType, NETMSG_ITEMSTATUS);
} }
} }
else if (msgDest == MSG_ALL) { else if (msgDest == MSG_ALL) {
@ -2769,6 +2781,18 @@ int pfnRegUserMsg (const char *name, int size) {
else if (strcmp (name, "BotVoice") == 0) { else if (strcmp (name, "BotVoice") == 0) {
engine.setMessageId (NETMSG_BOTVOICE, message); engine.setMessageId (NETMSG_BOTVOICE, message);
} }
else if (strcmp (name, "NVGToggle") == 0) {
engine.setMessageId (NETMSG_NVGTOGGLE, message);
}
else if (strcmp (name, "FlashBat") == 0) {
engine.setMessageId (NETMSG_FLASHBAT, message);
}
else if (strcmp (name, "Flashlight") == 0) {
engine.setMessageId (NETMSG_FLASHLIGHT, message);
}
else if (strcmp (name, "ItemStatus") == 0) {
engine.setMessageId (NETMSG_ITEMSTATUS, message);
}
return message; return message;
} }

View file

@ -1191,6 +1191,8 @@ void Bot::newRound (void) {
m_currentWeapon = 0; m_currentWeapon = 0;
} }
m_flashLevel = 100.0f;
m_checkDarkTime = engine.timebase ();
m_knifeAttackTime = engine.timebase () + rng.getFloat (1.3f, 2.6f); m_knifeAttackTime = engine.timebase () + rng.getFloat (1.3f, 2.6f);
m_nextBuyTime = engine.timebase () + rng.getFloat (0.6f, 2.0f); m_nextBuyTime = engine.timebase () + rng.getFloat (0.6f, 2.0f);