edict_t *CServer::CreateFakeClient(const char *name) { edict_t *pEdict; pEdict = CREATE_FAKE_CLIENT(name); if (!FNullEnt(pEdict)) { char ptr[128]; // allocate space for message from ClientConnect if (pEdict->pvPrivateData != NULL) FREE_PRIVATE(pEdict); // free our predecessor's private data pEdict->pvPrivateData = NULL; // null out the private data pointer pEdict->v.frags = 0; // reset his frag count // set the max speed for this player pEdict->v.maxspeed = CVAR_GET_FLOAT("sv_maxspeed"); // create the player entity by calling MOD's player function // (from LINK_ENTITY_TO_CLASS for player object) if (g_fIsMetamod) { CALL_GAME_ENTITY(PLID, "player", VARS(pEdict)); } else { player(VARS(pEdict)); } MDLL_ClientConnect(pEdict, "bot", "127.0.0.1", ptr); MDLL_ClientPutInServer(pEdict); // let this bot actually spawn into the game return pEdict; } return NULL; }
Bot::Bot (edict_t *bot, int skill, int personality, int team, int member) { // this function does core operation of creating bot, it's called by CreateBot (), // when bot setup completed, (this is a bot class constructor) char rejectReason[128]; int clientIndex = ENTINDEX (bot); memset (this, 0, sizeof (Bot)); pev = VARS (bot); if (bot->pvPrivateData != null) FREE_PRIVATE (bot); bot->pvPrivateData = null; bot->v.frags = 0; // create the player entity by calling MOD's player function BotControl::CallGameEntity (&bot->v); // set all info buffer keys for this bot char *buffer = GET_INFOKEYBUFFER (bot); SET_CLIENT_KEYVALUE (clientIndex, buffer, "model", ""); SET_CLIENT_KEYVALUE (clientIndex, buffer, "rate", "3500.000000"); SET_CLIENT_KEYVALUE (clientIndex, buffer, "cl_updaterate", "20"); SET_CLIENT_KEYVALUE (clientIndex, buffer, "cl_lw", "1"); SET_CLIENT_KEYVALUE (clientIndex, buffer, "cl_lc", "1"); SET_CLIENT_KEYVALUE (clientIndex, buffer, "tracker", "0"); SET_CLIENT_KEYVALUE (clientIndex, buffer, "cl_dlmax", "128"); SET_CLIENT_KEYVALUE (clientIndex, buffer, "friends", "0"); SET_CLIENT_KEYVALUE (clientIndex, buffer, "dm", "0"); SET_CLIENT_KEYVALUE (clientIndex, buffer, "_ah", "0"); if (yb_tagbots.GetBool ()) SET_CLIENT_KEYVALUE (clientIndex, buffer, "*bot", "1"); SET_CLIENT_KEYVALUE (clientIndex, buffer, "_vgui_menus", "0"); memset (rejectReason, 0, sizeof (rejectReason)); // reset the reject reason template string MDLL_ClientConnect (bot, "fakeclient", FormatBuffer ("192.168.1.%d", ENTINDEX (bot) + 100), rejectReason); if (!IsNullString (rejectReason)) { AddLogEntry (true, LOG_WARNING, "Server refused '%s' connection (%s)", STRING (bot->v.netname), rejectReason); ServerCommand ("kick \"%s\"", STRING (bot->v.netname)); // kick the bot player if the server refused it bot->v.flags |= FL_KILLME; } if (IsDedicatedServer () && engine->GetDeveloperLevel () > 0) { if (engine->GetDeveloperLevel () == 2) { ServerPrint ("Server requiring authentication"); ServerPrint ("Client '%s' connected", STRING (bot->v.netname)); ServerPrint ("Adr: 127.0.0.%d:27005", ENTINDEX (bot) + 100); } ServerPrint ("Verifying and uploading resources..."); ServerPrint ("Custom resources total 0 bytes"); ServerPrint (" Decals: 0 bytes"); ServerPrint ("----------------------"); ServerPrint ("Resources to request: 0 bytes"); } MDLL_ClientPutInServer (bot); bot->v.flags = 0; bot->v.flags |= FL_FAKECLIENT | FL_CLIENT; // set this player as fakeclient // initialize all the variables for this bot... m_notStarted = true; // hasn't joined game yet m_startAction = CMENU_IDLE; m_moneyAmount = 0; m_logotypeIndex = engine->RandomInt (0, 5); // initialize msec value m_msecNum = m_msecDel = 0.0f; m_msecInterval = engine->GetTime (); m_msecVal = static_cast <uint8_t> (g_pGlobals->frametime * 1000.0f); m_msecBuiltin = engine->RandomInt (1, 4); // assign how talkative this bot will be m_sayTextBuffer.chatDelay = engine->RandomFloat (3.8f, 10.0f); m_sayTextBuffer.chatProbability = engine->RandomInt (1, 100); m_notKilled = false; m_skill = skill; m_weaponBurstMode = BURST_DISABLED; m_lastThinkTime = engine->GetTime (); m_frameInterval = engine->GetTime (); bot->v.idealpitch = bot->v.v_angle.x; bot->v.ideal_yaw = bot->v.v_angle.y; bot->v.yaw_speed = engine->RandomFloat (g_skillTab[m_skill / 20].minTurnSpeed, g_skillTab[m_skill / 20].maxTurnSpeed); bot->v.pitch_speed = engine->RandomFloat (g_skillTab[m_skill / 20].minTurnSpeed, g_skillTab[m_skill / 20].maxTurnSpeed); switch (personality) { case 1: m_personality = PERSONALITY_RUSHER; m_baseAgressionLevel = engine->RandomFloat (0.7f, 1.0f); m_baseFearLevel = engine->RandomFloat (0.0f, 0.4f); break; case 2: m_personality = PERSONALITY_CAREFUL; m_baseAgressionLevel = engine->RandomFloat (0.0f, 0.4f); m_baseFearLevel = engine->RandomFloat (0.7f, 1.0f); break; default: m_personality = PERSONALITY_NORMAL; m_baseAgressionLevel = engine->RandomFloat (0.4f, 0.7f); m_baseFearLevel = engine->RandomFloat (0.4f, 0.7f); break; } memset (&m_ammoInClip, 0, sizeof (m_ammoInClip)); memset (&m_ammo, 0, sizeof (m_ammo)); m_currentWeapon = 0; // current weapon is not assigned at start m_voicePitch = engine->RandomInt (166, 250) / 2; // assign voice pitch // copy them over to the temp level variables m_agressionLevel = m_baseAgressionLevel; m_fearLevel = m_baseFearLevel; m_nextEmotionUpdate = engine->GetTime () + 0.5f; // just to be sure m_actMessageIndex = 0; m_pushMessageIndex = 0; // assign team and class m_wantedTeam = team; m_wantedClass = member; NewRound (); }
// Add bot -> ARG1(team), ARG2(skill), ARG3(model), ARG4(name) int cGame::CreateBot(edict_t * pPlayer, const char *arg1, const char *arg2, const char *arg3, const char *arg4) { edict_t *BotEnt; cBot *pBot; char c_skin[BOT_SKIN_LEN + 1]; char c_name[BOT_NAME_LEN + 1]; // clear memset(c_skin, 0, sizeof(c_skin)); memset(c_name, 0, sizeof(c_name)); int skill; int i, j, length; if ((arg4 != NULL) && (*arg4 != 0)) { strncpy(c_name, arg4, BOT_NAME_LEN - 1); c_name[BOT_NAME_LEN] = 0; // make sure c_name is null terminated } else { if (NamesAvailable()) SelectName(c_name); else strcpy(c_name, "RealBot"); } skill = -2; // -2, not valid if ((arg2 != NULL) && (*arg2 != 0)) skill = atoi(arg2); // set to given skill // when not valid (-2), it has default skill if ((skill < -1) || (skill > 10)) skill = iDefaultBotSkill; // When skill is -1, random, we set it by boundries given if (skill == -1) skill = RANDOM_LONG(iRandomMinSkill, iRandomMaxSkill); // length of name length = strlen(c_name); // remove any illegal characters from name... for (i = 0; i < length; i++) { if ((c_name[i] <= ' ') || (c_name[i] > '~') || (c_name[i] == '"')) { for (j = i; j < length; j++) // shuffle chars left (and null) c_name[j] = c_name[j + 1]; length--; } } BotEnt = (*g_engfuncs.pfnCreateFakeClient) (c_name); if (FNullEnt(BotEnt)) { REALBOT_PRINT(NULL, "cGame::CreateBot", "Cannot create bot, server is full"); return GAME_MSG_FAIL_SERVERFULL; // failed } else { char ptr[128]; // allocate space for message from ClientConnect char *infobuffer; int clientIndex; int index; index = 0; while ((bots[index].bIsUsed) && (index < 32)) index++; if (index == 32) { return GAME_MSG_FAILURE; } // create the player entity by calling MOD's player function // (from LINK_ENTITY_TO_CLASS for player object) // FIX: Free data for bot, so we can fill in new if (BotEnt->pvPrivateData != NULL) FREE_PRIVATE(BotEnt); BotEnt->pvPrivateData = NULL; BotEnt->v.frags = 0; // END OF FIX: --- score resetted CALL_GAME_ENTITY(PLID, "player", VARS(BotEnt)); infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer) (BotEnt); clientIndex = ENTINDEX(BotEnt); (*g_engfuncs.pfnSetClientKeyValue) (clientIndex, infobuffer, "model", ""); (*g_engfuncs.pfnSetClientKeyValue) (clientIndex, infobuffer, "rate", "3500.000000"); (*g_engfuncs.pfnSetClientKeyValue) (clientIndex, infobuffer, "cl_updaterate", "20"); (*g_engfuncs.pfnSetClientKeyValue) (clientIndex, infobuffer, "cl_lw", "1"); (*g_engfuncs.pfnSetClientKeyValue) (clientIndex, infobuffer, "cl_lc", "1"); (*g_engfuncs.pfnSetClientKeyValue) (clientIndex, infobuffer, "tracker", "0"); (*g_engfuncs.pfnSetClientKeyValue) (clientIndex, infobuffer, "cl_dlmax", "128"); if (RANDOM_LONG(0, 100) < 50) { (*g_engfuncs.pfnSetClientKeyValue) (clientIndex, infobuffer, "lefthand", "1"); } else { (*g_engfuncs.pfnSetClientKeyValue) (clientIndex, infobuffer, "lefthand", "0"); } (*g_engfuncs.pfnSetClientKeyValue) (clientIndex, infobuffer, "friends", "0"); (*g_engfuncs.pfnSetClientKeyValue) (clientIndex, infobuffer, "dm", "0"); (*g_engfuncs.pfnSetClientKeyValue) (clientIndex, infobuffer, "ah", "1"); (*g_engfuncs.pfnSetClientKeyValue) (clientIndex, infobuffer, "_vgui_menus", "0"); MDLL_ClientConnect(BotEnt, c_name, "127.0.0.1", ptr); // Pieter van Dijk - use instead of DispatchSpawn() - Hip Hip Hurray! MDLL_ClientPutInServer(BotEnt); BotEnt->v.flags |= FL_THIRDPARTYBOT; // initialize all the variables for this bot... // Retrieve Pointer pBot = &bots[index]; // Set variables pBot->iIndex = index; pBot->bIsUsed = true; pBot->respawn_state = RESPAWN_IDLE; pBot->fCreateTime = gpGlobals->time; pBot->fKickTime = 0.0; pBot->name[0] = 0; // name not set by server yet pBot->bot_money = 0; strcpy(pBot->skin, c_skin); pBot->pEdict = BotEnt; pBot->bStarted = false; // hasn't joined game yet // CS Message IDLE.. pBot->start_action = MSG_CS_IDLE; pBot->SpawnInit(); pBot->bInitialize = false; // don't need to initialize yet BotEnt->v.idealpitch = BotEnt->v.v_angle.x; BotEnt->v.ideal_yaw = BotEnt->v.v_angle.y; BotEnt->v.pitch_speed = BOT_PITCH_SPEED; BotEnt->v.yaw_speed = BOT_YAW_SPEED; pBot->bot_skill = skill; // Personality related pBot->ipHostage = 0; pBot->ipBombspot = 0; pBot->ipRandom = 0; pBot->ipTurnSpeed = 20; pBot->ipReplyToRadio = 0; pBot->ipCreateRadio = 0; pBot->ipHelpTeammate = 0; pBot->ipWalkWithKnife = 0; pBot->ipDroppedBomb = 0; pBot->ipCampRate = 0; pBot->ipChatRate = 0; pBot->ipFearRate = 0; pBot->ipHearRate = 0; pBot->played_rounds = 0; // Buy-personality related pBot->ipFavoPriWeapon = -1; pBot->ipFavoSecWeapon = -1; pBot->ipBuyFlashBang = 0; pBot->ipBuyGrenade = 0; pBot->ipBuySmokeGren = 0; pBot->ipBuyDefuseKit = 0; pBot->ipSaveForWeapon = 0; pBot->ipBuyArmour = 0; // here we set team if ((arg1 != NULL) && (arg1[0] != 0)) { pBot->iTeam = atoi(arg1); // and class if ((arg3 != NULL) && (arg3[0] != 0)) { pBot->bot_class = atoi(arg3); } } // Parsing name into bot identity INI_PARSE_BOTS(c_name, pBot); // return success return GAME_MSG_SUCCESS; } } // CreateBot()