Fixed detection mp_freeforall for regamedll.
Added missing addon entities for regamedll. Fixed bots keep adding to game event when there is now spawn points left on map. Reduced a little bot difficulty at higher levels.
This commit is contained in:
parent
78b2cb968a
commit
5a7dbc2463
8 changed files with 110 additions and 30 deletions
|
|
@ -607,7 +607,7 @@ public:
|
|||
return;
|
||||
}
|
||||
#ifdef PLATFORM_WIN32
|
||||
FreeLibrary ((HMODULE)m_ptr);
|
||||
FreeLibrary (static_cast <HMODULE> (m_ptr));
|
||||
#else
|
||||
dlclose (m_ptr);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ struct LangComprarer {
|
|||
class Engine : public Singleton <Engine> {
|
||||
private:
|
||||
int m_drawModels[DRAW_NUM];
|
||||
int m_spawnCount[TEAM_UNASSIGNED];
|
||||
|
||||
// bot client command
|
||||
char m_arguments[256];
|
||||
|
|
@ -243,6 +244,11 @@ public:
|
|||
return m_startEntity;
|
||||
}
|
||||
|
||||
// get spawn count for team
|
||||
inline int getSpawnCount (int team) {
|
||||
return m_spawnCount[team];
|
||||
}
|
||||
|
||||
// gets the player team
|
||||
inline int getTeam (edict_t *ent) {
|
||||
extern Client g_clients[MAX_ENGINE_PLAYERS];
|
||||
|
|
|
|||
|
|
@ -55,11 +55,12 @@ enum GameFlags {
|
|||
GAME_LEGACY = (1 << 3), // counter-strike 1.3-1.5 with/without steam
|
||||
GAME_MOBILITY = (1 << 4), // additional flag that bot is running on android (additional flag)
|
||||
GAME_OFFICIAL_CSBOT = (1 << 5), // additional flag that indicates official cs bots are in game
|
||||
GAME_METAMOD = (1 << 6), // game running under metamod
|
||||
GAME_METAMOD = (1 << 6), // game running under meta\mod
|
||||
GAME_CSDM = (1 << 7), // csdm mod currently in use
|
||||
GAME_CSDM_FFA = (1 << 8), // csdm mod with ffa mode
|
||||
GAME_SUPPORT_SVC_PINGS = (1 << 9), // on that game version we can fake bots pings
|
||||
GAME_SUPPORT_BOT_VOICE = (1 << 10) // on that game version we can use chatter
|
||||
GAME_REGAMEDLL = (1 << 9), // server dll is a regamedll
|
||||
GAME_SUPPORT_SVC_PINGS = (1 << 10), // on that game version we can fake bots pings
|
||||
GAME_SUPPORT_BOT_VOICE = (1 << 11) // on that game version we can use chatter
|
||||
};
|
||||
|
||||
// bot menu ids
|
||||
|
|
@ -1297,6 +1298,7 @@ private:
|
|||
float m_entityUpdateTime; // time to update intresting entities
|
||||
|
||||
int m_lastWinner; // the team who won previous round
|
||||
int m_lastDifficulty; // last bots difficulty
|
||||
|
||||
bool m_leaderChoosen[MAX_TEAM_COUNT]; // is team leader choose theese round
|
||||
bool m_economicsGood[MAX_TEAM_COUNT]; // is team able to buy anything
|
||||
|
|
@ -1371,6 +1373,7 @@ public:
|
|||
void listBots (void);
|
||||
void setWeaponMode (int selection);
|
||||
void updateTeamEconomics (int team, bool setTrue = false);
|
||||
void updateBotDifficulties (void);
|
||||
|
||||
static void execGameEntity (entvars_t *vars);
|
||||
|
||||
|
|
|
|||
|
|
@ -2868,13 +2868,13 @@ void Bot::checkDarkness (void) {
|
|||
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;
|
||||
}
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -201,6 +201,8 @@ bool Bot::lookupEnemies (void) {
|
|||
edict_t *player, *newEnemy = nullptr;
|
||||
float nearestDistance = cr::square (m_viewDistance);
|
||||
|
||||
extern ConVar yb_whose_your_daddy;
|
||||
|
||||
// clear suspected flag
|
||||
if (!engine.isNullEntity (m_enemy) && (m_states & STATE_SEEING_ENEMY)) {
|
||||
m_states &= ~STATE_SUSPECT_ENEMY;
|
||||
|
|
@ -272,8 +274,8 @@ bool Bot::lookupEnemies (void) {
|
|||
m_aimFlags |= AIM_ENEMY;
|
||||
m_states |= STATE_SEEING_ENEMY;
|
||||
|
||||
// if enemy is still visible and in field of view, keep it keep track of when we last saw an enemy
|
||||
if (newEnemy == m_enemy) {
|
||||
// if enemy is still visible and in field of view, keep it keep track of when we last saw an enemy
|
||||
m_seeEnemyTime = engine.timebase ();
|
||||
|
||||
// zero out reaction time
|
||||
|
|
@ -284,12 +286,12 @@ bool Bot::lookupEnemies (void) {
|
|||
return true;
|
||||
}
|
||||
else {
|
||||
if (m_seeEnemyTime + 3.0 < engine.timebase () && (m_hasC4 || hasHostage () || !engine.isNullEntity (m_targetEntity))) {
|
||||
if (m_seeEnemyTime + 3.0f < engine.timebase () && (m_hasC4 || hasHostage () || !engine.isNullEntity (m_targetEntity))) {
|
||||
pushRadioMessage (RADIO_ENEMY_SPOTTED);
|
||||
}
|
||||
m_targetEntity = nullptr; // stop following when we see an enemy...
|
||||
|
||||
if (rng.getInt (0, 100) < m_difficulty * 25) {
|
||||
if (yb_whose_your_daddy.boolean ()) {
|
||||
m_enemySurpriseTime = m_actualReactionTime * 0.5f;
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ Engine::Engine (void) {
|
|||
|
||||
memset (m_arguments, 0, sizeof (m_arguments));
|
||||
memset (m_drawModels, 0, sizeof (m_drawModels));
|
||||
memset (m_spawnCount, 0, sizeof (m_spawnCount));
|
||||
|
||||
m_cvars.clear ();
|
||||
}
|
||||
|
|
@ -69,6 +70,9 @@ void Engine::levelInitialize (void) {
|
|||
// this function precaches needed models and initialize class variables
|
||||
|
||||
m_localEntity = nullptr;
|
||||
|
||||
m_spawnCount[TEAM_COUNTER] = 0;
|
||||
m_spawnCount[TEAM_TERRORIST] = 0;
|
||||
|
||||
// go thru the all entities on map, and do whatever we're want
|
||||
for (int i = 0; i < g_pGlobals->maxEntities; i++) {
|
||||
|
|
@ -101,6 +105,8 @@ void Engine::levelInitialize (void) {
|
|||
ent->v.rendermode = kRenderTransAlpha; // set its render mode to transparency
|
||||
ent->v.renderamt = 127; // set its transparency amount
|
||||
ent->v.effects |= EF_NODRAW;
|
||||
|
||||
m_spawnCount[TEAM_COUNTER]++;
|
||||
}
|
||||
else if (strcmp (classname, "info_player_deathmatch") == 0) {
|
||||
g_engfuncs.pfnSetModel (ent, ENGINE_STR ("models/player/terror/terror.mdl"));
|
||||
|
|
@ -108,6 +114,8 @@ void Engine::levelInitialize (void) {
|
|||
ent->v.rendermode = kRenderTransAlpha; // set its render mode to transparency
|
||||
ent->v.renderamt = 127; // set its transparency amount
|
||||
ent->v.effects |= EF_NODRAW;
|
||||
|
||||
m_spawnCount[TEAM_TERRORIST]++;
|
||||
}
|
||||
|
||||
else if (strcmp (classname, "info_vip_start") == 0) {
|
||||
|
|
@ -1280,5 +1288,5 @@ float LightMeasure::getLightLevel (const Vector &point) {
|
|||
}
|
||||
|
||||
float LightMeasure::getSkyColor (void) {
|
||||
return (sv_skycolor_r.flt () + sv_skycolor_g.flt () + sv_skycolor_b.flt ()) / 3;
|
||||
return sv_skycolor_r.flt () + sv_skycolor_g.flt () + sv_skycolor_b.flt ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2247,18 +2247,22 @@ void StartFrame (void) {
|
|||
// calculate light levels for all waypoints if needed
|
||||
waypoints.initLightLevels ();
|
||||
|
||||
if (g_gameFlags & GAME_METAMOD) {
|
||||
if (g_gameFlags & (GAME_METAMOD | GAME_REGAMEDLL)) {
|
||||
static auto dmActive = g_engfuncs.pfnCVarGetPointer ("csdm_active");
|
||||
static auto freeForAll = g_engfuncs.pfnCVarGetPointer ("mp_freeforall");
|
||||
|
||||
if (dmActive && freeForAll) {
|
||||
// csdm is only with amxx and metamod
|
||||
if (dmActive) {
|
||||
if (dmActive->value > 0.0f) {
|
||||
g_gameFlags |= GAME_CSDM;
|
||||
}
|
||||
else if (g_gameFlags & GAME_CSDM) {
|
||||
g_gameFlags &= ~GAME_CSDM;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// but this can be provided by regamedll
|
||||
if (freeForAll) {
|
||||
if (freeForAll->value > 0.0f) {
|
||||
g_gameFlags |= GAME_CSDM_FFA;
|
||||
}
|
||||
|
|
@ -3031,8 +3035,9 @@ SHARED_LIBRARAY_EXPORT void Meta_Init (void) {
|
|||
Library *LoadCSBinary (void) {
|
||||
const char *modname = engine.getModName ();
|
||||
|
||||
if (!modname)
|
||||
if (!modname) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if defined(PLATFORM_WIN32)
|
||||
const char *libs[] = {"mp.dll", "cs.dll"};
|
||||
|
|
@ -3042,6 +3047,22 @@ Library *LoadCSBinary (void) {
|
|||
const char *libs[] = {"cs.dylib"};
|
||||
#endif
|
||||
|
||||
auto libCheck = [] (Library *lib, const char *modname, const char *dll) {
|
||||
// try to load gamedll
|
||||
if (!lib->isValid ()) {
|
||||
logEntry (true, LL_FATAL | LL_IGNORE, "Unable to load gamedll \"%s\". Exiting... (gamedir: %s)", dll, modname);
|
||||
|
||||
return false;
|
||||
}
|
||||
auto ent = lib->resolve <entity_func_t> ("trigger_random_unique");
|
||||
|
||||
// detect regamedll by addon entity they provide
|
||||
if (ent != nullptr) {
|
||||
g_gameFlags |= GAME_REGAMEDLL;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// search the libraries inside game dlls directory
|
||||
for (size_t i = 0; i < cr::arrsize (libs); i++) {
|
||||
auto *path = format ("%s/dlls/%s", modname, libs[i]);
|
||||
|
|
@ -3058,18 +3079,24 @@ Library *LoadCSBinary (void) {
|
|||
if (g_gameFlags & GAME_METAMOD) {
|
||||
return nullptr;
|
||||
}
|
||||
return new Library (path);
|
||||
}
|
||||
else {
|
||||
Library *game = new Library (path);
|
||||
|
||||
// try to load gamedll
|
||||
if (!game->isValid ()) {
|
||||
logEntry (true, LL_FATAL | LL_IGNORE, "Unable to load gamedll \"%s\". Exiting... (gamedir: %s)", libs[i], modname);
|
||||
auto game = new Library (path);
|
||||
|
||||
// verify dll is OK
|
||||
if (!libCheck (game, modname, libs[i])) {
|
||||
delete game;
|
||||
return nullptr;
|
||||
}
|
||||
return game;
|
||||
}
|
||||
else {
|
||||
auto game = new Library (path);
|
||||
|
||||
// verify dll is OK
|
||||
if (!libCheck (game, modname, libs[i])) {
|
||||
delete game;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// detect if we're running modern game
|
||||
auto entity = game->resolve <entity_func_t> ("weapon_famas");
|
||||
|
||||
|
|
@ -3159,8 +3186,7 @@ DLL_GIVEFNPTRSTODLL GiveFnptrsToDll (enginefuncs_t *functionTable, globalvars_t
|
|||
delete g_gameLib;
|
||||
}
|
||||
#else
|
||||
g_gameLib = LoadCSBinary ();
|
||||
{
|
||||
g_gameLib = LoadCSBinary (); {
|
||||
if (!g_gameLib && !(g_gameFlags & GAME_METAMOD)) {
|
||||
logEntry (true, LL_FATAL | LL_IGNORE, "Mod that you has started, not supported by this bot (gamedir: %s)", engine.getModName ());
|
||||
return;
|
||||
|
|
@ -3178,6 +3204,7 @@ DLL_GIVEFNPTRSTODLL GiveFnptrsToDll (enginefuncs_t *functionTable, globalvars_t
|
|||
else if (g_gameFlags & GAME_CSTRIKE16) {
|
||||
gameVersionStr.assign ("v1.6");
|
||||
}
|
||||
|
||||
if (g_gameFlags & GAME_XASH_ENGINE) {
|
||||
gameVersionStr.append (" @ Xash3D Engine");
|
||||
|
||||
|
|
@ -3191,6 +3218,10 @@ DLL_GIVEFNPTRSTODLL GiveFnptrsToDll (enginefuncs_t *functionTable, globalvars_t
|
|||
gameVersionStr.append (" (BV)");
|
||||
}
|
||||
|
||||
if (g_gameFlags & GAME_REGAMEDLL) {
|
||||
gameVersionStr.append (" (RE)");
|
||||
}
|
||||
|
||||
if (g_gameFlags & GAME_SUPPORT_SVC_PINGS) {
|
||||
gameVersionStr.append (" (SVC)");
|
||||
}
|
||||
|
|
@ -3357,6 +3388,7 @@ LINK_ENTITY (info_teleport_destination)
|
|||
LINK_ENTITY (info_vip_start)
|
||||
LINK_ENTITY (infodecal)
|
||||
LINK_ENTITY (item_airtank)
|
||||
LINK_ENTITY (item_airbox)
|
||||
LINK_ENTITY (item_antidote)
|
||||
LINK_ENTITY (item_assaultsuit)
|
||||
LINK_ENTITY (item_battery)
|
||||
|
|
@ -3382,6 +3414,8 @@ LINK_ENTITY (path_track)
|
|||
LINK_ENTITY (player)
|
||||
LINK_ENTITY (player_loadsaved)
|
||||
LINK_ENTITY (player_weaponstrip)
|
||||
LINK_ENTITY (point_clientcommand)
|
||||
LINK_ENTITY (point_servercommand)
|
||||
LINK_ENTITY (soundent)
|
||||
LINK_ENTITY (spark_shower)
|
||||
LINK_ENTITY (speaker)
|
||||
|
|
@ -3402,7 +3436,11 @@ LINK_ENTITY (trigger_monsterjump)
|
|||
LINK_ENTITY (trigger_multiple)
|
||||
LINK_ENTITY (trigger_once)
|
||||
LINK_ENTITY (trigger_push)
|
||||
LINK_ENTITY (trigger_random)
|
||||
LINK_ENTITY (trigger_random_time)
|
||||
LINK_ENTITY (trigger_random_unique)
|
||||
LINK_ENTITY (trigger_relay)
|
||||
LINK_ENTITY (trigger_setorigin)
|
||||
LINK_ENTITY (trigger_teleport)
|
||||
LINK_ENTITY (trigger_transition)
|
||||
LINK_ENTITY (weapon_ak47)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ ConVar mp_autoteambalance ("mp_autoteambalance", nullptr, VT_NOREGISTER);
|
|||
BotManager::BotManager (void) {
|
||||
// this is a bot manager class constructor
|
||||
|
||||
m_lastDifficulty = 0;
|
||||
m_lastWinner = -1;
|
||||
m_deathMsgSent = false;
|
||||
|
||||
|
|
@ -385,6 +386,10 @@ void BotManager::maintainQuota (void) {
|
|||
if (m_quotaMaintainTime > engine.timebase ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// not a best place for this, but whatever
|
||||
updateBotDifficulties ();
|
||||
|
||||
yb_quota.set (cr::clamp <int> (yb_quota.integer (), 0, engine.maxClients ()));
|
||||
|
||||
int totalHumansInGame = getHumansCount ();
|
||||
|
|
@ -417,9 +422,10 @@ void BotManager::maintainQuota (void) {
|
|||
else {
|
||||
desiredBotCount = cr::min <int> (desiredBotCount, maxClients - humanPlayersInGame);
|
||||
}
|
||||
int maxSpawnCount = engine.getSpawnCount (TEAM_TERRORIST) + engine.getSpawnCount (TEAM_COUNTER);
|
||||
|
||||
// add bots if necessary
|
||||
if (desiredBotCount > botsInGame) {
|
||||
if (desiredBotCount > botsInGame && botsInGame < maxSpawnCount) {
|
||||
createRandom ();
|
||||
}
|
||||
else if (desiredBotCount < botsInGame) {
|
||||
|
|
@ -825,6 +831,23 @@ void BotManager::updateTeamEconomics (int team, bool forceGoodEconomics) {
|
|||
}
|
||||
}
|
||||
|
||||
void BotManager::updateBotDifficulties (void) {
|
||||
int difficulty = yb_difficulty.integer ();
|
||||
|
||||
if (difficulty != m_lastDifficulty) {
|
||||
|
||||
// sets new difficulty for all bots
|
||||
for (int i = 0; i < engine.maxClients (); i++) {
|
||||
auto bot = m_bots[i];
|
||||
|
||||
if (bot != nullptr) {
|
||||
m_bots[i]->m_difficulty = difficulty;
|
||||
}
|
||||
}
|
||||
m_lastDifficulty = difficulty;
|
||||
}
|
||||
}
|
||||
|
||||
void BotManager::destroy (void) {
|
||||
// this function free all bots slots (used on server shutdown)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue