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; }
void BotControl::CallGameEntity (entvars_t *vars) { // this function calls gamedll player() function, in case to create player entity in game if (g_isMetamod) { CALL_GAME_ENTITY (PLID, "player", vars); return; } static EntityPtr_t playerFunction = null; if (playerFunction == null) playerFunction = (EntityPtr_t) g_gameLib->GetFunctionAddr ("player"); if (playerFunction != null) (*playerFunction) (vars); }
cell AMX_NATIVE_CALL Rage::GetFunctionFromClass(AMX* amx,cell* params) { int len; char *func_name = g_fn_GetAmxString(amx,params[1],0,&len); VirtualFunction** virtual_function_ptr = Global::virtualFunctionsManager.get_by_label(func_name); if(!virtual_function_ptr) { MF_LogError(amx, AMX_ERR_NATIVE, "Virtual function %s not registered",func_name); return -1; } VirtualFunction* virtual_function = *virtual_function_ptr; char* class_name = g_fn_GetAmxString(amx,params[2],0,&len); static char class_name_cp[50]; strncpy(class_name_cp,class_name,49); edict_t *entity = CREATE_ENTITY(); CALL_GAME_ENTITY(PLID,class_name,&entity->v); if(!entity->pvPrivateData) { REMOVE_ENTITY(entity); MF_LogError(amx, AMX_ERR_NATIVE,"Unable to create an entity of class '%s'",class_name); return -1; } int ret = virtual_function->create_get_id(entity->pvPrivateData,class_name_cp); REMOVE_ENTITY(entity); return ret; }
void AddNodeEntity(const Vector &origin, int effects) { edict_t *pNode = CREATE_ENTITY(); if (g_fIsMetamod) { CALL_GAME_ENTITY(PLID, "info_node", VARS(pNode)); } else { info_node(VARS(pNode)); } pNode->v.classname = MAKE_STRING("info_node"); SET_ORIGIN(pNode, origin); pNode->v.rendercolor.x = 255; pNode->v.rendercolor.y = 255; pNode->v.rendercolor.z = 0; pNode->v.rendermode = kRenderTransAdd; pNode->v.movetype = MOVETYPE_NONE; pNode->v.solid = SOLID_TRIGGER; SET_SIZE(ENT(&pNode->v), Vector(-8, -8, -8), Vector(8, 8, 8)); pNode->v.renderfx = kRenderFxNoDissipation; pNode->v.renderamt = 255; pNode->v.scale = 0.2; SET_MODEL(ENT(pNode), "sprites/glow02.spr"); pNode->v.effects = effects; }
static cell AMX_NATIVE_CALL RegisterHam(AMX *amx, cell *params) { // Make sure the function we're requesting is within bounds int func=params[1]; int post=params[4]; CHECK_FUNCTION(func); char *function=MF_GetAmxString(amx, params[3], 0, NULL); char *classname=MF_GetAmxString(amx, params[2], 1, NULL); // Check the entity // create an entity, assign it the gamedll's class, hook it and destroy it edict_t *Entity=CREATE_ENTITY(); CALL_GAME_ENTITY(PLID,classname,&Entity->v); if (Entity->pvPrivateData == NULL) { REMOVE_ENTITY(Entity); MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); return 0; } void **vtable=GetVTable(Entity->pvPrivateData, Offsets.GetBase()); REMOVE_ENTITY(Entity); if (vtable == NULL) { MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve vtable for \"%s\", hook for \"%s\" not active.",classname,function); return 0; } // Verify that the function is valid // Don't fail the plugin if this fails, just emit a normal error int fwd=hooklist[func].makefunc(amx, function); if (fwd == -1) { MF_LogError(amx, AMX_ERR_NATIVE, "Function %s not found.", function); return 0; } // We've passed all tests... int **ivtable=(int **)vtable; void *vfunction=(void *)ivtable[hooklist[func].vtid]; // Check the list of this function's hooks, see if the function we have is a hook CVector<Hook *>::iterator end=hooks[func].end(); for (CVector<Hook *>::iterator i=hooks[func].begin(); i!=end; ++i) { if ((*i)->tramp == vfunction) { // Yes, this function is hooked Forward *pfwd=new Forward(fwd); if (post) { (*i)->post.push_back(pfwd); } else { (*i)->pre.push_back(pfwd); } return reinterpret_cast<cell>(pfwd); } } // If we got here, the function is not hooked Hook *hook=new Hook(vtable, hooklist[func].vtid, hooklist[func].targetfunc, hooklist[func].isvoid, hooklist[func].paramcount, classname); hooks[func].push_back(hook); Forward *pfwd=new Forward(fwd); if (post) { hook->post.push_back(pfwd); } else { hook->pre.push_back(pfwd); } return reinterpret_cast<cell>(pfwd); }
static cell AMX_NATIVE_CALL RegisterHam(AMX *amx, cell *params) { // Make sure the function we're requesting is within bounds int func=params[1]; int post=params[4]; CHECK_FUNCTION(func); char *function=MF_GetAmxString(amx, params[3], 0, NULL); char *classname=MF_GetAmxString(amx, params[2], 1, NULL); // Check the entity // create an entity, assign it the gamedll's class, hook it and destroy it edict_t *Entity=CREATE_ENTITY(); CALL_GAME_ENTITY(PLID,classname,&Entity->v); if (Entity->pvPrivateData == NULL) { REMOVE_ENTITY(Entity); MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); return 0; } void **vtable=GetVTable(Entity->pvPrivateData, Offsets.GetBase()); REMOVE_ENTITY(Entity); if (vtable == NULL) { MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve vtable for \"%s\", hook for \"%s\" not active.",classname,function); return 0; } // Verify that the function is valid // Don't fail the plugin if this fails, just emit a normal error int fwd=hooklist[func].makefunc(amx, function); if (fwd == -1) { MF_LogError(amx, AMX_ERR_NATIVE, "Function %s not found.", function); return 0; } bool enableSpecialBot = false; // Old plugin doesn't have this param. if (*params / sizeof(cell) == 5) { enableSpecialBot = params[5] > 0; } Forward *pfwd = new Forward(fwd); // We've passed all tests... if (strcmp(classname, "player") == 0 && enableSpecialBot) { SpecialbotHandler.RegisterHamSpecialBot(amx, func, function, post, pfwd); } int **ivtable=(int **)vtable; void *vfunction=(void *)ivtable[hooklist[func].vtid]; // Check the list of this function's hooks, see if the function we have is a hook for (size_t i = 0; i < hooks[func].length(); ++i) { if (hooks[func].at(i)->tramp == vfunction) { // Yes, this function is hooked if (post) { hooks[func].at(i)->post.append(pfwd); } else { hooks[func].at(i)->pre.append(pfwd); } return reinterpret_cast<cell>(pfwd); } } // If we got here, the function is not hooked Hook *hook = new Hook(vtable, hooklist[func].vtid, hooklist[func].targetfunc, hooklist[func].isvoid, hooklist[func].needsretbuf, hooklist[func].paramcount, classname); hooks[func].append(hook); if (post) { hook->post.append(pfwd); } else { hook->pre.append(pfwd); } return reinterpret_cast<cell>(pfwd); }
// 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()