void CG_PrevWeapon_f( void ) { int i, original; if ( !cg.snap || CG_IsSpectating() ) return; if ( cg.snap->ps.emplacedIndex ) return; cg.weaponSelectTime = cg.time; original = cg.weaponSelect; for ( i = 0; i < WP_NUM_WEAPONS; i++ ) { //*SIGH*... Hack to put concussion rifle before rocketlauncher if ( cg.weaponSelect == WP_ROCKET_LAUNCHER ) cg.weaponSelect = WP_CONCUSSION; else if ( cg.weaponSelect == WP_CONCUSSION ) cg.weaponSelect = WP_FLECHETTE; else if ( cg.weaponSelect == WP_BRYAR_OLD ) cg.weaponSelect = WP_DET_PACK; else cg.weaponSelect--; if ( cg.weaponSelect == -1 ) cg.weaponSelect = WP_NUM_WEAPONS - 1; if ( CG_WeaponSelectable( cg.weaponSelect ) ) break; } if ( i == WP_NUM_WEAPONS ) cg.weaponSelect = original; else trap->S_MuteSound( cg.snap->ps.clientNum, CHAN_WEAPON ); }
/* =============== CG_PrevWeapon_f =============== */ void CG_PrevWeapon_f( void ) { int i; int original; if( !cg.snap ) return; if( cg.snap->ps.pm_flags & PMF_FOLLOW ) { trap_SendClientCommand( "follownext\n" ); return; } if( BG_Buildable(cg.snap->ps.stats[STAT_BUILDABLE]&~SB_VALID_TOGGLEBIT,NULL)->cuboid ) { CG_CuboidResize(qfalse); return; } cg.weaponSelectTime = cg.time; original = cg.weaponSelect; for( i = 0; i < 64; i++ ) { cg.weaponSelect--; if( cg.weaponSelect == -1 ) cg.weaponSelect = 63; if( cg.weaponSelect < 32 ) { if( CG_WeaponSelectable( cg.weaponSelect ) ) break; } else { if( CG_UpgradeSelectable( cg.weaponSelect - 32 ) ) break; } } if( i == 64 ) cg.weaponSelect = original; }
// The current weapon has just run out of ammo void CG_OutOfAmmoChange( int oldWeapon ) { int i; cg.weaponSelectTime = cg.time; for ( i = LAST_USEABLE_WEAPON; i > 0; i-- ) { // We don't want the emplaced or turret if ( CG_WeaponSelectable( i ) ) { //rww - Don't we want to make sure i != one of these if autoswitch is 1 (safe)? if ( cg_autoSwitch.integer != 1 || (i != WP_TRIP_MINE && i != WP_DET_PACK && i != WP_THERMAL && i != WP_ROCKET_LAUNCHER) ) { if ( i != oldWeapon ) { // don't even do anything if we're just selecting the weapon we already have/had cg.weaponSelect = i; break; } } } } trap->S_MuteSound( cg.snap->ps.clientNum, CHAN_WEAPON ); }
/* =============== CG_PrevWeapon_f =============== */ void CG_PrevWeapon_f( void ) { int i; int original; if( !cg.snap ) return; if( cg.snap->ps.pm_flags & PMF_FOLLOW ) { trap_SendClientCommand( "follownext\n" ); return; } cg.weaponSelectTime = cg.time; original = cg.weaponSelect; for( i = 0; i < 64; i++ ) { cg.weaponSelect--; if( cg.weaponSelect == -1 ) cg.weaponSelect = 63; if( cg.weaponSelect <= 32 ) { if( CG_WeaponSelectable( cg.weaponSelect ) ) break; } else if( cg.weaponSelect > 32 ) { if( CG_UpgradeSelectable( cg.weaponSelect - 32 ) ) break; } } if( i == 64 ) cg.weaponSelect = original; }
void CG_Weapon_f( void ) { int num; if ( !cg.snap || CG_IsSpectating() || cg.snap->ps.emplacedIndex ) return; num = atoi( CG_Argv( 1 ) ); if ( num < 1 || num > LAST_USEABLE_WEAPON ) return; if ( num == 1 && cg.snap->ps.weapon == WP_SABER ) { if ( cg.snap->ps.weaponTime < 1 ) trap->SendConsoleCommand( "sv_saberswitch\n" ); return; } //rww - hack to make weapon numbers same as single player if ( num > WP_STUN_BATON ) num += 2; else { if ( cg.snap->ps.stats[STAT_WEAPONS] & (1 << WP_SABER) ) num = WP_SABER; else num = WP_MELEE; } if ( num > LAST_USEABLE_WEAPON + 1 ) return; if ( num >= WP_THERMAL && num <= WP_DET_PACK ) { int weap, i = 0; // already in cycle range so start with next cycle item if ( cg.snap->ps.weapon >= WP_THERMAL && cg.snap->ps.weapon <= WP_DET_PACK ) weap = cg.snap->ps.weapon + 1; else // not in cycle range, so start with thermal detonator weap = WP_THERMAL; // prevent an endless loop while ( i <= 4 ) { if ( weap > WP_DET_PACK ) weap = WP_THERMAL; if ( CG_WeaponSelectable( weap ) ) { num = weap; break; } weap++; i++; } } if ( !CG_WeaponSelectable( num ) ) return; cg.weaponSelectTime = cg.time; if ( !(cg.snap->ps.stats[STAT_WEAPONS] & (1 << num)) ) { if ( num == WP_SABER ) { // don't have saber, try melee on the same slot num = WP_MELEE; if ( !(cg.snap->ps.stats[STAT_WEAPONS] & (1 << num)) ) return; } else return; // don't have the weapon } if ( cg.weaponSelect != num ) trap->S_MuteSound( cg.snap->ps.clientNum, CHAN_WEAPON ); cg.weaponSelect = num; }
void CG_DrawWeaponSelect( void ) { int i, bits, count, smallIconSize, bigIconSize, holdX, x, y, pad, sideLeftIconCnt, sideRightIconCnt, sideMax, holdCount, iconCnt, yOffset = 0; qboolean drewConc = qfalse; // can't cycle when on a weapon if ( cg.predictedPlayerState.emplacedIndex ) cg.weaponSelectTime = 0; // Time is up for the HUD to display if ( (cg.weaponSelectTime + WEAPON_SELECT_TIME) < cg.time ) return; // don't display if dead if ( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 ) return; // showing weapon select clears pickup item display, but not the blend blob cg.itemPickupTime = 0; bits = cg.predictedPlayerState.stats[STAT_WEAPONS]; // count the number of weapons owned count = 0; // display this weapon that we don't actually "have" as unhighlighted until it's deselected // since it's selected we must increase the count to display the proper number of valid selectable weapons if ( !CG_WeaponSelectable( cg.weaponSelect ) && (cg.weaponSelect == WP_THERMAL || cg.weaponSelect == WP_TRIP_MINE) ) count++; for ( i = 1; i < WP_NUM_WEAPONS; i++ ) { if ( bits & (1 << i) ) { if ( CG_WeaponSelectable( i ) || (i != WP_THERMAL && i != WP_TRIP_MINE) ) count++; } } if ( !count ) // If no weapons, don't display return; sideMax = 3; // Max number of icons on the side // Calculate how many icons will appear to either side of the center one holdCount = count - 1; // -1 for the center icon if ( holdCount == 0 ) { // No icons to either side sideLeftIconCnt = 0; sideRightIconCnt = 0; } else if ( count > (2 * sideMax) ) { // Go to the max on each side sideLeftIconCnt = sideMax; sideRightIconCnt = sideMax; } else { // Less than max, so do the calc sideLeftIconCnt = holdCount / 2; sideRightIconCnt = holdCount - sideLeftIconCnt; } if ( cg.weaponSelect == WP_CONCUSSION ) i = WP_FLECHETTE; else i = cg.weaponSelect - 1; if ( i < 1 ) i = LAST_USEABLE_WEAPON; smallIconSize = 40; bigIconSize = 80; pad = 12; x = (SCREEN_WIDTH / 2); y = 410; // Left side ICONS trap->R_SetColor( &colorTable[CT_WHITE] ); // Work backwards from current icon holdX = x - ((bigIconSize / 2) + pad + smallIconSize) * cgs.widthRatioCoef; drewConc = qfalse; for ( iconCnt = 1; iconCnt < (sideLeftIconCnt + 1); i-- ) { if ( i == WP_CONCUSSION ) i--; else if ( i == WP_FLECHETTE && !drewConc && cg.weaponSelect != WP_CONCUSSION ) i = WP_CONCUSSION; if ( i < 1 ) i = LAST_USEABLE_WEAPON; // Does he have this weapon? if ( !(bits & (1 << i)) ) { if ( i == WP_CONCUSSION ) { drewConc = qtrue; i = WP_ROCKET_LAUNCHER; } continue; } // Don't show thermal and tripmine when out of them if ( !CG_WeaponSelectable( i ) && (i == WP_THERMAL || i == WP_TRIP_MINE) ) continue; ++iconCnt; // Good icon if ( media.gfx.interface.weaponIcons[i] ) { CG_RegisterWeapon( i ); trap->R_SetColor( &colorTable[CT_WHITE] ); if ( !CG_WeaponCheck( i ) ) CG_DrawPic(holdX, y + 10 + yOffset, smallIconSize * cgs.widthRatioCoef, smallIconSize, media.gfx.interface.weaponIconsInactive[i]); else CG_DrawPic(holdX, y + 10 + yOffset, smallIconSize * cgs.widthRatioCoef, smallIconSize, media.gfx.interface.weaponIcons[i]); holdX -= (smallIconSize + pad) * cgs.widthRatioCoef; } if ( i == WP_CONCUSSION ) { drewConc = qtrue; i = WP_ROCKET_LAUNCHER; } } // Current Center Icon if ( media.gfx.interface.weaponIcons[cg.weaponSelect] ) { CG_RegisterWeapon( cg.weaponSelect ); trap->R_SetColor( &colorTable[CT_WHITE] ); if ( !CG_WeaponCheck( cg.weaponSelect ) ) CG_DrawPic(x - (bigIconSize / 2 * cgs.widthRatioCoef), (y - ((bigIconSize - smallIconSize) / 2)) + 10 + yOffset, bigIconSize * cgs.widthRatioCoef, bigIconSize, media.gfx.interface.weaponIconsInactive[cg.weaponSelect]); else CG_DrawPic(x - (bigIconSize / 2 * cgs.widthRatioCoef), (y - ((bigIconSize - smallIconSize) / 2)) + 10 + yOffset, bigIconSize * cgs.widthRatioCoef, bigIconSize, media.gfx.interface.weaponIcons[cg.weaponSelect]); } if ( cg.weaponSelect == WP_CONCUSSION ) i = WP_ROCKET_LAUNCHER; else i = cg.weaponSelect + 1; if ( i > LAST_USEABLE_WEAPON ) i = 1; // Right side ICONS // Work forwards from current icon holdX = x + ((bigIconSize / 2) + pad) * cgs.widthRatioCoef; for ( iconCnt = 1; iconCnt<(sideRightIconCnt + 1); i++ ) { if ( i == WP_CONCUSSION ) i++; else if ( i == WP_ROCKET_LAUNCHER && !drewConc && cg.weaponSelect != WP_CONCUSSION ) i = WP_CONCUSSION; if ( i > LAST_USEABLE_WEAPON ) i = 1; if ( !(bits & (1 << i)) ) { if ( i == WP_CONCUSSION ) { drewConc = qtrue; i = WP_FLECHETTE; } continue; } // Don't show thermal and tripmine when out of them if ( !CG_WeaponSelectable( i ) && (i == WP_THERMAL || i == WP_TRIP_MINE) ) continue; ++iconCnt; // Good icon if ( media.gfx.interface.weaponIcons[i] ) { CG_RegisterWeapon( i ); // No ammo for this weapon? trap->R_SetColor( &colorTable[CT_WHITE] ); if ( !CG_WeaponCheck( i ) ) CG_DrawPic(holdX, y + 10 + yOffset, smallIconSize * cgs.widthRatioCoef, smallIconSize, media.gfx.interface.weaponIconsInactive[i]); else CG_DrawPic(holdX, y + 10 + yOffset, smallIconSize * cgs.widthRatioCoef, smallIconSize, media.gfx.interface.weaponIcons[i]); holdX += (smallIconSize + pad); } if ( i == WP_CONCUSSION ) { drewConc = qtrue; i = WP_FLECHETTE; } } // draw the selected name if ( cg_weapons[cg.weaponSelect].item ) { vector4 textColor = { .875f, .718f, .121f, 1.0f }; char upperKey[1024]; Com_sprintf( upperKey, sizeof(upperKey), "SP_INGAME_%s", cg_weapons[cg.weaponSelect].item->classname ); Q_strupr( upperKey ); const char *s = nullptr; char text[1024]; if ( trap->SE_GetStringTextString( upperKey, text, sizeof(text) ) ) { s = text; } else { s = cg_weapons[cg.weaponSelect].item->classname; } const Font font( FONT_SMALL, 1.0f, false ); const float width = font.Width( s ); font.Paint( (SCREEN_WIDTH / 2) - (width / 2.0f), y + 45 + yOffset, s, &textColor, ITEM_TEXTSTYLE_SHADOWED ); } trap->R_SetColor( NULL ); }
// Version of the above which doesn't add +2 to a weapon. The above can't trigger WP_MELEE or WP_STUN_BATON. // Derogatory comments go here. void CG_WeaponClean_f( void ) { int num; if ( !cg.snap || CG_IsSpectating() || cg.snap->ps.emplacedIndex ) return; num = atoi( CG_Argv( 1 ) ); if ( num < 1 || num > LAST_USEABLE_WEAPON ) return; if ( num == 1 && cg.snap->ps.weapon == WP_SABER ) { if ( cg.predictedPlayerState.weaponTime < 1 ) trap->SendConsoleCommand( "sv_saberswitch\n" ); return; } if ( num == WP_STUN_BATON ) { if ( cg.snap->ps.stats[STAT_WEAPONS] & (1 << WP_SABER) ) num = WP_SABER; else num = WP_MELEE; } // other weapons are off limits due to not actually being weapon weapons if ( num > LAST_USEABLE_WEAPON + 1 ) return; if ( num >= WP_THERMAL && num <= WP_DET_PACK ) { int weap, i; if ( cg.snap->ps.weapon >= WP_THERMAL && cg.snap->ps.weapon <= WP_DET_PACK ) weap = cg.snap->ps.weapon + 1; else weap = WP_THERMAL; // prevent an endless loop for ( i = 0; i <= 4; i++ ) { if ( weap > WP_DET_PACK ) weap = WP_THERMAL; if ( CG_WeaponSelectable( weap ) ) { num = weap; break; } weap++; } } if ( !CG_WeaponSelectable( num ) ) return; cg.weaponSelectTime = cg.time; if ( !(cg.snap->ps.stats[STAT_WEAPONS] & (1 << num)) ) { if ( num == WP_SABER ) { // don't have saber, try melee on the same slot num = WP_MELEE; if ( !(cg.snap->ps.stats[STAT_WEAPONS] & (1 << num)) ) return; } else return; // don't have the weapon } if ( cg.weaponSelect != num ) trap->S_MuteSound( cg.snap->ps.clientNum, CHAN_WEAPON ); cg.weaponSelect = num; }
/* =================== CG_DrawItemSelect =================== */ void CG_DrawItemSelect( rectDef_t *rect, vec4_t color ) { int i; int x = rect->x; int y = rect->y; int width = rect->w; int height = rect->h; int iconsize; int items[ 64 ]; int numItems = 0, selectedItem = 0; int length; int selectWindow; qboolean vertical; centity_t *cent; playerState_t *ps; cent = &cg_entities[ cg.snap->ps.clientNum ]; ps = &cg.snap->ps; // don't display if dead if( cg.predictedPlayerState.stats[ STAT_HEALTH ] <= 0 ) return; if( !( cg.snap->ps.pm_flags & PMF_FOLLOW ) ) { // first make sure that whatever it selected is actually selectable if( cg.weaponSelect <= 32 && !CG_WeaponSelectable( cg.weaponSelect ) ) CG_NextWeapon_f( ); else if( cg.weaponSelect > 32 && !CG_UpgradeSelectable( cg.weaponSelect - 32 ) ) CG_NextWeapon_f( ); } // showing weapon select clears pickup item display, but not the blend blob cg.itemPickupTime = 0; if( height > width ) { vertical = qtrue; iconsize = width; length = height / width; } else if( height <= width ) { vertical = qfalse; iconsize = height; length = width / height; } selectWindow = length / 2; for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) { if( !BG_InventoryContainsWeapon( i, cg.snap->ps.stats ) ) continue; if( i == cg.weaponSelect ) selectedItem = numItems; CG_RegisterWeapon( i ); items[ numItems ] = i; numItems++; } for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) { if( !BG_InventoryContainsUpgrade( i, cg.snap->ps.stats ) ) continue; if( i == cg.weaponSelect - 32 ) selectedItem = numItems; CG_RegisterUpgrade( i ); items[ numItems ] = i + 32; numItems++; } for( i = 0; i < length; i++ ) { int displacement = i - selectWindow; int item = displacement + selectedItem; if( ( item >= 0 ) && ( item < numItems ) ) { trap_R_SetColor( color ); if( items[ item ] <= 32 ) CG_DrawPic( x, y, iconsize, iconsize, cg_weapons[ items[ item ] ].weaponIcon ); else if( items[ item ] > 32 ) CG_DrawPic( x, y, iconsize, iconsize, cg_upgrades[ items[ item ] - 32 ].upgradeIcon ); trap_R_SetColor( NULL ); } if( vertical ) y += iconsize; else x += iconsize; } }
/* =================== CG_DrawItemSelect =================== */ void CG_DrawItemSelect( rectDef_t *rect, vec4_t color ) { int i; float x = rect->x; float y = rect->y; float width = rect->w; float height = rect->h; float iconWidth; float iconHeight; int items[ 64 ]; int colinfo[ 64 ]; int numItems = 0, selectedItem = 0; int length; qboolean vertical; centity_t *cent; playerState_t *ps; cent = &cg_entities[ cg.snap->ps.clientNum ]; ps = &cg.snap->ps; // don't display if dead if( cg.predictedPlayerState.stats[ STAT_HEALTH ] <= 0 ) return; if( !( cg.snap->ps.pm_flags & PMF_FOLLOW ) ) { // first make sure that whatever it selected is actually selectable if( cg.weaponSelect < 32 ) { if( !CG_WeaponSelectable( cg.weaponSelect ) ) CG_NextWeapon_f( ); } else { if( !CG_UpgradeSelectable( cg.weaponSelect - 32 ) ) CG_NextWeapon_f( ); } } // showing weapon select clears pickup item display, but not the blend blob cg.itemPickupTime = 0; // put all weapons in the items list for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) { if( !BG_InventoryContainsWeapon( i, cg.snap->ps.stats ) ) continue; if( !ps->ammo && !ps->clips && !BG_Weapon( i )->infiniteAmmo ) colinfo[ numItems ] = 1; else colinfo[ numItems ] = 0; if( i == cg.weaponSelect ) selectedItem = numItems; if( !cg_weapons[ i ].registered ) { Com_Printf( S_COLOR_YELLOW "WARNING: CG_DrawItemSelect: weapon %d (%s) " "is not registered\n", i, BG_Weapon( i )->name ); continue; } items[ numItems ] = i; numItems++; } // put all upgrades in the weapons list for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) { if( !BG_InventoryContainsUpgrade( i, cg.snap->ps.stats ) ) continue; colinfo[ numItems ] = 0; if( !BG_Upgrade( i )->usable ) colinfo[ numItems ] = 2; if( i == cg.weaponSelect - 32 ) selectedItem = numItems; if( !cg_upgrades[ i ].registered ) { Com_Printf( S_COLOR_YELLOW "WARNING: CG_DrawItemSelect: upgrade %d (%s) " "is not registered\n", i, BG_Upgrade( i )->name ); continue; } items[ numItems ] = i + 32; numItems++; } // compute the length of the display window and determine orientation vertical = height > width; if( vertical ) { iconWidth = width * cgDC.aspectScale; iconHeight = width; length = height / ( width * cgDC.aspectScale ); } else { iconWidth = height * cgDC.aspectScale; iconHeight = height; length = width / ( height * cgDC.aspectScale ); } // render icon ring for( i = 0; i < length; i++ ) { int item = i - length / 2 + selectedItem; if( item < 0 ) item += length; else if( item >= length ) item -= length; if( item >= 0 && item < numItems ) { switch( colinfo[ item ] ) { case 0: color = colorCyan; break; case 1: color = colorRed; break; case 2: color = colorMdGrey; break; } color[3] = 0.5; trap_R_SetColor( color ); if( items[ item ] < 32 ) CG_DrawPic( x, y, iconWidth, iconHeight, cg_weapons[ items[ item ] ].weaponIcon ); else CG_DrawPic( x, y, iconWidth, iconHeight, cg_upgrades[ items[ item ] - 32 ].upgradeIcon ); } if( vertical ) y += iconHeight; else x += iconWidth; } trap_R_SetColor( NULL ); }