/* ================ CG_DrawHead Used for both the status bar and the scoreboard ================ */ void CG_DrawHead( float x, float y, float w, float h, int clientNum, vec3_t headAngles ) { clipHandle_t cm; clientInfo_t *ci; float len; vec3_t origin; vec3_t mins, maxs; tierConfig_cg *tier; qhandle_t icon; ci = &cgs.clientinfo[clientNum]; tier = &ci->tierConfig[ci->tierCurrent]; if(!cg_draw3dIcons.integer){ icon = tier->icon2D[0]; CG_DrawPic(qfalse, x, y, w, h,icon); } else{ cm = ci->headModel[ci->tierCurrent]; if(!cm){return;} trap_R_ModelBounds(cm,mins,maxs,0); len = 0.7 * ( maxs[2] - mins[2] ); origin[0] = len / (1.0 - tier->icon3DZoom); origin[1] = 0.5 * (mins[1] + maxs[1]); origin[2] = -0.5 * (mins[2] + maxs[2]); headAngles[0] = tier->icon3DRotation[0]; headAngles[1] = tier->icon3DRotation[1]; headAngles[2] = tier->icon3DRotation[2]; CG_Draw3DModel(x+tier->icon3DOffset[0],y+tier->icon3DOffset[1],w+tier->icon3DSize[0],h+tier->icon3DSize[1],ci->headModel[ci->tierCurrent],ci->headSkin[ci->tierCurrent],origin,headAngles); } }
/* ================ CG_DrawFlagModel Used for both the status bar and the scoreboard ================ */ void CG_DrawFlagModel( float x, float y, float w, float h, int team, qboolean force2D ) { qhandle_t cm; float len; vec3_t origin, angles; vec3_t mins, maxs; qhandle_t handle; if ( !force2D && cg_draw3dIcons.integer ) { VectorClear( angles ); cm = cgs.media.redFlagModel; // offset the origin y and z to center the flag trap_R_ModelBounds( cm, mins, maxs ); origin[2] = -0.5 * ( mins[2] + maxs[2] ); origin[1] = 0.5 * ( mins[1] + maxs[1] ); // calculate distance so the flag nearly fills the box // assume heads are taller than wide len = 0.5 * ( maxs[2] - mins[2] ); origin[0] = len / 0.268; // len / tan( fov/2 ) angles[YAW] = 60 * sin( (cg.time / 2000.0) + cg.timeFraction / 2000.0 );; if( team == TEAM_RED ) { handle = cgs.media.redFlagModel; } else if( team == TEAM_BLUE ) { handle = cgs.media.blueFlagModel; } else if( team == TEAM_FREE ) { handle = cgs.media.neutralFlagModel; } else { return; } CG_Draw3DModel( x, y, w, h, handle, 0, origin, angles ); } else if ( cg_drawIcons.integer ) { gitem_t *item; if( team == TEAM_RED ) { item = BG_FindItemForPowerup( PW_REDFLAG ); } else if( team == TEAM_BLUE ) { item = BG_FindItemForPowerup( PW_BLUEFLAG ); } else if( team == TEAM_FREE ) { item = BG_FindItemForPowerup( PW_NEUTRALFLAG ); } else { return; } if (item) { CG_DrawPic( x, y, w, h, cg_items[ ITEM_INDEX(item) ].icon ); } } }
static void CG_DrawPlayerArmorIcon( rectDef_t *rect, qboolean draw2D ) { vector3 angles; vector3 origin; if ( cg_drawStatus->integer == 0 ) { return; } if ( draw2D || ( !cg_draw3dIcons->integer && cg_drawIcons->integer) ) { CG_DrawPic( rect->x, rect->y + rect->h/2 + 1, rect->w, rect->h, cgs.media.armorIcon ); } else if (cg_draw3dIcons->integer) { VectorClear( &angles ); origin.x = 90; origin.y = 0; origin.z = -10; angles.yaw = ( cg.time & 2047 ) * 360 / 2048.0f; CG_Draw3DModel( rect->x, rect->y, rect->w, rect->h, cgs.media.armorModel, 0, &origin, &angles ); } }
/* ================ CG_DrawHead Used for both the status bar and the scoreboard ================ */ void CG_DrawHead( float x, float y, float w, float h, int clientNum, vec3_t headAngles ) { clipHandle_t cm; clientInfo_t *ci; float len; vec3_t origin; vec3_t mins, maxs; ci = &cgs.clientinfo[ clientNum ]; if ( cg_draw3dIcons.integer ) { cm = ci->headModel; if ( !cm ) { return; } // offset the origin y and z to center the head trap_R_ModelBounds( cm, mins, maxs ); origin[2] = -0.5 * ( mins[2] + maxs[2] ); origin[1] = 0.5 * ( mins[1] + maxs[1] ); // calculate distance so the head nearly fills the box // assume heads are taller than wide len = 0.7 * ( maxs[2] - mins[2] ); origin[0] = len / 0.268; // len / tan( fov/2 ) // allow per-model tweaking VectorAdd( origin, ci->headOffset, origin ); CG_Draw3DModel( x, y, w, h, ci->headModel, ci->headSkin, origin, headAngles ); } else if ( cg_drawIcons.integer ) { CG_DrawPic( x, y, w, h, ci->modelIcon ); } // if they are deferred, draw a cross out if ( ci->deferred ) { CG_DrawPic( x, y, w, h, cgs.media.deferShader ); } }
static void CG_DrawPlayerItem( rectDef_t *rect, float scale, qboolean draw2D) { int value; vector3 origin, angles; value = cg.snap->ps.stats[STAT_HOLDABLE_ITEM]; if ( value ) { CG_RegisterItemVisuals( value ); if (qtrue) { CG_RegisterItemVisuals( value ); CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_items[ value ].icon ); } else { VectorClear( &angles ); origin.x = 90; origin.y = 0; origin.z = -10; angles.yaw = ( cg.time & 2047 ) * 360 / 2048.0f; CG_Draw3DModel(rect->x, rect->y, rect->w, rect->h, cg_items[ value ].models[0], 0, &origin, &angles ); } } }
static void CG_DrawPlayerAmmoIcon( rectDef_t *rect, qboolean draw2D ) { centity_t *cent; vector3 angles; vector3 origin; cent = &cg_entities[cg.snap->ps.clientNum]; if ( draw2D || (!cg_draw3dIcons->integer && cg_drawIcons->integer) ) { qhandle_t icon; icon = cg_weapons[ cg.predictedPlayerState.weapon ].ammoIcon; if ( icon ) { CG_DrawPic( rect->x, rect->y, rect->w, rect->h, icon ); } } else if (cg_draw3dIcons->integer) { if ( cent->currentState.weapon && cg_weapons[ cent->currentState.weapon ].ammoModel ) { VectorClear( &angles ); origin.x = 70; origin.y = 0; origin.z = 0; angles.yaw = 90 + 20 * sinf( cg.time / 1000.0f ); CG_Draw3DModel( rect->x, rect->y, rect->w, rect->h, cg_weapons[ cent->currentState.weapon ].ammoModel, 0, &origin, &angles ); } } }
/* ================ CG_DrawStatusBar ================ */ static void CG_DrawStatusBar( void ) { int color; centity_t *cent; playerState_t *ps; int value; vec4_t hcolor; vec3_t angles; vec3_t origin; static float colors[4][4] = { // { 0.2, 1.0, 0.2, 1.0 } , { 1.0, 0.2, 0.2, 1.0 }, {0.5, 0.5, 0.5, 1} }; { 1.0f, 0.69f, 0.0f, 1.0f }, // normal { 1.0f, 0.2f, 0.2f, 1.0f }, // low health { 0.5f, 0.5f, 0.5f, 1.0f }, // weapon firing { 1.0f, 1.0f, 1.0f, 1.0f } }; // health > 100 if ( cg_drawStatus.integer == 0 ) { return; } // draw the team background CG_DrawTeamBackground( 0, 420, 640, 60, 0.33f, cg.snap->ps.persistant[PERS_TEAM] ); cent = &cg_entities[cg.snap->ps.clientNum]; ps = &cg.snap->ps; VectorClear( angles ); // draw any 3D icons first, so the changes back to 2D are minimized if ( cent->currentState.weapon && cg_weapons[ cent->currentState.weapon ].ammoModel ) { origin[0] = 70; origin[1] = 0; origin[2] = 0; angles[YAW] = 90 + 20 * sin( (cg.time / 1000.0) + cg.timeFraction / 1000.0 ); CG_Draw3DModel( (CHAR_WIDTH*3 + TEXT_ICON_SPACE)*cgs.widthRatioCoef, 432, ICON_SIZE*cgs.widthRatioCoef, ICON_SIZE, cg_weapons[ cent->currentState.weapon ].ammoModel, 0, origin, angles ); } CG_DrawStatusBarHead( 185 + (CHAR_WIDTH*3 + TEXT_ICON_SPACE)*cgs.widthRatioCoef ); if( cg.predictedPlayerState.powerups[PW_REDFLAG] ) { CG_DrawStatusBarFlag( 185 + CHAR_WIDTH*3 + TEXT_ICON_SPACE + ICON_SIZE, TEAM_RED ); } else if( cg.predictedPlayerState.powerups[PW_BLUEFLAG] ) { CG_DrawStatusBarFlag( 185 + CHAR_WIDTH*3 + TEXT_ICON_SPACE + ICON_SIZE, TEAM_BLUE ); } else if( cg.predictedPlayerState.powerups[PW_NEUTRALFLAG] ) { CG_DrawStatusBarFlag( 185 + CHAR_WIDTH*3 + TEXT_ICON_SPACE + ICON_SIZE, TEAM_FREE ); } if ( ps->stats[ STAT_ARMOR ] ) { origin[0] = 90; origin[1] = 0; origin[2] = -10; angles[YAW] = ( (cg.time & 2047) + cg.timeFraction ) * 360 / 2048.0; CG_Draw3DModel( 370 + (CHAR_WIDTH*3 + TEXT_ICON_SPACE)*cgs.widthRatioCoef, 432, ICON_SIZE*cgs.widthRatioCoef, ICON_SIZE, cgs.media.armorModel, 0, origin, angles ); } // // ammo // if ( cent->currentState.weapon ) { value = ps->ammo[cent->currentState.weapon]; if ( value > -1 ) { if ( cg.predictedPlayerState.weaponstate == WEAPON_FIRING && cg.predictedPlayerState.weaponTime > 100 ) { // draw as dark grey when reloading color = 2; // dark grey } else { if ( value >= 0 ) { color = 0; // green } else { color = 1; // red } } trap_R_SetColor( colors[color] ); CG_DrawField (0, 432, 3, value); trap_R_SetColor( NULL ); // if we didn't draw a 3D icon, draw a 2D icon for ammo if ( !cg_draw3dIcons.integer && cg_drawIcons.integer ) { qhandle_t icon; icon = cg_weapons[ cg.predictedPlayerState.weapon ].ammoIcon; if ( icon ) { CG_DrawPic( (CHAR_WIDTH*3 + TEXT_ICON_SPACE)*cgs.widthRatioCoef, 432, ICON_SIZE*cgs.widthRatioCoef, ICON_SIZE, icon ); } } } } // // health // value = ps->stats[STAT_HEALTH]; if ( value > 100 ) { trap_R_SetColor( colors[3] ); // white } else if (value > 25) { trap_R_SetColor( colors[0] ); // green } else if (value > 0) { color = (cg.time >> 8) & 1; // flash trap_R_SetColor( colors[color] ); } else {