/* =============== CG_UseItem =============== */ static void CG_UseItem( centity_t *cent ) { playerInfo_t *pi; int itemNum, playerNum; gitem_t *item; entityState_t *es; int i; es = ¢->currentState; itemNum = (es->event & ~EV_EVENT_BITS) - EV_USE_ITEM0; if ( itemNum < 0 || itemNum > HI_NUM_HOLDABLE ) { itemNum = 0; } // print a message if the local player for (i = 0; i < CG_MaxSplitView(); i++) { if ( es->number != cg.snap->pss[i].playerNum ) { continue; } if ( !itemNum ) { CG_CenterPrint( i, "No item to use", SCREEN_HEIGHT * 0.30, 0.5 ); } else { item = BG_FindItemForHoldable( itemNum ); CG_CenterPrint( i, va("Use %s", item->pickup_name), SCREEN_HEIGHT * 0.30, 0.5 ); } } switch ( itemNum ) { default: case HI_NONE: trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.useNothingSound ); break; case HI_TELEPORTER: break; case HI_MEDKIT: playerNum = cent->currentState.playerNum; if ( playerNum >= 0 && playerNum < MAX_CLIENTS ) { pi = &cgs.playerinfo[ playerNum ]; pi->medkitUsageTime = cg.time; } trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.medkitSound ); break; #ifdef MISSIONPACK case HI_KAMIKAZE: break; case HI_PORTAL: break; case HI_INVULNERABILITY: trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.useInvulnerabilitySound ); break; #endif } }
/* =============== CG_UseItem =============== */ static void CG_UseItem( centity_t *cent ) { clientInfo_t *ci; int itemNum, clientNum; gitem_t *item; entityState_t *es; es = ¢->currentState; itemNum = (es->event & ~EV_EVENT_BITS) - EV_USE_ITEM0; if ( itemNum < 0 || itemNum > HI_NUM_HOLDABLE ) { itemNum = 0; } // print a message if the local player if ( es->number == cg.snap->ps.clientNum ) { if ( !itemNum ) { CG_CenterPrint( "No item to use", SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); } else { item = BG_FindItemForHoldable( itemNum ); CG_CenterPrint( va("Use %s", item->pickup_name), SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); } } switch ( itemNum ) { default: case HI_NONE: trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.useNothingSound ); break; case HI_TELEPORTER: break; case HI_MEDKIT: clientNum = cent->currentState.clientNum; if ( clientNum >= 0 && clientNum < MAX_CLIENTS ) { ci = &cgs.clientinfo[ clientNum ]; ci->medkitUsageTime = cg.time; } trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.medkitSound ); break; #ifdef MISSIONPACK case HI_KAMIKAZE: break; case HI_PORTAL: break; case HI_INVULNERABILITY: trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.useInvulnerabilitySound ); break; #endif } }
// The server has issued a map_restart, so the next snapshot is completely new and should not be interpolated to. // A tournament restart will clear everything, but doesn't require a reload of all the media static void CG_MapRestart( void ) { if ( cg_showMiss.integer ) trap->Print( "CG_MapRestart\n" ); trap->R_ClearDecals(); //FIXME: trap->FX_Reset? CG_InitLocalEntities(); CG_InitMarkPolys(); CG_KillCEntityInstances(); cg.fraglimitWarnings = 0; cg.timelimitWarnings = 0; cg.intermissionStarted = qfalse; cgs.voteTime = 0; cg.mapRestart = qtrue; CG_StartMusic( qtrue ); trap->S_ClearLoopingSounds(); // we really should clear more parts of cg here and stop sounds // play the "fight" sound if this is a restart without warmup if ( cg.warmup == 0 && cgs.gametype != GT_SIEGE && cgs.gametype != GT_POWERDUEL ) { trap->S_StartLocalSound( media.sounds.warning.countFight, CHAN_ANNOUNCER ); CG_CenterPrint( CG_GetStringEdString( "MP_SVGAME", "BEGIN_DUEL" ), 120, GIANTCHAR_WIDTH * 2 ); } }
// [ERGO MOD START] void CG_ModHRInfo(entityState_t *es) { int currentHr; char *s; vec4_t color; currentHr = es->eventParm; //if msgIdentifier == HR_ //CG_Printf("EV_JUMP_PAD w/effect #%i\n", es->eventParm); s = va("HR: %d", currentHr); // blue color[0] = 0; color[1] = 0; color[2] = 1; color[3] = 1; //640 - (Q_PrintStrlen(s) * BIGCHAR_WIDTH) //UI_DrawProportionalString(320, 300, s, // UI_CENTER | UI_SMALLFONT | UI_DROPSHADOW, colorWhite); //CG_DrawStringExt(320, 25, s, colorWhite, qfalse, qtrue, BIGCHAR_WIDTH, BIGCHAR_HEIGHT, 0); //CG_DrawStringExt(300, 300, s, color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0); //CG_DrawString(SCREEN_WIDTH * 0.2F, SCREEN_HEIGHT * 0.30F, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, s, 1.0F); CG_CenterPrint(s, SCREEN_HEIGHT * 0.30, SMALLCHAR_WIDTH); }
/* =============== CG_MapRestart The server has issued a map_restart, so the next snapshot is completely new and should not be interpolated to. A tournement restart will clear everything, but doesn't require a reload of all the media =============== */ static void CG_MapRestart( void ) { if ( cg_showmiss.integer ) { CG_Printf( "CG_MapRestart\n" ); } CG_InitMarkPolys(); // make sure the "3 frags left" warnings play again cg.fraglimitWarnings = 0; cg.timelimitWarnings = 0; cg.intermissionStarted = qfalse; cgs.voteTime = 0; cg.mapRestart = qtrue; CG_StartMusic(); trap_S_ClearLoopingSounds( qtrue ); // we really should clear more parts of cg here and stop sounds // play the "fight" sound if this is a restart without warmup if ( cg.warmup == 0 ) { CG_CenterPrint( "FIGHT!", 120, GIANTCHAR_WIDTH * 2 ); } trap_Cvar_Set( "cg_thirdPerson", "0" ); }
/* ================ CG_AnnounceHumanStageTransistion ================ */ static void CG_AnnounceHumanStageTransistion( stage_t from, stage_t to ) { if( cg.predictedPlayerState.stats[ STAT_TEAM ] != TEAM_HUMANS ) return; trap_S_StartLocalSound( cgs.media.humanStageTransition, CHAN_ANNOUNCER ); CG_CenterPrint( "Reinforcements have arrived!", 200, GIANTCHAR_WIDTH * 4 ); }
void target_autosave_use(gentity_t *self, gentity_t *other, gentity_t *activator) { G_ActivateBehavior(self,BSET_USE); //gi.SendServerCommand( NULL, "cp @SP_INGAME_CHECKPOINT" ); CG_CenterPrint( "@SP_INGAME_CHECKPOINT", SCREEN_HEIGHT * 0.25 ); //jump the network gi.SendConsoleCommand( "wait 2;save auto\n" ); }
/* ================ CG_AnnounceAlienStageTransistion ================ */ static void CG_AnnounceAlienStageTransistion( stage_t from, stage_t to ) { if( cg.predictedPlayerState.stats[ STAT_TEAM ] != TEAM_ALIENS ) return; trap_S_StartLocalSound( cgs.media.alienStageTransition, CHAN_ANNOUNCER ); CG_CenterPrint( "We have evolved!", 200, GIANTCHAR_WIDTH * 4 ); }
/* =================== CG_CenterEcho_f =================== */ void CG_CenterEcho_f( int localPlayerNum ) { char text[1024]; trap_Args( text, sizeof( text ) ); CG_ReplaceCharacter( text, '\\', '\n' ); CG_CenterPrint( localPlayerNum, text, SCREEN_HEIGHT * 0.30, 0.5 ); }
static void CG_spLose_f( void) { trap_Cvar_Set("cg_cameraOrbit", "2"); trap_Cvar_Set("cg_cameraOrbitDelay", "35"); trap_Cvar_Set("cg_thirdPerson", "1"); trap_Cvar_Set("cg_thirdPersonAngle", "0"); trap_Cvar_Set("cg_thirdPersonRange", "100"); CG_AddBufferedSound(cgs.media.loserSound); //trap_S_StartLocalSound(cgs.media.loserSound, CHAN_ANNOUNCER); CG_CenterPrint("YOU LOSE...", SCREEN_HEIGHT * .30, 0); }
static void CG_CenterPrintSE_f( void ) { char strEd[MAX_STRINGED_SV_STRING] = {0}; char *x = (char *)CG_Argv( 1 ); if ( x[0] == '@' ) x++; trap->SE_GetStringTextString( x, strEd, MAX_STRINGED_SV_STRING ); CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); }
static void CG_spWin_f( void) { trap_Cvar_Set("cg_cameraOrbit", "2"); trap_Cvar_Set("cg_cameraOrbitDelay", "35"); trap_Cvar_Set("cg_thirdPerson", "1"); trap_Cvar_Set("cg_thirdPersonAngle", "0"); trap_Cvar_Set("cg_thirdPersonRange", "100"); CG_AddBufferedSound(cgs.media.winnerSound); //trap_S_StartLocalSound(cgs.media.winnerSound, CHAN_ANNOUNCER); CG_CenterPrint(CG_GetStringEdString("MP_INGAME", "YOU_WIN"), SCREEN_HEIGHT * .30, 0); }
void CG_BodyObituary( entityState_t *ent, char *targetName ) { int target, attacker; char *message; char *message2; const char *attackerInfo; char attackerName[ 32 ]; gender_t gender; char *s; target = ent->otherEntityNum; attacker = ent->otherEntityNum2; attackerInfo = CG_ConfigString( CS_PLAYERS + attacker ); if ( !attackerInfo ) return; Q_strncpyz( attackerName, Info_ValueForKey( attackerInfo, "n" ), sizeof ( attackerName ) - 2 ); strcat( attackerName, S_COLOR_WHITE ); if ( rand() & 1 ) { message = "thawed"; message2 = "like a package of frozen peas"; } else { gender = cgs.clientinfo[ target ].gender; message = "evicted"; if ( gender == GENDER_FEMALE ) { message2 = "from her igloo"; } else if ( gender == GENDER_NEUTER ) { message2 = "from its igloo"; } else { message2 = "from his igloo"; } } if ( attacker == cg.snap->ps.clientNum ) { s = va( "You thawed %s", targetName ); CG_CenterPrint( s, SCREEN_HEIGHT * 0.25, BIGCHAR_WIDTH ); } if ( target == cg.snap->ps.clientNum ) { s = va( "%s unfroze you", attackerName ); CG_CenterPrint( s, SCREEN_HEIGHT * 0.25, BIGCHAR_WIDTH ); } CG_Printf( "%s %s %s %s.\n", attackerName, message, targetName, message2 ); }
static void CG_spWin_f( void) { trap_Cvar_Set("cg_cameraOrbit", "2"); trap_Cvar_Set("cg_cameraOrbitDelay", "35"); trap_Cvar_Set("cg_thirdPerson", "1"); trap_Cvar_Set("cg_thirdPersonAngle", "0"); trap_Cvar_Set("cg_thirdPersonRange", "100"); #ifndef SMOKINGUNS CG_AddBufferedSound(cgs.media.winnerSound); #endif //trap_S_StartLocalSound(cgs.media.winnerSound, CHAN_ANNOUNCER); CG_CenterPrint("YOU WIN!", SCREEN_HEIGHT * .30, 0); }
static void CG_spLose_f(void) { trap_cvarsetstr("cg_cameraOrbit", "2"); trap_cvarsetstr("cg_cameraOrbitDelay", "35"); trap_cvarsetstr("cg_thirdperson", "1"); trap_cvarsetstr("cg_thirdPersonAngle", "0"); trap_cvarsetstr("cg_thirdpersonrange", "100"); CG_AddBufferedSound(cgs.media.loserSound); /* trap_sndstartlocalsound(cgs.media.loserSound, CHAN_ANNOUNCER); */ CG_CenterPrint("YOU LOSE...", SCREEN_HEIGHT * .30, 0); }
static void CG_spWin_f(void) { trap_cvarsetstr("cg_cameraOrbit", "2"); trap_cvarsetstr("cg_cameraOrbitDelay", "35"); trap_cvarsetstr("cg_thirdperson", "1"); trap_cvarsetstr("cg_thirdpersonyaw", "0"); trap_cvarsetstr("cg_thirdpersonpitch", "0"); trap_cvarsetstr("cg_thirdpersonrange", "100"); CG_AddBufferedSound(cgs.media.winnerSound); /* trap_sndstartlocalsound(cgs.media.winnerSound, CHAN_ANNOUNCER); */ CG_CenterPrint("YOU WIN!", SCREEN_HEIGHT * .30, 0); }
/* =============== CG_UseItem =============== */ static void CG_UseItem( centity_t *cent ) { clientInfo_t *ci = 0; int itemNum; gitem_t *item; entityState_t *es; es = ¢->currentState; itemNum = (es->event & ~EV_EVENT_BITS) - EV_USE_ITEM0; if ( itemNum < 0 || itemNum > HI_NUM_HOLDABLE ) { itemNum = 0; } // print a message if the local player if ( es->number == cg.snap->ps.clientNum ) { if ( !itemNum ) { CG_CenterPrint( "No item to use" ); } else { item = BG_FindItemForHoldable( itemNum ); CG_CenterPrint( va("Use %s", item->pickup_name) ); } } switch ( itemNum ) { default: case HI_NONE: trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.useNothingSound ); break; case HI_TELEPORTER: break; case HI_MEDKIT: trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.medkitSound ); break; } }
static void InformUnlockableStatusChanges(int* statusChanges, int count) { char text[MAX_STRING_CHARS]; char* textptr = text; int unlockableNum; bool firstPass = true, unlocked = true; unlockable_t* unlockable; for (unlockableNum = 0; unlockableNum < NUM_UNLOCKABLES; unlockableNum++) { unlockable = &unlockables[unlockableNum]; if (!statusChanges[unlockableNum] || Disabled(unlockable)) { continue; } if (firstPass) { if (statusChanges[unlockableNum] > 0) { Com_sprintf(text, sizeof(text), S_COLOR_GREEN "ITEM%s UNLOCKED: " S_COLOR_WHITE, (count > 1) ? "S" : ""); } else { unlocked = false; Com_sprintf(text, sizeof(text), S_COLOR_RED "ITEM%s LOCKED: " S_COLOR_WHITE, (count > 1) ? "S" : ""); } textptr = text + strlen(text); firstPass = false; } else { Com_sprintf(textptr, sizeof(text) - (textptr - text), ", "); textptr += 2; } Com_sprintf(textptr, sizeof(text) - (textptr - text), "%s", UnlockableHumanName(unlockable)); textptr += strlen(textptr); } // TODO: Add sound for items being locked for each team switch (cg.snap->ps.persistant[PERS_TEAM]) { case TEAM_ALIENS: if (unlocked) { trap_S_StartLocalSound(cgs.media.weHaveEvolved, CHAN_ANNOUNCER); } break; case TEAM_HUMANS: default: if (unlocked) { trap_S_StartLocalSound(cgs.media.reinforcement, CHAN_ANNOUNCER); } break; } CG_CenterPrint(text, SCREEN_HEIGHT * 0.3, GIANTCHAR_WIDTH * 2); }
static void CG_LimboMessage_f( void ) { char teamStr[80], classStr[80], weapStr[80]; if ( cgs.gametype != GT_WOLF ) { return; } Q_strncpyz( teamStr, CG_Argv( 1 ), 80 ); Q_strncpyz( classStr, CG_Argv( 2 ), 80 ); Q_strncpyz( weapStr, CG_Argv( 3 ), 80 ); CG_CenterPrint( va( "You will spawn as a %s \n%s with a %s.", teamStr, classStr, weapStr ), SCREEN_HEIGHT - ( SCREEN_HEIGHT * 0.25 ), SMALLCHAR_WIDTH ); }
/* =============== CG_MapRestart The server has issued a map_restart, so the next snapshot is completely new and should not be interpolated to. A tournement restart will clear everything, but doesn't require a reload of all the media =============== */ static void CG_MapRestart(void) { if(cg_showmiss.integer) { CG_Printf("CG_MapRestart\n"); } CG_InitLocalEntities(); CG_InitMarkPolys(); CG_InitParticles(); // make sure the "3 frags left" warnings play again cg.fraglimitWarnings = 0; cg.timelimitWarnings = 0; cg.intermissionStarted = qfalse; cgs.voteTime = 0; cg.mapRestart = qtrue; CG_StartMusic(); trap_S_ClearLoopingSounds(qtrue); // we really should clear more parts of cg here and stop sounds // play the "fight" sound if this is a restart without warmup if(cg.warmup == 0 /* && cgs.gametype == GT_TOURNAMENT */ ) { trap_S_StartLocalSound(cgs.media.countFightSound, CHAN_ANNOUNCER); CG_CenterPrint("FIGHT!", 120, GIANTCHAR_WIDTH * 2); } #ifdef MISSIONPACK if(cg_singlePlayerActive.integer) { trap_Cvar_Set("ui_matchStartTime", va("%i", cg.time)); if(cg_recordSPDemo.integer && cg_recordSPDemoName.string && *cg_recordSPDemoName.string) { trap_SendConsoleCommand(va("set g_synchronousclients 1 ; record %s \n", cg_recordSPDemoName.string)); } } #endif trap_Cvar_Set("cg_cameraOrbit", "0"); trap_Cvar_Set("cg_thirdPerson", "0"); }
/* =============== CG_MapRestart The server has issued a map_restart, so the next snapshot is completely new and should not be interpolated to. A tournement restart will clear everything, but doesn't require a reload of all the media =============== */ static void CG_MapRestart( void ) { if ( cg_showMiss.integer ) { trap->Print( "CG_MapRestart\n" ); } trap->R_ClearDecals ( ); //FIXME: trap->FX_Reset? CG_InitLocalEntities(); CG_InitMarkPolys(); CG_KillCEntityInstances(); // make sure the "3 frags left" warnings play again cg.fraglimitWarnings = 0; cg.timelimitWarnings = 0; cg.intermissionStarted = qfalse; cgs.voteTime = 0; cg.mapRestart = qtrue; CG_StartMusic(qtrue); trap->S_ClearLoopingSounds(); // we really should clear more parts of cg here and stop sounds // play the "fight" sound if this is a restart without warmup if ( cg.warmup == 0 && cgs.gametype != GT_POWERDUEL/* && cgs.gametype == GT_DUEL */) { trap->S_StartLocalSound( cgs.media.countFightSound, CHAN_ANNOUNCER ); CG_CenterPrint( CG_GetStringEdString("MP_SVGAME", "BEGIN_DUEL"), 120, GIANTCHAR_WIDTH*2 ); } /* if (cg_singlePlayerActive.integer) { trap->Cvar_Set("ui_matchStartTime", va("%i", cg.time)); if (cg_recordSPDemo.integer && cg_recordSPDemoName.string && *cg_recordSPDemoName.string) { trap->SendConsoleCommand(va("set g_synchronousclients 1 ; record %s \n", cg_recordSPDemoName.string)); } } */ trap->Cvar_Set("cg_thirdPerson", "0"); cg.numItemsInInventory = 0; memset(cg.playerInventory, 0, sizeof(cg.playerInventory)); memset(cg.playerACI, -1, sizeof(cg.playerACI)); }
static void checkAutoSave() { static int timeToCheckpoint = 0; static int delayCountdown = 3; // delay a few frames before saving if(sv.time < timeToCheckpoint && timeToCheckpoint != 0) { allowNormalAutosave = false; } else { allowNormalAutosave = true; timeToCheckpoint = 0; } if(autosaveTrigger) { if( cls.uiStarted && cls.state == CA_ACTIVE && SG_GameAllowedToSaveHere(qfalse) && Cvar_VariableIntegerValue("disableAutoSave") == 0 ) { if(delayCountdown <= 0) { if(doAutoSave) { CG_CenterPrint( "@SP_INGAME_CHECKPOINT", SCREEN_HEIGHT * 0.25 ); //jump the network Cbuf_AddText( "save auto\n" ); } timeToCheckpoint = sv.time + 10000; autosaveTrigger = false; doAutoSave = false; allowNormalAutosave = false; delayCountdown = 3; } else { delayCountdown--; } } else { delayCountdown = 3; } } }
/* ================ vmMain This is the only way control passes into the module. This must be the very first function compiled into the .q3vm file ================ */ intptr_t vmMain( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10, int arg11 ) { switch ( command ) { case CG_INIT: CG_Init( arg0, arg1, arg2, arg3 ); return 0; case CG_SHUTDOWN: CG_Shutdown(); return 0; case CG_CONSOLE_COMMAND: return CG_ConsoleCommand(); case CG_DRAW_ACTIVE_FRAME: CG_DrawActiveFrame( arg0, arg1, arg2 ); return 0; case CG_DRAW_2D: CG_Draw2D( arg0, arg1, arg2 ); return 0; case CG_CROSSHAIR_PLAYER: return CG_CrosshairPlayer(); case CG_LAST_ATTACKER: return CG_LastAttacker(); case CG_KEY_EVENT: CG_KeyEvent(arg0, arg1); return 0; case CG_MOUSE_EVENT: CG_MouseEvent(arg0, arg1); return 0; case CG_EVENT_HANDLING: CG_EventHandling(arg0); return 0; case CG_CENTERPRINT: CG_CenterPrint( (const char*)arg0, 200, 10 ); return 0; case CG_LOCATIONPRINT: CG_LocationPrint( (const char*)arg0, arg1, arg2, 10 ); return 0; case CG_PARSEMSG: CG_ParseCGMessage(); return 0; default: CG_Error( "vmMain: unknown command %i", command ); break; } return -1; }
/** The server has issued a map_restart, so the next snapshot is completely new and should not be interpolated to. A tournament restart will clear everything, but doesn't require a reload of all the media */ static void CG_MapRestart(void) { if (cg_showmiss.integer) { CG_Printf("CG_MapRestart\n"); } CG_InitLocalEntities(); CG_InitMarkPolys(); CG_ClearParticles(); // make sure the "3 frags left" warnings play again cg.fraglimitWarnings = 0; cg.timelimitWarnings = 0; cg.rewardTime = 0; cg.rewardStack = 0; cg.intermissionStarted = qfalse; cg.levelShot = qfalse; memset(&cg.statsOwn, 0, sizeof cg.statsOwn); memset(&cg.statsFollow, 0, sizeof cg.statsFollow); memset(&cg.statsEnemy, 0, sizeof cg.statsEnemy); cgs.voteTime = 0; cg.mapRestart = qtrue; trap_S_ClearLoopingSounds(qtrue); // we really should clear more parts of cg here and stop sounds // play the "fight" sound if this is a restart without warmup if (cgs.warmup == 0) { trap_S_StartLocalSound(cgs.media.countFightSound, CHAN_ANNOUNCER); CG_CenterPrint("Fight!"); } trap_Cvar_Set("cg_thirdPerson", "0"); }
// These parameters are sent from game. See rune.c - Cmd_Rune_Drop for explanation // 0 Rune was removed // -1 No Rune // -2 Rune Removal Cancelled // -3 Can't remove runes // All other values indicate the length of time before the rune can be removed void CG_Rune_DropInform( int dropType ) { if (dropType==0) CG_CenterPrint("Rune removed",SCREEN_HEIGHT * 0.65,8); else if (dropType==-1) CG_CenterPrint("No Rune",SCREEN_HEIGHT * 0.65,8); else if (dropType==-2) CG_CenterPrint("Rune removal cancelled",SCREEN_HEIGHT * 0.65,8); else if (dropType==-3) CG_CenterPrint("You can't remove the rune you have",SCREEN_HEIGHT * 0.65,8); else if (dropType==-4) CG_CenterPrint("This was your rune",SCREEN_HEIGHT * 0.65,8); else { if (dropType>5) CG_CenterPrint(va("Rune will be removed in %i seconds",dropType),SCREEN_HEIGHT * 0.65,8); else CG_CenterPrint("Rune will be removed",SCREEN_HEIGHT * 0.65,8); } }
static void CG_CenterPrint_f( void ) { char strEd[MAX_STRINGED_SV_STRING] = {0}; CG_CheckSVStringEdRef( strEd, CG_Argv( 1 ) ); CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); }
/* ================= CG_ServerCommand The string has been tokenized and can be retrieved with Cmd_Argc() / Cmd_Argv() ================= */ static void CG_ServerCommand(void) { const char *cmd; char text[MAX_SAY_TEXT]; cmd = CG_Argv(0); if(!cmd[0]) { // server claimed the command return; } if(!strcmp(cmd, "cp")) { CG_CenterPrint(CG_Argv(1), SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH); return; } if(!strcmp(cmd, "cs")) { CG_ConfigStringModified(); return; } if(!strcmp(cmd, "print")) { CG_Printf("%s", CG_Argv(1)); cmd = CG_Argv(1); // yes, this is obviously a hack, but so is the way we hear about // votes passing or failing if(!Q_stricmpn(cmd, "vote failed", 11) || !Q_stricmpn(cmd, "team vote failed", 16)) { trap_S_StartLocalSound(cgs.media.voteFailed, CHAN_ANNOUNCER); } else if(!Q_stricmpn(cmd, "vote passed", 11) || !Q_stricmpn(cmd, "team vote passed", 16)) { trap_S_StartLocalSound(cgs.media.votePassed, CHAN_ANNOUNCER); } return; } if(!strcmp(cmd, "chat")) { if(!cg_teamChatsOnly.integer) { trap_S_StartLocalSound(cgs.media.talkSound, CHAN_LOCAL_SOUND); Q_strncpyz(text, CG_Argv(1), MAX_SAY_TEXT); CG_RemoveChatEscapeChar(text); CG_Printf("%s\n", text); } return; } if(!strcmp(cmd, "tchat")) { trap_S_StartLocalSound(cgs.media.talkSound, CHAN_LOCAL_SOUND); Q_strncpyz(text, CG_Argv(1), MAX_SAY_TEXT); CG_RemoveChatEscapeChar(text); CG_AddToTeamChat(text); CG_Printf("%s\n", text); return; } if(!strcmp(cmd, "vchat")) { CG_VoiceChat(SAY_ALL); return; } if(!strcmp(cmd, "vtchat")) { CG_VoiceChat(SAY_TEAM); return; } if(!strcmp(cmd, "vtell")) { CG_VoiceChat(SAY_TELL); return; } if(!strcmp(cmd, "scores")) { CG_ParseScores(); return; } if(!strcmp(cmd, "tinfo")) { CG_ParseTeamInfo(); return; } if(!strcmp(cmd, "map_restart")) { CG_MapRestart(); return; } if(Q_stricmp(cmd, "remapShader") == 0) { if(trap_Argc() == 4) { char shader1[MAX_QPATH]; char shader2[MAX_QPATH]; char shader3[MAX_QPATH]; Q_strncpyz(shader1, CG_Argv(1), sizeof(shader1)); Q_strncpyz(shader2, CG_Argv(2), sizeof(shader2)); Q_strncpyz(shader3, CG_Argv(3), sizeof(shader3)); trap_R_RemapShader(shader1, shader2, shader3); } return; } // loaddeferred can be both a servercmd and a consolecmd if(!strcmp(cmd, "loaddeferred")) { CG_LoadDeferredPlayers(); return; } // clientLevelShot is sent before taking a special screenshot for // the menu system during development if(!strcmp(cmd, "clientLevelShot")) { cg.levelShot = qtrue; return; } if(!strcmp(cmd, "spWin")) { CG_spWin(); return; } if(!strcmp(cmd, "spLose")) { CG_spLose(); return; } CG_Printf("Unknown client game command: %s\n", cmd); }
/* ============= CG_Obituary ============= */ static void CG_Obituary( entityState_t *ent ) { int mod; int target, attacker; char *message; char *message2; const char *targetInfo; const char *attackerInfo; char targetName[32]; char attackerName[32]; gender_t gender; clientInfo_t *ci; target = ent->otherEntityNum; attacker = ent->otherEntityNum2; mod = ent->eventParm; if ( target < 0 || target >= MAX_CLIENTS ) { CG_Error( "CG_Obituary: target out of range" ); } ci = &cgs.clientinfo[target]; if ( attacker < 0 || attacker >= MAX_CLIENTS ) { attacker = ENTITYNUM_WORLD; attackerInfo = NULL; } else { attackerInfo = CG_ConfigString( CS_PLAYERS + attacker ); } targetInfo = CG_ConfigString( CS_PLAYERS + target ); if ( !targetInfo ) { return; } Q_strncpyz( targetName, Info_ValueForKey( targetInfo, "n" ), sizeof(targetName) - 2); strcat( targetName, S_COLOR_WHITE ); message2 = ""; // check for single client messages switch( mod ) { case MOD_SUICIDE: message = "suicides"; break; case MOD_FALLING: message = "cratered"; break; case MOD_CRUSH: message = "was squished"; break; case MOD_WATER: message = "sank like a rock"; break; case MOD_SLIME: message = "melted"; break; case MOD_LAVA: message = "does a back flip into the lava"; break; case MOD_TARGET_LASER: message = "saw the light"; break; case MOD_TRIGGER_HURT: message = "was in the wrong place"; break; default: message = NULL; break; } if (attacker == target) { gender = ci->gender; switch (mod) { #ifdef MISSIONPACK case MOD_KAMIKAZE: message = "goes out with a bang"; break; #endif case MOD_GRENADE_SPLASH: if ( gender == GENDER_FEMALE ) message = "tripped on her own grenade"; else if ( gender == GENDER_NEUTER ) message = "tripped on its own grenade"; else message = "tripped on his own grenade"; break; case MOD_ROCKET_SPLASH: if ( gender == GENDER_FEMALE ) message = "blew herself up"; else if ( gender == GENDER_NEUTER ) message = "blew itself up"; else message = "blew himself up"; break; case MOD_PLASMA_SPLASH: if ( gender == GENDER_FEMALE ) message = "melted herself"; else if ( gender == GENDER_NEUTER ) message = "melted itself"; else message = "melted himself"; break; case MOD_BFG_SPLASH: message = "should have used a smaller gun"; break; #ifdef MISSIONPACK case MOD_PROXIMITY_MINE: if( gender == GENDER_FEMALE ) { message = "found her prox mine"; } else if ( gender == GENDER_NEUTER ) { message = "found its prox mine"; } else { message = "found his prox mine"; } break; #endif default: if ( gender == GENDER_FEMALE ) message = "killed herself"; else if ( gender == GENDER_NEUTER ) message = "killed itself"; else message = "killed himself"; break; } } if (message) { CG_Printf( "%s %s.\n", targetName, message); return; } // check for kill messages from the current clientNum if ( attacker == cg.snap->ps.clientNum ) { char *s; if ( cgs.gametype < GT_TEAM ) { s = va("You fragged %s\n%s place with %i", targetName, CG_PlaceString( cg.snap->ps.persistant[PERS_RANK] + 1 ), cg.snap->ps.persistant[PERS_SCORE] ); } else { s = va("You fragged %s", targetName ); } #ifdef MISSIONPACK if (!(cg_singlePlayerActive.integer && cg_cameraOrbit.integer)) { CG_CenterPrint( s, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); } #else CG_CenterPrint( s, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); #endif // print the text message as well } // check for double client messages if ( !attackerInfo ) { attacker = ENTITYNUM_WORLD; strcpy( attackerName, "noname" ); } else { Q_strncpyz( attackerName, Info_ValueForKey( attackerInfo, "n" ), sizeof(attackerName) - 2); strcat( attackerName, S_COLOR_WHITE ); // check for kill messages about the current clientNum if ( target == cg.snap->ps.clientNum ) { Q_strncpyz( cg.killerName, attackerName, sizeof( cg.killerName ) ); } } if ( attacker != ENTITYNUM_WORLD ) { switch (mod) { case MOD_GRAPPLE: message = "was caught by"; break; case MOD_GAUNTLET: message = "was pummeled by"; break; case MOD_MACHINEGUN: message = "was machinegunned by"; break; case MOD_SHOTGUN: message = "was gunned down by"; break; case MOD_GRENADE: message = "ate"; message2 = "'s grenade"; break; case MOD_GRENADE_SPLASH: message = "was shredded by"; message2 = "'s shrapnel"; break; case MOD_ROCKET: message = "ate"; message2 = "'s rocket"; break; case MOD_ROCKET_SPLASH: message = "almost dodged"; message2 = "'s rocket"; break; case MOD_PLASMA: message = "was melted by"; message2 = "'s plasmagun"; break; case MOD_PLASMA_SPLASH: message = "was melted by"; message2 = "'s plasmagun"; break; case MOD_RAILGUN: message = "was railed by"; break; case MOD_LIGHTNING: message = "was electrocuted by"; break; case MOD_BFG: case MOD_BFG_SPLASH: message = "was blasted by"; message2 = "'s BFG"; break; #ifdef MISSIONPACK case MOD_NAIL: message = "was nailed by"; break; case MOD_CHAINGUN: message = "got lead poisoning from"; message2 = "'s Chaingun"; break; case MOD_PROXIMITY_MINE: message = "was too close to"; message2 = "'s Prox Mine"; break; case MOD_KAMIKAZE: message = "falls to"; message2 = "'s Kamikaze blast"; break; case MOD_JUICED: message = "was juiced by"; break; #endif case MOD_TELEFRAG: message = "tried to invade"; message2 = "'s personal space"; break; default: message = "was killed by"; break; } if (message) { CG_Printf( "%s %s %s%s\n", targetName, message, attackerName, message2); return; } } // we don't know what it was CG_Printf( "%s died.\n", targetName ); }
/* ============== CG_EntityEvent An entity has an event value also called by CG_CheckPlayerstateEvents ============== */ void CG_EntityEvent( centity_t *cent, vec3_t position ) { entityState_t *es; int event; vec3_t dir; const char *s; int clientNum; clientInfo_t *ci; int steptime; if ( cg.snap->ps.persistant[ PERS_SPECSTATE ] != SPECTATOR_NOT ) { steptime = 200; } else { steptime = BG_Class( cg.snap->ps.stats[ STAT_CLASS ] )->steptime; } es = ¢->currentState; event = es->event & ~EV_EVENT_BITS; if ( cg_debugEvents.integer ) { CG_Printf( "ent:%3i event:%3i %s\n", es->number, event, BG_EventName( event ) ); } if ( !event ) { return; } clientNum = es->clientNum; if ( clientNum < 0 || clientNum >= MAX_CLIENTS ) { clientNum = 0; } ci = &cgs.clientinfo[ clientNum ]; switch ( event ) { case EV_FOOTSTEP: if ( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) { if ( ci->footsteps == FOOTSTEP_CUSTOM ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, ci->customFootsteps[ rand() & 3 ] ); } else { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.footsteps[ ci->footsteps ][ rand() & 3 ] ); } } break; case EV_FOOTSTEP_METAL: if ( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) { if ( ci->footsteps == FOOTSTEP_CUSTOM ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, ci->customMetalFootsteps[ rand() & 3 ] ); } else { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_METAL ][ rand() & 3 ] ); } } break; case EV_FOOTSTEP_SQUELCH: if ( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_FLESH ][ rand() & 3 ] ); } break; case EV_FOOTSPLASH: if ( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][ rand() & 3 ] ); } break; case EV_FOOTWADE: if ( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][ rand() & 3 ] ); } break; case EV_SWIM: if ( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][ rand() & 3 ] ); } break; case EV_FALL_SHORT: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.landSound ); if ( clientNum == cg.predictedPlayerState.clientNum ) { // smooth landing z changes cg.landChange = -8; cg.landTime = cg.time; } break; case EV_FALL_MEDIUM: // use a general pain sound trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*pain100_1.wav" ) ); if ( clientNum == cg.predictedPlayerState.clientNum ) { // smooth landing z changes cg.landChange = -16; cg.landTime = cg.time; } break; case EV_FALL_FAR: trap_S_StartSound( NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*fall1.wav" ) ); cent->pe.painTime = cg.time; // don't play a pain sound right after this if ( clientNum == cg.predictedPlayerState.clientNum ) { // smooth landing z changes cg.landChange = -24; cg.landTime = cg.time; } break; case EV_FALLING: trap_S_StartSound( NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*falling1.wav" ) ); break; case EV_STEP_4: case EV_STEP_8: case EV_STEP_12: case EV_STEP_16: // smooth out step up transitions case EV_STEPDN_4: case EV_STEPDN_8: case EV_STEPDN_12: case EV_STEPDN_16: // smooth out step down transitions { float oldStep; int delta; int step; if ( clientNum != cg.predictedPlayerState.clientNum ) { break; } // if we are interpolating, we don't need to smooth steps if ( cg.demoPlayback || ( cg.snap->ps.pm_flags & PMF_FOLLOW ) || cg_nopredict.integer || cg_synchronousClients.integer ) { break; } // check for stepping up before a previous step is completed delta = cg.time - cg.stepTime; if ( delta < steptime ) { oldStep = cg.stepChange * ( steptime - delta ) / steptime; } else { oldStep = 0; } // add this amount if ( event >= EV_STEPDN_4 ) { step = 4 * ( event - EV_STEPDN_4 + 1 ); cg.stepChange = oldStep - step; } else { step = 4 * ( event - EV_STEP_4 + 1 ); cg.stepChange = oldStep + step; } if ( cg.stepChange > MAX_STEP_CHANGE ) { cg.stepChange = MAX_STEP_CHANGE; } else if ( cg.stepChange < -MAX_STEP_CHANGE ) { cg.stepChange = -MAX_STEP_CHANGE; } cg.stepTime = cg.time; break; } case EV_JUMP: trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*jump1.wav" ) ); if ( BG_ClassHasAbility( cg.predictedPlayerState.stats[ STAT_CLASS ], SCA_WALLJUMPER ) ) { vec3_t surfNormal, refNormal = { 0.0f, 0.0f, 1.0f }; vec3_t rotAxis; if ( clientNum != cg.predictedPlayerState.clientNum ) { break; } //set surfNormal VectorCopy( cg.predictedPlayerState.grapplePoint, surfNormal ); //if we are moving from one surface to another smooth the transition if ( !VectorCompare( surfNormal, cg.lastNormal ) && surfNormal[ 2 ] != 1.0f ) { CrossProduct( refNormal, surfNormal, rotAxis ); VectorNormalize( rotAxis ); //add the op CG_addSmoothOp( rotAxis, 15.0f, 1.0f ); } //copy the current normal to the lastNormal VectorCopy( surfNormal, cg.lastNormal ); } break; case EV_LEV1_GRAB: trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL1Grab ); break; case EV_LEV4_TRAMPLE_PREPARE: trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL4ChargePrepare ); break; case EV_LEV4_TRAMPLE_START: //FIXME: stop cgs.media.alienL4ChargePrepare playing here trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL4ChargeStart ); break; case EV_TAUNT: if ( !cg_noTaunt.integer ) { trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*taunt.wav" ) ); } break; case EV_WATER_TOUCH: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.watrInSound ); break; case EV_WATER_LEAVE: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.watrOutSound ); break; case EV_WATER_UNDER: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.watrUnSound ); break; case EV_WATER_CLEAR: trap_S_StartSound( NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*gasp.wav" ) ); break; case EV_JETPACK_ENABLE: // TODO: Trigger jetpack enable animation break; case EV_JETPACK_DISABLE: // TODO: Trigger jetpack disable animation break; case EV_JETPACK_START: // TODO: Start jetpack gfx/sfx break; case EV_JETPACK_STOP: // TODO: Stop jetpack gfx/sfx break; case EV_NOAMMO: trap_S_StartSound( NULL, es->number, CHAN_WEAPON, cgs.media.weaponEmptyClick ); break; case EV_CHANGE_WEAPON: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.selectSound ); break; case EV_FIRE_WEAPON: CG_HandleFireWeapon( cent, WPM_PRIMARY ); break; case EV_FIRE_WEAPON2: CG_HandleFireWeapon( cent, WPM_SECONDARY ); break; case EV_FIRE_WEAPON3: CG_HandleFireWeapon( cent, WPM_TERTIARY ); break; case EV_WEAPON_RELOAD: if ( cg_weapons[ es->eventParm ].wim[ WPM_PRIMARY ].reloadSound ) { trap_S_StartSound( NULL, es->number, CHAN_WEAPON, cg_weapons[ es->eventParm ].wim[ WPM_PRIMARY ].reloadSound ); } break; case EV_PLAYER_TELEPORT_IN: //deprecated break; case EV_PLAYER_TELEPORT_OUT: CG_PlayerDisconnect( position ); break; case EV_BUILD_CONSTRUCT: break; case EV_BUILD_DESTROY: break; case EV_AMMO_REFILL: case EV_CLIPS_REFILL: case EV_FUEL_REFILL: // TODO: Add different sounds for EV_AMMO_REFILL, EV_CLIPS_REFILL, EV_FUEL_REFILL trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.repeaterUseSound ); break; case EV_GRENADE_BOUNCE: if ( rand() & 1 ) { trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.hardBounceSound1 ); } else { trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.hardBounceSound2 ); } break; case EV_WEAPON_HIT_ENTITY: CG_HandleWeaponHitEntity( es, position ); break; case EV_WEAPON_HIT_ENVIRONMENT: CG_HandleWeaponHitWall( es, position ); break; case EV_MISSILE_HIT_ENTITY: CG_HandleMissileHitEntity( es, position ); break; // currently there is no support for metal sounds case EV_MISSILE_HIT_ENVIRONMENT: case EV_MISSILE_HIT_METAL: CG_HandleMissileHitWall( es, position ); break; case EV_SHOTGUN: CG_HandleFireShotgun( es ); break; case EV_HUMAN_BUILDABLE_DYING: CG_HumanBuildableDying( (buildable_t) es->modelindex, position ); break; case EV_HUMAN_BUILDABLE_EXPLOSION: ByteToDir( es->eventParm, dir ); CG_HumanBuildableExplosion( (buildable_t) es->modelindex, position, dir ); break; case EV_ALIEN_BUILDABLE_EXPLOSION: ByteToDir( es->eventParm, dir ); CG_AlienBuildableExplosion( position, dir ); break; case EV_TESLATRAIL: cent->currentState.weapon = WP_TESLAGEN; { centity_t *source = &cg_entities[ es->generic1 ]; centity_t *target = &cg_entities[ es->clientNum ]; vec3_t sourceOffset = { 0.0f, 0.0f, 28.0f }; if ( !CG_IsTrailSystemValid( &source->muzzleTS ) ) { source->muzzleTS = CG_SpawnNewTrailSystem( cgs.media.teslaZapTS ); if ( CG_IsTrailSystemValid( &source->muzzleTS ) ) { CG_SetAttachmentCent( &source->muzzleTS->frontAttachment, source ); CG_SetAttachmentCent( &source->muzzleTS->backAttachment, target ); CG_AttachToCent( &source->muzzleTS->frontAttachment ); CG_AttachToCent( &source->muzzleTS->backAttachment ); CG_SetAttachmentOffset( &source->muzzleTS->frontAttachment, sourceOffset ); source->muzzleTSDeathTime = cg.time + cg_teslaTrailTime.integer; } } } break; case EV_GENERAL_SOUND: if ( cgs.gameSounds[ es->eventParm ] ) { trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.gameSounds[ es->eventParm ] ); } else { s = CG_ConfigString( CS_SOUNDS + es->eventParm ); trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, s ) ); } break; case EV_GLOBAL_SOUND: // play from the player's head so it never diminishes if ( cgs.gameSounds[ es->eventParm ] ) { trap_S_StartSound( NULL, cg.snap->ps.clientNum, CHAN_AUTO, cgs.gameSounds[ es->eventParm ] ); } else { s = CG_ConfigString( CS_SOUNDS + es->eventParm ); trap_S_StartSound( NULL, cg.snap->ps.clientNum, CHAN_AUTO, CG_CustomSound( es->number, s ) ); } break; case EV_PAIN: // local player sounds are triggered in CG_CheckLocalSounds, // so ignore events on the player if ( cent->currentState.number != cg.snap->ps.clientNum ) { CG_PainEvent( cent, es->eventParm ); } break; case EV_DEATH1: case EV_DEATH2: case EV_DEATH3: trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, va( "*death%i.wav", event - EV_DEATH1 + 1 ) ) ); break; case EV_OBITUARY: CG_Obituary( es ); break; case EV_GIB_PLAYER: // no gibbing break; case EV_STOPLOOPINGSOUND: trap_S_StopLoopingSound( es->number ); es->loopSound = 0; break; case EV_DEBUG_LINE: CG_Beam( cent ); break; case EV_BUILD_DELAY: if ( clientNum == cg.predictedPlayerState.clientNum ) { trap_S_StartLocalSound( cgs.media.buildableRepairedSound, CHAN_LOCAL_SOUND ); cg.lastBuildAttempt = cg.time; } break; case EV_BUILD_REPAIR: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.buildableRepairSound ); break; case EV_BUILD_REPAIRED: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.buildableRepairedSound ); break; case EV_OVERMIND_ATTACK_1: case EV_OVERMIND_ATTACK_2: if ( cg.predictedPlayerState.persistant[ PERS_TEAM ] == TEAM_ALIENS ) { trap_S_StartLocalSound( cgs.media.alienOvermindAttack, CHAN_ANNOUNCER ); CG_CenterPrint( va( "^%c%s", "31"[ event - EV_OVERMIND_ATTACK_1 ], _( "The Overmind is under attack!" ) ), 200, GIANTCHAR_WIDTH * 4 ); } break; case EV_OVERMIND_DYING: if ( cg.predictedPlayerState.persistant[ PERS_TEAM ] == TEAM_ALIENS ) { trap_S_StartLocalSound( cgs.media.alienOvermindDying, CHAN_ANNOUNCER ); CG_CenterPrint( _( "^1The Overmind is dying!" ), 200, GIANTCHAR_WIDTH * 4 ); } break; case EV_REACTOR_ATTACK_1: case EV_REACTOR_ATTACK_2: if ( cg.predictedPlayerState.persistant[ PERS_TEAM ] == TEAM_HUMANS ) { CG_CenterPrint( va( "^%c%s", "31"[ event - EV_REACTOR_ATTACK_1 ], _( "The reactor is under attack!" ) ), 200, GIANTCHAR_WIDTH * 4 ); } break; case EV_REACTOR_DYING: if ( cg.predictedPlayerState.persistant[ PERS_TEAM ] == TEAM_HUMANS ) { CG_CenterPrint( _( "^1The reactor is about to explode!" ), 200, GIANTCHAR_WIDTH * 4 ); } break; case EV_WARN_ATTACK: // if eventParm is non-zero, this is for humans and there's a nearby reactor or repeater, otherwise it's for aliens if ( es->eventParm >= MAX_CLIENTS && es->eventParm < MAX_GENTITIES ) { const char *location; qboolean base = cg_entities[ es->eventParm ].currentState.modelindex == BA_H_REACTOR; centity_t *locent = CG_GetLocation( cg_entities[ es->eventParm ].currentState.origin ); CG_CenterPrint( base ? _( "Our base is under attack!" ) : _( "A forward base is under attack!" ), 200, GIANTCHAR_WIDTH * 4 ); if ( locent ) { location = CG_ConfigString( CS_LOCATIONS + locent->currentState.generic1 ); } else { location = CG_ConfigString( CS_LOCATIONS ); } if ( location && *location ) { Com_Printf( _( "%s Under attack – %s\n" ), base ? "[reactor]" : "[repeater]", location ); } else { Com_Printf( _( "%s Under attack\n" ), base ? "[reactor]" : "[repeater]" ); } } else // this is for aliens, and the overmind is in range { CG_CenterPrint( _( "Our base is under attack!" ), 200, GIANTCHAR_WIDTH * 4 ); } break; case EV_MGTURRET_SPINUP: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.turretSpinupSound ); break; case EV_OVERMIND_SPAWNS: if ( cg.predictedPlayerState.persistant[ PERS_TEAM ] == TEAM_ALIENS ) { trap_S_StartLocalSound( cgs.media.alienOvermindSpawns, CHAN_ANNOUNCER ); CG_CenterPrint( "The Overmind needs spawns!", 200, GIANTCHAR_WIDTH * 4 ); } break; case EV_ALIEN_EVOLVE: trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.alienEvolveSound ); { particleSystem_t *ps = CG_SpawnNewParticleSystem( cgs.media.alienEvolvePS ); if ( CG_IsParticleSystemValid( &ps ) ) { CG_SetAttachmentCent( &ps->attachment, cent ); CG_AttachToCent( &ps->attachment ); } } if ( es->number == cg.clientNum ) { CG_ResetPainBlend(); cg.spawnTime = cg.time; } break; case EV_ALIEN_EVOLVE_FAILED: if ( clientNum == cg.predictedPlayerState.clientNum ) { //FIXME: change to "negative" sound trap_S_StartLocalSound( cgs.media.buildableRepairedSound, CHAN_LOCAL_SOUND ); cg.lastEvolveAttempt = cg.time; } break; case EV_ALIEN_ACIDTUBE: { particleSystem_t *ps = CG_SpawnNewParticleSystem( cgs.media.alienAcidTubePS ); if ( CG_IsParticleSystemValid( &ps ) ) { CG_SetAttachmentCent( &ps->attachment, cent ); ByteToDir( es->eventParm, dir ); CG_SetParticleSystemNormal( ps, dir ); CG_AttachToCent( &ps->attachment ); } } break; case EV_MEDKIT_USED: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.medkitUseSound ); break; case EV_PLAYER_RESPAWN: if ( es->number == cg.clientNum ) { cg.spawnTime = cg.time; } break; case EV_LEV2_ZAP: CG_Level2Zap( es ); break; case EV_HIT: cg.hitTime = cg.time; break; case EV_MOMENTUM: CG_Momentum( es ); break; default: CG_Error( "Unknown event: %i", event ); } }
/* ============= CG_Obituary ============= */ static void CG_Obituary( entityState_t *ent ) { int mod; int target, attacker; int attackerClass = -1; const char *message; const char *targetInfo; const char *attackerInfo; char targetName[ MAX_NAME_LENGTH ]; char attackerName[ MAX_NAME_LENGTH ]; gender_t gender; clientInfo_t *ci; qboolean teamKill = qfalse; qboolean attackerFirst = qfalse; target = ent->otherEntityNum; attacker = ent->otherEntityNum2; mod = ent->eventParm; if ( target < 0 || target >= MAX_CLIENTS ) { CG_Error( "CG_Obituary: target out of range" ); } ci = &cgs.clientinfo[ target ]; gender = ci->gender; if ( attacker < 0 || attacker >= MAX_CLIENTS ) { attacker = ENTITYNUM_WORLD; attackerInfo = NULL; } else { attackerInfo = CG_ConfigString( CS_PLAYERS + attacker ); if ( cgs.clientinfo[ attacker ].team == ci->team ) { teamKill = qtrue; } } targetInfo = CG_ConfigString( CS_PLAYERS + target ); if ( !targetInfo ) { return; } Q_strncpyz( targetName, Info_ValueForKey( targetInfo, "n" ), sizeof( targetName ) ); // check for single client messages switch ( mod ) { case MOD_FALLING: message = G_( "%s ^7fell foul to gravity\n" ); break; case MOD_CRUSH: message = G_( "%s ^7was squished\n" ); break; case MOD_WATER: message = G_( "%s ^7forgot to pack a snorkel\n" ); break; case MOD_SLIME: message = G_( "%s ^7melted\n" ); break; case MOD_LAVA: message = G_( "%s ^7did a back flip into the lava\n" ); break; case MOD_TARGET_LASER: message = G_( "%s ^7saw the light\n" ); break; case MOD_TRIGGER_HURT: message = G_( "%s ^7was in the wrong place\n" ); break; case MOD_HSPAWN: message = G_( "%s ^7should have run further\n" ); break; case MOD_ASPAWN: message = G_( "%s ^7shouldn't have trod in the acid\n" ); break; case MOD_MGTURRET: if ( cg_emoticonsInMessages.integer ) { message = "[turret] %s\n"; } else { message = G_( "%s ^7was gunned down by a turret\n" ); } break; case MOD_TESLAGEN: if ( cg_emoticonsInMessages.integer ) { message = "[tesla] %s\n"; } else { message = G_( "%s ^7was zapped by a tesla generator\n" ); } break; case MOD_ATUBE: if ( cg_emoticonsInMessages.integer ) { message = "[acidtube] %s\n"; } else { message = G_( "%s ^7was melted by an acid tube\n" ); } break; case MOD_OVERMIND: if ( cg_emoticonsInMessages.integer ) { message = "[overmind] %s\n"; } else { message = G_( "%s ^7got too close to the overmind\n" ); } break; case MOD_REACTOR: if ( cg_emoticonsInMessages.integer ) { message = "[reactor] %s\n"; } else { message = G_( "%s ^7got too close to the reactor\n" ); } break; case MOD_SLOWBLOB: message = G_( "%s ^7should have visited a medical station\n" ); break; case MOD_SWARM: if ( cg_emoticonsInMessages.integer ) { message = "[hive] %s\n"; } else { message = G_( "%s ^7was hunted down by the swarm\n" ); } break; default: message = NULL; break; } if ( !message && attacker == target ) { switch ( mod ) { case MOD_FLAMER_SPLASH: if ( cg_emoticonsInMessages.integer ) { message = "[flamer] %s\n"; } else { message = G_( "%s ^7toasted self\n" ); } break; case MOD_BURN: if ( cg_emoticonsInMessages.integer ) { message = "[fire] %s\n"; } else { message = G_( "%s ^7burned self\n" ); } break; case MOD_LCANNON_SPLASH: if ( cg_emoticonsInMessages.integer ) { message = "[lcannon] %s\n"; } else { message = G_( "%s ^7irradiated self\n" ); } break; case MOD_GRENADE: if ( cg_emoticonsInMessages.integer ) { message = "[grenade] %s\n"; } else // fall-through case MOD_FIREBOMB: if ( cg_emoticonsInMessages.integer ) { message = "[firebomb] %s\n"; } else { message = G_( "%s ^7blew self up\n" ); } break; case MOD_LEVEL3_BOUNCEBALL: if ( cg_emoticonsInMessages.integer ) { message = "[advdragoon] %s\n"; } else { message = G_( "%s ^7sniped self\n" ); } break; case MOD_PRIFLE: if ( cg_emoticonsInMessages.integer ) { message = "[prifle] %s\n"; } else { message = G_( "%s ^7pulse rifled self\n" ); } break; default: message = G_( "%s ^7killed self\n" ); break; } } if ( message ) { CG_Printf( message, targetName ); return; } // check for double client messages if ( !attackerInfo ) { attacker = ENTITYNUM_WORLD; strcpy( attackerName, "noname" ); } else { Q_strncpyz( attackerName, Info_ValueForKey( attackerInfo, "n" ), sizeof( attackerName ) ); // check for kill messages about the current clientNum if ( target == cg.snap->ps.clientNum ) { Q_strncpyz( cg.killerName, attackerName, sizeof( cg.killerName ) ); } } if ( attacker != ENTITYNUM_WORLD ) { switch ( mod ) { case MOD_PAINSAW: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [painsaw] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was sawn by %s%s\n" ); } break; case MOD_BLASTER: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [blaster] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was blasted by %s%s\n" ); } break; case MOD_MACHINEGUN: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [rifle] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was machinegunned by %s%s\n" ); } break; case MOD_CHAINGUN: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [chaingun] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was chaingunned by %s%s\n" ); } break; case MOD_SHOTGUN: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [shotgun] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was gunned down by %s%s\n" ); } break; case MOD_PRIFLE: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [prifle] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was pulse rifled by %s%s\n" ); } break; case MOD_MDRIVER: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [mdriver] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was mass driven by %s%s\n" ); } break; case MOD_LASGUN: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [lasgun] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was lasgunned by %s%s\n" ); } break; case MOD_FLAMER: case MOD_FLAMER_SPLASH: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [flamer] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was grilled by %s%s^7's flamer\n" ); } break; case MOD_BURN: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [flamer] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was burned by %s%s^7's fire\n" ); } break; case MOD_LCANNON: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [lcannon] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7felt the full force of %s%s^7's lucifer cannon\n" ); } break; case MOD_LCANNON_SPLASH: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [lcannon] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was caught in the fallout of %s%s^7's lucifer cannon\n" ); } break; case MOD_GRENADE: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [grenade] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7couldn't escape %s%s^7's grenade\n" ); } break; case MOD_FIREBOMB: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [firebomb] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7couldn't escape %s%s^7's firebomb\n" ); } break; case MOD_ABUILDER_CLAW: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [granger] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7should leave %s%s^7's buildings alone\n" ); } break; case MOD_LEVEL0_BITE: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [dretch] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was bitten by %s%s\n" ); } break; case MOD_LEVEL1_CLAW: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [basilisk] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was swiped by %s%s^7's %s\n" ); attackerClass = PCL_ALIEN_LEVEL1; } break; case MOD_LEVEL2_CLAW: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [marauder] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was clawed by %s%s^7's %s\n" ); attackerClass = PCL_ALIEN_LEVEL2; } break; case MOD_LEVEL2_ZAP: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [advmarauder] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was zapped by %s%s^7's %s\n" ); attackerClass = PCL_ALIEN_LEVEL2; } break; case MOD_LEVEL3_CLAW: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [dragoon] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was chomped by %s%s^7's %s\n" ); attackerClass = PCL_ALIEN_LEVEL3; } break; case MOD_LEVEL3_POUNCE: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [dragoon] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was pounced upon by %s%s^7's %s\n" ); attackerClass = PCL_ALIEN_LEVEL3; } break; case MOD_LEVEL3_BOUNCEBALL: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [advdragoon] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was sniped by %s%s^7's %s\n" ); attackerClass = PCL_ALIEN_LEVEL3; } break; case MOD_LEVEL4_CLAW: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [tyrant] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was mauled by %s%s^7's %s\n" ); attackerClass = PCL_ALIEN_LEVEL4; } break; case MOD_LEVEL4_TRAMPLE: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [tyrant] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7should have gotten out of the way of %s%s^7's %s\n" ); attackerClass = PCL_ALIEN_LEVEL4; } break; case MOD_WEIGHT_H: case MOD_WEIGHT_A: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 crushed %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was crushed under %s%s^7's weight\n" ); } break; case MOD_POISON: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [booster] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7should have used a medkit against %s%s^7's poison\n" ); } break; case MOD_LEVEL1_PCLOUD: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [advbasilisk] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7was gassed by %s%s^7's %s\n" ); attackerClass = PCL_ALIEN_LEVEL1; } break; case MOD_TELEFRAG: if ( cg_emoticonsInMessages.integer ) { message = "%s%s^7 [telenode] %s\n"; attackerFirst = qtrue; } else { message = G_( "%s ^7tried to invade %s%s^7's personal space\n" ); } break; default: message = G_( "%s ^7was killed by %s%s\n" ); break; } if ( message ) { if ( attackerFirst ) { // Argument order: "TEAMMATE"/"", attacker, victim CG_Printf( message, ( teamKill ) ? _("^1TEAMMATE^7 ") : "", attackerName, targetName ); } else { // Argument order: victim, ["TEAMMATE"/"", attacker [, alien class]] CG_Printf( message, targetName, ( teamKill ) ? _("^1TEAMMATE^7 ") : "", attackerName, ( attackerClass != -1 ) ? _( BG_ClassModelConfig( attackerClass )->humanName ) : NULL ); } if ( teamKill && attacker == cg.clientNum ) { CG_CenterPrint( va( _("You killed ^1TEAMMATE^7 %s"), targetName ), SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); } return; } } // we don't know what it was CG_Printf( G_( "%s^7 died\n" ), targetName ); }