
Team
Location, Taunt, and Miscellaneous
Not all of the maps have
"target_location" on them, which report where a player is. Here's how
you can spawn them in on maps when the weapons spawn. In g_spawn.c G_CallSpawn
// check item spawn functions for ( item=bg_itemlist+1 ; item->classname ; item++ ) { if ( !strcmp(item->classname, ent->classname) ) { // found it if( item->giType == IT_TEAM && g_gametype.integer != GT_CTF ) { return qfalse; } G_SpawnItem( ent, item );//freeze
Location_Spawn( ent );//freeze
return qtrue; } }
In g_freeze Location_Spawn
void SP_target_location( gentity_t *self );
void Location_Spawn( gentity_t *it_ent ) {gentity_t *ent;
int i;
if ( !it_ent->classname ) { return; } if ( !( it_ent->item && it_ent->item->pickup_name ) ) { return; } for ( i = 0; nearbyitems[ i ]; i++ ) { if ( Q_stricmp( it_ent->classname, nearbyitems[ i ] ) ) { continue; } ent = G_Spawn(); ent->classname = "target_location"; ent->message = it_ent->item->pickup_name;// This is important for later
ent->count = -1; VectorCopy( it_ent->r.currentOrigin, ent->s.origin ); SP_target_location( ent ); break; }}
This runs through a list
of items to see if we want to generate a "target_location" at that
spot. We make the team location message be that item's pickup name. Here's our
list
char *nearbyitems[] = { "item_armor_combat", "item_armor_body", "item_health_mega", "weapon_shotgun", "weapon_grenadelauncher", "weapon_rocketlauncher", "weapon_lightning", "weapon_railgun", "weapon_plasmagun", "weapon_bfg", "holdable_medkit", "item_quad", "item_enviro", "item_haste", "item_invis", "item_regen", "item_flight", "team_CTF_redflag", "team_CTF_blueflag", NULL};
Now, I want to make sure
these aren't made on a map that already has location spots. In g_target.c
target_location_linkup
int n;//freeze
qboolean locationLinked = qfalse;
//freeze
if (level.locationLinked) return;//freeze
for ( i = 0, ent = g_entities; i < level.num_entities; i++, ent++ ) { if ( ent->classname && !Q_stricmp( ent->classname, "target_location" ) ) {// Do we have one that wasn't "made" by my Location_Spawn?
if ( ent->count != -1 ) { locationLinked = qtrue; break; } } }//freeze
level.locationLinked = qtrue; level.locationHead = NULL; trap_SetConfigstring( CS_LOCATIONS, "unknown" ); for (i = 0, ent = g_entities, n = 1; i < level.num_entities; i++, ent++) { if (ent->classname && !Q_stricmp(ent->classname, "target_location")) {//freeze
if ( ent->count == -1 ) {// This will remove the item if we don't need it
if ( locationLinked ) { ent->think = G_FreeEntity; ent->nextthink = level.time + FRAMETIME; continue; } ent->count = 0; }//freeze
// lets overload some variables! ent->health = n; // use for location marking trap_SetConfigstring( CS_LOCATIONS + n, ent->message );
Note that function is only
run once. In g_team.c Team_GetLocation we make sure if you're frozen and flying
around, it reports where you died, not where you are. This fixes the team
overlay and when you speak to your team.
for (eloc = level.locationHead; eloc; eloc = eloc->nextTrain) { len = ( origin[0] - eloc->r.currentOrigin[0] ) * ( origin[0] - eloc->r.currentOrigin[0] ) + ( origin[1] - eloc->r.currentOrigin[1] ) * ( origin[1] - eloc->r.currentOrigin[1] ) + ( origin[2] - eloc->r.currentOrigin[2] ) * ( origin[2] - eloc->r.currentOrigin[2] );//freeze
if ( IsFrozen( ent ) ) { if ( eloc->health == ent->client->pers.teamState.location ) { return eloc; } }//freeze
if ( len > bestlen ) { continue; }
To have the player be able
to taunt we make it so if they taunt while near a frozen body, that frozen body
will make a taunt sound. First, in g_active.c ClientThink_real
// Let go of the hook if we aren't firing if ( client->ps.weapon == WP_GRAPPLING_HOOK && client->hook && !( ucmd->buttons & BUTTON_ATTACK ) ) { Weapon_HookFree(client->hook); }//freeze
if ( ucmd->buttons & BUTTON_GESTURE ) { FreezeAnimate( ent ); }//freeze
// set up for pmove oldEventSequence = client->ps.eventSequence;
And then in g_freeze
FreezeAnimate
void FreezeAnimate( gentity_t *ent ) {int i;
gentity_t *e;
vec3_t delta;
// Don't allow them to taunt all the time
// Using this fly_sound_debounce_time for my own whim
if ( ent->fly_sound_debounce_time > level.time ) { return; } if ( !IsFrozen( ent ) ) { return; }// Search all entities
for ( i = 0, e = g_entities; i < level.num_entities; i++, e++ ) { if ( !IsBody( e ) ) { continue; }// Is the body on our team?
if ( e->splashDamage != ent->client->sess.sessionTeam ) { continue; } VectorSubtract( e->s.pos.trBase, ent->s.pos.trBase, delta );// Are we close enough?
if ( VectorLength( delta ) > 192 ) { continue; }// Make that body make a noise
G_AddEvent( e, EV_TAUNT, e->r.ownerNum ); ent->fly_sound_debounce_time = level.time + ( 34 * 66 + 50 ); break; }}
We are using ownerNum as
an eventParm. In cg_event.c CG_EntityEvent
case EV_TAUNT: DEBUGNAME("EV_TAUNT");/*freeze
trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*taunt.wav" ) );freeze*/
trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->eventParm ? es->eventParm : es->number, "*taunt.wav" ) );//freeze
break;
If we have an eventParm
then use it. I do this because the body entity doesn't have a
"number", so we pass the number of the entity that created it (which
we happened to remember in the body's ownerNum). This will allow CG_CustomSound
to create the right "*taunt.wav" for that body.
Now some miscellaneous stuff. Force the
server to always be in team deathmatch or CTF. In g_main.c G_RegisterCvars
// check some things/*freeze
if ( g_gametype.integer < 0 || g_gametype.integer >= GT_MAX_GAME_TYPE ) { G_Printf( "g_gametype %i is out of range, defaulting to 0\n", g_gametype.integer ); trap_Cvar_Set( "g_gametype", "0" ); }freeze*/
if ( g_gametype.integer < GT_TEAM || g_gametype.integer >= GT_MAX_GAME_TYPE ) { G_Printf( "g_gametype %i is out of range, defaulting to 3\n", g_gametype.integer ); trap_Cvar_Set( "g_gametype", "3" ); }//freeze
level.warmupModificationCount = g_warmup.modificationCount;
In CheckIntermissionExit,
let the maps rotate even if noone's playing.
// if nobody wants to go, clear timer/*freeze
if ( !ready ) {freeze*/
if ( !ready && notReady ) {//freeze
level.readyToExit = qfalse; return; }
In g_items.c
Pickup_Weapon, don't wait 30 seconds to respawn a weapon.
if (ent->item->giTag == WP_GRAPPLING_HOOK) other->client->ps.ammo[ent->item->giTag] = -1; // unlimited ammo/*freeze
// team deathmatch has slow weapon respawns if ( g_gametype.integer == GT_TEAM ) { return RESPAWN_TEAM_WEAPON; }freeze*/
return g_weaponRespawn.integer;
In cg_info.c
CG_DrawInformation, display "Freeze Tag" for the client when the
level loads.
case GT_TOURNAMENT: s = "Tournament"; break; case GT_TEAM:/*freeze
s = "Team Deathmatch";freeze*/
s = "Freeze Tag";//freeze
break; case GT_CTF:/*freeze
s = "Capture The Flag";freeze*/
s = "Freeze Tag CTF";//freeze
break; default: s = "Unknown Gametype"; break;
Hope this information has
helped you in designing your mod.