void SP_gametype_item ( gentity_t* ent ) { gitem_t *item = NULL; char *value; int team = -1; G_SpawnString("teamfilter", "", &value); G_SetOrigin( ent, ent->s.origin ); // If a team filter is set then override any team settings for the spawns if ( level.mTeamFilter[0] ) { if ( Q_stricmp ( level.mTeamFilter, "red") == 0 ) { team = TEAM_RED; } else if ( Q_stricmp ( level.mTeamFilter, "blue") == 0 ) { team = TEAM_BLUE; } } if (ent->targetname && ent->targetname[0]) { if (team != -1) { if (strstr(ent->targetname, "flag")) { if (team == TEAM_RED) { item = BG_FindItem("team_CTF_redflag"); } else { //blue item = BG_FindItem("team_CTF_blueflag"); } } } else if (strstr(ent->targetname, "red_flag")) { item = BG_FindItem("team_CTF_redflag"); } else if (strstr(ent->targetname, "blue_flag")) { item = BG_FindItem("team_CTF_blueflag"); } else { item = NULL; } if (item) { ent->targetname = NULL; ent->classname = item->classname; G_SpawnItem( ent, item ); } } }
/* ============== ClearRegisteredItems ============== */ void ClearRegisteredItems( void ) { memset( itemRegistered, 0, sizeof( itemRegistered ) ); // players always start with the base weapon RegisterItem( BG_FindItemForWeapon( WP_PISTOL ) ); RegisterItem( BG_FindItemForWeapon( WP_GAUNTLET ) ); RegisterItem( BG_FindItem("Bag 'O Money" ) ); RegisterItem( BG_FindItem("Hidden Stash" ) ); }
/*QUAKED worldspawn(0 0 0) ? sun_cameraflare 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); // (SA) FIXME: todo: sun shader set for worldspawn 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, ""); 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 if (g_gametype.integer != GT_SINGLE_PLAYER) { ammoTable[WP_VENOM].maxHeat *= 0.25; 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_FindItem("Thompson"); item->giAmmoIndex = WP_THOMPSON; item = BG_FindItem("Sten"); item->giAmmoIndex = WP_STEN; item = BG_FindItem("MP40"); item->giAmmoIndex = WP_MP40; } }
/* =========== TossPlayerGametypeItems Drop CTF flag and Harvester cubes =========== */ void TossPlayerGametypeItems(gentity_t *ent) { int j; gitem_t *item; gentity_t *drop; int angle = 0; // drop flags in CTF item = NULL; j = 0; if ( ent->player->ps.powerups[ PW_REDFLAG ] ) { item = BG_FindItemForPowerup( PW_REDFLAG ); j = PW_REDFLAG; } else if ( ent->player->ps.powerups[ PW_BLUEFLAG ] ) { item = BG_FindItemForPowerup( PW_BLUEFLAG ); j = PW_BLUEFLAG; } else if ( ent->player->ps.powerups[ PW_NEUTRALFLAG ] ) { item = BG_FindItemForPowerup( PW_NEUTRALFLAG ); j = PW_NEUTRALFLAG; } if ( item ) { drop = Drop_Item( ent, item, angle ); angle += 45; // decide how many seconds it has left drop->count = ( ent->player->ps.powerups[ j ] - level.time ) / 1000; if ( drop->count < 1 ) { drop->count = 1; } ent->player->ps.powerups[ j ] = 0; } #ifdef MISSIONPACK if ( g_gametype.integer == GT_HARVESTER ) { if ( ent->player->ps.tokens > 0 ) { if ( ent->player->sess.sessionTeam == TEAM_RED ) { item = BG_FindItem( "Blue Cube" ); } else { item = BG_FindItem( "Red Cube" ); } if ( item ) { for ( j = 0; j < ent->player->ps.tokens; j++ ) { drop = Drop_Item( ent, item, angle ); if ( ent->player->sess.sessionTeam == TEAM_RED ) { drop->s.team = TEAM_BLUE; } else { drop->s.team = TEAM_RED; } angle += 45; } } ent->player->ps.tokens = 0; } } #endif }
/* ================== G_CheckTeamItems ================== */ void G_CheckTeamItems(void) { // Set up team stuff Team_InitGame(); if (g_gametype.integer == GT_CTF) { gitem_t *item; gentity_t *flag, *ent; // check for the two flags item = BG_FindItem("Silver Case"); if (!item || !itemRegistered[item - bg_itemlist]) { G_Printf(S_COLOR_YELLOW "WARNING: No team_CTF_redflag in map\n"); } item = BG_FindItem("Black Case"); if (!item || !itemRegistered[item - bg_itemlist]) { G_Printf(S_COLOR_YELLOW "WARNING: No team_CTF_blueflag in map\n"); } // NiceAss: Find the red flag flag = NULL; while ((flag = G_Find(flag, FOFS(classname), "team_CTF_redflag")) != NULL) { if (!(flag->flags & FL_DROPPED_ITEM)) break; } if (flag) { // Red team decal X ent = G_Spawn(); ent->classname = "Decal"; ent->s.eType = ET_DECAL; ent->s.pos.trType = TR_STATIONARY; ent->s.modelindex = TEAM_RED; G_SetOrigin(ent, flag->s.origin); trap_LinkEntity(ent); } // NiceAss: Find the blue flag flag = NULL; while ((flag = G_Find(flag, FOFS(classname), "team_CTF_blueflag")) != NULL) { if (!(flag->flags & FL_DROPPED_ITEM)) break; } if (flag) { // Red team decal X ent = G_Spawn(); ent->classname = "Decal"; ent->s.eType = ET_DECAL; ent->s.pos.trType = TR_STATIONARY; ent->s.modelindex = TEAM_BLUE; G_SetOrigin(ent, flag->s.origin); trap_LinkEntity(ent); } } }
/* ============== ClearRegisteredItems ============== */ void ClearRegisteredItems( void ) { memset( itemRegistered, 0, sizeof( itemRegistered ) ); // !TODO: Have map determine the base weapons: // players always start with the base weapon RegisterItem( BG_FindItemForWeapon( WP_MACHINEGUN ) ); RegisterItem( BG_FindItemForWeapon( WP_GAUNTLET ) ); if( g_gametype.integer == GT_HARVESTER ) { RegisterItem( BG_FindItem( "Red Cube" ) ); RegisterItem( BG_FindItem( "Blue Cube" ) ); } }
/* ============== ClearRegisteredItems ============== */ void ClearRegisteredItems( void ) { memset( itemRegistered, 0, sizeof( itemRegistered ) ); // players always start with the base weapon RegisterItem( BG_FindItemForWeapon( WP_MACHINEGUN ) ); RegisterItem( BG_FindItemForWeapon( WP_GAUNTLET ) ); #ifdef MISSIONPACK if( g_gametype.integer == GT_HARVESTER ) { RegisterItem( BG_FindItem( "Red Cube" ) ); RegisterItem( BG_FindItem( "Blue Cube" ) ); } #endif }
void TossClientCubes(gentity_t * self) { gitem_t *item; gentity_t *drop; vec3_t velocity; vec3_t angles; vec3_t origin; self->client->ps.generic1 = 0; // this should never happen but we should never // get the server to crash due to skull being spawned in if(!G_EntitiesFree()) { return; } if(self->client->sess.sessionTeam == TEAM_RED) { item = BG_FindItem("Red Cube"); } else { item = BG_FindItem("Blue Cube"); } angles[YAW] = (float)(level.time % 360); angles[PITCH] = 0; // always forward angles[ROLL] = 0; AngleVectors(angles, velocity, NULL, NULL); VectorScale(velocity, 150, velocity); velocity[2] += 200 + crandom() * 50; if(neutralObelisk) { VectorCopy(neutralObelisk->s.pos.trBase, origin); origin[2] += 44; } else { VectorClear(origin); } drop = LaunchItem(item, origin, velocity); drop->nextthink = level.time + g_cubeTimeout.integer * 1000; drop->think = G_FreeEntity; drop->spawnflags = self->client->sess.sessionTeam; }
/* ================== G_CheckTeamItems ================== */ void G_CheckTeamItems( void ) { if ( g_gametype.integer == GT_CTF ) { gitem_t *item; // make sure we actually have two flags... item = BG_FindItem( "Red Flag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { G_Error( "No team_CTF_redflag in map" ); } item = BG_FindItem( "Blue Flag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { G_Error( "No team_CTF_blueflag in map" ); } } }
void DropPortalDestination( gentity_t *player ) { gentity_t *ent; vec3_t snapped; // create the portal destination ent = G_Spawn(); ent->s.modelindex = G_ModelIndex( "models/powerups/teleporter/tele_exit.md3" ); VectorCopy( player->s.pos.trBase, snapped ); SnapVector( snapped ); G_SetOrigin( ent, snapped ); VectorCopy( player->r.mins, ent->r.mins ); VectorCopy( player->r.maxs, ent->r.maxs ); ent->classname = "hi_portal destination"; ent->s.pos.trType = TR_STATIONARY; ent->r.contents = CONTENTS_CORPSE; ent->takedamage = qtrue; ent->health = 200; ent->die = PortalDie; VectorCopy( player->s.apos.trBase, ent->s.angles ); ent->think = G_FreeEntity; ent->nextthink = level.time + 2 * 60 * 1000; trap_LinkEntity( ent ); player->client->portalID = ++level.portalSequence; ent->count = player->client->portalID; // give the item back so they can drop the source now player->client->ps.stats[STAT_HOLDABLE_ITEM] = BG_FindItem( "Portal" ) - bg_itemlist; }
Gametype_inf::Gametype_inf() { // Register the items // Boe!Man 11/29/12: Register items per gametype. gitem_t *item = BG_FindItem("briefcase"); if (item){ item->quantity = ITEM_BRIEFCASE; } // Boe!Man 11/29/12: Register triggers per gametype. gentity_t *find = NULL; while (NULL != (find = G_Find(find, FOFS(classname), "gametype_trigger"))) { if (strcmp(find->targetname, (const char*) "briefcase_destination")) { continue; } // Assign the id to it. find->health = TRIGGER_EXTRACTION; find->touch = gametype_trigger_touch; trap_LinkEntity(find); } caseTakenSound = G_SoundIndex("sound/ctf_flag.mp3"); caseCaptureSound = G_SoundIndex("sound/ctf_win.mp3"); caseReturnSound = G_SoundIndex("sound/ctf_return.mp3"); }
/* ============== ClearRegisteredItems ============== */ void ClearRegisteredItems() { #pragma message("this should probably be removed!") memset( itemRegistered, 0, sizeof( itemRegistered ) ); // Always load health/ammo/fuel pickups RegisterItem( BG_FindItem( "5 Health" ) ); RegisterItem( BG_FindItem( "25 Health" ) ); RegisterItem( BG_FindItem( "50 Health" ) ); RegisterItem( BG_FindItem( "Some Fuel" ) ); RegisterItem( BG_FindItem( "More Fuel" ) ); RegisterItem( BG_FindItem( "Shells" ) ); RegisterItem( BG_FindItem( "Bullets" ) ); RegisterItem( BG_FindItem( "Slugs" ) ); RegisterItem( BG_FindItem( "Rockets" ) ); }
/* ================== G_CheckTeamItems ================== */ void G_CheckTeamItems( void ) { // Set up team stuff Team_InitGame(); if( g_gametype.integer == GT_CTF ) { gitem_t *item; // check for the two flags item = BG_FindItem( "red Lolly" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { G_Printf( S_COLOR_YELLOW "WARNING: No team_CTL_redlolly in map" ); } item = BG_FindItem( "blue Lolly" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { G_Printf( S_COLOR_YELLOW "WARNING: No team_CTL_bluelolly in map" ); } } }
/* ================== G_CheckTeamItems ================== */ void G_CheckTeamItems( void ) { // Set up team stuff Team_InitGame(); if ( g_gametype.integer == GT_CTF ) { gitem_t *item; // make sure we actually have two flags... item = BG_FindItem( "team_CTF_redflag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { G_Printf( "^1WARNING: No team_CTF_redflag in map" ); } item = BG_FindItem( "team_CTF_blueflag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { G_Printf( "^1WARNING: No team_CTF_blueflag in map" ); } } }
/* =============== G_ParseGametypeItems =============== */ bool G_ParseGametypeItems ( TGPGroup* itemsGroup ) { TGPGroup itemGroup; int itemCount; char temp[MAX_QPATH]; gentity_t *ent; // Handle NULL for convienience if ( !itemsGroup ) { return false; } // Loop over all the items and add each itemGroup = trap_GPG_GetSubGroups ( itemsGroup ); itemCount = 0; while ( itemGroup ) { gitem_t* item; // Parse out the pickup name trap_GPG_GetName ( itemGroup, temp ); item = BG_FindItem ( temp ); if ( !item ) { item = &bg_itemlist[ MODELINDEX_GAMETYPE_ITEM + itemCount ]; item->pickup_name = (char *)trap_VM_LocalStringAlloc ( temp ); itemCount++; } // Handle the entity specific stuff by finding all matching items that // were spawned. ent = NULL; while ( NULL != (ent = G_Find ( ent, FOFS(targetname), item->pickup_name ) ) ) { // If not a gametype item then skip it if ( strcmp ( ent->classname, "gametype_item" ) ) { continue; } // Setup the gametype data ent->item = item; ent->nextthink = level.time + 200; ent->think = G_GametypeItemThink; } // Next sub group itemGroup = trap_GPG_GetNext(itemGroup); } return true; }
/* ============== ClearRegisteredItems ============== */ void ClearRegisteredItems( void ) { memset( itemRegistered, 0, sizeof( itemRegistered ) ); // players always start with the base weapon // (SA) Nope, not any more... //----(SA) this will be determined by the level or starting position, or the savegame // but for now, re-register the MP40 automatically // RegisterItem( BG_FindItemForWeapon( WP_MP40 ) ); RegisterItem( BG_FindItem( "Med Health" ) ); // NERVE - SMF - this is so med packs properly display }
/* ================== G_CheckTeamItems ================== */ void G_CheckTeamItems() { // Set up team stuff Team_InitGame(); if( g_gametype.integer == GT_CTF ) { gitem_t *item; // check for the two flags item = BG_FindItem( "Red Flag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { Com_Printf( S_COLOR_YELLOW "WARNING: No team_CTF_redflag in map" ); } item = BG_FindItem( "Blue Flag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { Com_Printf( S_COLOR_YELLOW "WARNING: No team_CTF_blueflag in map" ); } } }
void ammo_touch( gentity_t *self, gentity_t *other, trace_t *trace ) { int i, clientcount = 0, count; gentity_t* touchClients[MAX_CLIENTS]; memset(touchClients, 0, sizeof(touchClients)); if( other->client == NULL ) { return; } // flags is for the last entity number that got ammo if ( self->timestamp > level.time ) { return; } self->timestamp = level.time + 1000; for( i = 0; i < level.numConnectedClients; i++ ) { int j = level.sortedClients[i]; if( trap_EntityContactCapsule( g_entities[j].r.absmin, g_entities[j].r.absmax, self ) && G_IsAllowedAmmo( &g_entities[j] ) ) { touchClients[clientcount] = &g_entities[j]; clientcount++; } } if(clientcount == 0) { return; } // Gordon: if low, just give out what's left if(self->health == -9999) { count = clientcount; } else { count = min(clientcount, self->health / (float)self->damage ); } for( i = 0; i < count; i++) { int ammoAdded = qfalse; // self->damage contains the amount of ammo to add ammoAdded = AddMagicAmmo(touchClients[i], self->damage); if (ammoAdded) { // add the ammo pack event (to get sound, etc.) G_AddPredictableEvent( touchClients[i], EV_ITEM_PICKUP, BG_FindItem("Ammo Pack")-bg_itemlist ); if (self->health != -9999) { // reduce the ammount of available ammo by the added clip number self->health -= self->damage; // G_Printf("%i clips left\n", self->health ); } } } }
void G_CheckTeamItems( void ) { // Set up team stuff Team_InitGame(); if( level.gametype == GT_FLAGS ) { const gitem_t *item; // check for the two flags item = BG_FindItem( "team_redflag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { trap->Print( S_COLOR_YELLOW "WARNING: No team_redflag in map\n" ); } item = BG_FindItem( "team_blueflag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { trap->Print( S_COLOR_YELLOW "WARNING: No team_blueflag in map\n" ); } } if( level.gametype == GT_TROJAN ) { const gitem_t *item; // check for all three flags item = BG_FindItem( "team_redflag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { trap->Print( S_COLOR_YELLOW "WARNING: No team_redflag in map\n" ); } item = BG_FindItem( "team_blueflag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { trap->Print( S_COLOR_YELLOW "WARNING: No team_blueflag in map\n" ); } item = BG_FindItem( "team_neutralflag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { trap->Print( S_COLOR_YELLOW "WARNING: No team_neutralflag in map\n" ); } } }
/* ================== Cmd_Give_f Give items to a client ================== */ void Cmd_Give_f (gentity_t *ent) { char *name; gitem_t *it; int i; qboolean give_all; gentity_t *it_ent; trace_t trace; if ( !CheatsOk( ent ) ) { return; } name = ConcatArgs( 1 ); if (Q_stricmp(name, "all") == 0) give_all = qtrue; else give_all = qfalse; if (give_all || Q_stricmp( name, "health") == 0) { ent->health = ent->client->ps.stats[STAT_MAX_HEALTH]; if (!give_all) return; } if (give_all || Q_stricmp(name, "weapons") == 0) { ent->client->ps.stats[STAT_WEAPONS] = (1 << WP_NUM_WEAPONS) - 1 - ( 1 << WP_GRAPPLING_HOOK ) - ( 1 << WP_NONE ); if (!give_all) return; } if (give_all || Q_stricmp(name, "ammo") == 0) { for ( i = 0 ; i < MAX_WEAPONS ; i++ ) { ent->client->ps.ammo[i] = 999; } if (!give_all) return; } if (give_all || Q_stricmp(name, "armor") == 0) { ent->client->ps.stats[STAT_ARMOR] = 200; if (!give_all) return; } if (Q_stricmp(name, "excellent") == 0) { ent->client->ps.persistant[PERS_EXCELLENT_COUNT]++; return; } if (Q_stricmp(name, "impressive") == 0) { ent->client->ps.persistant[PERS_IMPRESSIVE_COUNT]++; return; } if (Q_stricmp(name, "gauntletaward") == 0) { ent->client->ps.persistant[PERS_GAUNTLET_FRAG_COUNT]++; return; } if (Q_stricmp(name, "defend") == 0) { ent->client->ps.persistant[PERS_DEFEND_COUNT]++; return; } if (Q_stricmp(name, "assist") == 0) { ent->client->ps.persistant[PERS_ASSIST_COUNT]++; return; } // spawn a specific item right on the player if ( !give_all ) { it = BG_FindItem (name); if (!it) { return; } it_ent = G_Spawn(); VectorCopy( ent->r.currentOrigin, it_ent->s.origin ); it_ent->classname = it->classname; G_SpawnItem (it_ent, it); FinishSpawningItem(it_ent ); memset( &trace, 0, sizeof( trace ) ); Touch_Item (it_ent, ent, &trace); if (it_ent->inuse) { G_FreeEntity( it_ent ); } } }
/* ================== G_CheckTeamItems ================== */ void G_CheckTeamItems( void ) { // Set up team stuff Team_InitGame(); if( g_gametype.integer == GT_CTF ) { gitem_t *item; // check for the two flags item = BG_FindItem( "Red Flag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { G_Printf( S_COLOR_YELLOW "WARNING: No team_CTF_redflag in map" ); } item = BG_FindItem( "Blue Flag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { G_Printf( S_COLOR_YELLOW "WARNING: No team_CTF_blueflag in map" ); } } #ifdef MISSIONPACK if( g_gametype.integer == GT_1FCTF ) { gitem_t *item; // check for all three flags item = BG_FindItem( "Red Flag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { G_Printf( S_COLOR_YELLOW "WARNING: No team_CTF_redflag in map" ); } item = BG_FindItem( "Blue Flag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { G_Printf( S_COLOR_YELLOW "WARNING: No team_CTF_blueflag in map" ); } item = BG_FindItem( "Neutral Flag" ); if ( !item || !itemRegistered[ item - bg_itemlist ] ) { G_Printf( S_COLOR_YELLOW "WARNING: No team_CTF_neutralflag in map" ); } } if( g_gametype.integer == GT_OBELISK ) { gentity_t *ent; // check for the two obelisks ent = NULL; ent = G_Find( ent, FOFS(classname), "team_redobelisk" ); if( !ent ) { G_Printf( S_COLOR_YELLOW "WARNING: No team_redobelisk in map" ); } ent = NULL; ent = G_Find( ent, FOFS(classname), "team_blueobelisk" ); if( !ent ) { G_Printf( S_COLOR_YELLOW "WARNING: No team_blueobelisk in map" ); } } if( g_gametype.integer == GT_HARVESTER ) { gentity_t *ent; // check for all three obelisks ent = NULL; ent = G_Find( ent, FOFS(classname), "team_redobelisk" ); if( !ent ) { G_Printf( S_COLOR_YELLOW "WARNING: No team_redobelisk in map" ); } ent = NULL; ent = G_Find( ent, FOFS(classname), "team_blueobelisk" ); if( !ent ) { G_Printf( S_COLOR_YELLOW "WARNING: No team_blueobelisk in map" ); } ent = NULL; ent = G_Find( ent, FOFS(classname), "team_neutralobelisk" ); if( !ent ) { G_Printf( S_COLOR_YELLOW "WARNING: No team_neutralobelisk in map" ); } } #endif }
/* =========== ClientDisconnect Called when a player drops from the server. Will not be called between levels. This should NOT be called directly by any game logic, call trap_DropClient(), which will call this and do server system housekeeping. ============ */ void ClientDisconnect(int clientNum) { gentity_t *ent; gentity_t *flag = NULL; gitem_t *item = NULL; vec3_t launchvel; int i; ent = g_entities + clientNum; if (!ent->client) { return; } G_RemoveClientFromFireteams(clientNum, qtrue, qfalse); G_RemoveFromAllIgnoreLists(clientNum); G_LeaveTank(ent, qfalse); // Nico, remove the client from all specInvited lists for (i = 0; i < level.numConnectedClients; ++i) { COM_BitClear(level.clients[level.sortedClients[i]].sess.specInvitedClients, clientNum); } // stop any following clients for (i = 0 ; i < level.numConnectedClients ; i++) { flag = g_entities + level.sortedClients[i]; if (flag->client->sess.sessionTeam == TEAM_SPECTATOR && flag->client->sess.spectatorState == SPECTATOR_FOLLOW && flag->client->sess.spectatorClient == clientNum) { StopFollowing(flag); } if (flag->client->ps.pm_flags & PMF_LIMBO && flag->client->sess.spectatorClient == clientNum) { Cmd_FollowCycle_f(flag, 1); } } G_FadeItems(ent, MOD_SATCHEL); // remove ourself from teamlists { mapEntityData_t *mEnt; mapEntityData_Team_t *teamList; for (i = 0; i < 2; i++) { teamList = &mapEntityData[i]; if ((mEnt = G_FindMapEntityData(&mapEntityData[0], ent - g_entities)) != NULL) { G_FreeMapEntityData(teamList, mEnt); } mEnt = G_FindMapEntityDataSingleClient(teamList, NULL, ent->s.number, -1); while (mEnt) { mapEntityData_t *mEntFree = mEnt; mEnt = G_FindMapEntityDataSingleClient(teamList, mEnt, ent->s.number, -1); G_FreeMapEntityData(teamList, mEntFree); } } } // send effect if they were completely connected if (ent->client->pers.connected == CON_CONNECTED && ent->client->sess.sessionTeam != TEAM_SPECTATOR && !(ent->client->ps.pm_flags & PMF_LIMBO)) { // They don't get to take powerups with them! // Especially important for stuff like CTF flags // New code for tossing flags if (ent->client->ps.powerups[PW_REDFLAG]) { item = BG_FindItem("Red Flag"); if (!item) { item = BG_FindItem("Objective"); } ent->client->ps.powerups[PW_REDFLAG] = 0; } if (ent->client->ps.powerups[PW_BLUEFLAG]) { item = BG_FindItem("Blue Flag"); if (!item) { item = BG_FindItem("Objective"); } ent->client->ps.powerups[PW_BLUEFLAG] = 0; } if (item) { // OSP - fix for suicide drop exploit through walls/gates launchvel[0] = 0; //crandom()*20; launchvel[1] = 0; //crandom()*20; launchvel[2] = 0; //10+random()*10; flag = LaunchItem(item, ent->r.currentOrigin, launchvel, ent - g_entities); flag->s.modelindex2 = ent->s.otherEntityNum2; // JPW NERVE FIXME set player->otherentitynum2 with old modelindex2 from flag and restore here flag->message = ent->message; // DHM - Nerve :: also restore item name // Clear out player's temp copies ent->s.otherEntityNum2 = 0; ent->message = NULL; } } G_LogPrintf("ClientDisconnect: %i\n", clientNum); trap_UnlinkEntity(ent); ent->s.modelindex = 0; ent->inuse = qfalse; ent->classname = "disconnected"; ent->client->pers.connected = CON_DISCONNECTED; ent->client->ps.persistant[PERS_TEAM] = TEAM_FREE; i = ent->client->sess.sessionTeam; ent->client->sess.sessionTeam = TEAM_FREE; ent->active = 0; trap_SetConfigstring(CS_PLAYERS + clientNum, ""); CalculateRanks(); }
/* ============ G_SpawnItem Sets the clipping size and plants the object on the floor. Items can't be immediately dropped to floor, because they might be on an entity that hasn't spawned yet. ============ */ void G_SpawnItem(gentity_t *ent, gitem_t *item) { char *MinHealth = "1"; qboolean Egg = qfalse; G_SpawnFloat("random", "0", &ent->random); G_SpawnFloat("wait", "0", &ent->wait); if (item->giType == IT_TEAM) { if (g_gametype.integer == GT_INVASION || g_gametype.integer == GT_DESTROY) { if (!Q_stricmp(item->pickup_name, "Blue Flag")) { gitem_t *NewItem = BG_FindItem("Alien Egg"); if (NewItem) { item = NewItem; MinHealth = "60";//2500; Egg = qtrue; } ent->classname = item->classname; } else if (!Q_stricmp(item->pickup_name, "Red Flag")) { gitem_t *NewItem = BG_FindItem("Teleporter"); if (NewItem) item = NewItem; ent->classname = item->classname; } else if (!Q_stricmp(item->pickup_name, "Alien Egg")) Egg = qtrue; } RegisterItem(item); } if (G_ItemDisabled(item)) return; if (Egg && g_gametype.integer == GT_DESTROY) { float Coeff, Radius; G_SpawnFloat("health", MinHealth, &Coeff); if (Coeff < 0.1f) Coeff = 0.1f; ent->health = Coeff * g_InvEggHealth.integer; if (ent->health < 1)//MinHealth) ent->health = 1;//MinHealth; else if (ent->health > 25000) ent->health = 25000; G_SpawnFloat("Radius", "6", &Radius); G_SpawnFloat("Height", "24", &Coeff); Radius = Com_Clamp(3, 50, Radius); Coeff = Com_Clamp(3, 200, Coeff); VectorSet(ent->r.mins, -Radius, -Radius, 0); VectorSet(ent->r.maxs, Radius, Radius, Coeff); G_SpawnInt("Number", "100", &ent->count); if (ent->count < 0) ent->count = 0; } ent->item = item; // some movers spawn on the second frame, so delay item // spawns until the third frame so they can ride trains ent->nextthink = level.time + FRAMETIME * 2; ent->think = FinishSpawningItem; ent->physicsBounce = 0.50; // items are bouncy if (item->giType == IT_POWERUP) { G_SoundIndex("sound/items/poweruprespawn.wav"); G_SpawnFloat("noglobalsound", "0", &ent->speed); } #ifdef MISSIONPACK if (item->giType == IT_PERSISTANT_POWERUP) { ent->s.generic1 = ent->spawnflags; } #endif }
void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath ) { int contents = 0, i, killer = ENTITYNUM_WORLD; char *killerName = "<world>"; qboolean nogib = qtrue; gitem_t *item = NULL; gentity_t *ent; qboolean killedintank = qfalse; //float timeLived; weapon_t weap = BG_WeaponForMOD( meansOfDeath ); // G_Printf( "player_die\n" ); if(attacker == self) { if(self->client) { self->client->pers.playerStats.suicides++; trap_PbStat ( self - g_entities , "suicide" , va ( "%d %d %d" , self->client->sess.sessionTeam , self->client->sess.playerType , weap ) ) ; } } else if(OnSameTeam( self, attacker )) { G_LogTeamKill( attacker, weap ); } else { G_LogDeath( self, weap ); G_LogKill( attacker, weap ); if( g_gamestate.integer == GS_PLAYING ) { if( attacker->client ) { attacker->client->combatState |= (1<<COMBATSTATE_KILLEDPLAYER); } } } // RF, record this death in AAS system so that bots avoid areas which have high death rates if( !OnSameTeam( self, attacker ) ) { // LC - not needed // BotRecordTeamDeath( self->s.number ); self->isProp = qfalse; // were we teamkilled or not? } else { self->isProp = qtrue; } // if we got killed by a landmine, update our map if( self->client && meansOfDeath == MOD_LANDMINE ) { // if it's an enemy mine, update both teamlists /*int teamNum; mapEntityData_t *mEnt; mapEntityData_Team_t *teamList; teamNum = inflictor->s.teamNum % 4; teamList = self->client->sess.sessionTeam == TEAM_AXIS ? &mapEntityData[0] : &mapEntityData[1]; if((mEnt = G_FindMapEntityData(teamList, inflictor-g_entities)) != NULL) { G_FreeMapEntityData( teamList, mEnt ); } if( teamNum != self->client->sess.sessionTeam ) { teamList = self->client->sess.sessionTeam == TEAM_AXIS ? &mapEntityData[1] : &mapEntityData[0]; if((mEnt = G_FindMapEntityData(teamList, inflictor-g_entities)) != NULL) { G_FreeMapEntityData( teamList, mEnt ); } }*/ mapEntityData_t *mEnt; if((mEnt = G_FindMapEntityData(&mapEntityData[0], inflictor-g_entities)) != NULL) { G_FreeMapEntityData( &mapEntityData[0], mEnt ); } if((mEnt = G_FindMapEntityData(&mapEntityData[1], inflictor-g_entities)) != NULL) { G_FreeMapEntityData( &mapEntityData[1], mEnt ); } } { mapEntityData_t *mEnt; mapEntityData_Team_t *teamList = self->client->sess.sessionTeam == TEAM_AXIS ? &mapEntityData[1] : &mapEntityData[0]; // swapped, cause enemy team mEnt = G_FindMapEntityDataSingleClient( teamList, NULL, self->s.number, -1 ); while( mEnt ) { if( mEnt->type == ME_PLAYER_DISGUISED ) { mapEntityData_t* mEntFree = mEnt; mEnt = G_FindMapEntityDataSingleClient( teamList, mEnt, self->s.number, -1 ); G_FreeMapEntityData( teamList, mEntFree ); } else { mEnt = G_FindMapEntityDataSingleClient( teamList, mEnt, self->s.number, -1 ); } } } if( self->tankLink ) { G_LeaveTank( self, qfalse ); killedintank = qtrue; } if( self->client->ps.pm_type == PM_DEAD || g_gamestate.integer == GS_INTERMISSION ) { return; } // OSP - death stats handled out-of-band of G_Damage for external calls G_addStats(self, attacker, damage, meansOfDeath); // OSP self->client->ps.pm_type = PM_DEAD; G_AddEvent( self, EV_STOPSTREAMINGSOUND, 0); if(attacker) { killer = attacker->s.number; killerName = (attacker->client) ? attacker->client->pers.netname : "<non-client>"; } if(attacker == 0 || killer < 0 || killer >= MAX_CLIENTS) { killer = ENTITYNUM_WORLD; killerName = "<world>"; } if(g_gamestate.integer == GS_PLAYING) { char *obit; if(meansOfDeath < 0 || meansOfDeath >= sizeof(modNames) / sizeof(modNames[0])) { obit = "<bad obituary>"; } else { obit = modNames[meansOfDeath]; } G_LogPrintf("Kill: %i %i %i: %s killed %s by %s\n", killer, self->s.number, meansOfDeath, killerName, self->client->pers.netname, obit ); } // broadcast the death event to everyone ent = G_TempEntity( self->r.currentOrigin, EV_OBITUARY ); ent->s.eventParm = meansOfDeath; ent->s.otherEntityNum = self->s.number; ent->s.otherEntityNum2 = killer; ent->r.svFlags = SVF_BROADCAST; // send to everyone self->enemy = attacker; self->client->ps.persistant[PERS_KILLED]++; // JPW NERVE -- if player is holding ticking grenade, drop it if ((self->client->ps.grenadeTimeLeft) && (self->s.weapon != WP_DYNAMITE) && (self->s.weapon != WP_LANDMINE) && (self->s.weapon != WP_SATCHEL) && (self->s.weapon != WP_TRIPMINE)) { vec3_t launchvel, launchspot; launchvel[0] = crandom(); launchvel[1] = crandom(); launchvel[2] = random(); VectorScale( launchvel, 160, launchvel ); VectorCopy(self->r.currentOrigin, launchspot); launchspot[2] += 40; { // Gordon: fixes premature grenade explosion, ta bani ;) gentity_t *m = fire_grenade(self, launchspot, launchvel, self->s.weapon); m->damage = 0; } } if (attacker && attacker->client) { if ( attacker == self || OnSameTeam (self, attacker ) ) { // DHM - Nerve :: Complaint lodging if( attacker != self && level.warmupTime <= 0 && g_gamestate.integer == GS_PLAYING) { if( attacker->client->pers.localClient ) { trap_SendServerCommand( self-g_entities, "complaint -4" ); } else { if( meansOfDeath != MOD_CRUSH_CONSTRUCTION && meansOfDeath != MOD_CRUSH_CONSTRUCTIONDEATH && meansOfDeath != MOD_CRUSH_CONSTRUCTIONDEATH_NOATTACKER ) { if( g_complaintlimit.integer ) { if( !(meansOfDeath == MOD_LANDMINE && g_disableComplaints.integer & TKFL_MINES ) && !((meansOfDeath == MOD_ARTY || meansOfDeath == MOD_AIRSTRIKE) && g_disableComplaints.integer & TKFL_AIRSTRIKE ) && !(meansOfDeath == MOD_MORTAR && g_disableComplaints.integer & TKFL_MORTAR ) ) { trap_SendServerCommand( self-g_entities, va( "complaint %i", attacker->s.number ) ); self->client->pers.complaintClient = attacker->s.clientNum; self->client->pers.complaintEndTime = level.time + 20500; } } } } } // high penalty to offset medic heal /* AddScore( attacker, WOLF_FRIENDLY_PENALTY ); */ if( g_gametype.integer == GT_WOLF_LMS ) { AddKillScore( attacker, WOLF_FRIENDLY_PENALTY ); } } else { //G_AddExperience( attacker, 1 ); // JPW NERVE -- mostly added as conveneience so we can tweak from the #defines all in one place AddScore(attacker, WOLF_FRAG_BONUS); if( g_gametype.integer == GT_WOLF_LMS ) { if( level.firstbloodTeam == -1 ) level.firstbloodTeam = attacker->client->sess.sessionTeam; AddKillScore( attacker, WOLF_FRAG_BONUS ); } attacker->client->lastKillTime = level.time; } } else { AddScore( self, -1 ); if( g_gametype.integer == GT_WOLF_LMS ) AddKillScore( self, -1 ); } // Add team bonuses Team_FragBonuses(self, inflictor, attacker); // drop flag regardless if (self->client->ps.powerups[PW_REDFLAG]) { item = BG_FindItem("Red Flag"); if (!item) item = BG_FindItem("Objective"); self->client->ps.powerups[PW_REDFLAG] = 0; } if (self->client->ps.powerups[PW_BLUEFLAG]) { item = BG_FindItem("Blue Flag"); if (!item) item = BG_FindItem("Objective"); self->client->ps.powerups[PW_BLUEFLAG] = 0; } if (item) { vec3_t launchvel = { 0, 0, 0 }; gentity_t *flag = LaunchItem(item, self->r.currentOrigin, launchvel, self->s.number); flag->s.modelindex2 = self->s.otherEntityNum2;// JPW NERVE FIXME set player->otherentitynum2 with old modelindex2 from flag and restore here flag->message = self->message; // DHM - Nerve :: also restore item name // Clear out player's temp copies self->s.otherEntityNum2 = 0; self->message = NULL; } // send a fancy "MEDIC!" scream. Sissies, ain' they? if (self->client != NULL) { if( self->health > GIB_HEALTH && meansOfDeath != MOD_SUICIDE && meansOfDeath != MOD_SWITCHTEAM ) { G_AddEvent( self, EV_MEDIC_CALL, 0 ); } } Cmd_Score_f( self ); // show scores // send updated scores to any clients that are following this one, // or they would get stale scoreboards for(i=0; i<level.numConnectedClients; i++) { gclient_t *client = &level.clients[level.sortedClients[i]]; if(client->pers.connected != CON_CONNECTED) continue; if(client->sess.sessionTeam != TEAM_SPECTATOR) continue; if(client->sess.spectatorClient == self->s.number) { Cmd_Score_f(g_entities + level.sortedClients[i]); } } self->takedamage = qtrue; // can still be gibbed self->r.contents = CONTENTS_CORPSE; //self->s.angles[2] = 0; self->s.powerups = 0; self->s.loopSound = 0; self->client->limboDropWeapon = self->s.weapon; // store this so it can be dropped in limbo LookAtKiller( self, inflictor, attacker ); self->client->ps.viewangles[0] = 0; self->client->ps.viewangles[2] = 0; //VectorCopy( self->s.angles, self->client->ps.viewangles ); // trap_UnlinkEntity( self ); self->r.maxs[2] = self->client->ps.crouchMaxZ; //% 0; // ydnar: so bodies don't clip into world self->client->ps.maxs[2] = self->client->ps.crouchMaxZ; //% 0; // ydnar: so bodies don't clip into world trap_LinkEntity( self ); // don't allow respawn until the death anim is done // g_forcerespawn may force spawning at some later time self->client->respawnTime = level.timeCurrent + 800; // remove powerups memset( self->client->ps.powerups, 0, sizeof(self->client->ps.powerups) ); // never gib in a nodrop // FIXME: contents is always 0 here if ( self->health <= GIB_HEALTH && !(contents & CONTENTS_NODROP) ) { GibEntity( self, killer ); nogib = qfalse; } if(nogib){ // normal death // for the no-blood option, we need to prevent the health // from going to gib level if ( self->health <= GIB_HEALTH ) { self->health = GIB_HEALTH + 1; } // Arnout: re-enable this for flailing /* if( self->client->ps.groundEntityNum == ENTITYNUM_NONE ) { self->client->ps.pm_flags |= PMF_FLAILING; self->client->ps.pm_time = 750; BG_AnimScriptAnimation( &self->client->ps, ANIM_MT_FLAILING, qtrue ); // Face explosion directory { vec3_t angles; vectoangles( self->client->ps.velocity, angles ); self->client->ps.viewangles[YAW] = angles[YAW]; SetClientViewAngle( self, self->client->ps.viewangles ); } } else*/ // DHM - Play death animation, and set pm_time to delay 'fallen' animation //if( G_IsSinglePlayerGame() && self->client->sess.sessionTeam == TEAM_ALLIES ) { // // play "falldown" animation since allies bots won't ever die completely // self->client->ps.pm_time = BG_AnimScriptEvent( &self->client->ps, self->client->pers.character->animModelInfo, ANIM_ET_FALLDOWN, qfalse, qtrue ); // G_StartPlayerAppropriateSound(self, "death"); //} else { self->client->ps.pm_time = BG_AnimScriptEvent( &self->client->ps, self->client->pers.character->animModelInfo, ANIM_ET_DEATH, qfalse, qtrue ); // death animation script already contains sound //} // record the death animation to be used later on by the corpse self->client->torsoDeathAnim = self->client->ps.torsoAnim; self->client->legsDeathAnim = self->client->ps.legsAnim; G_AddEvent( self, EV_DEATH1 + 1, killer ); // the body can still be gibbed self->die = body_die; } if( meansOfDeath == MOD_MACHINEGUN ) { switch( self->client->sess.sessionTeam ) { case TEAM_AXIS: level.axisMG42Counter = level.time; break; case TEAM_ALLIES: level.alliesMG42Counter = level.time; break; } } G_FadeItems( self, MOD_SATCHEL ); CalculateRanks(); if( killedintank /*Gordon: automatically go to limbo from tank*/ ) { limbo( self, qfalse ); // but no corpse } else if ( (meansOfDeath == MOD_SUICIDE && g_gamestate.integer == GS_PLAYING) ) { limbo( self, qtrue ); } else if( g_gametype.integer == GT_WOLF_LMS ) { if( !G_CountTeamMedics( self->client->sess.sessionTeam, qtrue ) ) { limbo( self, qtrue ); } } }
void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath ) { gentity_t *ent; // TTimo might be used uninitialized int contents = 0; int killer; int i; const char *killerName, *obit; qboolean nogib = qtrue; gitem_t *item = NULL; // JPW NERVE for flag drop vec3_t launchvel,launchspot; // JPW NERVE gentity_t *flag; // JPW NERVE if ( self->client->ps.pm_type == PM_DEAD ) { return; } if ( level.intermissiontime ) { return; } self->client->ps.pm_type = PM_DEAD; G_AddEvent( self, EV_STOPSTREAMINGSOUND, 0 ); if ( attacker ) { killer = attacker->s.number; if ( attacker->client ) { killerName = attacker->client->pers.netname; } else { killerName = "<non-client>"; } } else { killer = ENTITYNUM_WORLD; killerName = "<world>"; } if ( killer < 0 || killer >= MAX_CLIENTS ) { killer = ENTITYNUM_WORLD; killerName = "<world>"; } if ( meansOfDeath < 0 || meansOfDeath >= sizeof( modNames ) / sizeof( modNames[0] ) ) { obit = "<bad obituary>"; } else { obit = modNames[ meansOfDeath ]; } G_LogPrintf( "Kill: %i %i %i: %s killed %s by %s\n", killer, self->s.number, meansOfDeath, killerName, self->client->pers.netname, obit ); // broadcast the death event to everyone ent = G_TempEntity( self->r.currentOrigin, EV_OBITUARY ); ent->s.eventParm = meansOfDeath; ent->s.otherEntityNum = self->s.number; ent->s.otherEntityNum2 = killer; ent->r.svFlags = SVF_BROADCAST; // send to everyone self->enemy = attacker; self->client->ps.persistant[PERS_KILLED]++; // JPW NERVE -- if player is holding ticking grenade, drop it if ( g_gametype.integer != GT_SINGLE_PLAYER ) { if ( ( self->client->ps.grenadeTimeLeft ) && ( self->s.weapon != WP_DYNAMITE ) ) { launchvel[0] = crandom(); launchvel[1] = crandom(); launchvel[2] = random(); VectorScale( launchvel, 160, launchvel ); VectorCopy( self->r.currentOrigin, launchspot ); launchspot[2] += 40; fire_grenade( self, launchspot, launchvel, self->s.weapon ); } } // jpw if ( attacker && attacker->client ) { if ( attacker == self || OnSameTeam( self, attacker ) ) { // DHM - Nerve :: Complaint lodging if ( attacker != self && level.warmupTime <= 0 ) { if ( attacker->client->pers.localClient ) { trap_SendServerCommand( self - g_entities, "complaint -4" ); } else { trap_SendServerCommand( self - g_entities, va( "complaint %i", attacker->s.number ) ); self->client->pers.complaintClient = attacker->s.clientNum; self->client->pers.complaintEndTime = level.time + 20500; } } // dhm // JPW NERVE if ( g_gametype.integer >= GT_WOLF ) { // high penalty to offset medic heal AddScore( attacker, WOLF_FRIENDLY_PENALTY ); } else { // jpw AddScore( attacker, -1 ); } } else { // JPW NERVE -- mostly added as conveneience so we can tweak from the #defines all in one place if ( g_gametype.integer >= GT_WOLF ) { AddScore( attacker, WOLF_FRAG_BONUS ); } else { // jpw AddScore( attacker, 1 ); } attacker->client->lastKillTime = level.time; } } else { AddScore( self, -1 ); } // Add team bonuses Team_FragBonuses( self, inflictor, attacker ); // if client is in a nodrop area, don't drop anything // JPW NERVE new drop behavior if ( g_gametype.integer == GT_SINGLE_PLAYER ) { // only drop here in single player; in multiplayer, drop @ limbo contents = trap_PointContents( self->r.currentOrigin, -1 ); if ( !( contents & CONTENTS_NODROP ) ) { TossClientItems( self ); } } // drop flag regardless if ( g_gametype.integer != GT_SINGLE_PLAYER ) { if ( self->client->ps.powerups[PW_REDFLAG] ) { item = BG_FindItem( "Red Flag" ); if ( !item ) { item = BG_FindItem( "Objective" ); } self->client->ps.powerups[PW_REDFLAG] = 0; } if ( self->client->ps.powerups[PW_BLUEFLAG] ) { item = BG_FindItem( "Blue Flag" ); if ( !item ) { item = BG_FindItem( "Objective" ); } self->client->ps.powerups[PW_BLUEFLAG] = 0; } if ( item ) { launchvel[0] = crandom() * 20; launchvel[1] = crandom() * 20; launchvel[2] = 10 + random() * 10; flag = LaunchItem( item,self->r.currentOrigin,launchvel,self->s.number ); flag->s.modelindex2 = self->s.otherEntityNum2; // JPW NERVE FIXME set player->otherentitynum2 with old modelindex2 from flag and restore here flag->message = self->message; // DHM - Nerve :: also restore item name // Clear out player's temp copies self->s.otherEntityNum2 = 0; self->message = NULL; } // send a fancy "MEDIC!" scream. Sissies, ain' they? if ( self->client != NULL ) { if ( self->health > GIB_HEALTH && meansOfDeath != MOD_SUICIDE ) { if ( self->client->sess.sessionTeam == TEAM_RED ) { if ( random() > 0.5 ) { G_AddEvent( self, EV_GENERAL_SOUND, G_SoundIndex( "sound/multiplayer/axis/g-medic2.wav" ) ); } else { G_AddEvent( self, EV_GENERAL_SOUND, G_SoundIndex( "sound/multiplayer/axis/g-medic3.wav" ) ); } } else { if ( random() > 0.5 ) { G_AddEvent( self, EV_GENERAL_SOUND, G_SoundIndex( "sound/multiplayer/allies/a-medic3.wav" ) ); } else { G_AddEvent( self, EV_GENERAL_SOUND, G_SoundIndex( "sound/multiplayer/allies/a-medic2.wav" ) ); } } } } } // jpw Cmd_Score_f( self ); // show scores // send updated scores to any clients that are following this one, // or they would get stale scoreboards for ( i = 0 ; i < level.maxclients ; i++ ) { gclient_t *client; client = &level.clients[i]; if ( client->pers.connected != CON_CONNECTED ) { continue; } if ( client->sess.sessionTeam != TEAM_SPECTATOR ) { continue; } if ( client->sess.spectatorClient == self->s.number ) { Cmd_Score_f( g_entities + i ); } } self->takedamage = qtrue; // can still be gibbed self->r.contents = CONTENTS_CORPSE; self->s.powerups = 0; // JPW NERVE -- only corpse in SP; in MP, need CONTENTS_BODY so medic can operate if ( g_gametype.integer == GT_SINGLE_PLAYER ) { self->s.weapon = WP_NONE; self->s.angles[0] = 0; } else { self->client->limboDropWeapon = self->s.weapon; // store this so it can be dropped in limbo } // jpw self->s.angles[2] = 0; LookAtKiller( self, inflictor, attacker ); VectorCopy( self->s.angles, self->client->ps.viewangles ); self->s.loopSound = 0; trap_UnlinkEntity( self ); self->r.maxs[2] = 0; self->client->ps.maxs[2] = 0; trap_LinkEntity( self ); // don't allow respawn until the death anim is done // g_forcerespawn may force spawning at some later time self->client->respawnTime = level.time + 800; // remove powerups memset( self->client->ps.powerups, 0, sizeof( self->client->ps.powerups ) ); // never gib in a nodrop if ( self->health <= GIB_HEALTH && !( contents & CONTENTS_NODROP ) ) { GibEntity( self, killer ); nogib = qfalse; } if ( nogib ) { // normal death // for the no-blood option, we need to prevent the health // from going to gib level if ( self->health <= GIB_HEALTH ) { self->health = GIB_HEALTH + 1; } // JPW NERVE for medic self->client->medicHealAmt = 0; // jpw // DHM - Play death animation, and set pm_time to delay 'fallen' animation self->client->ps.pm_time = BG_AnimScriptEvent( &self->client->ps, ANIM_ET_DEATH, qfalse, qtrue ); G_AddEvent( self, EV_DEATH1 + 1, killer ); // the body can still be gibbed self->die = body_die; } trap_LinkEntity( self ); if ( g_gametype.integer >= GT_WOLF && meansOfDeath == MOD_SUICIDE ) { limbo( self, qtrue ); } }
static void G_Give( gentity_t *ent, const char *name, const char *args, int argc ) { const gitem_t *it; int i; qboolean give_all = qfalse; gentity_t *it_ent; trace_t trace; if ( !Q_stricmp( name, "all" ) ) give_all = qtrue; if ( give_all || !Q_stricmp( name, "health") ) { if ( argc == 3 ) ent->health = Q_clampi( 1, atoi( args ), MAX_HEALTH ); else ent->health = MAX_HEALTH; if ( !give_all ) return; } if ( give_all || !Q_stricmp( name, "armor" ) || !Q_stricmp( name, "shield" ) ) { if ( argc == 3 ) ent->client->ps.stats[STAT_ARMOR] = Q_clampi( 0, atoi( args ), MAX_ARMOR ); else ent->client->ps.stats[STAT_ARMOR] = MAX_ARMOR; if ( !give_all ) return; } if ( give_all || !Q_stricmp( name, "weapons" ) ) { ent->client->ps.stats[STAT_WEAPONS] = (1 << (WP_NUM_WEAPONS)) - (1 << WP_NONE); if ( !give_all ) return; } if ( !give_all && !Q_stricmp( name, "weaponnum" ) ) { ent->client->ps.stats[STAT_WEAPONS] |= (1 << atoi( args )); return; } if ( give_all || !Q_stricmp( name, "ammo" ) ) { int num = 999; if ( argc == 3 ) num = atoi( args ); for ( i=0; i<MAX_WEAPONS; i++ ) ent->client->ps.ammo[i] = num; if ( !give_all ) return; } // spawn a specific item right on the player if ( !give_all ) { it = BG_FindItem( name ); if ( !it ) return; it_ent = G_Spawn(); VectorCopy( &ent->r.currentOrigin, &it_ent->s.origin ); it_ent->classname = it->classname; G_SpawnItem( it_ent, it ); FinishSpawningItem( it_ent ); memset( &trace, 0, sizeof( trace ) ); Touch_Item( it_ent, ent, &trace ); if ( it_ent->inuse ) G_FreeEntity( it_ent ); } }
void CG_Drop_f( void ) { char command[ 128 ]; char message[ 128 ]; gitem_t *item; int j; if ( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR ) { return; } if ( cg.predictedPlayerState.stats[ STAT_HEALTH ] <= 0 ) { CG_Printf( "You must be alive to use this command.\n" ); return; } trap_Args( message, 128 ); item = BG_FindItem( message ); if ( !item ) { CG_Printf( "unknown item: %s\n", message ); return; } if ( !cg_items[ item->giTag ].registered ) { return; } j = item->giTag; switch ( item->giType ) { case IT_WEAPON: if ( cgs.dmflags & 256 ) { return; } if ( !( cg.snap->ps.stats[ STAT_WEAPONS ] & ( 1 << j ) ) ) { CG_Printf( "Out of item: %s\n", message ); return; } if ( cg.snap->ps.weaponstate != WEAPON_READY ) { return; } if ( j == cg.snap->ps.weapon ) { return; } if ( j <= WP_MACHINEGUN || j == WP_GRAPPLING_HOOK ) { CG_Printf( "Item is not dropable.\n" ); return; } case IT_AMMO: if ( cg.snap->ps.ammo[ j ] < 1 ) { CG_Printf( "Out of item: %s\n", message ); return; } break; case IT_POWERUP: if ( cg.snap->ps.powerups[ j ] <= cg.time ) { CG_Printf( "Out of item: %s\n", message ); return; } break; case IT_HOLDABLE: if ( j == HI_KAMIKAZE ) { CG_Printf( "Item is not dropable.\n" ); return; } if ( bg_itemlist[ cg.snap->ps.stats[ STAT_HOLDABLE_ITEM ] ].giTag != j ) { CG_Printf( "Out of item: %s\n", message ); return; } break; default: CG_Printf( "Item is not dropable.\n" ); return; } Com_sprintf( command, 128, "drop %s", message ); trap_SendClientCommand( command ); }
/* ============== ClearRegisteredItems ============== */ void ClearRegisteredItems( void ) { memset( itemRegistered, 0, sizeof( itemRegistered ) ); if(g_instantgib.integer) { if(g_instantgib.integer & 2) RegisterItem( BG_FindItemForWeapon( WP_GAUNTLET ) ); //RegisterItem( BG_FindItemForWeapon( WP_MACHINEGUN ) ); RegisterItem( BG_FindItemForWeapon( WP_RAILGUN ) ); } else if(g_rockets.integer) { //RegisterItem( BG_FindItemForWeapon( WP_GAUNTLET ) ); //RegisterItem( BG_FindItemForWeapon( WP_MACHINEGUN ) ); RegisterItem( BG_FindItemForWeapon( WP_ROCKET_LAUNCHER ) ); } else { // players always start with the base weapon RegisterItem( BG_FindItemForWeapon( WP_MACHINEGUN ) ); RegisterItem( BG_FindItemForWeapon( WP_GAUNTLET ) ); if(g_gametype.integer == GT_ELIMINATION || g_gametype.integer == GT_CTF_ELIMINATION || g_gametype.integer == GT_LMS || g_elimination_allgametypes.integer) { RegisterItem( BG_FindItemForWeapon( WP_SHOTGUN ) ); RegisterItem( BG_FindItemForWeapon( WP_GRENADE_LAUNCHER ) ); RegisterItem( BG_FindItemForWeapon( WP_ROCKET_LAUNCHER ) ); RegisterItem( BG_FindItemForWeapon( WP_LIGHTNING ) ); RegisterItem( BG_FindItemForWeapon( WP_RAILGUN ) ); RegisterItem( BG_FindItemForWeapon( WP_PLASMAGUN ) ); RegisterItem( BG_FindItemForWeapon( WP_BFG ) ); RegisterItem( BG_FindItemForWeapon( WP_NAILGUN ) ); RegisterItem( BG_FindItemForWeapon( WP_PROX_LAUNCHER ) ); RegisterItem( BG_FindItemForWeapon( WP_CHAINGUN ) ); } } if( g_gametype.integer == GT_HARVESTER ) { RegisterItem( BG_FindItem( "Red Cube" ) ); RegisterItem( BG_FindItem( "Blue Cube" ) ); } if(g_gametype.integer == GT_DOUBLE_D ) { RegisterItem( BG_FindItem( "Point A (Blue)" ) ); RegisterItem( BG_FindItem( "Point A (Red)" ) ); RegisterItem( BG_FindItem( "Point A (White)" ) ); RegisterItem( BG_FindItem( "Point B (Blue)" ) ); RegisterItem( BG_FindItem( "Point B (Red)" ) ); RegisterItem( BG_FindItem( "Point B (White)" ) ); } if(g_gametype.integer == GT_DOMINATION ) { RegisterItem( BG_FindItem( "Neutral domination point" ) ); RegisterItem( BG_FindItem( "Red domination point" ) ); RegisterItem( BG_FindItem( "Blue domination point" ) ); } }
/* ================ Bot_ScriptInitBot ================ */ qboolean Bot_ScriptInitBot(int entnum) { gentity_t *ent, *trav; bot_state_t *bs; char userinfo[MAX_INFO_STRING]; bot_script_global_data_t *bsgd; char *token, *p, *pBackup; int i, val = 0; int weapons[2]; gitem_t *item = NULL; char *name; // bs = &botstates[entnum]; if(!bs->inuse) { return qfalse; } if(bs->script.data) { return qtrue; } // set starting defaults bs->script.status.eventIndex = -1; bs->script.data = NULL; // ent = BotGetEntity(bs->entitynum); trap_GetUserinfo(bs->entitynum, userinfo, sizeof(userinfo)); name = Info_ValueForKey(userinfo, "scriptName"); if(!name || !name[0]) { return qfalse; } // find the script data for this bot bsgd = botCharacterScriptData; for(i = 0; i < numScriptCharacters; i++, bsgd++) { if(Q_stricmp(name, bsgd->name) != 0) { continue; } // check params p = bsgd->params; // // eliminate them with each condition not met while(qtrue) { token = COM_ParseExt(&p, qfalse); if(!token || !token[0]) { // we're done, we found a match break; } // if(token[0] != '/') { G_Error("BotScript, line %i: condition identifier expected, '%s' found\n", bsgd->lineNum, token); } // if(!Q_stricmp(token, "/team")) { token = COM_ParseExt(&p, qfalse); if(!token || !token[0] || token[0] == '/') { G_Error("BotScript, line %i: unexpected end of /team parameter", bsgd->lineNum); } // if(!Q_stricmp(token, "axis")) { val = TEAM_AXIS; } else if(!Q_stricmp(token, "allies")) { val = TEAM_ALLIES; } else { G_Error("BotScript, line %i: unknown team \"%s\"", bsgd->lineNum, token); } // eliminate player if(bs->mpTeam != val) { break; } } else // if(!Q_stricmp(token, "/class")) { token = COM_ParseExt(&p, qfalse); if(!token || !token[0] || token[0] == '/') { G_Error("BotScript, line %i: unexpected end of /class parameter", bsgd->lineNum); } // val = Team_ClassForString(token); if(val < 0) { G_Error("BotScript, line %i: unknown class \"%s\"", bsgd->lineNum, token); } if(bs->mpClass != val) { break; } } else // if(!Q_stricmp(token, "/weapon")) { memset(weapons, 0, sizeof(weapons)); // for each weapon while(qtrue) { // read the weapon token = COM_ParseExt(&p, qfalse); if(!token || !token[0] || token[0] == '/') { G_Error("BotScript, line %i: unexpected end of /weapon parameter", bsgd->lineNum); } // if((item = BG_FindItem(token))) { if(!item->giTag) { G_Error("BotScript, line %i: unknown weapon \"%s\"", bsgd->lineNum, token); } COM_BitSet(weapons, item->giTag); } else { G_Error("BotScript, line %i: unknown weapon \"%s\"", bsgd->lineNum, token); } // pBackup = p; token = COM_ParseExt(&p, qfalse); if(Q_stricmp(token, "or") != 0) { // not OR, so drop out of here p = pBackup; break; } } if(!(ent->client->ps.weapons[0] & weapons[0]) && !(ent->client->ps.weapons[1] & weapons[1])) { break; } } else // if(!Q_stricmp(token, "/within_range")) { // targetname token = COM_ParseExt(&p, qfalse); if(!token || !token[0] || token[0] == '/') { G_Error("BotScript, line %i: unexpected end of /within_range parameter", bsgd->lineNum); } trav = G_FindByTargetname(NULL, token); if(!trav) { G_Error("BotScript, line %i: unknown spawn point \"%s\"", bsgd->lineNum, token); } // range token = COM_ParseExt(&p, qfalse); if(!token || !token[0] || token[0] == '/') { G_Error("BotScript, line %i: range expected, not found", bsgd->lineNum); } // // eliminate players if(VectorDistanceSquared(ent->r.currentOrigin, trav->s.origin) > SQR(atof(token))) { break; } } } // // if there is a NOT a valid token waiting, then we passed all checks if(!token[0]) { break; } } // if(i < numScriptCharacters) { // we found a script for this character bs->script.data = bsgd->data; return qtrue; } // return qfalse; }
static void Cmd_Spawn_f (gentity_t *ent) { gentity_t *s; gitem_t *item; vec3_t origin; vec3_t forward; char name[MAX_STRING_CHARS]; char valBuffer[128]; float f; trace_t trace; if (!g_cheats.integer) { trap_SendServerCommand(ent-g_entities, va("print \"Cheats are not enabled on this server.\n\"")); return; } if (trap_Argc() < 2) { trap_SendServerCommand(ent-g_entities, "print \"usage: spawn <item classname> [forward amount]\n\""); return; } if (trap_Argc() > 2) { trap_Argv(2, valBuffer, sizeof(valBuffer)); f = atof(valBuffer); } else { f = 100; } trap_Argv(1, name, sizeof(name)); s = G_Spawn(); AngleVectors(ent->s.apos.trBase, forward, NULL, NULL); VectorNormalize(forward); VectorCopy(ent->s.pos.trBase, origin); VectorMA(origin, f, forward, origin); memset(&trace, 0, sizeof(trace)); trap_Trace(&trace, ent->s.pos.trBase, NULL, NULL, origin, ent - g_entities, MASK_SOLID); //VectorCopy(origin, s->s.pos.trBase); //VectorCopy(origin, s->r.currentOrigin); //VectorCopy(origin, s->s.origin); VectorCopy(trace.endpos, s->s.origin); item = BG_FindItem (name); if (item) { s->classname = item->classname; G_SpawnItem(s, item); FinishSpawningItem(s); return; } #if 0 // check item spawn functions for ( item=bg_itemlist+1 ; item->classname ; item++ ) { //if ( !strcmp(item->classname, name) ) { s->classname = item->classname; G_SpawnItem(s, item); FinishSpawningItem(s); //memset( &trace, 0, sizeof( trace ) ); //Touch_Item (it_ent, ent, &trace); //if (it_ent->inuse) { // G_FreeEntity( it_ent ); //} return; } }