Annotation of quake2/rogue/p_view.c, revision 1.1.1.1

1.1       root        1: 
                      2: #include "g_local.h"
                      3: #include "m_player.h"
                      4: 
                      5: 
                      6: 
                      7: static edict_t         *current_player;
                      8: static gclient_t       *current_client;
                      9: 
                     10: static vec3_t  forward, right, up;
                     11: float  xyspeed;
                     12: 
                     13: float  bobmove;
                     14: int            bobcycle;               // odd cycles are right foot going forward
                     15: float  bobfracsin;             // sin(bobfrac*M_PI)
                     16: 
                     17: /*
                     18: ===============
                     19: SV_CalcRoll
                     20: 
                     21: ===============
                     22: */
                     23: float SV_CalcRoll (vec3_t angles, vec3_t velocity)
                     24: {
                     25:        float   sign;
                     26:        float   side;
                     27:        float   value;
                     28:        
                     29:        side = DotProduct (velocity, right);
                     30:        sign = side < 0 ? -1 : 1;
                     31:        side = fabs(side);
                     32:        
                     33:        value = sv_rollangle->value;
                     34: 
                     35:        if (side < sv_rollspeed->value)
                     36:                side = side * value / sv_rollspeed->value;
                     37:        else
                     38:                side = value;
                     39:        
                     40:        return side*sign;
                     41:        
                     42: }
                     43: 
                     44: 
                     45: /*
                     46: ===============
                     47: P_DamageFeedback
                     48: 
                     49: Handles color blends and view kicks
                     50: ===============
                     51: */
                     52: void P_DamageFeedback (edict_t *player)
                     53: {
                     54:        gclient_t       *client;
                     55:        float   side;
                     56:        float   realcount, count, kick;
                     57:        vec3_t  v;
                     58:        int             r, l;
                     59:        static  vec3_t  power_color = {0.0, 1.0, 0.0};
                     60:        static  vec3_t  acolor = {1.0, 1.0, 1.0};
                     61:        static  vec3_t  bcolor = {1.0, 0.0, 0.0};
                     62: 
                     63:        client = player->client;
                     64: 
                     65:        // flash the backgrounds behind the status numbers
                     66:        client->ps.stats[STAT_FLASHES] = 0;
                     67:        if (client->damage_blood)
                     68:                client->ps.stats[STAT_FLASHES] |= 1;
                     69:        if (client->damage_armor && !(player->flags & FL_GODMODE) && (client->invincible_framenum <= level.framenum))
                     70:                client->ps.stats[STAT_FLASHES] |= 2;
                     71: 
                     72:        // total points of damage shot at the player this frame
                     73:        count = (client->damage_blood + client->damage_armor + client->damage_parmor);
                     74:        if (count == 0)
                     75:                return;         // didn't take any damage
                     76: 
                     77:        // start a pain animation if still in the player model
                     78:        if (client->anim_priority < ANIM_PAIN && player->s.modelindex == 255)
                     79:        {
                     80:                static int              i;
                     81: 
                     82:                client->anim_priority = ANIM_PAIN;
                     83:                if (client->ps.pmove.pm_flags & PMF_DUCKED)
                     84:                {
                     85:                        player->s.frame = FRAME_crpain1-1;
                     86:                        client->anim_end = FRAME_crpain4;
                     87:                }
                     88:                else
                     89:                {
                     90:                        i = (i+1)%3;
                     91:                        switch (i)
                     92:                        {
                     93:                        case 0:
                     94:                                player->s.frame = FRAME_pain101-1;
                     95:                                client->anim_end = FRAME_pain104;
                     96:                                break;
                     97:                        case 1:
                     98:                                player->s.frame = FRAME_pain201-1;
                     99:                                client->anim_end = FRAME_pain204;
                    100:                                break;
                    101:                        case 2:
                    102:                                player->s.frame = FRAME_pain301-1;
                    103:                                client->anim_end = FRAME_pain304;
                    104:                                break;
                    105:                        }
                    106:                }
                    107:        }
                    108: 
                    109:        realcount = count;
                    110:        if (count < 10)
                    111:                count = 10;     // always make a visible effect
                    112: 
                    113:        // play an apropriate pain sound
                    114:        if ((level.time > player->pain_debounce_time) && !(player->flags & FL_GODMODE) && (client->invincible_framenum <= level.framenum))
                    115:        {
                    116:                r = 1 + (rand()&1);
                    117:                player->pain_debounce_time = level.time + 0.7;
                    118:                if (player->health < 25)
                    119:                        l = 25;
                    120:                else if (player->health < 50)
                    121:                        l = 50;
                    122:                else if (player->health < 75)
                    123:                        l = 75;
                    124:                else
                    125:                        l = 100;
                    126:                gi.sound (player, CHAN_VOICE, gi.soundindex(va("*pain%i_%i.wav", l, r)), 1, ATTN_NORM, 0);
                    127:        }
                    128: 
                    129:        // the total alpha of the blend is always proportional to count
                    130:        if (client->damage_alpha < 0)
                    131:                client->damage_alpha = 0;
                    132:        client->damage_alpha += count*0.01;
                    133:        if (client->damage_alpha < 0.2)
                    134:                client->damage_alpha = 0.2;
                    135:        if (client->damage_alpha > 0.6)
                    136:                client->damage_alpha = 0.6;             // don't go too saturated
                    137: 
                    138:        // the color of the blend will vary based on how much was absorbed
                    139:        // by different armors
                    140:        VectorClear (v);
                    141:        if (client->damage_parmor)
                    142:                VectorMA (v, (float)client->damage_parmor/realcount, power_color, v);
                    143:        if (client->damage_armor)
                    144:                VectorMA (v, (float)client->damage_armor/realcount,  acolor, v);
                    145:        if (client->damage_blood)
                    146:                VectorMA (v, (float)client->damage_blood/realcount,  bcolor, v);
                    147:        VectorCopy (v, client->damage_blend);
                    148: 
                    149: 
                    150:        //
                    151:        // calculate view angle kicks
                    152:        //
                    153:        kick = abs(client->damage_knockback);
                    154:        if (kick && player->health > 0) // kick of 0 means no view adjust at all
                    155:        {
                    156:                kick = kick * 100 / player->health;
                    157: 
                    158:                if (kick < count*0.5)
                    159:                        kick = count*0.5;
                    160:                if (kick > 50)
                    161:                        kick = 50;
                    162: 
                    163:                VectorSubtract (client->damage_from, player->s.origin, v);
                    164:                VectorNormalize (v);
                    165:                
                    166:                side = DotProduct (v, right);
                    167:                client->v_dmg_roll = kick*side*0.3;
                    168:                
                    169:                side = -DotProduct (v, forward);
                    170:                client->v_dmg_pitch = kick*side*0.3;
                    171: 
                    172:                client->v_dmg_time = level.time + DAMAGE_TIME;
                    173:        }
                    174: 
                    175:        //
                    176:        // clear totals
                    177:        //
                    178:        client->damage_blood = 0;
                    179:        client->damage_armor = 0;
                    180:        client->damage_parmor = 0;
                    181:        client->damage_knockback = 0;
                    182: }
                    183: 
                    184: 
                    185: 
                    186: 
                    187: /*
                    188: ===============
                    189: SV_CalcViewOffset
                    190: 
                    191: Auto pitching on slopes?
                    192: 
                    193:   fall from 128: 400 = 160000
                    194:   fall from 256: 580 = 336400
                    195:   fall from 384: 720 = 518400
                    196:   fall from 512: 800 = 640000
                    197:   fall from 640: 960 = 
                    198: 
                    199:   damage = deltavelocity*deltavelocity  * 0.0001
                    200: 
                    201: ===============
                    202: */
                    203: void SV_CalcViewOffset (edict_t *ent)
                    204: {
                    205:        float           *angles;
                    206:        float           bob;
                    207:        float           ratio;
                    208:        float           delta;
                    209:        vec3_t          v;
                    210: 
                    211: 
                    212: //===================================
                    213: 
                    214:        // base angles
                    215:        angles = ent->client->ps.kick_angles;
                    216: 
                    217:        // if dead, fix the angle and don't add any kick
                    218:        if (ent->deadflag)
                    219:        {
                    220:                VectorClear (angles);
                    221: 
                    222:                if(ent->flags & FL_SAM_RAIMI)
                    223:                {
                    224:                        ent->client->ps.viewangles[ROLL] = 0;
                    225:                        ent->client->ps.viewangles[PITCH] = 0;
                    226:                }
                    227:                else
                    228:                {
                    229:                        ent->client->ps.viewangles[ROLL] = 40;
                    230:                        ent->client->ps.viewangles[PITCH] = -15;
                    231:                }
                    232:                ent->client->ps.viewangles[YAW] = ent->client->killer_yaw;
                    233:        }
                    234:        else
                    235:        {
                    236:                // add angles based on weapon kick
                    237: 
                    238:                VectorCopy (ent->client->kick_angles, angles);
                    239: 
                    240:                // add angles based on damage kick
                    241: 
                    242:                ratio = (ent->client->v_dmg_time - level.time) / DAMAGE_TIME;
                    243:                if (ratio < 0)
                    244:                {
                    245:                        ratio = 0;
                    246:                        ent->client->v_dmg_pitch = 0;
                    247:                        ent->client->v_dmg_roll = 0;
                    248:                }
                    249:                angles[PITCH] += ratio * ent->client->v_dmg_pitch;
                    250:                angles[ROLL] += ratio * ent->client->v_dmg_roll;
                    251: 
                    252:                // add pitch based on fall kick
                    253: 
                    254:                ratio = (ent->client->fall_time - level.time) / FALL_TIME;
                    255:                if (ratio < 0)
                    256:                        ratio = 0;
                    257:                angles[PITCH] += ratio * ent->client->fall_value;
                    258: 
                    259:                // add angles based on velocity
                    260: 
                    261:                delta = DotProduct (ent->velocity, forward);
                    262:                angles[PITCH] += delta*run_pitch->value;
                    263:                
                    264:                delta = DotProduct (ent->velocity, right);
                    265:                angles[ROLL] += delta*run_roll->value;
                    266: 
                    267:                // add angles based on bob
                    268: 
                    269:                delta = bobfracsin * bob_pitch->value * xyspeed;
                    270:                if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                    271:                        delta *= 6;             // crouching
                    272:                angles[PITCH] += delta;
                    273:                delta = bobfracsin * bob_roll->value * xyspeed;
                    274:                if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                    275:                        delta *= 6;             // crouching
                    276:                if (bobcycle & 1)
                    277:                        delta = -delta;
                    278:                angles[ROLL] += delta;
                    279:        }
                    280: 
                    281: //===================================
                    282: 
                    283:        // base origin
                    284: 
                    285:        VectorClear (v);
                    286: 
                    287:        // add view height
                    288: 
                    289:        v[2] += ent->viewheight;
                    290: 
                    291:        // add fall height
                    292: 
                    293:        ratio = (ent->client->fall_time - level.time) / FALL_TIME;
                    294:        if (ratio < 0)
                    295:                ratio = 0;
                    296:        v[2] -= ratio * ent->client->fall_value * 0.4;
                    297: 
                    298:        // add bob height
                    299: 
                    300:        bob = bobfracsin * xyspeed * bob_up->value;
                    301:        if (bob > 6)
                    302:                bob = 6;
                    303:        //gi.DebugGraph (bob *2, 255);
                    304:        v[2] += bob;
                    305: 
                    306:        // add kick offset
                    307: 
                    308:        VectorAdd (v, ent->client->kick_origin, v);
                    309: 
                    310:        // absolutely bound offsets
                    311:        // so the view can never be outside the player box
                    312: 
                    313:        if (v[0] < -14)
                    314:                v[0] = -14;
                    315:        else if (v[0] > 14)
                    316:                v[0] = 14;
                    317:        if (v[1] < -14)
                    318:                v[1] = -14;
                    319:        else if (v[1] > 14)
                    320:                v[1] = 14;
                    321:        if (v[2] < -22)
                    322:                v[2] = -22;
                    323:        else if (v[2] > 30)
                    324:                v[2] = 30;
                    325: 
                    326:        VectorCopy (v, ent->client->ps.viewoffset);
                    327: }
                    328: 
                    329: /*
                    330: ==============
                    331: SV_CalcGunOffset
                    332: ==============
                    333: */
                    334: void SV_CalcGunOffset (edict_t *ent)
                    335: {
                    336:        int             i;
                    337:        float   delta;
                    338:        //ROGUE
                    339:        static gitem_t  *heatbeam;
                    340: 
                    341:        if (!heatbeam)
                    342:                heatbeam = FindItemByClassname ("weapon_heatbeam");
                    343: 
                    344:        //ROGUE - heatbeam shouldn't bob so the beam looks right
                    345:        if (ent->client->pers.weapon != heatbeam)
                    346:        {
                    347:        // ROGUE
                    348:                // gun angles from bobbing
                    349:                ent->client->ps.gunangles[ROLL] = xyspeed * bobfracsin * 0.005;
                    350:                ent->client->ps.gunangles[YAW] = xyspeed * bobfracsin * 0.01;
                    351:                if (bobcycle & 1)
                    352:                {
                    353:                        ent->client->ps.gunangles[ROLL] = -ent->client->ps.gunangles[ROLL];
                    354:                        ent->client->ps.gunangles[YAW] = -ent->client->ps.gunangles[YAW];
                    355:                }
                    356: 
                    357:                ent->client->ps.gunangles[PITCH] = xyspeed * bobfracsin * 0.005;
                    358: 
                    359:                // gun angles from delta movement
                    360:                for (i=0 ; i<3 ; i++)
                    361:                {
                    362:                        delta = ent->client->oldviewangles[i] - ent->client->ps.viewangles[i];
                    363:                        if (delta > 180)
                    364:                                delta -= 360;
                    365:                        if (delta < -180)
                    366:                                delta += 360;
                    367:                        if (delta > 45)
                    368:                                delta = 45;
                    369:                        if (delta < -45)
                    370:                                delta = -45;
                    371:                        if (i == YAW)
                    372:                                ent->client->ps.gunangles[ROLL] += 0.1*delta;
                    373:                        ent->client->ps.gunangles[i] += 0.2 * delta;
                    374:                }
                    375:        }
                    376:        // ROGUE
                    377:        else
                    378:        {
                    379:                for (i=0; i<3; i++)
                    380:                        ent->client->ps.gunangles[i] = 0;
                    381:        }
                    382:        //ROGUE
                    383: 
                    384:        // gun height
                    385:        VectorClear (ent->client->ps.gunoffset);
                    386: //     ent->ps->gunorigin[2] += bob;
                    387: 
                    388:        // gun_x / gun_y / gun_z are development tools
                    389:        for (i=0 ; i<3 ; i++)
                    390:        {
                    391:                ent->client->ps.gunoffset[i] += forward[i]*(gun_y->value);
                    392:                ent->client->ps.gunoffset[i] += right[i]*gun_x->value;
                    393:                ent->client->ps.gunoffset[i] += up[i]* (-gun_z->value);
                    394:        }
                    395: }
                    396: 
                    397: 
                    398: /*
                    399: =============
                    400: SV_AddBlend
                    401: =============
                    402: */
                    403: void SV_AddBlend (float r, float g, float b, float a, float *v_blend)
                    404: {
                    405:        float   a2, a3;
                    406: 
                    407:        if (a <= 0)
                    408:                return;
                    409:        a2 = v_blend[3] + (1-v_blend[3])*a;     // new total alpha
                    410:        a3 = v_blend[3]/a2;             // fraction of color from old
                    411: 
                    412:        v_blend[0] = v_blend[0]*a3 + r*(1-a3);
                    413:        v_blend[1] = v_blend[1]*a3 + g*(1-a3);
                    414:        v_blend[2] = v_blend[2]*a3 + b*(1-a3);
                    415:        v_blend[3] = a2;
                    416: }
                    417: 
                    418: 
                    419: /*
                    420: =============
                    421: SV_CalcBlend
                    422: =============
                    423: */
                    424: void SV_CalcBlend (edict_t *ent)
                    425: {
                    426:        int             contents;
                    427:        vec3_t  vieworg;
                    428:        int             remaining;
                    429: 
                    430:        ent->client->ps.blend[0] = ent->client->ps.blend[1] = 
                    431:                ent->client->ps.blend[2] = ent->client->ps.blend[3] = 0;
                    432: 
                    433:        // add for contents
                    434:        VectorAdd (ent->s.origin, ent->client->ps.viewoffset, vieworg);
                    435:        contents = gi.pointcontents (vieworg);
                    436:        if (contents & (CONTENTS_LAVA|CONTENTS_SLIME|CONTENTS_WATER) )
                    437:                ent->client->ps.rdflags |= RDF_UNDERWATER;
                    438:        else
                    439:                ent->client->ps.rdflags &= ~RDF_UNDERWATER;
                    440: 
                    441:        if (contents & (CONTENTS_SOLID|CONTENTS_LAVA))
                    442:                SV_AddBlend (1.0, 0.3, 0.0, 0.6, ent->client->ps.blend);
                    443:        else if (contents & CONTENTS_SLIME)
                    444:                SV_AddBlend (0.0, 0.1, 0.05, 0.6, ent->client->ps.blend);
                    445:        else if (contents & CONTENTS_WATER)
                    446:                SV_AddBlend (0.5, 0.3, 0.2, 0.4, ent->client->ps.blend);
                    447: 
                    448:        // add for powerups
                    449:        if (ent->client->quad_framenum > level.framenum)
                    450:        {
                    451:                remaining = ent->client->quad_framenum - level.framenum;
                    452:                if (remaining == 30)    // beginning to fade
                    453:                        gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage2.wav"), 1, ATTN_NORM, 0);
                    454:                if (remaining > 30 || (remaining & 4) )
                    455:                        SV_AddBlend (0, 0, 1, 0.08, ent->client->ps.blend);
                    456:        }
                    457:        // PMM - double damage
                    458:        else if (ent->client->double_framenum > level.framenum)
                    459:        {
                    460:                remaining = ent->client->double_framenum - level.framenum;
                    461:                if (remaining == 30)    // beginning to fade
                    462:                        gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage2.wav"), 1, ATTN_NORM, 0);
                    463:                if (remaining > 30 || (remaining & 4) )
                    464:                        SV_AddBlend (0.9, 0.7, 0, 0.08, ent->client->ps.blend);
                    465:        }
                    466:        // PMM
                    467:        else if (ent->client->invincible_framenum > level.framenum)
                    468:        {
                    469:                remaining = ent->client->invincible_framenum - level.framenum;
                    470:                if (remaining == 30)    // beginning to fade
                    471:                        gi.sound(ent, CHAN_ITEM, gi.soundindex("items/protect2.wav"), 1, ATTN_NORM, 0);
                    472:                if (remaining > 30 || (remaining & 4) )
                    473:                        SV_AddBlend (1, 1, 0, 0.08, ent->client->ps.blend);
                    474:        }
                    475:        else if (ent->client->enviro_framenum > level.framenum)
                    476:        {
                    477:                remaining = ent->client->enviro_framenum - level.framenum;
                    478:                if (remaining == 30)    // beginning to fade
                    479:                        gi.sound(ent, CHAN_ITEM, gi.soundindex("items/airout.wav"), 1, ATTN_NORM, 0);
                    480:                if (remaining > 30 || (remaining & 4) )
                    481:                        SV_AddBlend (0, 1, 0, 0.08, ent->client->ps.blend);
                    482:        }
                    483:        else if (ent->client->breather_framenum > level.framenum)
                    484:        {
                    485:                remaining = ent->client->breather_framenum - level.framenum;
                    486:                if (remaining == 30)    // beginning to fade
                    487:                        gi.sound(ent, CHAN_ITEM, gi.soundindex("items/airout.wav"), 1, ATTN_NORM, 0);
                    488:                if (remaining > 30 || (remaining & 4) )
                    489:                        SV_AddBlend (0.4, 1, 0.4, 0.04, ent->client->ps.blend);
                    490:        }
                    491: 
                    492: //PGM
                    493:        if(ent->client->nuke_framenum > level.framenum)
                    494:        {
                    495:                float brightness;
                    496:                brightness = (ent->client->nuke_framenum - level.framenum) / 20.0;
                    497:                SV_AddBlend (1, 1, 1, brightness, ent->client->ps.blend);
                    498:        }
                    499:        if (ent->client->ir_framenum > level.framenum)
                    500:        {
                    501:                remaining = ent->client->ir_framenum - level.framenum;
                    502:                if(remaining > 30 || (remaining & 4))
                    503:                {
                    504:                        ent->client->ps.rdflags |= RDF_IRGOGGLES;
                    505:                        SV_AddBlend (1, 0, 0, 0.2, ent->client->ps.blend);
                    506:                }
                    507:                else
                    508:                        ent->client->ps.rdflags &= ~RDF_IRGOGGLES;
                    509:        }
                    510:        else
                    511:        {
                    512:                ent->client->ps.rdflags &= ~RDF_IRGOGGLES;
                    513:        }
                    514: //PGM
                    515: 
                    516:        // add for damage
                    517:        if (ent->client->damage_alpha > 0)
                    518:                SV_AddBlend (ent->client->damage_blend[0],ent->client->damage_blend[1]
                    519:                ,ent->client->damage_blend[2], ent->client->damage_alpha, ent->client->ps.blend);
                    520: 
                    521:        if (ent->client->bonus_alpha > 0)
                    522:                SV_AddBlend (0.85, 0.7, 0.3, ent->client->bonus_alpha, ent->client->ps.blend);
                    523: 
                    524:        // drop the damage value
                    525:        ent->client->damage_alpha -= 0.06;
                    526:        if (ent->client->damage_alpha < 0)
                    527:                ent->client->damage_alpha = 0;
                    528: 
                    529:        // drop the bonus value
                    530:        ent->client->bonus_alpha -= 0.1;
                    531:        if (ent->client->bonus_alpha < 0)
                    532:                ent->client->bonus_alpha = 0;
                    533: }
                    534: 
                    535: 
                    536: /*
                    537: =================
                    538: P_FallingDamage
                    539: =================
                    540: */
                    541: void P_FallingDamage (edict_t *ent)
                    542: {
                    543:        float   delta;
                    544:        int             damage;
                    545:        vec3_t  dir;
                    546: 
                    547:        if (ent->s.modelindex != 255)
                    548:                return;         // not in the player model
                    549: 
                    550:        if (ent->movetype == MOVETYPE_NOCLIP)
                    551:                return;
                    552: 
                    553:        if ((ent->client->oldvelocity[2] < 0) && (ent->velocity[2] > ent->client->oldvelocity[2]) && (!ent->groundentity))
                    554:        {
                    555:                delta = ent->client->oldvelocity[2];
                    556:        }
                    557:        else
                    558:        {
                    559:                if (!ent->groundentity)
                    560:                        return;
                    561:                delta = ent->velocity[2] - ent->client->oldvelocity[2];
                    562:        }
                    563:        delta = delta*delta * 0.0001;
                    564: 
                    565:        // never take falling damage if completely underwater
                    566:        if (ent->waterlevel == 3)
                    567:                return;
                    568:        if (ent->waterlevel == 2)
                    569:                delta *= 0.25;
                    570:        if (ent->waterlevel == 1)
                    571:                delta *= 0.5;
                    572: 
                    573:        if (delta < 1)
                    574:                return;
                    575: 
                    576:        if (delta < 15)
                    577:        {
                    578:                ent->s.event = EV_FOOTSTEP;
                    579:                return;
                    580:        }
                    581: 
                    582:        ent->client->fall_value = delta*0.5;
                    583:        if (ent->client->fall_value > 40)
                    584:                ent->client->fall_value = 40;
                    585:        ent->client->fall_time = level.time + FALL_TIME;
                    586: 
                    587:        if (delta > 30)
                    588:        {
                    589:                if (ent->health > 0)
                    590:                {
                    591:                        if (delta >= 55)
                    592:                                ent->s.event = EV_FALLFAR;
                    593:                        else
                    594:                                ent->s.event = EV_FALL;
                    595:                }
                    596:                ent->pain_debounce_time = level.time;   // no normal pain sound
                    597:                damage = (delta-30)/2;
                    598:                if (damage < 1)
                    599:                        damage = 1;
                    600:                VectorSet (dir, 0, 0, 1);
                    601: 
                    602:                if (!deathmatch->value || !((int)dmflags->value & DF_NO_FALLING) )
                    603:                        T_Damage (ent, world, world, dir, ent->s.origin, vec3_origin, damage, 0, 0, MOD_FALLING);
                    604:        }
                    605:        else
                    606:        {
                    607:                ent->s.event = EV_FALLSHORT;
                    608:                return;
                    609:        }
                    610: }
                    611: 
                    612: 
                    613: 
                    614: /*
                    615: =============
                    616: P_WorldEffects
                    617: =============
                    618: */
                    619: void P_WorldEffects (void)
                    620: {
                    621:        qboolean        breather;
                    622:        qboolean        envirosuit;
                    623:        int                     waterlevel, old_waterlevel;
                    624: 
                    625:        if (current_player->movetype == MOVETYPE_NOCLIP)
                    626:        {
                    627:                current_player->air_finished = level.time + 12; // don't need air
                    628:                return;
                    629:        }
                    630: 
                    631:        waterlevel = current_player->waterlevel;
                    632:        old_waterlevel = current_client->old_waterlevel;
                    633:        current_client->old_waterlevel = waterlevel;
                    634: 
                    635:        breather = current_client->breather_framenum > level.framenum;
                    636:        envirosuit = current_client->enviro_framenum > level.framenum;
                    637: 
                    638:        //
                    639:        // if just entered a water volume, play a sound
                    640:        //
                    641:        if (!old_waterlevel && waterlevel)
                    642:        {
                    643:                PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF);
                    644:                if (current_player->watertype & CONTENTS_LAVA)
                    645:                        gi.sound (current_player, CHAN_BODY, gi.soundindex("player/lava_in.wav"), 1, ATTN_NORM, 0);
                    646:                else if (current_player->watertype & CONTENTS_SLIME)
                    647:                        gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0);
                    648:                else if (current_player->watertype & CONTENTS_WATER)
                    649:                        gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0);
                    650:                current_player->flags |= FL_INWATER;
                    651: 
                    652:                // clear damage_debounce, so the pain sound will play immediately
                    653:                current_player->damage_debounce_time = level.time - 1;
                    654:        }
                    655: 
                    656:        //
                    657:        // if just completely exited a water volume, play a sound
                    658:        //
                    659:        if (old_waterlevel && ! waterlevel)
                    660:        {
                    661:                PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF);
                    662:                gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_out.wav"), 1, ATTN_NORM, 0);
                    663:                current_player->flags &= ~FL_INWATER;
                    664:        }
                    665: 
                    666:        //
                    667:        // check for head just going under water
                    668:        //
                    669:        if (old_waterlevel != 3 && waterlevel == 3)
                    670:        {
                    671:                gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_un.wav"), 1, ATTN_NORM, 0);
                    672:        }
                    673: 
                    674:        //
                    675:        // check for head just coming out of water
                    676:        //
                    677:        if (old_waterlevel == 3 && waterlevel != 3)
                    678:        {
                    679:                if (current_player->air_finished < level.time)
                    680:                {       // gasp for air
                    681:                        gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/gasp1.wav"), 1, ATTN_NORM, 0);
                    682:                        PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF);
                    683:                }
                    684:                else  if (current_player->air_finished < level.time + 11)
                    685:                {       // just break surface
                    686:                        gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/gasp2.wav"), 1, ATTN_NORM, 0);
                    687:                }
                    688:        }
                    689: 
                    690:        //
                    691:        // check for drowning
                    692:        //
                    693:        if (waterlevel == 3)
                    694:        {
                    695:                // breather or envirosuit give air
                    696:                if (breather || envirosuit)
                    697:                {
                    698:                        current_player->air_finished = level.time + 10;
                    699: 
                    700:                        if (((int)(current_client->breather_framenum - level.framenum) % 25) == 0)
                    701:                        {
                    702:                                if (!current_client->breather_sound)
                    703:                                        gi.sound (current_player, CHAN_AUTO, gi.soundindex("player/u_breath1.wav"), 1, ATTN_NORM, 0);
                    704:                                else
                    705:                                        gi.sound (current_player, CHAN_AUTO, gi.soundindex("player/u_breath2.wav"), 1, ATTN_NORM, 0);
                    706:                                current_client->breather_sound ^= 1;
                    707:                                PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF);
                    708:                                //FIXME: release a bubble?
                    709:                        }
                    710:                }
                    711: 
                    712:                // if out of air, start drowning
                    713:                if (current_player->air_finished < level.time)
                    714:                {       // drown!
                    715:                        if (current_player->client->next_drown_time < level.time 
                    716:                                && current_player->health > 0)
                    717:                        {
                    718:                                current_player->client->next_drown_time = level.time + 1;
                    719: 
                    720:                                // take more damage the longer underwater
                    721:                                current_player->dmg += 2;
                    722:                                if (current_player->dmg > 15)
                    723:                                        current_player->dmg = 15;
                    724: 
                    725:                                // play a gurp sound instead of a normal pain sound
                    726:                                if (current_player->health <= current_player->dmg)
                    727:                                        gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/drown1.wav"), 1, ATTN_NORM, 0);
                    728:                                else if (rand()&1)
                    729:                                        gi.sound (current_player, CHAN_VOICE, gi.soundindex("*gurp1.wav"), 1, ATTN_NORM, 0);
                    730:                                else
                    731:                                        gi.sound (current_player, CHAN_VOICE, gi.soundindex("*gurp2.wav"), 1, ATTN_NORM, 0);
                    732: 
                    733:                                current_player->pain_debounce_time = level.time;
                    734: 
                    735:                                T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, current_player->dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER);
                    736:                        }
                    737:                }
                    738:        }
                    739:        else
                    740:        {
                    741:                current_player->air_finished = level.time + 12;
                    742:                current_player->dmg = 2;
                    743:        }
                    744: 
                    745:        //
                    746:        // check for sizzle damage
                    747:        //
                    748:        if (waterlevel && (current_player->watertype&(CONTENTS_LAVA|CONTENTS_SLIME)) )
                    749:        {
                    750:                if (current_player->watertype & CONTENTS_LAVA)
                    751:                {
                    752:                        if (current_player->health > 0
                    753:                                && current_player->pain_debounce_time <= level.time
                    754:                                && current_client->invincible_framenum < level.framenum)
                    755:                        {
                    756:                                if (rand()&1)
                    757:                                        gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/burn1.wav"), 1, ATTN_NORM, 0);
                    758:                                else
                    759:                                        gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/burn2.wav"), 1, ATTN_NORM, 0);
                    760:                                current_player->pain_debounce_time = level.time + 1;
                    761:                        }
                    762: 
                    763:                        if (envirosuit) // take 1/3 damage with envirosuit
                    764:                                T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 1*waterlevel, 0, 0, MOD_LAVA);
                    765:                        else
                    766:                                T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 3*waterlevel, 0, 0, MOD_LAVA);
                    767:                }
                    768: 
                    769:                if (current_player->watertype & CONTENTS_SLIME)
                    770:                {
                    771:                        if (!envirosuit)
                    772:                        {       // no damage from slime with envirosuit
                    773:                                T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 1*waterlevel, 0, 0, MOD_SLIME);
                    774:                        }
                    775:                }
                    776:        }
                    777: }
                    778: 
                    779: 
                    780: /*
                    781: ===============
                    782: G_SetClientEffects
                    783: ===============
                    784: */
                    785: void G_SetClientEffects (edict_t *ent)
                    786: {
                    787:        int             pa_type;
                    788:        int             remaining;
                    789: 
                    790:        ent->s.effects = 0;
                    791: //     ent->s.renderfx = 0;
                    792: //PGM
                    793:        ent->s.renderfx = RF_IR_VISIBLE;
                    794: //PGM
                    795: 
                    796:        if(ent->flags & FL_DISGUISED)
                    797:                ent->s.renderfx = RF_USE_DISGUISE;
                    798: 
                    799:        if (ent->health <= 0 || level.intermissiontime)
                    800:                return;
                    801: 
                    802: //PGM
                    803:        if (gamerules && gamerules->value)
                    804:        {
                    805:                if(DMGame.PlayerEffects)
                    806:                        DMGame.PlayerEffects(ent);
                    807:        }
                    808: //PGM
                    809: 
                    810:        if (ent->powerarmor_time > level.time)
                    811:        {
                    812:                pa_type = PowerArmorType (ent);
                    813:                if (pa_type == POWER_ARMOR_SCREEN)
                    814:                {
                    815:                        ent->s.effects |= EF_POWERSCREEN;
                    816:                }
                    817:                else if (pa_type == POWER_ARMOR_SHIELD)
                    818:                {
                    819:                        ent->s.effects |= EF_COLOR_SHELL;
                    820:                        ent->s.renderfx |= RF_SHELL_GREEN;
                    821:                }
                    822:        }
                    823: 
                    824:        if (ent->client->quad_framenum > level.framenum)
                    825:        {
                    826:                remaining = ent->client->quad_framenum - level.framenum;
                    827:                if (remaining > 30 || (remaining & 4) )
                    828:                        ent->s.effects |= EF_QUAD;
                    829:        }
                    830: 
                    831: //=======
                    832: //ROGUE
                    833:        if (ent->client->double_framenum > level.framenum)
                    834:        {
                    835:                remaining = ent->client->double_framenum - level.framenum;
                    836:                if (remaining > 30 || (remaining & 4) )
                    837:                        ent->s.effects |= EF_DOUBLE;
                    838:        }
                    839:        if ((ent->client->owned_sphere) && (ent->client->owned_sphere->spawnflags == 1))
                    840:        {
                    841:                ent->s.effects |= EF_HALF_DAMAGE;
                    842:        }
                    843:        if (ent->client->tracker_pain_framenum > level.framenum)
                    844:        {
                    845:                ent->s.effects |= EF_TRACKERTRAIL;
                    846:        }
                    847: //ROGUE
                    848: //=======
                    849: 
                    850:        if (ent->client->invincible_framenum > level.framenum)
                    851:        {
                    852:                remaining = ent->client->invincible_framenum - level.framenum;
                    853:                if (remaining > 30 || (remaining & 4) )
                    854:                        ent->s.effects |= EF_PENT;
                    855:        }
                    856: 
                    857:        // show cheaters!!!
                    858:        if (ent->flags & FL_GODMODE)
                    859:        {
                    860:                ent->s.effects |= EF_COLOR_SHELL;
                    861:                ent->s.renderfx |= (RF_SHELL_RED|RF_SHELL_GREEN|RF_SHELL_BLUE);
                    862:        }
                    863: 
                    864: //PGM
                    865:        if (ent->client->torch_framenum > level.framenum)
                    866:        {
                    867:                gi.WriteByte (svc_temp_entity);
                    868:                gi.WriteByte (TE_FLASHLIGHT);
                    869:                gi.WritePosition (ent->s.origin);
                    870:                gi.WriteShort (ent - g_edicts);
                    871:                gi.multicast (ent->s.origin, MULTICAST_PVS);
                    872:        }
                    873: //PGM
                    874: }
                    875: 
                    876: 
                    877: /*
                    878: ===============
                    879: G_SetClientEvent
                    880: ===============
                    881: */
                    882: void G_SetClientEvent (edict_t *ent)
                    883: {
                    884:        if (ent->s.event)
                    885:                return;
                    886: 
                    887:        if ( ent->groundentity && xyspeed > 225)
                    888:        {
                    889:                if ( (int)(current_client->bobtime+bobmove) != bobcycle )
                    890:                        ent->s.event = EV_FOOTSTEP;
                    891:        }
                    892: }
                    893: 
                    894: /*
                    895: ===============
                    896: G_SetClientSound
                    897: ===============
                    898: */
                    899: void G_SetClientSound (edict_t *ent)
                    900: {
                    901:        char    *weap;
                    902: 
                    903:        if (ent->client->pers.game_helpchanged != game.helpchanged)
                    904:        {
                    905:                ent->client->pers.game_helpchanged = game.helpchanged;
                    906:                ent->client->pers.helpchanged = 1;
                    907:        }
                    908: 
                    909:        // help beep (no more than three times)
                    910:        if (ent->client->pers.helpchanged && ent->client->pers.helpchanged <= 3 && !(level.framenum&63) )
                    911:        {
                    912:                ent->client->pers.helpchanged++;
                    913:                gi.sound (ent, CHAN_VOICE, gi.soundindex ("misc/pc_up.wav"), 1, ATTN_STATIC, 0);
                    914:        }
                    915: 
                    916: 
                    917:        if (ent->client->pers.weapon)
                    918:                weap = ent->client->pers.weapon->classname;
                    919:        else
                    920:                weap = "";
                    921: 
                    922:        if (ent->waterlevel && (ent->watertype&(CONTENTS_LAVA|CONTENTS_SLIME)) )
                    923:                ent->s.sound = snd_fry;
                    924:        else if (strcmp(weap, "weapon_railgun") == 0)
                    925:                ent->s.sound = gi.soundindex("weapons/rg_hum.wav");
                    926:        else if (strcmp(weap, "weapon_bfg") == 0)
                    927:                ent->s.sound = gi.soundindex("weapons/bfg_hum.wav");
                    928:        else if (ent->client->weapon_sound)
                    929:                ent->s.sound = ent->client->weapon_sound;
                    930:        else
                    931:                ent->s.sound = 0;
                    932: }
                    933: 
                    934: /*
                    935: ===============
                    936: G_SetClientFrame
                    937: ===============
                    938: */
                    939: void G_SetClientFrame (edict_t *ent)
                    940: {
                    941:        gclient_t       *client;
                    942:        qboolean        duck, run;
                    943: 
                    944:        if (ent->s.modelindex != 255)
                    945:                return;         // not in the player model
                    946: 
                    947:        client = ent->client;
                    948: 
                    949:        if (client->ps.pmove.pm_flags & PMF_DUCKED)
                    950:                duck = true;
                    951:        else
                    952:                duck = false;
                    953:        if (xyspeed)
                    954:                run = true;
                    955:        else
                    956:                run = false;
                    957: 
                    958:        // check for stand/duck and stop/go transitions
                    959:        if (duck != client->anim_duck && client->anim_priority < ANIM_DEATH)
                    960:                goto newanim;
                    961:        if (run != client->anim_run && client->anim_priority == ANIM_BASIC)
                    962:                goto newanim;
                    963:        if (!ent->groundentity && client->anim_priority <= ANIM_WAVE)
                    964:                goto newanim;
                    965: 
                    966:        if(client->anim_priority == ANIM_REVERSE)
                    967:        {
                    968:                if(ent->s.frame > client->anim_end)
                    969:                {
                    970:                        ent->s.frame--;
                    971:                        return;
                    972:                }
                    973:        }
                    974:        else if (ent->s.frame < client->anim_end)
                    975:        {       // continue an animation
                    976:                ent->s.frame++;
                    977:                return;
                    978:        }
                    979: 
                    980:        if (client->anim_priority == ANIM_DEATH)
                    981:                return;         // stay there
                    982:        if (client->anim_priority == ANIM_JUMP)
                    983:        {
                    984:                if (!ent->groundentity)
                    985:                        return;         // stay there
                    986:                ent->client->anim_priority = ANIM_WAVE;
                    987:                ent->s.frame = FRAME_jump3;
                    988:                ent->client->anim_end = FRAME_jump6;
                    989:                return;
                    990:        }
                    991: 
                    992: newanim:
                    993:        // return to either a running or standing frame
                    994:        client->anim_priority = ANIM_BASIC;
                    995:        client->anim_duck = duck;
                    996:        client->anim_run = run;
                    997: 
                    998:        if (!ent->groundentity)
                    999:        {
                   1000:                client->anim_priority = ANIM_JUMP;
                   1001:                if (ent->s.frame != FRAME_jump2)
                   1002:                        ent->s.frame = FRAME_jump1;
                   1003:                client->anim_end = FRAME_jump2;
                   1004:        }
                   1005:        else if (run)
                   1006:        {       // running
                   1007:                if (duck)
                   1008:                {
                   1009:                        ent->s.frame = FRAME_crwalk1;
                   1010:                        client->anim_end = FRAME_crwalk6;
                   1011:                }
                   1012:                else
                   1013:                {
                   1014:                        ent->s.frame = FRAME_run1;
                   1015:                        client->anim_end = FRAME_run6;
                   1016:                }
                   1017:        }
                   1018:        else
                   1019:        {       // standing
                   1020:                if (duck)
                   1021:                {
                   1022:                        ent->s.frame = FRAME_crstnd01;
                   1023:                        client->anim_end = FRAME_crstnd19;
                   1024:                }
                   1025:                else
                   1026:                {
                   1027:                        ent->s.frame = FRAME_stand01;
                   1028:                        client->anim_end = FRAME_stand40;
                   1029:                }
                   1030:        }
                   1031: }
                   1032: 
                   1033: 
                   1034: /*
                   1035: =================
                   1036: ClientEndServerFrame
                   1037: 
                   1038: Called for each player at the end of the server frame
                   1039: and right after spawning
                   1040: =================
                   1041: */
                   1042: void ClientEndServerFrame (edict_t *ent)
                   1043: {
                   1044:        float   bobtime;
                   1045:        int             i;
                   1046: 
                   1047:        current_player = ent;
                   1048:        current_client = ent->client;
                   1049: 
                   1050:        //
                   1051:        // If the origin or velocity have changed since ClientThink(),
                   1052:        // update the pmove values.  This will happen when the client
                   1053:        // is pushed by a bmodel or kicked by an explosion.
                   1054:        // 
                   1055:        // If it wasn't updated here, the view position would lag a frame
                   1056:        // behind the body position when pushed -- "sinking into plats"
                   1057:        //
                   1058:        for (i=0 ; i<3 ; i++)
                   1059:        {
                   1060:                current_client->ps.pmove.origin[i] = ent->s.origin[i]*8.0;
                   1061:                current_client->ps.pmove.velocity[i] = ent->velocity[i]*8.0;
                   1062:        }
                   1063: 
                   1064:        //
                   1065:        // If the end of unit layout is displayed, don't give
                   1066:        // the player any normal movement attributes
                   1067:        //
                   1068:        if (level.intermissiontime)
                   1069:        {
                   1070:                // FIXME: add view drifting here?
                   1071:                current_client->ps.blend[3] = 0;
                   1072:                current_client->ps.fov = 90;
                   1073:                G_SetStats (ent);
                   1074:                return;
                   1075:        }
                   1076: 
                   1077:        AngleVectors (ent->client->v_angle, forward, right, up);
                   1078: 
                   1079:        // burn from lava, etc
                   1080:        P_WorldEffects ();
                   1081: 
                   1082:        //
                   1083:        // set model angles from view angles so other things in
                   1084:        // the world can tell which direction you are looking
                   1085:        //
                   1086:        if (ent->client->v_angle[PITCH] > 180)
                   1087:                ent->s.angles[PITCH] = (-360 + ent->client->v_angle[PITCH])/3;
                   1088:        else
                   1089:                ent->s.angles[PITCH] = ent->client->v_angle[PITCH]/3;
                   1090:        ent->s.angles[YAW] = ent->client->v_angle[YAW];
                   1091:        ent->s.angles[ROLL] = 0;
                   1092:        ent->s.angles[ROLL] = SV_CalcRoll (ent->s.angles, ent->velocity)*4;
                   1093: 
                   1094:        //
                   1095:        // calculate speed and cycle to be used for
                   1096:        // all cyclic walking effects
                   1097:        //
                   1098:        xyspeed = sqrt(ent->velocity[0]*ent->velocity[0] + ent->velocity[1]*ent->velocity[1]);
                   1099: 
                   1100:        if (xyspeed < 5)
                   1101:        {
                   1102:                bobmove = 0;
                   1103:                current_client->bobtime = 0;    // start at beginning of cycle again
                   1104:        }
                   1105:        else if (ent->groundentity)
                   1106:        {       // so bobbing only cycles when on ground
                   1107:                if (xyspeed > 210)
                   1108:                        bobmove = 0.25;
                   1109:                else if (xyspeed > 100)
                   1110:                        bobmove = 0.125;
                   1111:                else
                   1112:                        bobmove = 0.0625;
                   1113:        }
                   1114:        
                   1115:        bobtime = (current_client->bobtime += bobmove);
                   1116: 
                   1117:        if (current_client->ps.pmove.pm_flags & PMF_DUCKED)
                   1118:                bobtime *= 4;
                   1119: 
                   1120:        bobcycle = (int)bobtime;
                   1121:        bobfracsin = fabs(sin(bobtime*M_PI));
                   1122: 
                   1123:        // detect hitting the floor
                   1124:        P_FallingDamage (ent);
                   1125: 
                   1126:        // apply all the damage taken this frame
                   1127:        P_DamageFeedback (ent);
                   1128: 
                   1129:        // determine the view offsets
                   1130:        SV_CalcViewOffset (ent);
                   1131: 
                   1132:        // determine the gun offsets
                   1133:        SV_CalcGunOffset (ent);
                   1134: 
                   1135:        // determine the full screen color blend
                   1136:        // must be after viewoffset, so eye contents can be
                   1137:        // accurately determined
                   1138:        // FIXME: with client prediction, the contents
                   1139:        // should be determined by the client
                   1140:        SV_CalcBlend (ent);
                   1141: 
                   1142:        // chase cam stuff
                   1143:        if (ent->client->resp.spectator)
                   1144:                G_SetSpectatorStats(ent);
                   1145:        else
                   1146:                G_SetStats (ent);
                   1147: 
                   1148:        G_CheckChaseStats(ent);
                   1149: 
                   1150:        G_SetClientEvent (ent);
                   1151: 
                   1152:        G_SetClientEffects (ent);
                   1153: 
                   1154:        G_SetClientSound (ent);
                   1155: 
                   1156:        G_SetClientFrame (ent);
                   1157: 
                   1158:        VectorCopy (ent->velocity, ent->client->oldvelocity);
                   1159:        VectorCopy (ent->client->ps.viewangles, ent->client->oldviewangles);
                   1160: 
                   1161:        // clear weapon kicks
                   1162:        VectorClear (ent->client->kick_origin);
                   1163:        VectorClear (ent->client->kick_angles);
                   1164: 
                   1165:        // if the scoreboard is up, update it
                   1166:        if (ent->client->showscores && !(level.framenum & 31) )
                   1167:        {
                   1168:                DeathmatchScoreboardMessage (ent, ent->enemy);
                   1169:                gi.unicast (ent, false);
                   1170:        }
                   1171: }
                   1172: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.