/* ================= EndDMLevel The timelimit or fraglimit has been exceeded ================= */ void EndDMLevel (void) { edict_t *ent; // stay on same level flag if ((int)dmflags->value & DF_SAME_LEVEL) { ent = G_Spawn (); ent->classname = "target_changelevel"; ent->map = level.mapname; ent->spawnflags2 = 0; } else if (level.nextmap[0]) { // go to a specific map ent = G_Spawn (); ent->classname = "target_changelevel"; ent->map = level.nextmap; ent->spawnflags2 = 0; } else { // search for a changeleve ent = G_Find (NULL, FOFS(classname), "target_changelevel"); if (!ent) { // the map designer didn't include a changelevel, // so create a fake ent that goes back to the same level ent = G_Spawn (); ent->classname = "target_changelevel"; ent->map = level.mapname; ent->spawnflags2 = 0; } } BeginIntermission (ent); }
/*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; // allready 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) gi.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); }
void VotePassed () { if (!NextMap) BeginIntermission (CreateTargetChangeLevel(Map.CString())); else Level.NextMap = Map; }
/* ================= EndDMLevel The timelimit or fraglimit has been exceeded ================= */ void EndDMLevel (void) { edict_t *ent; char *s, *t, *f; static const char *seps = " ,\n\r"; // stay on same level flag if ((int)dmflags->value & DF_SAME_LEVEL) { BeginIntermission (CreateTargetChangeLevel (level.mapname) ); return; } if (*level.forcemap) { BeginIntermission (CreateTargetChangeLevel (level.forcemap) ); return; } // see if it's in the map list if (*sv_maplist->string) { s = strdup(sv_maplist->string); f = NULL; t = strtok(s, seps); while (t != NULL) { if (Q_stricmp(t, level.mapname) == 0) { // it's in the list, go to the next one t = strtok(NULL, seps); if (t == NULL) { // end of list, go to first one if (f == NULL) // there isn't a first one, same level BeginIntermission (CreateTargetChangeLevel (level.mapname) ); else BeginIntermission (CreateTargetChangeLevel (f) ); } else BeginIntermission (CreateTargetChangeLevel (t) ); free(s); return; } if (!f) f = t; t = strtok(NULL, seps); } free(s); } if (level.nextmap[0]) // go to a specific map BeginIntermission (CreateTargetChangeLevel (level.nextmap) ); else { // search for a changelevel ent = G_Find (NULL, FOFS(classname), "target_changelevel"); if (!ent) { // the map designer didn't include a changelevel, // so create a fake ent that goes back to the same level BeginIntermission (CreateTargetChangeLevel (level.mapname) ); return; } BeginIntermission (ent); } }
/*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) { int i; edict_t *scan; vec3_t v; qboolean ret = false; 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 coop, make sure all clients are nearby. if (coop->value) { for (i=0 ; i<maxclients->value ; i++) { scan = g_edicts + 1 + i; if (!scan->inuse) continue; if (!scan->client) continue; if (!scan->client->pers.loggedin) continue; VectorSubtract (activator->s.origin, scan->s.origin, v); if (VectorLength (v) > 500) { if (level.time < other->pain_debounce_time) { gi.cprintf(activator, PRINT_HIGH, "%s is too far away\n", scan->client->pers.netname); } ret = true; } } if (ret) { other->pain_debounce_time = level.time + 5.0; return; } } // if multiplayer, let everyone know who hit the exit /* if (deathmatch->value) { if (activator && activator->client) gi.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); }
/* ================== Cmd_LevelShot_f This is just to help generate the level pictures for the menus. It goes to the intermission immediately and sends over a command to the client to resize the view, hide the scoreboard, and take a special screenshot ================== */ void Cmd_LevelShot_f( gentity_t *ent ) { if ( !CheatsOk( ent ) ) { return; } // doesn't work in single player if ( g_gametype.integer != 0 ) { trap_SendServerCommand( ent-g_entities, "print \"Must be in g_gametype 0 for levelshot\n\"" ); return; } BeginIntermission(); trap_SendServerCommand( ent-g_entities, "clientLevelShot" ); }
void use_target_changelevel (edict_t *self, edict_t *other, edict_t *activator) { if (level.intermissiontime) return; // already activated // 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) gi.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); // Ridah, copy the episode_flags over if (activator->client) { activator->client->pers.episode_flags |= activator->episode_flags; } else // something has gone very wrong { { edict_t *player; player = &g_edicts[1]; activator = player; activator->client->pers.episode_flags |= activator->episode_flags; } } BeginIntermission (self); }
/* ================== Cmd_LevelShot_f This is just to help generate the level pictures for the menus. It goes to the intermission immediately and sends over a command to the client to resize the view, hide the scoreboard, and take a special screenshot ================== */ void Cmd_LevelShot_f(gentity_t *ent) { if(!ent->client->pers.localClient) { trap_SendServerCommand(ent-g_entities, "print \"The levelshot command must be executed by a local client\n\""); return; } if(!CheatsOk(ent)) return; // doesn't work in single player if(g_gametype.integer == GT_SINGLE_PLAYER) { trap_SendServerCommand(ent-g_entities, "print \"Must not be in singleplayer mode for levelshot\n\"" ); return; } BeginIntermission(); trap_SendServerCommand(ent-g_entities, "clientLevelShot"); }
/* ================= CheckExitRules There will be a delay between the time the exit is qualified for and the time everyone is moved to the intermission spot, so you can see the last frag. ================= */ void CheckExitRules( void ) { int i; gclient_t *cl; // if at the intermission, wait for all non-bots to // signal ready, then go to next level if ( level.intermissiontime ) { CheckIntermissionExit (); return; } if ( level.intermissionQueued ) { #ifdef MISSIONPACK int time = (g_singlePlayer.integer) ? SP_INTERMISSION_DELAY_TIME : INTERMISSION_DELAY_TIME; if ( level.time - level.intermissionQueued >= time ) { level.intermissionQueued = 0; BeginIntermission(); } #else if ( level.time - level.intermissionQueued >= INTERMISSION_DELAY_TIME ) { level.intermissionQueued = 0; BeginIntermission(); } #endif return; } // check for sudden death if ( ScoreIsTied() ) { // always wait for sudden death return; } if ( g_timelimit.integer && !level.warmupTime ) { if ( level.time - level.startTime >= g_timelimit.integer*60000 ) { trap_SendServerCommand( -1, "print \"Timelimit hit.\n\""); LogExit( "Timelimit hit." ); return; } } if ( g_gametype.integer < GT_CTF && g_fraglimit.integer ) { if ( level.teamScores[TEAM_RED] >= g_fraglimit.integer ) { trap_SendServerCommand( -1, "print \"Red hit the fraglimit.\n\"" ); LogExit( "Fraglimit hit." ); return; } if ( level.teamScores[TEAM_BLUE] >= g_fraglimit.integer ) { trap_SendServerCommand( -1, "print \"Blue hit the fraglimit.\n\"" ); LogExit( "Fraglimit hit." ); return; } for ( i=0 ; i< g_maxclients.integer ; i++ ) { cl = level.clients + i; if ( cl->pers.connected != CON_CONNECTED ) { continue; } if ( cl->sess.sessionTeam != TEAM_FREE ) { continue; } if ( cl->ps.persistant[PERS_SCORE] >= g_fraglimit.integer ) { LogExit( "Fraglimit hit." ); trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " hit the fraglimit.\n\"", cl->pers.netname ) ); return; } } } if ( g_gametype.integer >= GT_CTF && g_capturelimit.integer ) { if ( level.teamScores[TEAM_RED] >= g_capturelimit.integer ) { trap_SendServerCommand( -1, "print \"Red hit the capturelimit.\n\"" ); LogExit( "Capturelimit hit." ); return; } if ( level.teamScores[TEAM_BLUE] >= g_capturelimit.integer ) { trap_SendServerCommand( -1, "print \"Blue hit the capturelimit.\n\"" ); LogExit( "Capturelimit hit." ); return; } } }
/* ================= EndDMLevel The timelimit or fraglimit has been exceeded ================= */ void EndDMLevel () { char *s, *t, *f; static const char *seps = " ,\n\r"; // stay on same level flag if (DeathmatchFlags.dfSameLevel.IsEnabled()) { BeginIntermission (CreateTargetChangeLevel (Level.ServerLevelName.CString())); return; } if (!Level.ForceMap.IsNullOrEmpty()) { BeginIntermission (CreateTargetChangeLevel (Level.ForceMap.CString())); return; } // see if it's in the map list if (*CvarList[CV_MAPLIST].StringValue()) { s = Mem_StrDup(CvarList[CV_MAPLIST].StringValue()); f = NULL; t = strtok(s, seps); while (t != NULL) { if (Q_stricmp(t, Level.ServerLevelName.CString()) == 0) { // it's in the list, go to the next one t = strtok(NULL, seps); if (t == NULL) { // end of list, go to first one if (f == NULL) // there isn't a first one, same level BeginIntermission (CreateTargetChangeLevel (Level.ServerLevelName.CString()) ); else BeginIntermission (CreateTargetChangeLevel (f) ); } else BeginIntermission (CreateTargetChangeLevel (t) ); QDelete s; return; } if (!f) f = t; t = strtok(NULL, seps); } free(s); } if (!Level.NextMap.IsNullOrEmpty()) // go to a specific map BeginIntermission (CreateTargetChangeLevel (Level.NextMap.CString()) ); else { // search for a changelevel CTargetChangeLevel *Entity = CC_FindByClassName<CTargetChangeLevel, EF_BASE> (NULL, "target_changelevel"); if (!Entity) { // the map designer didn't include a changelevel, // so create a fake ent that goes back to the same level BeginIntermission (CreateTargetChangeLevel (Level.ServerLevelName.CString()) ); return; } BeginIntermission (Entity); } }
/* ================= CheckExitRules There will be a delay between the time the exit is qualified for and the time everyone is moved to the intermission spot, so you can see the last frag. ================= */ void CheckExitRules() { // if at the intermission, wait for all non-bots to // signal ready, then go to next level if( theLevel.intermissiontime_ ) { CheckIntermissionExit (); return; } if( theLevel.intermissionQueued_ ) { if ( theLevel.time_ - theLevel.intermissionQueued_ >= INTERMISSION_DELAY_TIME ) { theLevel.intermissionQueued_ = 0; BeginIntermission(); } return; } // check for sudden death if( ScoreIsTied() ) { // always wait for sudden death return; } if( g_timelimit.integer && !theLevel.warmupTime_ ) { if( theLevel.time_ - theLevel.startTime_ >= g_timelimit.integer*60000 ) { SV_GameSendServerCommand( -1, "print \"Timelimit hit.\n\" \"<scoreboard>\""); LogExit( "Timelimit hit." ); return; } } if( theLevel.numPlayingClients_ < 2 ) return; if( g_gametype.integer < GT_CTF && g_fraglimit.integer ) { if( theLevel.teamScores_[ClientBase::TEAM_RED] >= g_fraglimit.integer ) { SV_GameSendServerCommand( -1, "print \"Red hit the fraglimit.\n\" \"<scoreboard>\"" ); LogExit( "Fraglimit hit." ); return; } if( theLevel.teamScores_[ClientBase::TEAM_BLUE] >= g_fraglimit.integer ) { SV_GameSendServerCommand( -1, "print \"Blue hit the fraglimit.\n\" \"<scoreboard>\"" ); LogExit( "Fraglimit hit." ); return; } for( int i=1 ; i<= g_maxclients.integer ; i++ ) { GameClient *cl = theLevel.getClient(i); if( !cl || cl->pers_.connected_ != GameClient::ClientPersistant::CON_CONNECTED ) continue; if( cl->sess_.sessionTeam_ != ClientBase::TEAM_FREE ) continue; if( cl->ps_.persistant[PERS_SCORE] >= g_fraglimit.integer ) { LogExit( "Fraglimit hit." ); SV_GameSendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " hit the fraglimit.\n\" \"<scoreboard>\"", cl->pers_.netname_ ) ); return; } } } if( g_gametype.integer >= GT_CTF && g_capturelimit.integer ) { if( theLevel.teamScores_[ClientBase::TEAM_RED] >= g_capturelimit.integer ) { SV_GameSendServerCommand( -1, "print \"Red hit the capturelimit.\n\" \"<scoreboard>\"" ); LogExit( "Capturelimit hit." ); return; } if( theLevel.teamScores_[ClientBase::TEAM_BLUE] >= g_capturelimit.integer ) { SV_GameSendServerCommand( -1, "print \"Blue hit the capturelimit.\n\" \"<scoreboard>\"" ); LogExit( "Capturelimit hit." ); return; } } }
/* * The timelimit or fraglimit has been exceeded */ void EndDMLevel(void) { edict_t *ent; char *s, *t, *f; static const char *seps = " ,\n\r"; /* stay on same level flag */ if ((int) dmflags->value & DF_SAME_LEVEL) { BeginIntermission(CreateTargetChangeLevel(level.mapname)); return; } /* see if it's in the map list */ if (*sv_maplist->string) { s = strdup(sv_maplist->string); f = NULL; t = strtok(s, seps); while (t != NULL) { if (Q_stricmp(t, level.mapname) == 0) { /* it's in the list, go to the next one */ t = strtok(NULL, seps); if (t == NULL) /* end of list, go to first one */ { if (f == NULL) /* there isn't a first one, same level */ { BeginIntermission(CreateTargetChangeLevel(level.mapname)); } else { BeginIntermission(CreateTargetChangeLevel(f)); } } else { BeginIntermission(CreateTargetChangeLevel(t)); } free(s); return; } if (!f) { f = t; } t = strtok(NULL, seps); } free(s); } if (level.nextmap[0]) { BeginIntermission(CreateTargetChangeLevel(level.nextmap)); } else { ent = G_Find(NULL, FOFS(classname), "target_changelevel"); if (!ent) { BeginIntermission(CreateTargetChangeLevel(level.mapname)); return; } BeginIntermission(ent); } }
void use_target_changelevel (edict_t *self, edict_t *other, edict_t *activator) { int i, j, k; edict_t *e; 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) gi.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); // Ridah, 5-8-99, save this mapname for "pawn_" checking strcpy( last_changelevel, level.mapname ); // Ridah, copy the episode_flags over if (activator->client) { activator->client->pers.episode_flags |= activator->episode_flags; } else // something has gone very wrong { { edict_t *player; player = &g_edicts[1]; activator = player; activator->client->pers.episode_flags |= activator->episode_flags; } } if (!deathmatch->value) { // Ridah, save any followers temporarily so we can carry them through to the next level changing_levels = true; // Ridah, 7-5-99, prevent friendly's following into pawn-o-matic if (strstr( self->map, "pawn" ) != self->map) { for (i=0; i<level.num_characters; i++) { if (!level.characters[i]) continue; e = level.characters[i]; if (!e || e->client || e->health <= 0) continue; if (!e->leader) continue; if (e->leader != activator) continue; if (VectorDistance( e->s.origin, activator->s.origin ) > 512) continue; // mark them as followers e->flags |= FL_FOLLOWING; // save this dude strcpy( followers[num_followers].classname, e->classname ); if (e->name) strcpy( followers[num_followers].name, e->name ); else memset( followers[num_followers].name, 0, sizeof(followers[num_followers].name) ); if (e->art_skins) strcpy( followers[num_followers].art_skins, e->art_skins ); else memset( followers[num_followers].art_skins, 0, sizeof(followers[num_followers].art_skins) ); followers[num_followers].health = e->health; followers[num_followers].max_health = e->max_health; followers[num_followers].head = e->head; followers[num_followers].scale = e->cast_info.scale; followers[num_followers].spawnflags = e->spawnflags; followers[num_followers].count = e->count; // for the Runt for (j=0; j<e->s.num_parts; j++) { for (k=0; k<MAX_MODELPART_OBJECTS; k++) { followers[num_followers].skinofs[j][k] = ((int)e->s.model_parts[j].skinnum[k]) - e->s.model_parts[j].baseskin; } } num_followers++; if (num_followers > MAX_FOLLOWERS) break; } } } BeginIntermission (self, self->map); }