/* ============== R_IQMBuildSkeleton ============== */ static int IQMBuildSkeleton( refSkeleton_t *skel, skelAnimation_t *skelAnim, int startFrame, int endFrame, float frac ) { int i; IQAnim_t *anim; transform_t *newPose, *oldPose; vec3_t mins, maxs; anim = skelAnim->iqm; // Validate the frames so there is no chance of a crash. // This will write directly into the entity structure, so // when the surfaces are rendered, they don't need to be // range checked again. if( anim->flags & IQM_LOOP ) { startFrame %= anim->num_frames; endFrame %= anim->num_frames; } else { Q_clamp( startFrame, 0, anim->num_frames - 1 ); Q_clamp( endFrame, 0, anim->num_frames - 1 ); } // compute frame pointers oldPose = &anim->poses[ startFrame * anim->num_joints ]; newPose = &anim->poses[ endFrame * anim->num_joints ]; // calculate a bounding box in the current coordinate system if( anim->bounds ) { float *bounds = &anim->bounds[ 6 * startFrame ]; VectorCopy( bounds, mins ); VectorCopy( bounds + 3, maxs ); bounds = &anim->bounds[ 6 * endFrame ]; BoundsAdd( mins, maxs, bounds, bounds + 3 ); } for ( i = 0; i < anim->num_joints; i++ ) { TransStartLerp( &skel->bones[ i ].t ); TransAddWeight( 1.0f - frac, &oldPose[ i ], &skel->bones[ i ].t ); TransAddWeight( frac, &newPose[ i ], &skel->bones[ i ].t ); TransEndLerp( &skel->bones[ i ].t ); #if defined( REFBONE_NAMES ) Q_strncpyz( skel->bones[ i ].name, anim->name, sizeof( skel->bones[ i ].name ) ); #endif skel->bones[ i ].parentIndex = anim->jointParents[ i ]; } skel->numBones = anim->num_joints; skel->type = refSkeletonType_t::SK_RELATIVE; VectorCopy( mins, skel->bounds[ 0 ] ); VectorCopy( maxs, skel->bounds[ 1 ] ); return true; }
static qboolean G_VoteTimelimit( gentity_t *ent, int numArgs, const char *arg1, const char *arg2 ) { float tl = Q_clamp( 0.0f, (float)atof( arg2 ), 35790.0f ); Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %.3f", arg1, tl ); Q_strncpyz( level.voteDisplayString, level.voteString, sizeof( level.voteDisplayString ) ); Q_strncpyz( level.voteStringClean, level.voteString, sizeof( level.voteStringClean ) ); return qtrue; }
/* ============== RE_BuildSkeleton ============== */ int RE_BuildSkeleton(refSkeleton_t * skel, qhandle_t hAnim, int startFrame, int endFrame, float frac, qboolean clearOrigin) { skelAnimation_t *skelAnim; skelAnim = R_GetAnimationByHandle(hAnim); if(skelAnim->type == AT_MD5 && skelAnim->md5) { int i; md5Animation_t *anim; md5Channel_t *channel; md5Frame_t *newFrame, *oldFrame; vec3_t newOrigin, oldOrigin, lerpedOrigin; quat_t newQuat, oldQuat, lerpedQuat; int componentsApplied; anim = skelAnim->md5; // Validate the frames so there is no chance of a crash. // This will write directly into the entity structure, so // when the surfaces are rendered, they don't need to be // range checked again. /* if((startFrame >= anim->numFrames) || (startFrame < 0) || (endFrame >= anim->numFrames) || (endFrame < 0)) { ri.Printf(PRINT_DEVELOPER, "RE_BuildSkeleton: no such frame %d to %d for '%s'\n", startFrame, endFrame, anim->name); //startFrame = 0; //endFrame = 0; } */ Q_clamp(startFrame, 0, anim->numFrames - 1); Q_clamp(endFrame, 0, anim->numFrames - 1); // compute frame pointers oldFrame = &anim->frames[startFrame]; newFrame = &anim->frames[endFrame]; // calculate a bounding box in the current coordinate system for(i = 0; i < 3; i++) { skel->bounds[0][i] = oldFrame->bounds[0][i] < newFrame->bounds[0][i] ? oldFrame->bounds[0][i] : newFrame->bounds[0][i]; skel->bounds[1][i] = oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i]; } for(i = 0, channel = anim->channels; i < anim->numChannels; i++, channel++) { // set baseframe values VectorCopy(channel->baseOrigin, newOrigin); VectorCopy(channel->baseOrigin, oldOrigin); QuatCopy(channel->baseQuat, newQuat); QuatCopy(channel->baseQuat, oldQuat); componentsApplied = 0; // update tranlation bits if(channel->componentsBits & COMPONENT_BIT_TX) { oldOrigin[0] = oldFrame->components[channel->componentsOffset + componentsApplied]; newOrigin[0] = newFrame->components[channel->componentsOffset + componentsApplied]; componentsApplied++; } if(channel->componentsBits & COMPONENT_BIT_TY) { oldOrigin[1] = oldFrame->components[channel->componentsOffset + componentsApplied]; newOrigin[1] = newFrame->components[channel->componentsOffset + componentsApplied]; componentsApplied++; } if(channel->componentsBits & COMPONENT_BIT_TZ) { oldOrigin[2] = oldFrame->components[channel->componentsOffset + componentsApplied]; newOrigin[2] = newFrame->components[channel->componentsOffset + componentsApplied]; componentsApplied++; } // update quaternion rotation bits if(channel->componentsBits & COMPONENT_BIT_QX) { ((vec_t *) oldQuat)[0] = oldFrame->components[channel->componentsOffset + componentsApplied]; ((vec_t *) newQuat)[0] = newFrame->components[channel->componentsOffset + componentsApplied]; componentsApplied++; } if(channel->componentsBits & COMPONENT_BIT_QY) { ((vec_t *) oldQuat)[1] = oldFrame->components[channel->componentsOffset + componentsApplied]; ((vec_t *) newQuat)[1] = newFrame->components[channel->componentsOffset + componentsApplied]; componentsApplied++; } if(channel->componentsBits & COMPONENT_BIT_QZ) { ((vec_t *) oldQuat)[2] = oldFrame->components[channel->componentsOffset + componentsApplied]; ((vec_t *) newQuat)[2] = newFrame->components[channel->componentsOffset + componentsApplied]; } QuatCalcW(oldQuat); QuatNormalize(oldQuat); QuatCalcW(newQuat); QuatNormalize(newQuat); #if 1 VectorLerp(oldOrigin, newOrigin, frac, lerpedOrigin); QuatSlerp(oldQuat, newQuat, frac, lerpedQuat); #else VectorCopy(newOrigin, lerpedOrigin); QuatCopy(newQuat, lerpedQuat); #endif // copy lerped information to the bone + extra data skel->bones[i].parentIndex = channel->parentIndex; if(channel->parentIndex < 0 && clearOrigin) { VectorClear(skel->bones[i].origin); QuatClear(skel->bones[i].rotation); // move bounding box back VectorSubtract(skel->bounds[0], lerpedOrigin, skel->bounds[0]); VectorSubtract(skel->bounds[1], lerpedOrigin, skel->bounds[1]); } else { VectorCopy(lerpedOrigin, skel->bones[i].origin); } QuatCopy(lerpedQuat, skel->bones[i].rotation); #if defined(REFBONE_NAMES) Q_strncpyz(skel->bones[i].name, channel->name, sizeof(skel->bones[i].name)); #endif } skel->numBones = anim->numChannels; skel->type = SK_RELATIVE; return qtrue; } else if(skelAnim->type == AT_PSA && skelAnim->psa) { int i; psaAnimation_t *anim; axAnimationKey_t *newKey, *oldKey; axReferenceBone_t *refBone; vec3_t newOrigin, oldOrigin, lerpedOrigin; quat_t newQuat, oldQuat, lerpedQuat; refSkeleton_t skeleton; anim = skelAnim->psa; Q_clamp(startFrame, 0, anim->info.numRawFrames - 1); Q_clamp(endFrame, 0, anim->info.numRawFrames - 1); ClearBounds(skel->bounds[0], skel->bounds[1]); skel->numBones = anim->info.numBones; for(i = 0, refBone = anim->bones; i < anim->info.numBones; i++, refBone++) { oldKey = &anim->keys[startFrame * anim->info.numBones + i]; newKey = &anim->keys[endFrame * anim->info.numBones + i]; VectorCopy(newKey->position, newOrigin); VectorCopy(oldKey->position, oldOrigin); QuatCopy(newKey->quat, newQuat); QuatCopy(oldKey->quat, oldQuat); //QuatCalcW(oldQuat); //QuatNormalize(oldQuat); //QuatCalcW(newQuat); //QuatNormalize(newQuat); VectorLerp(oldOrigin, newOrigin, frac, lerpedOrigin); QuatSlerp(oldQuat, newQuat, frac, lerpedQuat); // copy lerped information to the bone + extra data skel->bones[i].parentIndex = refBone->parentIndex; if(refBone->parentIndex < 0 && clearOrigin) { VectorClear(skel->bones[i].origin); QuatClear(skel->bones[i].rotation); // move bounding box back VectorSubtract(skel->bounds[0], lerpedOrigin, skel->bounds[0]); VectorSubtract(skel->bounds[1], lerpedOrigin, skel->bounds[1]); } else { VectorCopy(lerpedOrigin, skel->bones[i].origin); } QuatCopy(lerpedQuat, skel->bones[i].rotation); #if defined(REFBONE_NAMES) Q_strncpyz(skel->bones[i].name, refBone->name, sizeof(skel->bones[i].name)); #endif // calculate absolute values for the bounding box approximation VectorCopy(skel->bones[i].origin, skeleton.bones[i].origin); QuatCopy(skel->bones[i].rotation, skeleton.bones[i].rotation); if(refBone->parentIndex >= 0) { vec3_t rotated; quat_t quat; refBone_t *parent; refBone_t *bone; bone = &skeleton.bones[i]; parent = &skeleton.bones[refBone->parentIndex]; QuatTransformVector(parent->rotation, bone->origin, rotated); VectorAdd(parent->origin, rotated, bone->origin); QuatMultiply1(parent->rotation, bone->rotation, quat); QuatCopy(quat, bone->rotation); AddPointToBounds(bone->origin, skel->bounds[0], skel->bounds[1]); } } skel->numBones = anim->info.numBones; skel->type = SK_RELATIVE; return qtrue; } //ri.Printf(PRINT_WARNING, "RE_BuildSkeleton: bad animation '%s' with handle %i\n", anim->name, hAnim); // FIXME: clear existing bones and bounds? return qfalse; }
/* =============== CG_AddReverbEffects =============== */ static void CG_AddReverbEffects( vec3_t loc ) { int i, j; float dist, weight; int selectedIdx[3] = { 0, 0, 0 }; float selectedWeight[3] = { 0.0f, 0.0f, 0.0f }; float totalWeight = 0.0f; qboolean haveGlobal = qfalse; // the first allocated reverb is special in that it may be global i = 0; if ( cgs.gameReverbEffects[0][0] && cgs.gameGradingModels[0] == -1 ) { selectedIdx[0] = 0; selectedWeight[0] = 2.0f; // won't be sorted down haveGlobal = qtrue; i = 1; } for(; i < MAX_REVERB_EFFECTS; i++ ) { if( !cgs.gameReverbEffects[i][0] ) { continue; } dist = trap_CM_DistanceToModel( loc, cgs.gameReverbModels[i] ); weight = 1.0f - dist / cgs.gameReverbDistances[i]; weight = Q_clamp( weight, 0.0f, 1.0f ); // Maths::clampFraction( weight ) // search 3 greatest weights if( weight <= selectedWeight[2] ) { continue; } for( j = 1; j >= 0; j-- ) { if( weight <= selectedWeight[j] ) { break; } selectedIdx[j+1] = selectedIdx[j]; selectedWeight[j+1] = selectedWeight[j]; } selectedIdx[j+1] = i; selectedWeight[j+1] = weight; } i = haveGlobal ? 1 : 0; for(; i < 3; i++ ) { totalWeight += selectedWeight[i]; } if (haveGlobal) { if (totalWeight > 1.0f) { selectedWeight[0] = 0; } else { selectedWeight[0] = 1.0f - totalWeight; totalWeight = 1.0f; } } if (totalWeight == 0.0f) { for(i = 0; i < 3; i++) { selectedWeight[i] = 0.0f; } } else { for(i = 0; i < 3; i++) { selectedWeight[i] /= totalWeight; } } for (i = 0; i < 3; i++) { // The mapper defined intensity is between 0 and 2 to have saner defaults (the presets are very strong) trap_S_SetReverb(i, cgs.gameReverbEffects[selectedIdx[i]], selectedWeight[i] / 2.0f * cgs.gameReverbIntensities[selectedIdx[i]]); } }
/* =============== CG_CalcColorGradingForPoint Sets cg.refdef.gradingWeights =============== */ static void CG_CalcColorGradingForPoint( vec3_t loc ) { int i, j; float dist, weight; int selectedIdx[3] = { 0, 0, 0 }; float selectedWeight[3] = { 0.0f, 0.0f, 0.0f }; float totalWeight = 0.0f; int freeSlot = -1; qboolean haveGlobal = qfalse; // the first allocated grading is special in that it may be global i = 0; if ( cgs.gameGradingTextures[0] && cgs.gameGradingModels[0] == -1 ) { selectedIdx[0] = 0; // shouldn't be needed selectedWeight[0] = 2.0f; // won't be sorted down haveGlobal = qtrue; i = 1; } for(; i < MAX_GRADING_TEXTURES; i++ ) { if( !cgs.gameGradingTextures[i] ) { continue; } dist = trap_CM_DistanceToModel( loc, cgs.gameGradingModels[i] ); weight = 1.0f - dist / cgs.gameGradingDistances[i]; weight = Q_clamp( weight, 0.0f, 1.0f ); // Maths::clampFraction( weight ) // search 3 greatest weights if( weight <= selectedWeight[2] ) { continue; } for( j = 1; j >= 0; j-- ) { if( weight <= selectedWeight[j] ) { break; } selectedIdx[j+1] = selectedIdx[j]; selectedWeight[j+1] = selectedWeight[j]; } selectedIdx[j+1] = i; selectedWeight[j+1] = weight; } i = 0; if( haveGlobal ) { trap_SetColorGrading( 1, cgs.gameGradingTextures[0] ); i = 1; } for(; i < 3; i++ ) { if( selectedWeight[i] > 0.0f ) { trap_SetColorGrading( i + 1, cgs.gameGradingTextures[selectedIdx[i]] ); totalWeight += selectedWeight[i]; } else { freeSlot = i; } } if( !haveGlobal && totalWeight < 1.0f ) { if(freeSlot >= 0) { //If there is a free slot, use it with the neutral cgrade //to make sure that using only the 3 map grade will always be ok trap_SetColorGrading( freeSlot + 1, cgs.media.neutralCgrade); selectedWeight[freeSlot] = 1.0f - totalWeight; totalWeight = 1.0f; } } cg.refdef.gradingWeights[0] = 0.0f; cg.refdef.gradingWeights[1] = haveGlobal ? ( 1.0f - totalWeight ) : ( selectedWeight[0] / totalWeight ); cg.refdef.gradingWeights[2] = totalWeight == 0.0f ? 0.0f : selectedWeight[1] / totalWeight; cg.refdef.gradingWeights[3] = totalWeight == 0.0f ? 0.0f : selectedWeight[2] / totalWeight; }
float RB_EvalExpression(const expression_t * exp, float defaultValue) { #if 1 int i; expOperation_t op; expOperation_t ops[MAX_EXPRESSION_OPS]; int numOps; float value; float value1; float value2; extern const opstring_t opStrings[]; numOps = 0; value = 0; value1 = 0; value2 = 0; if(!exp || !exp->active) { return defaultValue; } // http://www.qiksearch.com/articles/cs/postfix-evaluation/ // http://www.kyz.uklinux.net/evaluate/ for(i = 0; i < exp->numOps; i++) { op = exp->ops[i]; switch (op.type) { case OP_BAD: return defaultValue; case OP_NEG: { if(numOps < 1) { ri.Printf(PRINT_ALL, "WARNING: shader %s has numOps < 1 for unary - operator\n", tess.surfaceShader->name); return defaultValue; } value1 = GetOpValue(&ops[numOps - 1]); numOps--; value = -value1; // push result op.type = OP_NUM; op.value = value; ops[numOps++] = op; break; } case OP_NUM: case OP_TIME: case OP_PARM0: case OP_PARM1: case OP_PARM2: case OP_PARM3: case OP_PARM4: case OP_PARM5: case OP_PARM6: case OP_PARM7: case OP_PARM8: case OP_PARM9: case OP_PARM10: case OP_PARM11: case OP_GLOBAL0: case OP_GLOBAL1: case OP_GLOBAL2: case OP_GLOBAL3: case OP_GLOBAL4: case OP_GLOBAL5: case OP_GLOBAL6: case OP_GLOBAL7: case OP_FRAGMENTSHADERS: case OP_FRAMEBUFFEROBJECTS: case OP_SOUND: case OP_DISTANCE: ops[numOps++] = op; break; case OP_TABLE: { shaderTable_t *table; int numValues; float index; float lerp; int oldIndex; int newIndex; if(numOps < 1) { ri.Printf(PRINT_ALL, "WARNING: shader %s has numOps < 1 for table operator\n", tess.surfaceShader->name); return defaultValue; } value1 = GetOpValue(&ops[numOps - 1]); numOps--; table = tr.shaderTables[(int)op.value]; numValues = table->numValues; index = value1 * numValues; // float index into the table?s elements lerp = index - floor(index); // being inbetween two elements of the table oldIndex = (int)index; newIndex = (int)index + 1; if(table->clamp) { // clamp indices to table-range Q_clamp(oldIndex, 0, numValues - 1); Q_clamp(newIndex, 0, numValues - 1); } else { // wrap around indices oldIndex %= numValues; newIndex %= numValues; } if(table->snap) { // use fixed value value = table->values[oldIndex]; } else { // lerp value value = table->values[oldIndex] + ((table->values[newIndex] - table->values[oldIndex]) * lerp); } //ri.Printf(PRINT_ALL, "%s: %i %i %f\n", table->name, oldIndex, newIndex, value); // push result op.type = OP_NUM; op.value = value; ops[numOps++] = op; break; } default: { if(numOps < 2) { ri.Printf(PRINT_ALL, "WARNING: shader %s has numOps < 2 for binary operator %s\n", tess.surfaceShader->name, opStrings[op.type].s); return defaultValue; } value2 = GetOpValue(&ops[numOps - 1]); numOps--; value1 = GetOpValue(&ops[numOps - 1]); numOps--; switch (op.type) { case OP_LAND: value = value1 && value2; break; case OP_LOR: value = value1 || value2; break; case OP_GE: value = value1 >= value2; break; case OP_LE: value = value1 <= value2; break; case OP_LEQ: value = value1 == value2; break; case OP_LNE: value = value1 != value2; break; case OP_ADD: value = value1 + value2; break; case OP_SUB: value = value1 - value2; break; case OP_DIV: if(value2 == 0) { // don't divide by zero value = value1; } else { value = value1 / value2; } break; case OP_MOD: value = (float)((int)value1 % (int)value2); break; case OP_MUL: value = value1 * value2; break; case OP_LT: value = value1 < value2; break; case OP_GT: value = value1 > value2; break; default: value = value1 = value2 = 0; break; } //ri.Printf(PRINT_ALL, "%s: %f %f %f\n", opStrings[op.type].s, value, value1, value2); // push result op.type = OP_NUM; op.value = value; ops[numOps++] = op; break; } } } return GetOpValue(&ops[0]); #else return defaultValue; #endif }
/* * UI_SPSkillMenu_Init */ static void UI_SPSkillMenu_Init(void) { int skill; memset(&skillMenuInfo, 0, sizeof(skillMenuInfo)); skillMenuInfo.menu.fullscreen = qtrue; skillMenuInfo.menu.key = UI_SPSkillMenu_Key; UI_SPSkillMenu_Cache(); skillMenuInfo.art_frame.generic.type = MTYPE_BITMAP; skillMenuInfo.art_frame.generic.name = ART_FRAME; skillMenuInfo.art_frame.generic.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE; skillMenuInfo.art_frame.generic.x = 142; skillMenuInfo.art_frame.generic.y = 118; skillMenuInfo.art_frame.width = 359; skillMenuInfo.art_frame.height = 256; skillMenuInfo.art_banner.generic.type = MTYPE_BTEXT; skillMenuInfo.art_banner.generic.flags = QMF_CENTER_JUSTIFY; skillMenuInfo.art_banner.generic.x = 320; skillMenuInfo.art_banner.generic.y = 16; skillMenuInfo.art_banner.string = "DIFFICULTY"; skillMenuInfo.art_banner.color = color_white; skillMenuInfo.art_banner.style = UI_CENTER; skillMenuInfo.item_baby.generic.type = MTYPE_PTEXT; skillMenuInfo.item_baby.generic.flags = QMF_CENTER_JUSTIFY| QMF_PULSEIFFOCUS; skillMenuInfo.item_baby.generic.x = 320; skillMenuInfo.item_baby.generic.y = 170; skillMenuInfo.item_baby.generic.callback = UI_SPSkillMenu_SkillEvent; skillMenuInfo.item_baby.generic.id = ID_BABY; skillMenuInfo.item_baby.string = "I Can Win"; skillMenuInfo.item_baby.color = color_red; skillMenuInfo.item_baby.style = UI_CENTER; skillMenuInfo.item_easy.generic.type = MTYPE_PTEXT; skillMenuInfo.item_easy.generic.flags = QMF_CENTER_JUSTIFY| QMF_PULSEIFFOCUS; skillMenuInfo.item_easy.generic.x = 320; skillMenuInfo.item_easy.generic.y = 198; skillMenuInfo.item_easy.generic.callback = UI_SPSkillMenu_SkillEvent; skillMenuInfo.item_easy.generic.id = ID_EASY; skillMenuInfo.item_easy.string = "Bring It On"; skillMenuInfo.item_easy.color = color_red; skillMenuInfo.item_easy.style = UI_CENTER; skillMenuInfo.item_medium.generic.type = MTYPE_PTEXT; skillMenuInfo.item_medium.generic.flags = QMF_CENTER_JUSTIFY| QMF_PULSEIFFOCUS; skillMenuInfo.item_medium.generic.x = 320; skillMenuInfo.item_medium.generic.y = 227; skillMenuInfo.item_medium.generic.callback = UI_SPSkillMenu_SkillEvent; skillMenuInfo.item_medium.generic.id = ID_MEDIUM; skillMenuInfo.item_medium.string = "Hurt Me Plenty"; skillMenuInfo.item_medium.color = color_red; skillMenuInfo.item_medium.style = UI_CENTER; skillMenuInfo.item_hard.generic.type = MTYPE_PTEXT; skillMenuInfo.item_hard.generic.flags = QMF_CENTER_JUSTIFY| QMF_PULSEIFFOCUS; skillMenuInfo.item_hard.generic.x = 320; skillMenuInfo.item_hard.generic.y = 255; skillMenuInfo.item_hard.generic.callback = UI_SPSkillMenu_SkillEvent; skillMenuInfo.item_hard.generic.id = ID_HARD; skillMenuInfo.item_hard.string = "Hardcore"; skillMenuInfo.item_hard.color = color_red; skillMenuInfo.item_hard.style = UI_CENTER; skillMenuInfo.item_nightmare.generic.type = MTYPE_PTEXT; skillMenuInfo.item_nightmare.generic.flags = QMF_CENTER_JUSTIFY| QMF_PULSEIFFOCUS; skillMenuInfo.item_nightmare.generic.x = 320; skillMenuInfo.item_nightmare.generic.y = 283; skillMenuInfo.item_nightmare.generic.callback = UI_SPSkillMenu_SkillEvent; skillMenuInfo.item_nightmare.generic.id = ID_NIGHTMARE; skillMenuInfo.item_nightmare.string = "NIGHTMARE!"; skillMenuInfo.item_nightmare.color = color_red; skillMenuInfo.item_nightmare.style = UI_CENTER; skillMenuInfo.item_back.generic.type = MTYPE_BITMAP; skillMenuInfo.item_back.generic.name = ART_BACK; skillMenuInfo.item_back.generic.flags = QMF_LEFT_JUSTIFY| QMF_PULSEIFFOCUS; skillMenuInfo.item_back.generic.x = 0; skillMenuInfo.item_back.generic.y = 480-64; skillMenuInfo.item_back.generic.callback = UI_SPSkillMenu_BackEvent; skillMenuInfo.item_back.generic.id = ID_BACK; skillMenuInfo.item_back.width = 128; skillMenuInfo.item_back.height = 64; skillMenuInfo.item_back.focuspic = ART_BACK_FOCUS; skillMenuInfo.art_skillPic.generic.type = MTYPE_BITMAP; skillMenuInfo.art_skillPic.generic.flags = QMF_LEFT_JUSTIFY| QMF_INACTIVE; skillMenuInfo.art_skillPic.generic.x = 320-64; skillMenuInfo.art_skillPic.generic.y = 368; skillMenuInfo.art_skillPic.width = 128; skillMenuInfo.art_skillPic.height = 96; skillMenuInfo.item_fight.generic.type = MTYPE_BITMAP; skillMenuInfo.item_fight.generic.name = ART_FIGHT; skillMenuInfo.item_fight.generic.flags = QMF_RIGHT_JUSTIFY| QMF_PULSEIFFOCUS; skillMenuInfo.item_fight.generic.callback = UI_SPSkillMenu_FightEvent; skillMenuInfo.item_fight.generic.id = ID_FIGHT; skillMenuInfo.item_fight.generic.x = 640; skillMenuInfo.item_fight.generic.y = 480-64; skillMenuInfo.item_fight.width = 128; skillMenuInfo.item_fight.height = 64; skillMenuInfo.item_fight.focuspic = ART_FIGHT_FOCUS; Menu_AddItem(&skillMenuInfo.menu, ( void* )&skillMenuInfo.art_frame); Menu_AddItem(&skillMenuInfo.menu, ( void* )&skillMenuInfo.art_banner); Menu_AddItem(&skillMenuInfo.menu, ( void* )&skillMenuInfo.item_baby); Menu_AddItem(&skillMenuInfo.menu, ( void* )&skillMenuInfo.item_easy); Menu_AddItem(&skillMenuInfo.menu, ( void* )&skillMenuInfo.item_medium); Menu_AddItem(&skillMenuInfo.menu, ( void* )&skillMenuInfo.item_hard); Menu_AddItem(&skillMenuInfo.menu, ( void* )&skillMenuInfo.item_nightmare); Menu_AddItem(&skillMenuInfo.menu, ( void* )&skillMenuInfo.art_skillPic); Menu_AddItem(&skillMenuInfo.menu, ( void* )&skillMenuInfo.item_back); Menu_AddItem(&skillMenuInfo.menu, ( void* )&skillMenuInfo.item_fight); skill = (int)Q_clamp(1, 5, trap_cvargetf("g_spSkill")); SetSkillColor(skill, color_white); skillMenuInfo.art_skillPic.shader = skillMenuInfo.skillpics[skill - 1]; if(skill == 5) trap_sndstartlocalsound(skillMenuInfo.nightmareSound, CHAN_ANNOUNCER); }