Annotation of quake2/ctf/p_view.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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