void Cmd_Sub_f(edict_t * ent) { if (!matchmode->value) { gi.cprintf(ent, PRINT_HIGH, "This command needs matchmode to be enabled\n"); return; } if (ent->client->resp.team == NOTEAM) { gi.cprintf(ent, PRINT_HIGH, "You need to be on a team for that...\n"); return; } if (!ent->client->resp.subteam) { killPlayer(ent, true); // lets kill em. gi.bprintf(PRINT_HIGH, "%s is now a substitute for %s\n", ent->client->pers.netname, teams[ent->client->resp.team].name); ent->client->resp.subteam = ent->client->resp.team; return; } gi.bprintf(PRINT_HIGH, "%s is no longer a substitute for %s\n", ent->client->pers.netname, teams[ent->client->resp.team].name); ent->client->resp.subteam = 0; if (team_round_going && !(gameSettings & GS_ROUNDBASED)) { PutClientInServer (ent); AddToTransparentList (ent); } }
/* ===================== ClientBeginDeathmatch A client has just connected to the server in deathmatch mode, so clear everything out before starting them. ===================== */ void ClientBeginDeathmatch (edict_t *ent) { G_InitEdict (ent); InitClientResp (ent->client); // locate ent at a spawn point PutClientInServer (ent); if (level.intermissiontime) { MoveClientToIntermission (ent); } else { // send effect gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_LOGIN); gi.multicast (ent->s.origin, MULTICAST_PVS); } gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname); // make sure all view stuff is valid ClientEndServerFrame (ent); }
/* =========== ClientBegin called when a client has finished connecting, and is ready to be placed into the game. This will happen every level load. ============ */ void ClientBegin (edict_t *ent) { int i; ent->client = game.clients + (ent - g_edicts - 1); if (deathmatch->value) { ClientBeginDeathmatch (ent); return; } // if there is already a body waiting for us (a loadgame), just // take it, otherwise spawn one from scratch if (ent->inuse == true) { // the client has cleared the client side viewangles upon // connecting to the server, which is different than the // state when the game is saved, so we need to compensate // with deltaangles for (i=0 ; i<3 ; i++) ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(ent->client->ps.viewangles[i]); } else { // a spawn point will completely reinitialize the entity // except for the persistant data that was initialized at // ClientConnect() time G_InitEdict (ent); ent->classname = "player"; InitClientResp (ent->client); PutClientInServer (ent); } if (level.intermissiontime) { MoveClientToIntermission (ent); } else { // send effect if in a multiplayer game if (game.maxclients > 1) { 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 #else gi.bprintf #endif (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname); } } // make sure all view stuff is valid ClientEndServerFrame (ent); }
void respawn (edict_t *self) { if (deathmatch->value || coop->value) { #ifdef WITH_ACEBOT // ACEBOT_ADD special respawning code if (self->is_bot) { ACESP_Respawn (self); return; } // ACEBOT_END #endif CopyToBodyQue (self); PutClientInServer (self); // add a teleportation effect self->s.event = EV_PLAYER_TELEPORT; // hold in place briefly self->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT; self->client->ps.pmove.pm_time = 14; self->client->respawn_time = level.time; return; } // restart the entire server gi.AddCommandString ("menu_loadgame\n"); }
void respawn (edict_t *self) { if (deathmatch->value || coop->value) { // spectator's don't leave bodies if (self->movetype != MOVETYPE_NOCLIP) CopyToBodyQue (self); self->svflags &= ~SVF_NOCLIENT; PutClientInServer (self); // add a teleportation effect self->s.event = EV_PLAYER_TELEPORT; // hold in place briefly self->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT; self->client->ps.pmove.pm_time = 14; self->client->respawn_time = level.time; return; } // restart the entire server gi.AddCommandString ("menu_loadgame\n"); }
qboolean Teamplay_ValidateJoinTeam( edict_t *self, int teamindex ) { // NOTE: this is called by each player on level change, as well as when a player issues a "join XXX" command // TODO: player limit per team? cvar? Teamplay_ValidateSkin( self ); // InitClientPersistant (self->client); self->client->pers.team = teamindex; self->client->pers.spectator = PLAYING; if ((level.modeset != MATCHSPAWN) && (level.modeset != PUBLICSPAWN)) { gi.bprintf( PRINT_HIGH, "%s joined %s\n", self->client->pers.netname, team_names[teamindex] ); } if ((level.modeset == PUBLIC) || (level.modeset == MATCH) || (level.modeset == MATCHSPAWN) || (level.modeset == PUBLICSPAWN)) { /* // Validate skins { char *str[256]; strcpy( str, self->client->pers.userinfo ); ClientUserinfoChanged ( self, str ); } */ if (self->client->resp.enterframe!=level.framenum) PutClientInServer( self ); // find a new spawn point } return true; }
/////////////////////////////////////////////////////////////////////// // 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 }
//========================================== // BOT_DMClass_JoinGame // put the bot into the game. //========================================== void BOT_DMClass_JoinGame (edict_t *ent, char *team_name) { char *s; //int rnd = CLASS_PALADIN; if ( !BOT_JoinCTFTeam(ent, team_name) ) gi.bprintf (PRINT_HIGH, "[BOT] %s joined the game.\n", ent->client->pers.netname); ent->think = AI_Think; ent->nextthink = level.time + FRAMETIME; // az: Vortex stuff disableAbilities(ent); ent->myskills.level = AveragePlayerLevel(); ent->myskills.speciality_points = ent->myskills.level * 2; s = Info_ValueForKey (ent->client->pers.userinfo, "skin"); /*while (1) // except the knight, any class. { rnd = GetRandom(1, CLASS_MAX); if (rnd != CLASS_PALADIN && rnd != CLASS_POLTERGEIST) break; } ent->myskills.class_num = rnd;*/ ent->myskills.class_num = CLASS_SOLDIER; ent->myskills.respawn_weapon = GetRandom(1, 11); ent->client->pers.spectator = false; ent->client->resp.spectator = false; vrx_add_respawn_items(ent); vrx_add_respawn_weapon(ent, ent->myskills.respawn_weapon); vrx_assign_abilities(ent); vrx_set_talents(ent); ent->myskills.streak = 0; BOT_VortexAssignSkills(ent); //join game ent->movetype = MOVETYPE_WALK; ent->solid = SOLID_BBOX; ent->svflags &= ~SVF_NOCLIENT; ent->client->ps.gunindex = 0; PutClientInServer(ent); if (!KillBox (ent)) { // could't spawn in? } gi.linkentity (ent); }
/* ===================== 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); }
void ClientBeginDeathmatch (edict_t *ent) { // STEVE added these 3 local variables FILE *motd_file; char motd[500]; char line[80]; G_InitEdict (ent); 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); gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname); // STEVE changed this bit : read the motd from a file if (motd_file = fopen("motd.txt", "r")) { // we successfully opened the file "motd.txt" if ( fgets(motd, 500, motd_file) ) { // we successfully read a line from "motd.txt" into motd // ... read the remaining lines now while ( fgets(line, 80, motd_file) ) { // add each new line to motd, to create a BIG message string. // we are using strcat: STRing conCATenation function here. strcat(motd, line); } // print our message. gi.centerprintf (ent, motd); } // be good now ! ... close the file fclose(motd_file); } // make sure all view stuff is valid ClientEndServerFrame (ent); }
/////////////////////////////////////////////////////////////////////// // Respawn the bot /////////////////////////////////////////////////////////////////////// void BOT_Respawn (edict_t *self) { CopyToBodyQue (self); PutClientInServer (self); // add a teleportation effect self->s.event = EV_PLAYER_TELEPORT; // hold in place briefly self->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT; self->client->ps.pmove.pm_time = 14; self->client->respawn_time = level.time; AI_ResetWeights(self); AI_ResetNavigation(self); }
//========================================== // BOT_JoinCTFTeam // Assign a team for the bot //========================================== qboolean BOT_JoinCTFTeam (edict_t *ent, char *team_name) { char *s; int team; // edict_t *event; if (ent->teamnum != CTF_NOTEAM) return false; // find what ctf team if ((team_name !=NULL) && (strcmp(team_name, "blue") == 0)) team = CTF_TEAM2; else if ((team_name !=NULL) && (strcmp(team_name, "red") == 0)) team = CTF_TEAM1; else team = BOT_NextCTFTeam(); if (team == CTF_NOTEAM) return false; //join ctf team ent->svflags &= ~SVF_NOCLIENT; //ent->client->resp.ctf_state = 1;//0? ent->teamnum = team; s = Info_ValueForKey (ent->client->pers.userinfo, "skin"); // az todo: assign skin // CTFAssignSkin(ent, s); PutClientInServer(ent); // hold in place briefly ent->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT; ent->client->ps.pmove.pm_time = 14; /* // az: fixme Com_Printf ( "%s joined the %s team.\n", ent->client->pers.netname, CTFTeamName(ent->teamnum)); */ return true; }
void respawn (edict_t *self) { if (deathmatch->value || coop->value) { CopyToBodyQue (self); PutClientInServer (self); // add a teleportation effect self->s.event = EV_PLAYER_TELEPORT; // hold in place briefly self->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT; self->client->ps.pmove.pm_time = 14; self->client->respawn_time = level.time; return; } // restart the entire server gi.AddCommandString ("menu_loadgame\n"); }
int vmMain( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10, int arg11 ) { ClearGlobals(); switch ( command ) { case GAME_INIT: api_ver = trap_GetApiVersion(); if ( api_ver < MIN_API_VERSION ) { G_conprintf("Mod requried API_VERSION %d or higher, server have %d\n", MIN_API_VERSION, api_ver); return 0; } if( api_ver >= MIN_API_VERSION && api_ver <= GAME_API_VERSION ) { gamedata.APIversion = api_ver; } G_InitGame( arg0, arg1 ); return ( int ) ( &gamedata ); case GAME_LOADENTS: G_SpawnEntitiesFromString(); return 1; case GAME_START_FRAME: StartFrame( arg0 ); return 1; case GAME_CLIENT_CONNECT: self = PROG_TO_EDICT( g_globalvars.self ); self->auth_time = g_globalvars.time + 10.0; self->isSpectator = arg0?1:0; if ( arg0 ) SpectatorConnect(); else ClientConnect(); return 1; case GAME_PUT_CLIENT_IN_SERVER: self = PROG_TO_EDICT( g_globalvars.self ); if ( !arg0 ) PutClientInServer(); return 1; case GAME_CLIENT_DISCONNECT: self = PROG_TO_EDICT( g_globalvars.self ); if ( arg0 ) SpectatorDisconnect(); else ClientDisconnect(); return 1; case GAME_SETNEWPARMS: SetNewParms(); return 1; case GAME_CLIENT_PRETHINK: self = PROG_TO_EDICT( g_globalvars.self ); if ( !arg0 ) PlayerPreThink(); return 1; case GAME_CLIENT_POSTTHINK: self = PROG_TO_EDICT( g_globalvars.self ); if ( !arg0 ) PlayerPostThink(); else SpectatorThink(); return 1; case GAME_EDICT_TOUCH: G_EdictTouch(); return 1; case GAME_EDICT_THINK: G_EdictThink(); return 1; case GAME_EDICT_BLOCKED: G_EdictBlocked(); return 1; case GAME_SETCHANGEPARMS: //called before spawn new server for save client params self = PROG_TO_EDICT( g_globalvars.self ); SetChangeParms(); return 1; case GAME_CLIENT_COMMAND: self = PROG_TO_EDICT( g_globalvars.self ); return ClientCommand(); case GAME_CLIENT_USERINFO_CHANGED: // called on user /cmd setinfo if value changed // return not zero dont allow change // params like GAME_CLIENT_COMMAND, but argv(0) always "setinfo" and argc always 3 self = PROG_TO_EDICT( g_globalvars.self ); return ClientUserInfoChanged(); case GAME_SHUTDOWN: return 0; case GAME_CONSOLE_COMMAND: // called on server console command "mod" // params like GAME_CLIENT_COMMAND, but argv(0) always "mod" // self - rconner if can detect else world // other //SV_CMD_CONSOLE 0 //SV_CMD_RCON 1 //SV_CMD_MASTER 2 //SV_CMD_BOT 3 self = PROG_TO_EDICT( g_globalvars.self ); ModCommand(); return 0; } return 0; }
/* * only called when pers.spectator changes * note that resp.spectator should be the opposite of pers.spectator here */ void spectator_respawn (edict_t *ent) { int i, numspec; // if the user wants to become a spectator, make sure he doesn't // exceed max_spectators if (ent->client->pers.spectator) { char *value = Info_ValueForKey (ent->client->pers.userinfo, "spectator"); if (*spectator_password->string && strcmp(spectator_password->string, "none") && strcmp(spectator_password->string, value)) { gi.cprintf(ent, PRINT_HIGH, "Spectator password incorrect.\n"); ent->client->pers.spectator = false; gi.WriteByte (svc_stufftext); gi.WriteString ("spectator 0\n"); gi.unicast(ent, true); return; } // count spectators for (i = 1, numspec = 0; i <= maxclients->value; i++) if (g_edicts[i].inuse && g_edicts[i].client->pers.spectator) numspec++; if (numspec >= maxspectators->value) { gi.cprintf(ent, PRINT_HIGH, "Server spectator limit is full."); ent->client->pers.spectator = false; // reset his spectator var gi.WriteByte (svc_stufftext); gi.WriteString ("spectator 0\n"); gi.unicast(ent, true); return; } } else { // he was a spectator and wants to join the game // he must have the right password char *value = Info_ValueForKey (ent->client->pers.userinfo, "password"); if (*password->string && strcmp(password->string, "none") && strcmp(password->string, value)) { gi.cprintf(ent, PRINT_HIGH, "Password incorrect.\n"); ent->client->pers.spectator = true; gi.WriteByte (svc_stufftext); gi.WriteString ("spectator 1\n"); gi.unicast(ent, true); return; } } // clear client on respawn ent->client->resp.score = ent->client->pers.score = 0; ent->svflags &= ~SVF_NOCLIENT; PutClientInServer (ent); // add a teleportation effect if (!ent->client->pers.spectator) { // send effect gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_LOGIN); gi.multicast (ent->s.origin, MULTICAST_PVS); // hold in place briefly ent->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT; ent->client->ps.pmove.pm_time = 14; } ent->client->respawn_time = level.time; if (ent->client->pers.spectator) gi.bprintf (PRINT_HIGH, "%s has moved to the sidelines\n", ent->client->pers.netname); else gi.bprintf (PRINT_HIGH, "%s joined the game\n", ent->client->pers.netname); }
/* ================ vmMain This is the only way control passes into the module. This must be the very first function compiled into the .q3vm file ================ */ int vmMain( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10, int arg11 ) { ClearGlobals(); switch ( command ) { case GAME_INIT: if ( trap_GetApiVersion() < GAME_API_VERSION ) return 0; G_InitGame( arg0, arg1 ); return ( int ) ( &gamedata ); case GAME_LOADENTS: G_SpawnEntitiesFromString(); return 1; case GAME_START_FRAME: StartFrame( arg0 ); return 1; case GAME_CLIENT_CONNECT: self = PROG_TO_EDICT( g_globalvars.self ); if ( arg0 ) SpectatorConnect(); else ClientConnect(); return 1; case GAME_PUT_CLIENT_IN_SERVER: self = PROG_TO_EDICT( g_globalvars.self ); if ( !arg0 ) PutClientInServer(); return 1; case GAME_CLIENT_DISCONNECT: self = PROG_TO_EDICT( g_globalvars.self ); if ( arg0 ) SpectatorDisconnect(); else ClientDisconnect(); return 1; case GAME_SETNEWPARMS: SetNewParms(); return 1; case GAME_CLIENT_PRETHINK: self = PROG_TO_EDICT( g_globalvars.self ); if ( !arg0 ) PlayerPreThink(); return 1; case GAME_CLIENT_POSTTHINK: self = PROG_TO_EDICT( g_globalvars.self ); if ( !arg0 ) PlayerPostThink(); else SpectatorThink(); return 1; case GAME_EDICT_TOUCH: G_EdictTouch(); return 1; case GAME_EDICT_THINK: G_EdictThink(); return 1; case GAME_EDICT_BLOCKED: G_EdictBlocked(); return 1; case GAME_SETCHANGEPARMS: self = PROG_TO_EDICT( g_globalvars.self ); SetChangeParms(); return 1; case GAME_CLIENT_COMMAND: return ClientCommand(); /* case GAME_SHUTDOWN: G_ShutdownGame( arg0 ); return 0; case GAME_CLIENT_USERINFO_CHANGED: ClientUserinfoChanged( arg0 ); return 0; case GAME_CONSOLE_COMMAND: return ConsoleCommand();*/ } return 0; }