void BecomeExplosion1 (edict_t *self) { //ZOID //flags are important if (strcmp(self->classname, "item_flag_team1") == 0) { CTFResetFlag(CTF_TEAM1); // this will free self! safe_bprintf(PRINT_HIGH, "The %s flag has returned!\n", CTFTeamName(CTF_TEAM1)); return; } if (strcmp(self->classname, "item_flag_team2") == 0) { CTFResetFlag(CTF_TEAM2); // this will free self! safe_bprintf(PRINT_HIGH, "The %s flag has returned!\n", CTFTeamName(CTF_TEAM1)); return; } // techs are important too if (self->item && (self->item->flags & IT_TECH)) { CTFRespawnTech(self); // this frees self! return; } //ZOID gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_EXPLOSION1); gi.WritePosition (self->s.origin); gi.multicast (self->s.origin, MULTICAST_PVS); G_FreeEdict (self); }
/////////////////////////////////////////////////////////////////////// // Remove a bot by name or all bots /////////////////////////////////////////////////////////////////////// void ACESP_RemoveBot(char *name) { int i; qboolean freed=false; edict_t *bot; for(i=0;i<maxclients->value;i++) { bot = g_edicts + i + 1; if(bot->inuse) { if(bot->is_bot && (strcmp(bot->client->pers.netname,name)==0 || strcmp(name,"all")==0)) { bot->health = 0; player_die (bot, bot, bot, 100000, vec3_origin); // don't even bother waiting for death frames bot->deadflag = DEAD_DEAD; bot->inuse = false; freed = true; ACEIT_PlayerRemoved (bot); safe_bprintf (PRINT_MEDIUM, "%s removed\n", bot->client->pers.netname); } } } if(!freed) safe_bprintf (PRINT_MEDIUM, "%s not found\n", name); if (botauto_respawn->value) { ACESP_SaveBots(); // Save them again } }
/* ======================== objective_area ======================== */ void objective_area_think (edict_t *self) { edict_t *ent = NULL; int count = 0; int newteam = 0; int delay; self->nextthink = level.time + FRAMETIME; if (self->delay) // if there's a counter running { } while ((ent = findradius(ent, self->s.origin, self->obj_area)) != NULL) { if (!ent->inuse) continue; if (!IsValidPlayer(ent)) continue; newteam = ent->client->resp.team_on->index; if (newteam != self->obj_owner) count++; //gi.dprintf(DEVELOPER_MSG_GAME, "Found %d players\n", count); } if (count >= self->obj_count) { team_list[self->obj_owner]->score -= self->obj_loss; self->obj_owner = team_list[newteam]->index; team_list[self->obj_owner]->score += self->obj_gain; if (team_list[self->obj_owner]->time_to_win) // If there already is a counter somwhere else { if (team_list[self->obj_owner]->time_to_win > (self->obj_time + level.time) ) // If the counter is longer, shorten it up to this one team_list[self->obj_owner]->time_to_win = (self->obj_time + level.time); } else // there is no counter team_list[self->obj_owner]->time_to_win = (self->obj_time + level.time); delay = (int)(team_list[self->obj_owner]->time_to_win - level.time); if ((delay/60) >= 1) safe_bprintf(PRINT_HIGH, "Team %s has %i minutes before they win the battle.\n", team_list[self->obj_owner]->teamname, (delay/60)); else safe_bprintf(PRINT_HIGH, "Team %s has %i seconds before they win the battle.\n", team_list[self->obj_owner]->teamname, delay); gi.sound(self, CHAN_NO_PHS_ADD, gi.soundindex(va("%s/objectives/area_cap.wav", team_list[self->obj_owner]->teamid)), 1, 0, 0); if (dedicated->value) safe_cprintf(NULL, PRINT_HIGH, "Objective %s taken by team %s!\n", self->obj_name, team_list[self->obj_owner]->teamname); centerprintall("Objective %s taken\n by team %s!\n", self->obj_name, team_list[self->obj_owner]->teamname); } }
/* ================= CheckDMRules ================= */ void CheckDMRules(void) { if (level.intermissiontime || !deathmatch->value) return; if (timelimit->value && level.time >= timelimit->value * 60) { safe_bprintf(PRINT_HIGH, "Timelimit hit.\n"); EndDMLevel(); return; } if (fraglimit->value) { for (int i = 0; i < maxclients->value; i++) { gclient_t *cl = game.clients + i; if (!g_edicts[i + 1].inuse) continue; if (cl->resp.score >= fraglimit->value) { safe_bprintf(PRINT_HIGH, "Fraglimit hit.\n"); EndDMLevel(); return; } } } }
/////////////////////////////////////////////////////////////////////// // This function will resolve all paths that are incomplete // usually called before saving to disk /////////////////////////////////////////////////////////////////////// void ACEND_ResolveAllPaths() { int i, from, to; int num=0; safe_bprintf(PRINT_HIGH,"Resolving all paths..."); for(from=0;from<numnodes;from++) for(to=0;to<numnodes;to++) { // update unresolved paths // Not equal to itself, not equal to -1 and equal to the last link if(from != to && path_table[from][to] == to) { num++; // Now for the self-referencing part linear time for each link added for(i=0;i<numnodes;i++) if(path_table[i][from] != -1) { if(i == to) { path_table[i][to] = -1; // make sure we terminate } else { path_table[i][to] = path_table[i][from]; } } } } safe_bprintf(PRINT_MEDIUM,"done (%d updated)\n",num); }
/////////////////////////////////////////////////////////////////////// // Special command processor /////////////////////////////////////////////////////////////////////// qboolean ACECM_Commands(edict_t *ent) { char *cmd; int node; cmd = gi.argv(0); if ((Q_strcasecmp(cmd, "addnode") == 0) && debug_mode) { ent->last_node = ACEND_AddNode(ent, atoi(gi.argv(1))); } else if ((Q_strcasecmp(cmd, "removelink") == 0) && debug_mode) { ACEND_RemoveNodeEdge(ent, atoi(gi.argv(1)), atoi(gi.argv(2))); } else if ((Q_strcasecmp(cmd, "addlink") == 0) && debug_mode) { ACEND_UpdateNodeEdge(atoi(gi.argv(1)), atoi(gi.argv(2))); } else if ((Q_strcasecmp(cmd, "showpath") == 0) && debug_mode) { ACEND_ShowPath(ent, atoi(gi.argv(1))); } else if ((Q_strcasecmp(cmd, "findnode") == 0) && debug_mode) { node = ACEND_FindClosestReachableNode(ent, NODE_DENSITY, NODE_ALL); safe_bprintf(PRINT_MEDIUM, "node: %d type: %d x: %f y: %f z %f\n", node, nodes[node].type, nodes[node].origin[0], nodes[node].origin[1], nodes[node].origin[2]); } else if ((Q_strcasecmp(cmd, "movenode") == 0) && debug_mode) { node = atoi(gi.argv(1)); nodes[node].origin[0] = atof(gi.argv(2)); nodes[node].origin[1] = atof(gi.argv(3)); nodes[node].origin[2] = atof(gi.argv(4)); safe_bprintf(PRINT_MEDIUM, "node: %d moved to x: %f y: %f z %f\n", node, nodes[node].origin[0], nodes[node].origin[1], nodes[node].origin[2]); } else { return false; } return true; }
/*QUAKED target_changelevel (1 0 0) (-8 -8 -8) (8 8 8) Changes level to "map" when fired */ void use_target_changelevel (edict_t *self, edict_t *other, edict_t *activator) { if (level.intermissiontime) return; // already activated if (!deathmatch->value && !coop->value) { if (g_edicts[1].health <= 0) return; } // if noexit, do a ton of damage to other if (deathmatch->value && !( (int)dmflags->value & DF_ALLOW_EXIT) && other != world) { T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 10 * other->max_health, 1000, 0, MOD_EXIT); return; } // if multiplayer, let everyone know who hit the exit if (deathmatch->value) { if (activator && activator->client) safe_bprintf (PRINT_HIGH, "%s exited the level.\n", activator->client->pers.netname); } // if going to a new unit, clear cross triggers if (strstr(self->map, "*")) game.serverflags &= ~(SFL_CROSS_TRIGGER_MASK); BeginIntermission (self); }
/* ================= ServerCommand ServerCommand will be called when an "sv" command is issued. The game can issue gi.argc() / gi.argv() commands to get the rest of the parameters ================= */ void ServerCommand (void) { char *cmd; cmd = gi.argv(1); if (Q_stricmp (cmd, "test") == 0) Svcmd_Test_f (); else if (Q_stricmp (cmd, "addip") == 0) SVCmd_AddIP_f (); else if (Q_stricmp (cmd, "removeip") == 0) SVCmd_RemoveIP_f (); else if (Q_stricmp (cmd, "listip") == 0) SVCmd_ListIP_f (); else if (Q_stricmp (cmd, "writeip") == 0) SVCmd_WriteIP_f (); #ifdef WITH_ACEBOT // ACEBOT_ADD else if(Q_stricmp (cmd, "acedebug") == 0) if (strcmp(gi.argv(2),"on")==0) { safe_bprintf (PRINT_MEDIUM, "ACE: Debug Mode On\n"); debug_mode = true; } else { safe_bprintf (PRINT_MEDIUM, "ACE: Debug Mode Off\n"); debug_mode = false; } else if (Q_stricmp (cmd, "addbot") == 0) ACESP_SpawnBot (NULL, gi.argv(2), gi.argv(3), NULL); // removebot else if(Q_stricmp (cmd, "removebot") == 0) ACESP_RemoveBot(gi.argv(2)); // Node saving else if(Q_stricmp (cmd, "savenodes") == 0) ACEND_SaveNodes(); // ACEBOT_END #endif else #ifdef WITH_ACEBOT safe_cprintf #else gi.cprintf #endif (NULL, PRINT_HIGH, "Unknown server command \"%s\"\n", cmd); }
/* ===================== ClientBeginDeathmatch A client has just connected to the server in deathmatch mode, so clear everything out before starting them. ===================== */ void ClientBeginDeathmatch (edict_t *ent) { #ifdef WITH_ACEBOT // ACEBOT_ADD static char current_map[55]; // ACEBOT_END #endif G_InitEdict (ent); #ifdef WITH_ACEBOT // ACEBOT_ADD ACEIT_PlayerAdded(ent); // ACEBOT_END #endif InitClientResp (ent->client); // locate ent at a spawn point PutClientInServer (ent); // send effect gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_LOGIN); gi.multicast (ent->s.origin, MULTICAST_PVS); #ifdef WITH_ACEBOT safe_bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname); safe_centerprintf(ent,"\nQ2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2\n\nZaero Bots\n\n\n'sv addbot' to add a new bot.\n\n'sv removebot <name>' to remove bot.\n\n\nhttp://qudos.quakedev.com\n\n\nQ2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2\n\n"); // If the map changes on us, init and reload the nodes if(strcmp(level.mapname,current_map)) { ACEND_InitNodes(); ACEND_LoadNodes(); if (botauto_respawn->value) { ACESP_LoadBots(); } strcpy(current_map,level.mapname); } safe_bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname); // ACEBOT_END #else gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname); #endif // make sure all view stuff is valid ClientEndServerFrame (ent); }
/////////////////////////////////////////////////////////////////////// // Spawn the bot /////////////////////////////////////////////////////////////////////// void BOT_SpawnBot (char *team, char *name, char *skin, char *userinfo) { edict_t *bot; if( !nav.loaded ) { Com_Printf("Can't spawn bots without a valid navigation file\n"); return; } bot = BOT_FindFreeClient (); if (!bot) { safe_bprintf (PRINT_MEDIUM, "Server is full, increase Maxclients.\n"); return; } //init the bot bot->inuse = true; bot->yaw_speed = 100; // To allow bots to respawn if(userinfo == NULL) BOT_SetName(bot, name, skin, team); else ClientConnect (bot, userinfo); G_InitEdict (bot); G_SpawnAI(bot); //jabot092(2) bot->ai->is_bot = true; InitClientResp (bot->client); PutClientInServer(bot); BOT_StartAsSpectator (bot); //skill bot->ai->pers.skillLevel = (int)(random()*MAX_BOT_SKILL); if (bot->ai->pers.skillLevel > MAX_BOT_SKILL) //fix if off-limits bot->ai->pers.skillLevel = MAX_BOT_SKILL; else if (bot->ai->pers.skillLevel < 0) bot->ai->pers.skillLevel = 0; BOT_DMclass_InitPersistant(bot); AI_ResetWeights(bot); AI_ResetNavigation(bot); bot->think = BOT_JoinGame; bot->nextthink = level.time + (int)(random()*6.0); if( ctf->value && team != NULL ) { if( !Q_stricmp( team, "blue" ) ) bot->think = BOT_JoinBlue; else if( !Q_stricmp( team, "red" ) ) bot->think = BOT_JoinRed; } AI_EnemyAdded (bot); // let the ai know we added another }
/* ================= CheckDMRules ================= */ void CheckDMRules (void) { int i; gclient_t *cl; if (level.intermissiontime) return; if (!deathmatch->value) return; //ZOID if (ctf->value && CTFCheckRules()) { EndDMLevel (); return; } if (CTFInMatch()) return; // no checking in match mode //ZOID if (timelimit->value) { if (level.time >= timelimit->value*60) { safe_bprintf (PRINT_HIGH, "Timelimit hit.\n"); EndDMLevel (); return; } } if (fraglimit->value) for (i=0 ; i<maxclients->value ; i++) { cl = game.clients + i; if (!g_edicts[i+1].inuse) continue; if (cl->resp.score >= fraglimit->value) { safe_bprintf (PRINT_HIGH, "Fraglimit hit.\n"); EndDMLevel (); return; } } }
/////////////////////////////////////////////////////////////////////// // Remove a bot by name or all bots /////////////////////////////////////////////////////////////////////// void ACESP_RemoveBot(char *name) { int i, j; qboolean freed=false; edict_t *bot; for (i=0;i<maxclients->value;i++) { bot = g_edicts + i + 1; if (bot->inuse) { if (bot->is_bot && (Q_stricmp(bot->client->pers.netname,name)==0 || Q_stricmp(name,"all")==0)) { bot->health = 0; player_die(bot, bot, bot, 100000, vec3_origin); // don't even bother waiting for death frames bot->deadflag = DEAD_DEAD; bot->inuse = false; freed = true; ACEIT_PlayerRemoved (bot); safe_bprintf(PRINT_MEDIUM, "%s removed\n", bot->client->pers.netname); // Knightmare- decrement this bot name's counter and exit loop if (Q_stricmp(name,"all")) { for (j = 0; j < num_botinfo; j++) if (!Q_stricmp(name, bot_info[j].name)) { bot_info[j].ingame_count--; bot_info[j].ingame_count = max(bot_info[j].ingame_count, 0); break; } break; } } } } if (!freed) safe_bprintf(PRINT_MEDIUM, "%s not found\n", name); // Knightmare- removed this //ACESP_SaveBots(); // Save them again }
/////////////////////////////////////////////////////////////////////// // Save to disk file // // Since my compression routines are one thing I did not want to // release, I took out the compressed format option. Most levels will // save out to a node file around 50-200k, so compression is not really // a big deal. /////////////////////////////////////////////////////////////////////// void ACEND_SaveNodes() { FILE *pOut; char tempname[MAX_QPATH] = ""; char filename[MAX_QPATH] = ""; // char filename[60]; int i,j; int version = 1; // Resolve paths ACEND_ResolveAllPaths(); safe_bprintf(PRINT_MEDIUM,"Saving node table..."); // Knightmare- rewote this GameDirRelativePath ("nav", filename); // create nav dir if needed _mkdir (filename); sprintf (tempname, "nav/%s.nod", level.mapname); GameDirRelativePath (tempname, filename); //strcpy(filename,"ace\\nav\\"); //strcat(filename,level.mapname); //strcat(filename,".nod"); if((pOut = fopen(filename, "wb" )) == NULL) return; // bail fwrite(&version,sizeof(int),1,pOut); // write version fwrite(&numnodes,sizeof(int),1,pOut); // write count fwrite(&num_items,sizeof(int),1,pOut); // write facts count fwrite(nodes,sizeof(node_t),numnodes,pOut); // write nodes for(i=0;i<numnodes;i++) for(j=0;j<numnodes;j++) fwrite(&path_table[i][j],sizeof(int16_t),1,pOut); // write count fwrite(item_table,sizeof(item_table_t),num_items,pOut); // write out the fact table fclose(pOut); safe_bprintf(PRINT_MEDIUM,"done.\n"); }
/////////////////////////////////////////////////////////////////////// // Load a table of bots from bots.cfg. /////////////////////////////////////////////////////////////////////// void ACESP_LoadBotInfo() { FILE *pIn; char filename[MAX_OSPATH] = ""; char line[256], *parseline; char *token; char botname[128]; if (num_botinfo > 0) // already loaded return; // Knightmare- rewote this GameDirRelativePath ("bots.cfg", filename); if ((pIn = fopen(filename, "rb" )) == NULL) { safe_bprintf(PRINT_MEDIUM,"ACE: No bots.cfg file found, using default bots.\n"); return; // bail } safe_bprintf(PRINT_MEDIUM,"ACE: Loading bot data..."); while (fgets(line, sizeof(line), pIn) && num_botinfo < MAX_BOTS) { parseline = line; token = COM_Parse (&parseline); if (!token || !strlen(token)) // catch bad line continue; // strncpy (botname, token, sizeof(botname)-1); Q_strncpyz(botname, token, sizeof(botname)); token = COM_Parse (&parseline); if (!token || !strlen(token)) // catch bad line continue; // strncpy (bot_info[num_botinfo].name, botname, sizeof(bot_info[num_botinfo].name)-1); // strncpy (bot_info[num_botinfo].skin, token, sizeof(bot_info[num_botinfo].skin)-1); Q_strncpyz(bot_info[num_botinfo].name, botname, sizeof(bot_info[num_botinfo].name)); Q_strncpyz(bot_info[num_botinfo].skin, token, sizeof(bot_info[num_botinfo].skin)); //gi.dprintf("%s %s\n", bot_info[num_botinfo].name, bot_info[num_botinfo].skin); bot_info[num_botinfo].ingame_count = 0; num_botinfo++; } //gi.dprintf("Number of bots loaded: %d\n\n", num_botinfo); safe_bprintf(PRINT_MEDIUM, "done.\n"); fclose(pIn); }
/////////////////////////////////////////////////////////////////////// // Read from disk file /////////////////////////////////////////////////////////////////////// void ACEND_LoadNodes(void) { FILE *pIn; int i,j; char tempname[MAX_QPATH] = ""; char filename[MAX_QPATH] = ""; //char filename[60]; int version; // Knightmare- rewote this sprintf (tempname, "nav/%s.nod", level.mapname); GameDirRelativePath (tempname, filename); //strcpy(filename,"ace\\nav\\"); //strcat(filename,level.mapname); //strcat(filename,".nod"); if((pIn = fopen(filename, "rb" )) == NULL) { // Create item table safe_bprintf(PRINT_MEDIUM, "ACE: No node file found, creating new one..."); ACEIT_BuildItemNodeTable(false); safe_bprintf(PRINT_MEDIUM, "done.\n"); return; } // determine version fread(&version,sizeof(int),1,pIn); // read version if(version == 1) { safe_bprintf(PRINT_MEDIUM,"ACE: Loading node table..."); fread(&numnodes,sizeof(int),1,pIn); // read count fread(&num_items,sizeof(int),1,pIn); // read facts count fread(nodes,sizeof(node_t),numnodes,pIn); for(i=0;i<numnodes;i++) for(j=0;j<numnodes;j++) fread(&path_table[i][j],sizeof(int16_t),1,pIn); // write count // Knightmare- is this needed? It's all re-built anyway, and may cause problems. // The item_table array is better left blank. //fread(item_table,sizeof(item_table_t),num_items,pIn); fclose(pIn); } else { // Create item table safe_bprintf(PRINT_MEDIUM, "ACE: No node file found, creating new one..."); ACEIT_BuildItemNodeTable(false); safe_bprintf(PRINT_MEDIUM, "done.\n"); return; // bail } safe_bprintf(PRINT_MEDIUM, "done.\n"); ACEIT_BuildItemNodeTable(true); }
/////////////////////////////////////////////////////////////////////// // Save to disk file // // Since my compression routines are one thing I did not want to // release, I took out the compressed format option. Most levels will // save out to a node file around 50-200k, so compression is not really // a big deal. /////////////////////////////////////////////////////////////////////// void ACEND_SaveNodes() { FILE *pOut; char filename[60]; int i,j; int version = 1; // Resolve paths ACEND_ResolveAllPaths(); safe_bprintf(PRINT_MEDIUM,"Saving node table..."); strcpy(filename,"ace_botroutes/"); mkdir(filename, 0777); strcat(filename,level.mapname); strcat(filename,".nod"); if((pOut = fopen(filename, "wb" )) == NULL) return; // bail fwrite(&version,sizeof(int),1,pOut); // write version fwrite(&numnodes,sizeof(int),1,pOut); // write count fwrite(&num_items,sizeof(int),1,pOut); // write facts count fwrite(nodes,sizeof(node_t),numnodes,pOut); // write nodes for(i=0;i<numnodes;i++) for(j=0;j<numnodes;j++) fwrite(&path_table[i][j],sizeof(short int),1,pOut); // write count fwrite(item_table,sizeof(item_table_t),num_items,pOut); // write out the fact table fclose(pOut); safe_bprintf(PRINT_MEDIUM,"done.\n"); }
/////////////////////////////////////////////////////////////////////// // Called by PutClient in Server to actually release the bot into the game // Keep from killin' each other when all spawned at once /////////////////////////////////////////////////////////////////////// void ACESP_HoldSpawn(edict_t *self) { if (!KillBox(self)) { // could't spawn in? } gi.linkentity(self); self->think = ACEAI_Think; self->nextthink = level.time + FRAMETIME; // send effect gi.WriteByte(svc_muzzleflash); gi.WriteShort(self-g_edicts); gi.WriteByte(MZ_LOGIN); gi.multicast(self->s.origin, MULTICAST_PVS); if (ctf->value) safe_bprintf(PRINT_MEDIUM, "%s joined the %s team.\n", self->client->pers.netname, CTFTeamName(self->client->resp.ctf_team)); else safe_bprintf(PRINT_MEDIUM, "%s entered the game\n", self->client->pers.netname); }
/////////////////////////////////////////////////////////////////////// // Read from disk file /////////////////////////////////////////////////////////////////////// void ACEND_LoadNodes(void) { FILE *pIn; int i,j; char filename[60]; int version; strcpy(filename,"ace_botroutes/"); strcat(filename,level.mapname); strcat(filename,".nod"); if((pIn = fopen(filename, "rb" )) == NULL) { // Create item table safe_bprintf(PRINT_MEDIUM, "ACE: No node file found, creating new one..."); ACEIT_BuildItemNodeTable(false); safe_bprintf(PRINT_MEDIUM, "done.\n"); return; } // determin version fread(&version,sizeof(int),1,pIn); // read version if(version == 1) { safe_bprintf(PRINT_MEDIUM,"ACE: Loading node table..."); fread(&numnodes,sizeof(int),1,pIn); // read count fread(&num_items,sizeof(int),1,pIn); // read facts count fread(nodes,sizeof(node_t),numnodes,pIn); for(i=0;i<numnodes;i++) for(j=0;j<numnodes;j++) fread(&path_table[i][j],sizeof(short int),1,pIn); // write count fread(item_table,sizeof(item_table_t),num_items,pIn); fclose(pIn); } else { // Create item table safe_bprintf(PRINT_MEDIUM, "ACE: No node file found, creating new one..."); ACEIT_BuildItemNodeTable(false); safe_bprintf(PRINT_MEDIUM, "done.\n"); return; // bail } safe_bprintf(PRINT_MEDIUM, "done.\n"); ACEIT_BuildItemNodeTable(true); }
/////////////////////////////////////////////////////////////////////// // Spawn the bot /////////////////////////////////////////////////////////////////////// void ACESP_SpawnBot (char *team, char *name, char *skin, char *userinfo) { edict_t *bot; bot = ACESP_FindFreeClient (); if (!bot) { safe_bprintf (PRINT_MEDIUM, "Server is full, increase Maxclients.\n"); return; } bot->yaw_speed = 100; // yaw speed bot->inuse = true; bot->is_bot = true; // To allow bots to respawn if(userinfo == NULL) ACESP_SetName(bot, name, skin, team); else ClientConnect (bot, userinfo); G_InitEdict (bot); InitClientResp (bot->client); // locate ent at a spawn point /*if(ctf->value) { if (team != NULL && strcmp(team,"red")==0) ACESP_PutClientInServer (bot,false, CTF_TEAM1); else ACESP_PutClientInServer (bot,false, CTF_TEAM2); } else*/ ACESP_PutClientInServer (bot,false,0); // make sure all view stuff is valid ClientEndServerFrame (bot); ACEIT_PlayerAdded (bot); // let the world know we added another ACEAI_PickLongRangeGoal(bot); // pick a new goal }
void timed_objective_touch_think (edict_t *self) { self->nextthink = level.time + FRAMETIME; if (!self->wait) return; if (self->wait) { // safe_bprintf (PRINT_HIGH, "%i \n", (int)(self->wait + self->obj_time - level.time)); level.obj_time =(int)(self->wait + self->obj_time - level.time + 1); level.obj_team = self->obj_owner; } if (level.intermissiontime) { G_FreeEdict(self); return; } if (level.obj_time <= 0) { if (dedicated->value) safe_cprintf(NULL, PRINT_HIGH, "%s has been Successfully Held by the %s!\n", self->message, team_list[self->obj_owner]->teamname); safe_bprintf (PRINT_HIGH, "%s Has been Successfully Held by the %s!\n", self->message, team_list[self->obj_owner]->teamname); team_list[self->obj_owner]->score += self->health; level.obj_time = 0; // self->obj_count = level.framenum; // reset the touch count G_FreeEdict(self); } }
/////////////////////////////////////////////////////////////////////// // Spawn the bot /////////////////////////////////////////////////////////////////////// void ACESP_SpawnBot(char *team, char *name, char *skin, char *userinfo) { edict_t *bot = ACESP_FindFreeClient(); if (!bot) { safe_bprintf(PRINT_MEDIUM, "Server is full, increase Maxclients.\n"); return; } bot->yaw_speed = 100; // yaw speed bot->inuse = true; bot->is_bot = true; // To allow bots to respawn if (userinfo == NULL) ACESP_SetName(bot, name, skin, team); else ClientConnect (bot, userinfo); G_InitEdict (bot); InitClientResp (bot->client); // locate ent at a spawn point if (ctf->value) { // Knightmare- rewrote this int team1count = 0, team2count = 0, team3count = 0; int jointeam; const float r = random(); for (int i = 1; i <= maxclients->value; i++) { edict_t *player = &g_edicts[i]; if (!player->inuse || !player->client || player == bot) continue; switch (player->client->resp.ctf_team) { case CTF_TEAM1: team1count++; break; case CTF_TEAM2: team2count++; break; case CTF_TEAM3: team3count++; break; } } if (ttctf->value) { if (team != NULL && strcmp(team,"red")==0) jointeam = CTF_TEAM1; else if (team != NULL && strcmp(team,"blue")==0) jointeam = CTF_TEAM2; else if (team != NULL && strcmp(team,"green")==0) jointeam = CTF_TEAM3; // join either of the outnumbered teams else if (team1count == team2count && team1count < team3count) jointeam = (r < 0.5) ? CTF_TEAM1 : CTF_TEAM2; else if (team1count == team3count && team1count < team2count) jointeam = (r < 0.5) ? CTF_TEAM1 : CTF_TEAM3; else if (team2count == team3count && team2count < team1count) jointeam = (r < 0.5) ? CTF_TEAM2 : CTF_TEAM3; // join outnumbered team else if (team1count < team2count && team1count < team3count) jointeam = CTF_TEAM1; else if (team2count < team1count && team2count < team3count) jointeam = CTF_TEAM2; else if (team3count < team1count && team3count < team2count) jointeam = CTF_TEAM3; // pick random team else if (r < 0.33) jointeam = CTF_TEAM1; else if (r < 0.66) jointeam = CTF_TEAM2; else jointeam = CTF_TEAM3; } else { if (team != NULL && strcmp(team,"red")==0) jointeam = CTF_TEAM1; else if (team != NULL && strcmp(team,"blue")==0) jointeam = CTF_TEAM2; // join outnumbered team else if (team1count < team2count) jointeam = CTF_TEAM1; else if (team2count < team1count) jointeam = CTF_TEAM2; // pick random team else if (r < 0.5) jointeam = CTF_TEAM1; else jointeam = CTF_TEAM2; } ACESP_PutClientInServer (bot,false, jointeam); } else ACESP_PutClientInServer (bot,false,0); // make sure all view stuff is valid ClientEndServerFrame(bot); ACEIT_PlayerAdded(bot); // let the world know we added another ACEAI_PickLongRangeGoal(bot); // pick a new goal }
/* ================= ServerCommand ServerCommand will be called when an "sv" command is issued. The game can issue gi.argc() / gi.argv() commands to get the rest of the parameters ================= */ void ServerCommand (void) { char *cmd; cmd = gi.argv(1); if (Q_strcasecmp (cmd, "test") == 0) Svcmd_Test_f (); else if (Q_strcasecmp (cmd, "addip") == 0) SVCmd_AddIP_f (); else if (Q_strcasecmp (cmd, "removeip") == 0) SVCmd_RemoveIP_f (); else if (Q_strcasecmp (cmd, "listip") == 0) SVCmd_ListIP_f (); else if (Q_strcasecmp (cmd, "writeip") == 0) SVCmd_WriteIP_f (); // ACEBOT_ADD else if(Q_strcasecmp (cmd, "acedebug") == 0) if (strcmp(gi.argv(2),"on")==0) { safe_bprintf (PRINT_MEDIUM, "ACE: Debug Mode On\n"); debug_mode = true; } else { safe_bprintf (PRINT_MEDIUM, "ACE: Debug Mode Off\n"); debug_mode = false; } else if (Q_strcasecmp (cmd, "addbot") == 0) { if (!deathmatch->value) // Knightmare added { safe_bprintf (PRINT_MEDIUM, "ACE: Can only spawn bots in deathmatch mode.\n"); return; } if(ctf->value) // name, skin, team ACESP_SpawnBot (gi.argv(2), gi.argv(3), gi.argv(4), NULL); else // name, skin ACESP_SpawnBot (NULL, gi.argv(2), gi.argv(3), NULL); } // removebot else if(Q_strcasecmp (cmd, "removebot") == 0) ACESP_RemoveBot(gi.argv(2)); // Node saving else if(Q_strcasecmp (cmd, "savenodes") == 0) ACEND_SaveNodes(); // ACEBOT_END // Knightmare added- DM pause else if(Q_strcasecmp (cmd, "dmpause") == 0) { if (!deathmatch->value) { safe_cprintf (NULL, PRINT_HIGH, "Dmpause only works in deathmatch.\n", cmd); paused = false; return; } paused = !paused; if (!paused) // unfreeze players { int i; edict_t *player; for (i=0; i<game.maxclients; i++) { player = &g_edicts[1+i]; if (!player->inuse || !player->client) continue; if (player->is_bot || player->client->ctf_grapple) continue; player->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; } safe_bprintf (PRINT_HIGH, "Game unpaused\n"); } } else safe_cprintf (NULL, PRINT_HIGH, "Unknown server command \"%s\"\n", cmd); }