/*QUAKED worldspawn (0 0 0) ? Every map should have exactly one worldspawn. "music" music wav file "gravity" 800 is default gravity "message" Text to print during connection process */ void SP_worldspawn(void) { char *s; G_SpawnString("classname", "", &s); if (Q_stricmp(s, "worldspawn")) G_Error("SP_worldspawn: The first entity isn't 'worldspawn'"); // make some data visible to connecting client trap_SetConfigstring(CS_GAME_VERSION, GAME_VERSION); trap_SetConfigstring(CS_LEVEL_START_TIME, va("%i", level.startTime)); trap_SetConfigstring(CS_ZOMBIERECORDS, va("%i %i %i", level.survivalRecords[0], level.survivalRecords[1], level.survivalRecords[2])); G_SpawnString("music", "", &s); trap_SetConfigstring(CS_MUSIC, s); G_SpawnString("message", "", &s); trap_SetConfigstring(CS_MESSAGE, s); // map specific message trap_SetConfigstring(CS_MOTD, g_motd.string); // message of the day G_SpawnString("gravity", "800", &s); trap_Cvar_Set("g_gravity", s); G_SpawnString("humanBuildPoints", DEFAULT_HUMAN_BUILDPOINTS, &s); trap_Cvar_Set("g_humanBuildPoints", s); G_SpawnString("humanMaxStage", DEFAULT_HUMAN_MAX_STAGE, &s); trap_Cvar_Set("g_humanMaxStage", s); G_SpawnString("humanStage2Threshold", DEFAULT_HUMAN_STAGE2_THRESH, &s); trap_Cvar_Set("g_humanStage2Threshold", s); G_SpawnString("humanStage3Threshold", DEFAULT_HUMAN_STAGE3_THRESH, &s); trap_Cvar_Set("g_humanStage3Threshold", s); G_SpawnString("alienBuildPoints", DEFAULT_ALIEN_BUILDPOINTS, &s); trap_Cvar_Set("g_alienBuildPoints", s); G_SpawnString("alienMaxStage", DEFAULT_ALIEN_MAX_STAGE, &s); trap_Cvar_Set("g_alienMaxStage", s); G_SpawnString("alienStage2Threshold", DEFAULT_ALIEN_STAGE2_THRESH, &s); trap_Cvar_Set("g_alienStage2Threshold", s); G_SpawnString("alienStage3Threshold", DEFAULT_ALIEN_STAGE3_THRESH, &s); trap_Cvar_Set("g_alienStage3Threshold", s); G_SpawnString("enableDust", "0", &s); trap_Cvar_Set("g_enableDust", s); G_SpawnString("enableBreath", "0", &s); trap_Cvar_Set("g_enableBreath", s); G_SpawnString("disabledEquipment", "", &s); trap_Cvar_Set("g_disabledEquipment", s); G_SpawnString("disabledClasses", "", &s); trap_Cvar_Set("g_disabledClasses", s); G_SpawnString("disabledBuildables", "", &s); trap_Cvar_Set("g_disabledBuildables", s); g_entities[ ENTITYNUM_WORLD ].s.number = ENTITYNUM_WORLD; g_entities[ ENTITYNUM_WORLD ].classname = "worldspawn"; if (g_restarted.integer) trap_Cvar_Set("g_restarted", "0"); }
/* =================== G_SpawnGEntityFromSpawnVars Spawn an entity and fill in all of the level fields from level.spawnVars[], then call the class specfic spawn function =================== */ void G_SpawnGEntityFromSpawnVars( qboolean inSubBSP ) { int i; gentity_t *ent; char *s, *value, *gametypeName; static char *gametypeNames[] = {"ffa", "holocron", "jedimaster", "duel", "powerduel", "single", "team", "siege", "ctf", "cty"}; // get the next free entity ent = G_Spawn(); for ( i = 0 ; i < level.numSpawnVars ; i++ ) { G_ParseField( level.spawnVars[i][0], level.spawnVars[i][1], ent ); } // check for "notsingle" flag if ( g_gametype.integer == GT_SINGLE_PLAYER ) { G_SpawnInt( "notsingle", "0", &i ); if ( i ) { ADJUST_AREAPORTAL(); G_FreeEntity( ent ); return; } } // check for "notteam" flag (GT_FFA, GT_DUEL, GT_SINGLE_PLAYER) if ( g_gametype.integer >= GT_TEAM ) { G_SpawnInt( "notteam", "0", &i ); if ( i ) { ADJUST_AREAPORTAL(); G_FreeEntity( ent ); return; } } else { G_SpawnInt( "notfree", "0", &i ); if ( i ) { ADJUST_AREAPORTAL(); G_FreeEntity( ent ); return; } } if( G_SpawnString( "gametype", NULL, &value ) ) { if( g_gametype.integer >= GT_FFA && g_gametype.integer < GT_MAX_GAME_TYPE ) { gametypeName = gametypeNames[g_gametype.integer]; s = strstr( value, gametypeName ); if( !s ) { ADJUST_AREAPORTAL(); G_FreeEntity( ent ); return; } } } // move editor origin to pos VectorCopy( ent->s.origin, ent->s.pos.trBase ); VectorCopy( ent->s.origin, ent->r.currentOrigin ); // if we didn't get a classname, don't bother spawning anything if ( !G_CallSpawn( ent ) ) { G_FreeEntity( ent ); } //Tag on the ICARUS scripting information only to valid recipients if ( trap_ICARUS_ValidEnt( ent ) ) { trap_ICARUS_InitEnt( ent ); if ( ent->classname && ent->classname[0] ) { if ( Q_strncmp( "NPC_", ent->classname, 4 ) != 0 ) {//Not an NPC_spawner (rww - probably don't even care for MP, but whatever) G_ActivateBehavior( ent, BSET_SPAWN ); } } } }
static void HandleEntityAdjustment(void) { char *value; vec3_t origin, newOrigin, angles; char temp[MAX_QPATH]; float rotation; G_SpawnString("origin", NOVALUE, &value); if (Q_stricmp(value, NOVALUE) != 0) { sscanf( value, "%f %f %f", &origin[0], &origin[1], &origin[2] ); } else { origin[0] = origin[1] = origin[2] = 0.0; } rotation = DEG2RAD(level.mRotationAdjust); newOrigin[0] = origin[0]*cos(rotation) - origin[1]*sin(rotation); newOrigin[1] = origin[0]*sin(rotation) + origin[1]*cos(rotation); newOrigin[2] = origin[2]; VectorAdd(newOrigin, level.mOriginAdjust, newOrigin); // damn VMs don't handle outputing a float that is compatible with sscanf in all cases Com_sprintf(temp, MAX_QPATH, "%0.0f %0.0f %0.0f", newOrigin[0], newOrigin[1], newOrigin[2]); AddSpawnField("origin", temp); G_SpawnString("angles", NOVALUE, &value); if (Q_stricmp(value, NOVALUE) != 0) { sscanf( value, "%f %f %f", &angles[0], &angles[1], &angles[2] ); angles[1] = fmod(angles[1] + level.mRotationAdjust, 360.0f); // damn VMs don't handle outputing a float that is compatible with sscanf in all cases Com_sprintf(temp, MAX_QPATH, "%0.0f %0.0f %0.0f", angles[0], angles[1], angles[2]); AddSpawnField("angles", temp); } else { G_SpawnString("angle", NOVALUE, &value); if (Q_stricmp(value, NOVALUE) != 0) { sscanf( value, "%f", &angles[1] ); } else { angles[1] = 0.0; } angles[1] = fmod(angles[1] + level.mRotationAdjust, 360.0f); Com_sprintf(temp, MAX_QPATH, "%0.0f", angles[1]); AddSpawnField("angle", temp); } // RJR experimental code for handling "direction" field of breakable brushes // though direction is rarely ever used. G_SpawnString("direction", NOVALUE, &value); if (Q_stricmp(value, NOVALUE) != 0) { sscanf( value, "%f %f %f", &angles[0], &angles[1], &angles[2] ); } else { angles[0] = angles[1] = angles[2] = 0.0; } angles[1] = fmod(angles[1] + level.mRotationAdjust, 360.0f); Com_sprintf(temp, MAX_QPATH, "%0.0f %0.0f %0.0f", angles[0], angles[1], angles[2]); AddSpawnField("direction", temp); AddSpawnField("BSPInstanceID", level.mTargetAdjust); G_SpawnString("targetname", NOVALUE, &value); if (Q_stricmp(value, NOVALUE) != 0) { Com_sprintf(temp, MAX_QPATH, "%s%s", level.mTargetAdjust, value); AddSpawnField("targetname", temp); } G_SpawnString("target", NOVALUE, &value); if (Q_stricmp(value, NOVALUE) != 0) { Com_sprintf(temp, MAX_QPATH, "%s%s", level.mTargetAdjust, value); AddSpawnField("target", temp); } G_SpawnString("killtarget", NOVALUE, &value); if (Q_stricmp(value, NOVALUE) != 0) { Com_sprintf(temp, MAX_QPATH, "%s%s", level.mTargetAdjust, value); AddSpawnField("killtarget", temp); } G_SpawnString("brushparent", NOVALUE, &value); if (Q_stricmp(value, NOVALUE) != 0) { Com_sprintf(temp, MAX_QPATH, "%s%s", level.mTargetAdjust, value); AddSpawnField("brushparent", temp); } G_SpawnString("brushchild", NOVALUE, &value); if (Q_stricmp(value, NOVALUE) != 0) { Com_sprintf(temp, MAX_QPATH, "%s%s", level.mTargetAdjust, value); AddSpawnField("brushchild", temp); } G_SpawnString("enemy", NOVALUE, &value); if (Q_stricmp(value, NOVALUE) != 0) { Com_sprintf(temp, MAX_QPATH, "%s%s", level.mTargetAdjust, value); AddSpawnField("enemy", temp); } G_SpawnString("ICARUSname", NOVALUE, &value); if (Q_stricmp(value, NOVALUE) != 0) { Com_sprintf(temp, MAX_QPATH, "%s%s", level.mTargetAdjust, value); AddSpawnField("ICARUSname", temp); } }
/* ================ InitMover "pos1", "pos2", and "speed" should be set before calling, so the movement delta can be calculated ================ */ void InitMover( gentity_t *ent ) { vec3_t move; float distance; float light; vec3_t color; qboolean lightSet, colorSet; char *sound; // if the "model2" key is set, use a seperate model // for drawing, but clip against the brushes if ( ent->model2 ) { ent->s.modelindex2 = G_ModelIndex( ent->model2 ); } // if the "loopsound" key is set, use a constant looping sound when moving if ( G_SpawnString( "noise", "100", &sound ) ) { ent->s.loopSound = G_SoundIndex( sound ); } // if the "color" or "light" keys are set, setup constantLight lightSet = G_SpawnFloat( "light", "100", &light ); colorSet = G_SpawnVector( "color", "1 1 1", color ); if ( lightSet || colorSet ) { int r, g, b, i; r = color[0] * 255; if ( r > 255 ) { r = 255; } g = color[1] * 255; if ( g > 255 ) { g = 255; } b = color[2] * 255; if ( b > 255 ) { b = 255; } i = light / 4; if ( i > 255 ) { i = 255; } ent->s.constantLight = r | ( g << 8 ) | ( b << 16 ) | ( i << 24 ); } ent->use = Use_BinaryMover; ent->reached = Reached_BinaryMover; ent->moverState = MOVER_POS1; ent->r.svFlags = SVF_USE_CURRENT_ORIGIN; ent->s.eType = ET_MOVER; VectorCopy (ent->pos1, ent->r.currentOrigin); trap_LinkEntity (ent); ent->s.pos.trType = TR_STATIONARY; VectorCopy( ent->pos1, ent->s.pos.trBase ); // calculate time to reach second position from speed VectorSubtract( ent->pos2, ent->pos1, move ); distance = VectorLength( move ); if ( ! ent->speed ) { ent->speed = 100; } VectorScale( move, ent->speed, ent->s.pos.trDelta ); ent->s.pos.trDuration = distance * 1000 / ent->speed; if ( ent->s.pos.trDuration <= 0 ) { ent->s.pos.trDuration = 1; } }
void SP_worldspawn( void ) { char *text, temp[32]; int i; int lengthRed, lengthBlue, lengthGreen; //I want to "cull" entities out of net sends to clients to reduce //net traffic on our larger open maps -rww G_SpawnFloat("distanceCull", "6000.0", &g_cullDistance); trap_SetServerCull(g_cullDistance); G_SpawnString( "classname", "", &text ); if ( Q_stricmp( text, "worldspawn" ) ) { G_Error( "SP_worldspawn: The first entity isn't 'worldspawn'" ); } for ( i = 0 ; i < level.numSpawnVars ; i++ ) { if ( Q_stricmp( "spawnscript", level.spawnVars[i][0] ) == 0 ) {//ONly let them set spawnscript, we don't want them setting an angle or something on the world. G_ParseField( level.spawnVars[i][0], level.spawnVars[i][1], &g_entities[ENTITYNUM_WORLD] ); } } //The server will precache the standard model and animations, so that there is no hit //when the first client connnects. if (!BGPAFtextLoaded) { BG_ParseAnimationFile("models/players/_humanoid/animation.cfg", bgHumanoidAnimations, qtrue); } if (!precachedKyle) { int defSkin; trap_G2API_InitGhoul2Model(&precachedKyle, "models/players/kyle/model.glm", 0, 0, -20, 0, 0); if (precachedKyle) { defSkin = trap_R_RegisterSkin("models/players/kyle/model_default.skin"); trap_G2API_SetSkin(precachedKyle, 0, defSkin, defSkin); } } if (!g2SaberInstance) { trap_G2API_InitGhoul2Model(&g2SaberInstance, "models/weapons2/saber/saber_w.glm", 0, 0, -20, 0, 0); if (g2SaberInstance) { // indicate we will be bolted to model 0 (ie the player) on bolt 0 (always the right hand) when we get copied trap_G2API_SetBoltInfo(g2SaberInstance, 0, 0); // now set up the gun bolt on it trap_G2API_AddBolt(g2SaberInstance, 0, "*blade1"); } } if (g_gametype.integer == GT_SIEGE) { //a tad bit of a hack, but.. EWebPrecache(); } // make some data visible to connecting client trap_SetConfigstring( CS_GAME_VERSION, GAME_VERSION ); trap_SetConfigstring( CS_LEVEL_START_TIME, va("%i", level.startTime ) ); G_SpawnString( "music", "", &text ); trap_SetConfigstring( CS_MUSIC, text ); G_SpawnString( "message", "", &text ); trap_SetConfigstring( CS_MESSAGE, text ); // map specific message trap_SetConfigstring( CS_MOTD, g_motd.string ); // message of the day G_SpawnString( "gravity", "800", &text ); trap_Cvar_Set( "g_gravity", text ); G_SpawnString( "enableBreath", "0", &text ); trap_Cvar_Set( "g_enableBreath", text ); G_SpawnString( "soundSet", "default", &text ); trap_SetConfigstring( CS_GLOBAL_AMBIENT_SET, text ); g_entities[ENTITYNUM_WORLD].s.number = ENTITYNUM_WORLD; g_entities[ENTITYNUM_WORLD].classname = "worldspawn"; // see if we want a warmup time trap_SetConfigstring( CS_WARMUP, "" ); if ( g_restarted.integer ) { trap_Cvar_Set( "g_restarted", "0" ); level.warmupTime = 0; } //Raz: Fix warmup #if 0 /* else if ( g_doWarmup.integer && g_gametype.integer != GT_DUEL && g_gametype.integer != GT_POWERDUEL ) { // Turn it on else if ( g_doWarmup.integer && level.gametype != GT_DUEL && level.gametype != GT_POWERDUEL ) { // Turn it on level.warmupTime = -1; trap_SetConfigstring( CS_WARMUP, va("%i", level.warmupTime) ); G_LogPrintf( "Warmup:\n" ); } */ #else else if ( g_doWarmup.integer && g_gametype.integer != GT_DUEL && g_gametype.integer != GT_POWERDUEL && g_gametype.integer != GT_SIEGE ) { // Turn it on level.warmupTime = -1; trap_SetConfigstring( CS_WARMUP, va("%i", level.warmupTime) ); G_LogPrintf( "Warmup:\n" ); } #endif trap_SetConfigstring(CS_LIGHT_STYLES+(LS_STYLES_START*3)+0, defaultStyles[0][0]); trap_SetConfigstring(CS_LIGHT_STYLES+(LS_STYLES_START*3)+1, defaultStyles[0][1]); trap_SetConfigstring(CS_LIGHT_STYLES+(LS_STYLES_START*3)+2, defaultStyles[0][2]); for(i=1;i<LS_NUM_STYLES;i++) { Com_sprintf(temp, sizeof(temp), "ls_%dr", i); G_SpawnString(temp, defaultStyles[i][0], &text); lengthRed = strlen(text); trap_SetConfigstring(CS_LIGHT_STYLES+((i+LS_STYLES_START)*3)+0, text); Com_sprintf(temp, sizeof(temp), "ls_%dg", i); G_SpawnString(temp, defaultStyles[i][1], &text); lengthGreen = strlen(text); trap_SetConfigstring(CS_LIGHT_STYLES+((i+LS_STYLES_START)*3)+1, text); Com_sprintf(temp, sizeof(temp), "ls_%db", i); G_SpawnString(temp, defaultStyles[i][2], &text); lengthBlue = strlen(text); trap_SetConfigstring(CS_LIGHT_STYLES+((i+LS_STYLES_START)*3)+2, text); if (lengthRed != lengthGreen || lengthGreen != lengthBlue) { Com_Error(ERR_DROP, "Style %d has inconsistent lengths: R %d, G %d, B %d", i, lengthRed, lengthGreen, lengthBlue); } } }
/* =================== G_SpawnGEntityFromSpawnVars Spawn an entity and fill in all of the level fields from level.spawnVars[], then call the class specfic spawn function =================== */ void G_SpawnGEntityFromSpawnVars( void ) { int i; gentity_t *ent; char *s, *value, *gametypeName; static char *gametypeNames[] = {"ffa", "tournament", "single", "team", "ctf", "oneflag", "obelisk", "harvester", "elimination", "ctf", "lms", "dd", "dom"}; // get the next free entity ent = G_Spawn(); for ( i = 0 ; i < level.numSpawnVars ; i++ ) { G_ParseField( level.spawnVars[i][0], level.spawnVars[i][1], ent ); } // check for "notsingle" flag if ( g_gametype.integer == GT_SINGLE_PLAYER ) { G_SpawnInt( "notsingle", "0", &i ); if ( i ) { G_FreeEntity( ent ); return; } } // check for "notteam" flag (GT_FFA, GT_TOURNAMENT, GT_SINGLE_PLAYER) if ( g_gametype.integer >= GT_TEAM && !g_ffa_gt ) { G_SpawnInt( "notteam", "0", &i ); if ( i ) { G_FreeEntity( ent ); return; } } else { G_SpawnInt( "notfree", "0", &i ); if ( i ) { G_FreeEntity( ent ); return; } } #ifdef MISSIONPACK G_SpawnInt( "notta", "0", &i ); if ( i ) { G_FreeEntity( ent ); return; } #else G_SpawnInt( "notq3a", "0", &i ); if ( i ) { G_FreeEntity( ent ); return; } #endif if( G_SpawnString( "!gametype", NULL, &value ) ) { if( g_gametype.integer >= GT_FFA && g_gametype.integer < GT_MAX_GAME_TYPE ) { gametypeName = gametypeNames[g_gametype.integer]; s = strstr( value, gametypeName ); if( s ) { G_FreeEntity( ent ); return; } } } if( G_SpawnString( "gametype", NULL, &value ) ) { if( g_gametype.integer >= GT_FFA && g_gametype.integer < GT_MAX_GAME_TYPE ) { gametypeName = gametypeNames[g_gametype.integer]; s = strstr( value, gametypeName ); if( !s ) { G_FreeEntity( ent ); return; } } } // move editor origin to pos VectorCopy( ent->s.origin, ent->s.pos.trBase ); VectorCopy( ent->s.origin, ent->r.currentOrigin ); // if we didn't get a classname, don't bother spawning anything if ( !G_CallSpawn( ent ) ) { G_FreeEntity( ent ); } }
/*QUAKED worldspawn (0 0 0) ? NO_GT_WOLF NO_STOPWATCH NO_CHECKPOINT Every map should have exactly one worldspawn. "music" Music wav file "gravity" 800 is default gravity "message" Text to print during connection process "ambient" Ambient light value (must use '_color') "_color" Ambient light color (must be used with 'ambient') "sun" Shader to use for 'sun' image */ void SP_worldspawn( void ) { char *s; gitem_t *item; // JPW NERVE G_SpawnString( "classname", "", &s ); if ( Q_stricmp( s, "worldspawn" ) ) { G_Error( "SP_worldspawn: The first entity isn't 'worldspawn'" ); } // make some data visible to connecting client trap_SetConfigstring( CS_GAME_VERSION, GAME_VERSION ); trap_SetConfigstring( CS_LEVEL_START_TIME, va( "%i", level.startTime ) ); G_SpawnString( "music", "", &s ); trap_SetConfigstring( CS_MUSIC, s ); G_SpawnString( "message", "", &s ); trap_SetConfigstring( CS_MESSAGE, s ); // map specific message trap_SetConfigstring( CS_MOTD, g_motd.string ); // message of the day G_SpawnString( "gravity", "800", &s ); trap_Cvar_Set( "g_gravity", s ); G_SpawnString( "spawnflags", "0", &s ); g_entities[ENTITYNUM_WORLD].spawnflags = atoi( s ); g_entities[ENTITYNUM_WORLD].r.worldflags = g_entities[ENTITYNUM_WORLD].spawnflags; g_entities[ENTITYNUM_WORLD].s.number = ENTITYNUM_WORLD; g_entities[ENTITYNUM_WORLD].classname = "worldspawn"; // see if we want a warmup time trap_SetConfigstring( CS_WARMUP, "" ); if ( g_restarted.integer ) { trap_Cvar_Set( "g_restarted", "0" ); level.warmupTime = 0; } // JPW NERVE change minigun overheat time for single player -- this array gets reloaded every time the server is reset, // so this is as good a place as any to do stuff like this { int i; ammoTable[WP_VENOM].maxHeat *= 0.25; for ( i = 0; i < strlen( testid2 ); i++ ) testid2[i] -= ( i + 1 ); ammoTable[WP_DYNAMITE].uses = 0; // regens based on recharge time // reset ammo for subs to be distinct for multiplayer (so running out of rifle ammo doesn't deplete sidearm) // if player runs out of SMG ammunition, it shouldn't *also* deplete pistol ammunition. If you change this, change // g_spawn.c as well item = BG_FindItemByIndex( IL_WEAPON_THOMPSON ); item->giAmmoIndex = WP_THOMPSON; item = BG_FindItemByIndex( IL_WEAPON_STEN ); item->giAmmoIndex = WP_STEN; for ( i = 0; i < strlen( testid1 ); i++ ) testid1[i] -= ( i + 1 ); item = BG_FindItemByIndex( IL_WEAPON_MP40 ); item->giAmmoIndex = WP_MP40; ammoTable[WP_VENOM_FULL].nextShotTime = 500; for ( i = 0; i < strlen( testid3 ); i++ ) testid3[i] -= ( i + 1 ); ammoTable[WP_PANZERFAUST].fireDelayTime = 750; item = BG_FindItemByIndex( IL_WEAPON_PANZERFAUST ); item->world_model[4] = "models/multiplayer/panzerfaust/multi_pf.md3"; } }
void SP_trigger_objective_info(gentity_t *ent) { char *scorestring; char *customimage; int cix, cia, objflags; if (!ent->track) { G_Error("'trigger_objective_info' does not have a 'track' \n"); } if (ent->spawnflags & MESSAGE_OVERRIDE) { if (!ent->spawnitem) { G_Error("'trigger_objective_info' has override flag set but no override text\n"); } } // for specifying which commandmap objectives this entity "belongs" to G_SpawnInt("objflags", "0", &objflags); if (G_SpawnString("customimage", "", &customimage)) { cix = cia = G_ShaderIndex(customimage); } else { if (G_SpawnString("customaxisimage", "", &customimage)) { cix = G_ShaderIndex(customimage); } else { cix = 0; } if (G_SpawnString("customalliesimage", "", &customimage)) { cia = G_ShaderIndex(customimage); } else if (G_SpawnString("customalliedimage", "", &customimage)) { cia = G_ShaderIndex(customimage); } else { cia = 0; } } G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "e", va("%i", (int)(ent - g_entities))); G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "o", va("%i", objflags)); if (cix) { G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "cix", va("%i", cix)); } if (cia) { G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "cia", va("%i", cia)); } G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "s", va("%i", ent->spawnflags)); G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "n", ent->message ? ent->message : ""); if (level.numOidTriggers >= MAX_OID_TRIGGERS) { G_Error("Exceeded maximum number of 'trigger_objective_info' entities\n"); } // if this trigger has a "score" field set, then blowing up an objective // inside of this field will add "score" to the right player team. storing this // in ent->accuracy since that's unused. G_SpawnString("score", "0", &scorestring); ent->accuracy = atof(scorestring); trap_SetConfigstring(CS_OID_TRIGGERS + level.numOidTriggers, ent->track); InitTrigger(ent); if (ent->s.origin[0] || ent->s.origin[1] || ent->s.origin[2]) { G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "x", va("%i", (int)ent->s.origin[0])); G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "y", va("%i", (int)ent->s.origin[1])); G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "z", va("%i", (int)ent->s.origin[2])); } else { vec3_t mid; VectorAdd(ent->r.absmin, ent->r.absmax, mid); VectorScale(mid, 0.5f, mid); G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "x", va("%i", (int)mid[0])); G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "y", va("%i", (int)mid[1])); G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "z", va("%i", (int)mid[2])); } ent->s.teamNum = level.numOidTriggers++; // unlike other triggers, we need to send this one to the client ent->r.svFlags &= ~SVF_NOCLIENT; ent->s.eType = ET_OID_TRIGGER; if (!ent->target) { // no target - just link and go trap_LinkEntity(ent); } else { // finalize spawing on fourth frame to allow for proper linking with targets ent->nextthink = level.time + (3 * FRAMETIME); ent->think = Think_SetupObjectiveInfo; } }
/*QUAKED worldspawn (0 0 0) ? Every map should have exactly one worldspawn. "music" music wav file "gravity" 800 is default gravity "message" Text to print during connection process */ void SP_worldspawn( void ) { char *s; G_SpawnString( "classname", "", &s ); if ( Q_stricmp( s, "worldspawn" ) ) { G_Error( "SP_worldspawn: The first entity isn't 'worldspawn'" ); } // make some data visible to connecting client trap_SetConfigstring( CS_GAME_VERSION, GAME_VERSION ); trap_SetConfigstring( CS_LEVEL_START_TIME, va( "%i", level.startTime ) ); G_SpawnString( "music", "", &s ); trap_SetConfigstring( CS_MUSIC, s ); G_SpawnString( "message", "", &s ); trap_SetConfigstring( CS_MESSAGE, s ); // map specific message trap_SetConfigstring( CS_MOTD, g_motd.string ); // message of the day if ( G_SpawnString( "gravity", "", &s ) ) { trap_Cvar_Set( "g_gravity", s ); } if ( G_SpawnString( "humanMaxStage", "", &s ) ) { trap_Cvar_Set( "g_humanMaxStage", s ); } if ( G_SpawnString( "alienMaxStage", "", &s ) ) { trap_Cvar_Set( "g_alienMaxStage", s ); } if ( G_SpawnString( "humanRepeaterBuildPoints", "", &s ) ) trap_Cvar_Set( "g_humanRepeaterBuildPoints", s ); if ( G_SpawnString( "humanBuildPoints", "", &s ) ) trap_Cvar_Set( "g_humanBuildPoints", s ); if ( G_SpawnString( "alienBuildPoints", "", &s ) ) trap_Cvar_Set( "g_alienBuildPoints", s ); G_SpawnString( "disabledEquipment", "", &s ); trap_Cvar_Set( "g_disabledEquipment", s ); G_SpawnString( "disabledClasses", "", &s ); trap_Cvar_Set( "g_disabledClasses", s ); G_SpawnString( "disabledBuildables", "", &s ); trap_Cvar_Set( "g_disabledBuildables", s ); g_entities[ ENTITYNUM_WORLD ].s.number = ENTITYNUM_WORLD; g_entities[ ENTITYNUM_WORLD ].r.ownerNum = ENTITYNUM_NONE; g_entities[ ENTITYNUM_WORLD ].classname = "worldspawn"; g_entities[ ENTITYNUM_NONE ].s.number = ENTITYNUM_NONE; g_entities[ ENTITYNUM_NONE ].r.ownerNum = ENTITYNUM_NONE; g_entities[ ENTITYNUM_NONE ].classname = "nothing"; // see if we want a warmup time trap_SetConfigstring( CS_WARMUP, "-1" ); if ( g_doWarmup.integer ) { level.warmupTime = level.time - level.startTime + ( g_warmup.integer * 1000 ); trap_SetConfigstring( CS_WARMUP, va( "%i", level.warmupTime ) ); G_LogPrintf( "Warmup: %i\n", g_warmup.integer ); } level.timelimit = g_timelimit.integer; }
/*QUAKED worldspawn (0 0 0) ? Used for game-world global options. Every map should have exactly one. === KEYS === ; message: Text to print during connection process. Used for the name of level. ; music: path/name of looping .wav file used for level's music (eg. music/sonic5.wav). ; gravity: level gravity [g_gravity (800)] ; humanBuildPoints: maximum amount of power the humans can use. [g_humanBuildPoints] ; humanRepeaterBuildPoints: maximum amount of power the humans can use around each repeater. [g_humanRepeaterBuildPoints] ; alienBuildPoints: maximum amount of sentience available to the overmind. [g_alienBuildPoints] ; humanMaxStage: The highest stage the humans are allowed to use (0/1/2). [g_alienMaxStage (2)] ; alienMaxStage: The highest stage the aliens are allowed to use (0/1/2). [g_humanMaxStage (2)] ; disabledEquipment: A comma delimited list of human weapons or upgrades to disable for this map. [g_disabledEquipment ()] ; disabledClasses: A comma delimited list of alien classes to disable for this map. [g_disabledClasses ()] ; disabledBuildables: A comma delimited list of buildables to disable for this map. [g_disabledBuildables ()] */ void SP_worldspawn( void ) { char *s; G_SpawnString( "classname", "", &s ); if ( Q_stricmp( s, S_WORLDSPAWN ) ) { G_Error( "SP_worldspawn: The first entry in the spawn string isn't of expected type '" S_WORLDSPAWN "'" ); } // make some data visible to connecting client trap_SetConfigstring( CS_GAME_VERSION, GAME_VERSION ); trap_SetConfigstring( CS_LEVEL_START_TIME, va( "%i", level.startTime ) ); G_SpawnString( "music", "", &s ); trap_SetConfigstring( CS_MUSIC, s ); G_SpawnString( "message", "", &s ); trap_SetConfigstring( CS_MESSAGE, s ); // map specific message if(G_SpawnString( "colorGrade", "", &s )) { trap_SetConfigstring( CS_GRADING_TEXTURES, va( "%i %f %s", -1, 0.0f, s ) ); } if(G_SpawnString( "gradingTexture", "", &s )) trap_SetConfigstring( CS_GRADING_TEXTURES, va( "%i %f %s", 0, 0.0f, s ) ); trap_SetConfigstring( CS_MOTD, g_motd.string ); // message of the day G_SpawnStringIntoCVarIfSet( "gravity", "g_gravity" ); G_SpawnStringIntoCVarIfSet( "humanMaxStage", "g_humanMaxStage" ); G_SpawnStringIntoCVarIfSet( "alienMaxStage", "g_alienMaxStage" ); G_SpawnStringIntoCVarIfSet( "humanBuildPoints", "g_humanBuildPoints" ); G_SpawnStringIntoCVarIfSet( "humanRepeaterBuildPoints", "g_humanRepeaterBuildPoints" ); G_SpawnStringIntoCVarIfSet( "alienBuildPoints", "g_alienBuildPoints" ); G_SpawnStringIntoCVar( "disabledEquipment", "g_disabledEquipment" ); G_SpawnStringIntoCVar( "disabledClasses", "g_disabledClasses" ); G_SpawnStringIntoCVar( "disabledBuildables", "g_disabledBuildables" ); g_entities[ ENTITYNUM_WORLD ].s.number = ENTITYNUM_WORLD; g_entities[ ENTITYNUM_WORLD ].r.ownerNum = ENTITYNUM_NONE; g_entities[ ENTITYNUM_WORLD ].classname = S_WORLDSPAWN; g_entities[ ENTITYNUM_NONE ].s.number = ENTITYNUM_NONE; g_entities[ ENTITYNUM_NONE ].r.ownerNum = ENTITYNUM_NONE; g_entities[ ENTITYNUM_NONE ].classname = "nothing"; // see if we want a warmup time trap_SetConfigstring( CS_WARMUP, "-1" ); if ( g_doWarmup.integer ) { level.warmupTime = level.time - level.startTime + ( g_warmup.integer * 1000 ); trap_SetConfigstring( CS_WARMUP, va( "%i", level.warmupTime ) ); G_LogPrintf( "Warmup: %i\n", g_warmup.integer ); } level.timelimit = g_timelimit.integer; }
/** * @brief SP_team_WOLF_checkpoint * @details QUAKED team_WOLF_checkpoint (.9 .3 .9) (-16 -16 0) (16 16 128) SPAWNPOINT CP_HOLD AXIS_ONLY ALLIED_ONLY * This is the flagpole players touch in Capture and Hold game scenarios. * * It will call specific trigger funtions in the map script for this object. * When allies capture, it will call "allied_capture". * When axis capture, it will call "axis_capture". * * if spawnpoint flag is set, think will turn on spawnpoints (specified as targets) * for capture team and turn *off* targeted spawnpoints for opposing team * * @param[in,out] ent */ void SP_team_WOLF_checkpoint(gentity_t *ent) { char *capture_sound; if (!ent->scriptName) { G_Error("team_WOLF_checkpoint must have a \"scriptname\"\n"); } // Make sure the ET_TRAP entity type stays valid ent->s.eType = ET_TRAP; // Model is user assignable, but it will always try and use the animations for flagpole.md3 if (ent->model) { ent->s.modelindex = G_ModelIndex(ent->model); } else { ent->s.modelindex = G_ModelIndex("models/multiplayer/flagpole/flagpole.md3"); } G_SpawnString("noise", "sound/movers/doors/door6_open.wav", &capture_sound); ent->soundPos1 = G_SoundIndex(capture_sound); ent->clipmask = CONTENTS_SOLID; ent->r.contents = CONTENTS_SOLID; VectorSet(ent->r.mins, -8, -8, 0); VectorSet(ent->r.maxs, 8, 8, 128); G_SetOrigin(ent, ent->s.origin); G_SetAngle(ent, ent->s.angles); // s.frame is the animation number ent->s.frame = WCP_ANIM_NOFLAG; // s.teamNum is which set of animations to use ( only 1 right now ) ent->s.teamNum = 1; // Used later to set animations (and delay between captures) ent->nextthink = 0; // Used to time how long it must be "held" to switch ent->health = -1; ent->count2 = -1; // 'count' signifies which team holds the checkpoint ent->count = -1; if (ent->spawnflags & SPAWNPOINT) { ent->touch = checkpoint_spawntouch; } else { if (ent->spawnflags & CP_HOLD) { ent->use = checkpoint_use; } else { ent->touch = checkpoint_touch; } } trap_LinkEntity(ent); }
/*QUAKED script_mover (0.5 0.25 1.0) ? TRIGGERSPAWN SOLID EXPLOSIVEDAMAGEONLY RESURECTABLE COMPASS ALLIED AXIS MOUNTED_GUN Scripted brush entity. A simplified means of moving brushes around based on events. "modelscale" - Scale multiplier (defaults to 1, and scales uniformly) "modelscale_vec" - Set scale per-axis. Overrides "modelscale", so if you have both the "modelscale" is ignored "model2" optional md3 to draw over the solid clip brush "scriptname" name used for scripting purposes (like aiName in AI scripting) "health" optionally make this entity damagable "description" used with health, if the entity is damagable, it draws a healthbar with this description above it. */ void SP_script_mover(gentity_t *ent) { float scale[3] = {1,1,1}; vec3_t scalevec; char tagname[MAX_QPATH]; char* modelname; char* tagent; char cs[MAX_INFO_STRING]; char* s; if (!ent->model) G_Error("script_mover must have a \"model\"\n" ); if (!ent->scriptName) G_Error("script_mover must have a \"scriptname\"\n" ); ent->blocked = script_mover_blocked; // first position at start VectorCopy( ent->s.origin, ent->pos1 ); // VectorCopy( ent->r.currentOrigin, ent->pos1 ); VectorCopy( ent->pos1, ent->pos2 ); // don't go anywhere just yet trap_SetBrushModel( ent, ent->model ); InitMover( ent ); ent->reached = NULL; ent->s.animMovetype = 0; ent->s.density = 0; if (ent->spawnflags & 256) { ent->s.density |= 2; } if (ent->spawnflags & 8) { ent->use = script_mover_use; } if (ent->spawnflags & 16) { ent->s.time2 = 1; } else { ent->s.time2 = 0; } if (ent->spawnflags & 32) { ent->s.teamNum = TEAM_ALLIES; } else if (ent->spawnflags & 64) { ent->s.teamNum = TEAM_AXIS; } else { ent->s.teamNum = TEAM_FREE; } if (ent->spawnflags & 1) { ent->use = script_mover_use; trap_UnlinkEntity(ent); // make sure it's not visible return; } G_SetAngle (ent, ent->s.angles); G_SpawnInt( "health", "0", &ent->health ); if(ent->health) { ent->takedamage = qtrue; ent->count = ent->health; // client needs to know about it as well ent->s.effect1Time = ent->count; ent->s.dl_intensity = 255; if( G_SpawnString( "description", "", &s ) ) { trap_GetConfigstring( CS_SCRIPT_MOVER_NAMES, cs, sizeof(cs) ); Info_SetValueForKey( cs, va("%i",ent-g_entities), s ); trap_SetConfigstring( CS_SCRIPT_MOVER_NAMES, cs ); } } else { ent->count = 0; } ent->die = script_mover_die; // look for general scaling if(G_SpawnFloat( "modelscale", "1", &scale[0])) { scale[2] = scale[1] = scale[0]; } if(G_SpawnString( "model2", "", &modelname ) ) { COM_StripExtension( modelname, tagname ); Q_strcat( tagname, MAX_QPATH, ".tag" ); ent->tagNumber = trap_LoadTag( tagname ); /* if( !(ent->tagNumber = trap_LoadTag( tagname )) ) { Com_Error( ERR_DROP, "Failed to load Tag File (%s)\n", tagname ); }*/ } // look for axis specific scaling if(G_SpawnVector("modelscale_vec", "1 1 1", &scalevec[0])) { VectorCopy(scalevec, scale); } if(scale[0] != 1 || scale[1] != 1 || scale[2] != 1) { ent->s.density |= 1; // scale is stored in 'angles2' VectorCopy(scale, ent->s.angles2); } if (ent->spawnflags & 128) { ent->s.density |= 4; ent->waterlevel = 0; if( G_SpawnString( "gun", "", &modelname ) ) { if( !Q_stricmp( modelname, "browning" ) ) { ent->s.density |= 8; } } G_SpawnString("tagent", "", &tagent); Q_strncpyz( ent->tagBuffer, tagent, 16 ); ent->s.powerups = -1; } ent->think = script_mover_spawn; ent->nextthink = level.time + FRAMETIME; }