Annotation of quake2/ctf/p_weapon.c, revision 1.1.1.1

1.1       root        1: // g_weapon.c
                      2: 
                      3: #include "g_local.h"
                      4: #include "m_player.h"
                      5: 
                      6: 
                      7: static qboolean        is_quad;
                      8: static byte            is_silenced;
                      9: 
                     10: 
                     11: void weapon_grenade_fire (edict_t *ent, qboolean held);
                     12: 
                     13: 
                     14: void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
                     15: {
                     16:        vec3_t  _distance;
                     17: 
                     18:        VectorCopy (distance, _distance);
                     19:        if (client->pers.hand == LEFT_HANDED)
                     20:                _distance[1] *= -1;
                     21:        else if (client->pers.hand == CENTER_HANDED)
                     22:                _distance[1] = 0;
                     23:        G_ProjectSource (point, _distance, forward, right, result);
                     24: }
                     25: 
                     26: 
                     27: /*
                     28: ===============
                     29: PlayerNoise
                     30: 
                     31: Each player can have two noise objects associated with it:
                     32: a personal noise (jumping, pain, weapon firing), and a weapon
                     33: target noise (bullet wall impacts)
                     34: 
                     35: Monsters that don't directly see the player can move
                     36: to a noise in hopes of seeing the player from there.
                     37: ===============
                     38: */
                     39: void PlayerNoise(edict_t *who, vec3_t where, int type)
                     40: {
                     41:        edict_t         *noise;
                     42: 
                     43:        if (type == PNOISE_WEAPON)
                     44:        {
                     45:                if (who->client->silencer_shots)
                     46:                {
                     47:                        who->client->silencer_shots--;
                     48:                        return;
                     49:                }
                     50:        }
                     51: 
                     52:        if (deathmatch->value)
                     53:                return;
                     54: 
                     55:        if (who->flags & FL_NOTARGET)
                     56:                return;
                     57: 
                     58: 
                     59:        if (!who->mynoise)
                     60:        {
                     61:                noise = G_Spawn();
                     62:                noise->classname = "player_noise";
                     63:                VectorSet (noise->mins, -8, -8, -8);
                     64:                VectorSet (noise->maxs, 8, 8, 8);
                     65:                noise->owner = who;
                     66:                noise->svflags = SVF_NOCLIENT;
                     67:                who->mynoise = noise;
                     68: 
                     69:                noise = G_Spawn();
                     70:                noise->classname = "player_noise";
                     71:                VectorSet (noise->mins, -8, -8, -8);
                     72:                VectorSet (noise->maxs, 8, 8, 8);
                     73:                noise->owner = who;
                     74:                noise->svflags = SVF_NOCLIENT;
                     75:                who->mynoise2 = noise;
                     76:        }
                     77: 
                     78:        if (type == PNOISE_SELF || type == PNOISE_WEAPON)
                     79:        {
                     80:                noise = who->mynoise;
                     81:                level.sound_entity = noise;
                     82:                level.sound_entity_framenum = level.framenum;
                     83:        }
                     84:        else // type == PNOISE_IMPACT
                     85:        {
                     86:                noise = who->mynoise2;
                     87:                level.sound2_entity = noise;
                     88:                level.sound2_entity_framenum = level.framenum;
                     89:        }
                     90: 
                     91:        VectorCopy (where, noise->s.origin);
                     92:        VectorSubtract (where, noise->maxs, noise->absmin);
                     93:        VectorAdd (where, noise->maxs, noise->absmax);
                     94:        noise->teleport_time = level.time;
                     95:        gi.linkentity (noise);
                     96: }
                     97: 
                     98: 
                     99: qboolean Pickup_Weapon (edict_t *ent, edict_t *other)
                    100: {
                    101:        int                     index;
                    102:        gitem_t         *ammo;
                    103: 
                    104:        index = ITEM_INDEX(ent->item);
                    105: 
                    106:        if ( ( ((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value) 
                    107:                && other->client->pers.inventory[index])
                    108:        {
                    109:                if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM) ) )
                    110:                        return false;   // leave the weapon for others to pickup
                    111:        }
                    112: 
                    113:        other->client->pers.inventory[index]++;
                    114: 
                    115:        if (!(ent->spawnflags & DROPPED_ITEM) )
                    116:        {
                    117:                // give them some ammo with it
                    118:                ammo = FindItem (ent->item->ammo);
                    119:                if ( (int)dmflags->value & DF_INFINITE_AMMO )
                    120:                        Add_Ammo (other, ammo, 1000);
                    121:                else
                    122:                        Add_Ammo (other, ammo, ammo->quantity);
                    123: 
                    124:                if (! (ent->spawnflags & DROPPED_PLAYER_ITEM) )
                    125:                {
                    126:                        if (deathmatch->value)
                    127:                        {
                    128:                                if ((int)(dmflags->value) & DF_WEAPONS_STAY)
                    129:                                        ent->flags |= FL_RESPAWN;
                    130:                                else
                    131:                                        SetRespawn (ent, 30);
                    132:                        }
                    133:                        if (coop->value)
                    134:                                ent->flags |= FL_RESPAWN;
                    135:                }
                    136:        }
                    137: 
                    138:        if (other->client->pers.weapon != ent->item && 
                    139:                (other->client->pers.inventory[index] == 1) &&
                    140:                ( !deathmatch->value || other->client->pers.weapon == FindItem("blaster") ) )
                    141:                other->client->newweapon = ent->item;
                    142: 
                    143:        return true;
                    144: }
                    145: 
                    146: 
                    147: /*
                    148: ===============
                    149: ChangeWeapon
                    150: 
                    151: The old weapon has been dropped all the way, so make the new one
                    152: current
                    153: ===============
                    154: */
                    155: void ChangeWeapon (edict_t *ent)
                    156: {
                    157:        int i;
                    158: 
                    159:        if (ent->client->grenade_time)
                    160:        {
                    161:                ent->client->grenade_time = level.time;
                    162:                ent->client->weapon_sound = 0;
                    163:                weapon_grenade_fire (ent, false);
                    164:                ent->client->grenade_time = 0;
                    165:        }
                    166: 
                    167:        ent->client->pers.lastweapon = ent->client->pers.weapon;
                    168:        ent->client->pers.weapon = ent->client->newweapon;
                    169:        ent->client->newweapon = NULL;
                    170:        ent->client->machinegun_shots = 0;
                    171: 
                    172:        // set visible model
                    173:        if (ent->s.modelindex == 255) {
                    174:                if (ent->client->pers.weapon)
                    175:                        i = ((ent->client->pers.weapon->weapmodel & 0xff) << 8);
                    176:                else
                    177:                        i = 0;
                    178:                ent->s.skinnum = (ent - g_edicts - 1) | i;
                    179:        }
                    180: 
                    181:        if (ent->client->pers.weapon && ent->client->pers.weapon->ammo)
                    182:                ent->client->ammo_index = ITEM_INDEX(FindItem(ent->client->pers.weapon->ammo));
                    183:        else
                    184:                ent->client->ammo_index = 0;
                    185: 
                    186:        if (!ent->client->pers.weapon)
                    187:        {       // dead
                    188:                ent->client->ps.gunindex = 0;
                    189:                return;
                    190:        }
                    191: 
                    192:        ent->client->weaponstate = WEAPON_ACTIVATING;
                    193:        ent->client->ps.gunframe = 0;
                    194:        ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model);
                    195: 
                    196:        ent->client->anim_priority = ANIM_PAIN;
                    197:        if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                    198:        {
                    199:                        ent->s.frame = FRAME_crpain1;
                    200:                        ent->client->anim_end = FRAME_crpain4;
                    201:        }
                    202:        else
                    203:        {
                    204:                        ent->s.frame = FRAME_pain301;
                    205:                        ent->client->anim_end = FRAME_pain304;
                    206:                        
                    207:        }
                    208: }
                    209: 
                    210: /*
                    211: =================
                    212: NoAmmoWeaponChange
                    213: =================
                    214: */
                    215: void NoAmmoWeaponChange (edict_t *ent)
                    216: {
                    217:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("slugs"))]
                    218:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("railgun"))] )
                    219:        {
                    220:                ent->client->newweapon = FindItem ("railgun");
                    221:                return;
                    222:        }
                    223:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))]
                    224:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("hyperblaster"))] )
                    225:        {
                    226:                ent->client->newweapon = FindItem ("hyperblaster");
                    227:                return;
                    228:        }
                    229:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
                    230:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("chaingun"))] )
                    231:        {
                    232:                ent->client->newweapon = FindItem ("chaingun");
                    233:                return;
                    234:        }
                    235:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
                    236:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("machinegun"))] )
                    237:        {
                    238:                ent->client->newweapon = FindItem ("machinegun");
                    239:                return;
                    240:        }
                    241:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))] > 1
                    242:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("super shotgun"))] )
                    243:        {
                    244:                ent->client->newweapon = FindItem ("super shotgun");
                    245:                return;
                    246:        }
                    247:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))]
                    248:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("shotgun"))] )
                    249:        {
                    250:                ent->client->newweapon = FindItem ("shotgun");
                    251:                return;
                    252:        }
                    253:        ent->client->newweapon = FindItem ("blaster");
                    254: }
                    255: 
                    256: /*
                    257: =================
                    258: Think_Weapon
                    259: 
                    260: Called by ClientBeginServerFrame and ClientThink
                    261: =================
                    262: */
                    263: void Think_Weapon (edict_t *ent)
                    264: {
                    265:        // if just died, put the weapon away
                    266:        if (ent->health < 1)
                    267:        {
                    268:                ent->client->newweapon = NULL;
                    269:                ChangeWeapon (ent);
                    270:        }
                    271: 
                    272:        // call active weapon think routine
                    273:        if (ent->client->pers.weapon && ent->client->pers.weapon->weaponthink)
                    274:        {
                    275:                is_quad = (ent->client->quad_framenum > level.framenum);
                    276:                if (ent->client->silencer_shots)
                    277:                        is_silenced = MZ_SILENCED;
                    278:                else
                    279:                        is_silenced = 0;
                    280:                ent->client->pers.weapon->weaponthink (ent);
                    281:        }
                    282: }
                    283: 
                    284: 
                    285: /*
                    286: ================
                    287: Use_Weapon
                    288: 
                    289: Make the weapon ready if there is ammo
                    290: ================
                    291: */
                    292: void Use_Weapon (edict_t *ent, gitem_t *item)
                    293: {
                    294:        int                     ammo_index;
                    295:        gitem_t         *ammo_item;
                    296: 
                    297:        // see if we're already using it
                    298:        if (item == ent->client->pers.weapon)
                    299:                return;
                    300: 
                    301:        if (item->ammo && !g_select_empty->value && !(item->flags & IT_AMMO))
                    302:        {
                    303:                ammo_item = FindItem(item->ammo);
                    304:                ammo_index = ITEM_INDEX(ammo_item);
                    305: 
                    306:                if (!ent->client->pers.inventory[ammo_index])
                    307:                {
                    308:                        gi.cprintf (ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
                    309:                        return;
                    310:                }
                    311: 
                    312:                if (ent->client->pers.inventory[ammo_index] < item->quantity)
                    313:                {
                    314:                        gi.cprintf (ent, PRINT_HIGH, "Not enough %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
                    315:                        return;
                    316:                }
                    317:        }
                    318: 
                    319:        // change to this weapon when down
                    320:        ent->client->newweapon = item;
                    321: }
                    322: 
                    323: 
                    324: 
                    325: /*
                    326: ================
                    327: Drop_Weapon
                    328: ================
                    329: */
                    330: void Drop_Weapon (edict_t *ent, gitem_t *item)
                    331: {
                    332:        int             index;
                    333: 
                    334:        if ((int)(dmflags->value) & DF_WEAPONS_STAY)
                    335:                return;
                    336: 
                    337:        index = ITEM_INDEX(item);
                    338:        // see if we're already using it
                    339:        if ( ((item == ent->client->pers.weapon) || (item == ent->client->newweapon))&& (ent->client->pers.inventory[index] == 1) )
                    340:        {
                    341:                gi.cprintf (ent, PRINT_HIGH, "Can't drop current weapon\n");
                    342:                return;
                    343:        }
                    344: 
                    345:        Drop_Item (ent, item);
                    346:        ent->client->pers.inventory[index]--;
                    347: }
                    348: 
                    349: 
                    350: /*
                    351: ================
                    352: Weapon_Generic
                    353: 
                    354: A generic function to handle the basics of weapon thinking
                    355: ================
                    356: */
                    357: #define FRAME_FIRE_FIRST               (FRAME_ACTIVATE_LAST + 1)
                    358: #define FRAME_IDLE_FIRST               (FRAME_FIRE_LAST + 1)
                    359: #define FRAME_DEACTIVATE_FIRST (FRAME_IDLE_LAST + 1)
                    360: 
                    361: static void Weapon_Generic2 (edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int *pause_frames, int *fire_frames, void (*fire)(edict_t *ent))
                    362: {
                    363:        int             n;
                    364: 
                    365:        if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses
                    366:        {
                    367:                return;
                    368:        }
                    369: 
                    370:        if (ent->client->weaponstate == WEAPON_DROPPING)
                    371:        {
                    372:                if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST)
                    373:                {
                    374:                        ChangeWeapon (ent);
                    375:                        return;
                    376:                }
                    377:                else if ((FRAME_DEACTIVATE_LAST - ent->client->ps.gunframe) == 4)
                    378:                {
                    379:                        ent->client->anim_priority = ANIM_REVERSE;
                    380:                        if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                    381:                        {
                    382:                                ent->s.frame = FRAME_crpain4+1;
                    383:                                ent->client->anim_end = FRAME_crpain1;
                    384:                        }
                    385:                        else
                    386:                        {
                    387:                                ent->s.frame = FRAME_pain304+1;
                    388:                                ent->client->anim_end = FRAME_pain301;
                    389:                                
                    390:                        }
                    391:                }
                    392: 
                    393:                ent->client->ps.gunframe++;
                    394:                return;
                    395:        }
                    396: 
                    397:        if (ent->client->weaponstate == WEAPON_ACTIVATING)
                    398:        {
                    399:                if (ent->client->ps.gunframe == FRAME_ACTIVATE_LAST || instantweap->value)
                    400:                {
                    401:                        ent->client->weaponstate = WEAPON_READY;
                    402:                        ent->client->ps.gunframe = FRAME_IDLE_FIRST;
                    403:                        // we go recursive here to instant ready the weapon
                    404:                        Weapon_Generic2 (ent, FRAME_ACTIVATE_LAST, FRAME_FIRE_LAST, 
                    405:                                FRAME_IDLE_LAST, FRAME_DEACTIVATE_LAST, pause_frames, 
                    406:                                fire_frames, fire);
                    407:                        return;
                    408:                }
                    409: 
                    410:                ent->client->ps.gunframe++;
                    411:                return;
                    412:        }
                    413: 
                    414:        if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING))
                    415:        {
                    416:                ent->client->weaponstate = WEAPON_DROPPING;
                    417:                if (instantweap->value) {
                    418:                        ChangeWeapon(ent);
                    419:                        return;
                    420:                } else
                    421:                        ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST;
                    422: 
                    423:                if ((FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < 4)
                    424:                {
                    425:                        ent->client->anim_priority = ANIM_REVERSE;
                    426:                        if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                    427:                        {
                    428:                                ent->s.frame = FRAME_crpain4+1;
                    429:                                ent->client->anim_end = FRAME_crpain1;
                    430:                        }
                    431:                        else
                    432:                        {
                    433:                                ent->s.frame = FRAME_pain304+1;
                    434:                                ent->client->anim_end = FRAME_pain301;
                    435:                                
                    436:                        }
                    437:                }
                    438:                return;
                    439:        }
                    440: 
                    441:        if (ent->client->weaponstate == WEAPON_READY)
                    442:        {
                    443:                if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) )
                    444:                {
                    445:                        ent->client->latched_buttons &= ~BUTTON_ATTACK;
                    446:                        if ((!ent->client->ammo_index) || 
                    447:                                ( ent->client->pers.inventory[ent->client->ammo_index] >= ent->client->pers.weapon->quantity))
                    448:                        {
                    449:                                ent->client->ps.gunframe = FRAME_FIRE_FIRST;
                    450:                                ent->client->weaponstate = WEAPON_FIRING;
                    451: 
                    452:                                // start the animation
                    453:                                ent->client->anim_priority = ANIM_ATTACK;
                    454:                                if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                    455:                                {
                    456:                                        ent->s.frame = FRAME_crattak1-1;
                    457:                                        ent->client->anim_end = FRAME_crattak9;
                    458:                                }
                    459:                                else
                    460:                                {
                    461:                                        ent->s.frame = FRAME_attack1-1;
                    462:                                        ent->client->anim_end = FRAME_attack8;
                    463:                                }
                    464:                        }
                    465:                        else
                    466:                        {
                    467:                                if (level.time >= ent->pain_debounce_time)
                    468:                                {
                    469:                                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
                    470:                                        ent->pain_debounce_time = level.time + 1;
                    471:                                }
                    472:                                NoAmmoWeaponChange (ent);
                    473:                        }
                    474:                }
                    475:                else
                    476:                {
                    477:                        if (ent->client->ps.gunframe == FRAME_IDLE_LAST)
                    478:                        {
                    479:                                ent->client->ps.gunframe = FRAME_IDLE_FIRST;
                    480:                                return;
                    481:                        }
                    482: 
                    483:                        if (pause_frames)
                    484:                        {
                    485:                                for (n = 0; pause_frames[n]; n++)
                    486:                                {
                    487:                                        if (ent->client->ps.gunframe == pause_frames[n])
                    488:                                        {
                    489:                                                if (rand()&15)
                    490:                                                        return;
                    491:                                        }
                    492:                                }
                    493:                        }
                    494: 
                    495:                        ent->client->ps.gunframe++;
                    496:                        return;
                    497:                }
                    498:        }
                    499: 
                    500:        if (ent->client->weaponstate == WEAPON_FIRING)
                    501:        {
                    502:                for (n = 0; fire_frames[n]; n++)
                    503:                {
                    504:                        if (ent->client->ps.gunframe == fire_frames[n])
                    505:                        {
                    506: //ZOID
                    507:                                if (!CTFApplyStrengthSound(ent))
                    508: //ZOID
                    509:                                if (ent->client->quad_framenum > level.framenum)
                    510:                                        gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0);
                    511: //ZOID
                    512:                                CTFApplyHasteSound(ent);
                    513: //ZOID
                    514: 
                    515:                                fire (ent);
                    516:                                break;
                    517:                        }
                    518:                }
                    519: 
                    520:                if (!fire_frames[n])
                    521:                        ent->client->ps.gunframe++;
                    522: 
                    523:                if (ent->client->ps.gunframe == FRAME_IDLE_FIRST+1)
                    524:                        ent->client->weaponstate = WEAPON_READY;
                    525:        }
                    526: }
                    527: 
                    528: //ZOID
                    529: void Weapon_Generic (edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int *pause_frames, int *fire_frames, void (*fire)(edict_t *ent))
                    530: {
                    531:        int oldstate = ent->client->weaponstate;
                    532: 
                    533:        Weapon_Generic2 (ent, FRAME_ACTIVATE_LAST, FRAME_FIRE_LAST, 
                    534:                FRAME_IDLE_LAST, FRAME_DEACTIVATE_LAST, pause_frames, 
                    535:                fire_frames, fire);
                    536: 
                    537:        // run the weapon frame again if hasted
                    538:        if (stricmp(ent->client->pers.weapon->pickup_name, "Grapple") == 0 &&
                    539:                ent->client->weaponstate == WEAPON_FIRING)
                    540:                return;
                    541: 
                    542:        if ((CTFApplyHaste(ent) ||
                    543:                (Q_stricmp(ent->client->pers.weapon->pickup_name, "Grapple") == 0 &&
                    544:                ent->client->weaponstate != WEAPON_FIRING))
                    545:                && oldstate == ent->client->weaponstate) {
                    546:                Weapon_Generic2 (ent, FRAME_ACTIVATE_LAST, FRAME_FIRE_LAST, 
                    547:                        FRAME_IDLE_LAST, FRAME_DEACTIVATE_LAST, pause_frames, 
                    548:                        fire_frames, fire);
                    549:        }
                    550: }
                    551: //ZOID
                    552: 
                    553: /*
                    554: ======================================================================
                    555: 
                    556: GRENADE
                    557: 
                    558: ======================================================================
                    559: */
                    560: 
                    561: #define GRENADE_TIMER          3.0
                    562: #define GRENADE_MINSPEED       400
                    563: #define GRENADE_MAXSPEED       800
                    564: 
                    565: void weapon_grenade_fire (edict_t *ent, qboolean held)
                    566: {
                    567:        vec3_t  offset;
                    568:        vec3_t  forward, right;
                    569:        vec3_t  start;
                    570:        int             damage = 125;
                    571:        float   timer;
                    572:        int             speed;
                    573:        float   radius;
                    574: 
                    575:        radius = damage+40;
                    576:        if (is_quad)
                    577:                damage *= 4;
                    578: 
                    579:        VectorSet(offset, 8, 8, ent->viewheight-8);
                    580:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                    581:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                    582: 
                    583:        timer = ent->client->grenade_time - level.time;
                    584:        speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER);
                    585:        fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held);
                    586: 
                    587:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                    588:                ent->client->pers.inventory[ent->client->ammo_index]--;
                    589: 
                    590:        ent->client->grenade_time = level.time + 1.0;
                    591: 
                    592:        if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses
                    593:        {
                    594:                return;
                    595:        }
                    596: 
                    597:        if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                    598:        {
                    599:                ent->client->anim_priority = ANIM_ATTACK;
                    600:                ent->s.frame = FRAME_crattak1-1;
                    601:                ent->client->anim_end = FRAME_crattak3;
                    602:        }
                    603:        else
                    604:        {
                    605:                ent->client->anim_priority = ANIM_REVERSE;
                    606:                ent->s.frame = FRAME_wave08;
                    607:                ent->client->anim_end = FRAME_wave01;
                    608:        }
                    609: }
                    610: 
                    611: void Weapon_Grenade (edict_t *ent)
                    612: {
                    613:        if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY))
                    614:        {
                    615:                ChangeWeapon (ent);
                    616:                return;
                    617:        }
                    618: 
                    619:        if (ent->client->weaponstate == WEAPON_ACTIVATING)
                    620:        {
                    621:                ent->client->weaponstate = WEAPON_READY;
                    622:                ent->client->ps.gunframe = 16;
                    623:                return;
                    624:        }
                    625: 
                    626:        if (ent->client->weaponstate == WEAPON_READY)
                    627:        {
                    628:                if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) )
                    629:                {
                    630:                        ent->client->latched_buttons &= ~BUTTON_ATTACK;
                    631:                        if (ent->client->pers.inventory[ent->client->ammo_index])
                    632:                        {
                    633:                                ent->client->ps.gunframe = 1;
                    634:                                ent->client->weaponstate = WEAPON_FIRING;
                    635:                                ent->client->grenade_time = 0;
                    636:                        }
                    637:                        else
                    638:                        {
                    639:                                if (level.time >= ent->pain_debounce_time)
                    640:                                {
                    641:                                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
                    642:                                        ent->pain_debounce_time = level.time + 1;
                    643:                                }
                    644:                                NoAmmoWeaponChange (ent);
                    645:                        }
                    646:                        return;
                    647:                }
                    648: 
                    649:                if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48))
                    650:                {
                    651:                        if (rand()&15)
                    652:                                return;
                    653:                }
                    654: 
                    655:                if (++ent->client->ps.gunframe > 48)
                    656:                        ent->client->ps.gunframe = 16;
                    657:                return;
                    658:        }
                    659: 
                    660:        if (ent->client->weaponstate == WEAPON_FIRING)
                    661:        {
                    662:                if (ent->client->ps.gunframe == 5)
                    663:                        gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0);
                    664: 
                    665:                if (ent->client->ps.gunframe == 11)
                    666:                {
                    667:                        if (!ent->client->grenade_time)
                    668:                        {
                    669:                                ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2;
                    670:                                ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav");
                    671:                        }
                    672: 
                    673:                        // they waited too long, detonate it in their hand
                    674:                        if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time)
                    675:                        {
                    676:                                ent->client->weapon_sound = 0;
                    677:                                weapon_grenade_fire (ent, true);
                    678:                                ent->client->grenade_blew_up = true;
                    679:                        }
                    680: 
                    681:                        if (ent->client->buttons & BUTTON_ATTACK)
                    682:                                return;
                    683: 
                    684:                        if (ent->client->grenade_blew_up)
                    685:                        {
                    686:                                if (level.time >= ent->client->grenade_time)
                    687:                                {
                    688:                                        ent->client->ps.gunframe = 15;
                    689:                                        ent->client->grenade_blew_up = false;
                    690:                                }
                    691:                                else
                    692:                                {
                    693:                                        return;
                    694:                                }
                    695:                        }
                    696:                }
                    697: 
                    698:                if (ent->client->ps.gunframe == 12)
                    699:                {
                    700:                        ent->client->weapon_sound = 0;
                    701:                        weapon_grenade_fire (ent, false);
                    702:                }
                    703: 
                    704:                if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time))
                    705:                        return;
                    706: 
                    707:                ent->client->ps.gunframe++;
                    708: 
                    709:                if (ent->client->ps.gunframe == 16)
                    710:                {
                    711:                        ent->client->grenade_time = 0;
                    712:                        ent->client->weaponstate = WEAPON_READY;
                    713:                }
                    714:        }
                    715: }
                    716: 
                    717: /*
                    718: ======================================================================
                    719: 
                    720: GRENADE LAUNCHER
                    721: 
                    722: ======================================================================
                    723: */
                    724: 
                    725: void weapon_grenadelauncher_fire (edict_t *ent)
                    726: {
                    727:        vec3_t  offset;
                    728:        vec3_t  forward, right;
                    729:        vec3_t  start;
                    730:        int             damage = 120;
                    731:        float   radius;
                    732: 
                    733:        radius = damage+40;
                    734:        if (is_quad)
                    735:                damage *= 4;
                    736: 
                    737:        VectorSet(offset, 8, 8, ent->viewheight-8);
                    738:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                    739:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                    740: 
                    741:        VectorScale (forward, -2, ent->client->kick_origin);
                    742:        ent->client->kick_angles[0] = -1;
                    743: 
                    744:        fire_grenade (ent, start, forward, damage, 600, 2.5, radius);
                    745: 
                    746:        gi.WriteByte (svc_muzzleflash);
                    747:        gi.WriteShort (ent-g_edicts);
                    748:        gi.WriteByte (MZ_GRENADE | is_silenced);
                    749:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                    750: 
                    751:        ent->client->ps.gunframe++;
                    752: 
                    753:        PlayerNoise(ent, start, PNOISE_WEAPON);
                    754: 
                    755:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                    756:                ent->client->pers.inventory[ent->client->ammo_index]--;
                    757: }
                    758: 
                    759: void Weapon_GrenadeLauncher (edict_t *ent)
                    760: {
                    761:        static int      pause_frames[]  = {34, 51, 59, 0};
                    762:        static int      fire_frames[]   = {6, 0};
                    763: 
                    764:        Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire);
                    765: }
                    766: 
                    767: /*
                    768: ======================================================================
                    769: 
                    770: ROCKET
                    771: 
                    772: ======================================================================
                    773: */
                    774: 
                    775: void Weapon_RocketLauncher_Fire (edict_t *ent)
                    776: {
                    777:        vec3_t  offset, start;
                    778:        vec3_t  forward, right;
                    779:        int             damage;
                    780:        float   damage_radius;
                    781:        int             radius_damage;
                    782: 
                    783:        damage = 100 + (int)(random() * 20.0);
                    784:        radius_damage = 120;
                    785:        damage_radius = 120;
                    786:        if (is_quad)
                    787:        {
                    788:                damage *= 4;
                    789:                radius_damage *= 4;
                    790:        }
                    791: 
                    792:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                    793: 
                    794:        VectorScale (forward, -2, ent->client->kick_origin);
                    795:        ent->client->kick_angles[0] = -1;
                    796: 
                    797:        VectorSet(offset, 8, 8, ent->viewheight-8);
                    798:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                    799:        fire_rocket (ent, start, forward, damage, 650, damage_radius, radius_damage);
                    800: 
                    801:        // send muzzle flash
                    802:        gi.WriteByte (svc_muzzleflash);
                    803:        gi.WriteShort (ent-g_edicts);
                    804:        gi.WriteByte (MZ_ROCKET | is_silenced);
                    805:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                    806: 
                    807:        ent->client->ps.gunframe++;
                    808: 
                    809:        PlayerNoise(ent, start, PNOISE_WEAPON);
                    810: 
                    811:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                    812:                ent->client->pers.inventory[ent->client->ammo_index]--;
                    813: }
                    814: 
                    815: void Weapon_RocketLauncher (edict_t *ent)
                    816: {
                    817:        static int      pause_frames[]  = {25, 33, 42, 50, 0};
                    818:        static int      fire_frames[]   = {5, 0};
                    819: 
                    820:        Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire);
                    821: }
                    822: 
                    823: 
                    824: /*
                    825: ======================================================================
                    826: 
                    827: BLASTER / HYPERBLASTER
                    828: 
                    829: ======================================================================
                    830: */
                    831: 
                    832: void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect)
                    833: {
                    834:        vec3_t  forward, right;
                    835:        vec3_t  start;
                    836:        vec3_t  offset;
                    837: 
                    838:        if (is_quad)
                    839:                damage *= 4;
                    840:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                    841:        VectorSet(offset, 24, 8, ent->viewheight-8);
                    842:        VectorAdd (offset, g_offset, offset);
                    843:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                    844: 
                    845:        VectorScale (forward, -2, ent->client->kick_origin);
                    846:        ent->client->kick_angles[0] = -1;
                    847: 
                    848:        fire_blaster (ent, start, forward, damage, 1000, effect, hyper);
                    849: 
                    850:        // send muzzle flash
                    851:        gi.WriteByte (svc_muzzleflash);
                    852:        gi.WriteShort (ent-g_edicts);
                    853:        if (hyper)
                    854:                gi.WriteByte (MZ_HYPERBLASTER | is_silenced);
                    855:        else
                    856:                gi.WriteByte (MZ_BLASTER | is_silenced);
                    857:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                    858: 
                    859:        PlayerNoise(ent, start, PNOISE_WEAPON);
                    860: }
                    861: 
                    862: 
                    863: void Weapon_Blaster_Fire (edict_t *ent)
                    864: {
                    865:        int             damage;
                    866: 
                    867:        if (deathmatch->value)
                    868:                damage = 15;
                    869:        else
                    870:                damage = 10;
                    871:        Blaster_Fire (ent, vec3_origin, damage, false, EF_BLASTER);
                    872:        ent->client->ps.gunframe++;
                    873: }
                    874: 
                    875: void Weapon_Blaster (edict_t *ent)
                    876: {
                    877:        static int      pause_frames[]  = {19, 32, 0};
                    878:        static int      fire_frames[]   = {5, 0};
                    879: 
                    880:        Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire);
                    881: }
                    882: 
                    883: 
                    884: void Weapon_HyperBlaster_Fire (edict_t *ent)
                    885: {
                    886:        float   rotation;
                    887:        vec3_t  offset;
                    888:        int             effect;
                    889:        int             damage;
                    890: 
                    891:        ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav");
                    892: 
                    893:        if (!(ent->client->buttons & BUTTON_ATTACK))
                    894:        {
                    895:                ent->client->ps.gunframe++;
                    896:        }
                    897:        else
                    898:        {
                    899:                if (! ent->client->pers.inventory[ent->client->ammo_index] )
                    900:                {
                    901:                        if (level.time >= ent->pain_debounce_time)
                    902:                        {
                    903:                                gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
                    904:                                ent->pain_debounce_time = level.time + 1;
                    905:                        }
                    906:                        NoAmmoWeaponChange (ent);
                    907:                }
                    908:                else
                    909:                {
                    910:                        rotation = (ent->client->ps.gunframe - 5) * 2*M_PI/6;
                    911:                        offset[0] = -4 * sin(rotation);
                    912:                        offset[1] = 0;
                    913:                        offset[2] = 4 * cos(rotation);
                    914: 
                    915:                        if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9))
                    916:                                effect = EF_HYPERBLASTER;
                    917:                        else
                    918:                                effect = 0;
                    919:                        if (deathmatch->value)
                    920:                                damage = 15;
                    921:                        else
                    922:                                damage = 20;
                    923:                        Blaster_Fire (ent, offset, damage, true, effect);
                    924:                        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                    925:                                ent->client->pers.inventory[ent->client->ammo_index]--;
                    926: 
                    927:                        ent->client->anim_priority = ANIM_ATTACK;
                    928:                        if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                    929:                        {
                    930:                                ent->s.frame = FRAME_crattak1 - 1;
                    931:                                ent->client->anim_end = FRAME_crattak9;
                    932:                        }
                    933:                        else
                    934:                        {
                    935:                                ent->s.frame = FRAME_attack1 - 1;
                    936:                                ent->client->anim_end = FRAME_attack8;
                    937:                        }
                    938:                }
                    939: 
                    940:                ent->client->ps.gunframe++;
                    941:                if (ent->client->ps.gunframe == 12 && ent->client->pers.inventory[ent->client->ammo_index])
                    942:                        ent->client->ps.gunframe = 6;
                    943:        }
                    944: 
                    945:        if (ent->client->ps.gunframe == 12)
                    946:        {
                    947:                gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0);
                    948:                ent->client->weapon_sound = 0;
                    949:        }
                    950: 
                    951: }
                    952: 
                    953: void Weapon_HyperBlaster (edict_t *ent)
                    954: {
                    955:        static int      pause_frames[]  = {0};
                    956:        static int      fire_frames[]   = {6, 7, 8, 9, 10, 11, 0};
                    957: 
                    958:        Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire);
                    959: }
                    960: 
                    961: /*
                    962: ======================================================================
                    963: 
                    964: MACHINEGUN / CHAINGUN
                    965: 
                    966: ======================================================================
                    967: */
                    968: 
                    969: void Machinegun_Fire (edict_t *ent)
                    970: {
                    971:        int     i;
                    972:        vec3_t          start;
                    973:        vec3_t          forward, right;
                    974:        vec3_t          angles;
                    975:        int                     damage = 8;
                    976:        int                     kick = 2;
                    977:        vec3_t          offset;
                    978: 
                    979:        if (!(ent->client->buttons & BUTTON_ATTACK))
                    980:        {
                    981:                ent->client->machinegun_shots = 0;
                    982:                ent->client->ps.gunframe++;
                    983:                return;
                    984:        }
                    985: 
                    986:        if (ent->client->ps.gunframe == 5)
                    987:                ent->client->ps.gunframe = 4;
                    988:        else
                    989:                ent->client->ps.gunframe = 5;
                    990: 
                    991:        if (ent->client->pers.inventory[ent->client->ammo_index] < 1)
                    992:        {
                    993:                ent->client->ps.gunframe = 6;
                    994:                if (level.time >= ent->pain_debounce_time)
                    995:                {
                    996:                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
                    997:                        ent->pain_debounce_time = level.time + 1;
                    998:                }
                    999:                NoAmmoWeaponChange (ent);
                   1000:                return;
                   1001:        }
                   1002: 
                   1003:        if (is_quad)
                   1004:        {
                   1005:                damage *= 4;
                   1006:                kick *= 4;
                   1007:        }
                   1008: 
                   1009:        for (i=1 ; i<3 ; i++)
                   1010:        {
                   1011:                ent->client->kick_origin[i] = crandom() * 0.35;
                   1012:                ent->client->kick_angles[i] = crandom() * 0.7;
                   1013:        }
                   1014:        ent->client->kick_origin[0] = crandom() * 0.35;
                   1015:        ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5;
                   1016: 
                   1017:        // raise the gun as it is firing
                   1018:        if (!deathmatch->value)
                   1019:        {
                   1020:                ent->client->machinegun_shots++;
                   1021:                if (ent->client->machinegun_shots > 9)
                   1022:                        ent->client->machinegun_shots = 9;
                   1023:        }
                   1024: 
                   1025:        // get start / end positions
                   1026:        VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles);
                   1027:        AngleVectors (angles, forward, right, NULL);
                   1028:        VectorSet(offset, 0, 8, ent->viewheight-8);
                   1029:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1030:        fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN);
                   1031: 
                   1032:        gi.WriteByte (svc_muzzleflash);
                   1033:        gi.WriteShort (ent-g_edicts);
                   1034:        gi.WriteByte (MZ_MACHINEGUN | is_silenced);
                   1035:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                   1036: 
                   1037:        PlayerNoise(ent, start, PNOISE_WEAPON);
                   1038: 
                   1039:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1040:                ent->client->pers.inventory[ent->client->ammo_index]--;
                   1041: 
                   1042:        ent->client->anim_priority = ANIM_ATTACK;
                   1043:        if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                   1044:        {
                   1045:                ent->s.frame = FRAME_crattak1 - (int) (random()+0.25);
                   1046:                ent->client->anim_end = FRAME_crattak9;
                   1047:        }
                   1048:        else
                   1049:        {
                   1050:                ent->s.frame = FRAME_attack1 - (int) (random()+0.25);
                   1051:                ent->client->anim_end = FRAME_attack8;
                   1052:        }
                   1053: }
                   1054: 
                   1055: void Weapon_Machinegun (edict_t *ent)
                   1056: {
                   1057:        static int      pause_frames[]  = {23, 45, 0};
                   1058:        static int      fire_frames[]   = {4, 5, 0};
                   1059: 
                   1060:        Weapon_Generic (ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire);
                   1061: }
                   1062: 
                   1063: void Chaingun_Fire (edict_t *ent)
                   1064: {
                   1065:        int                     i;
                   1066:        int                     shots;
                   1067:        vec3_t          start;
                   1068:        vec3_t          forward, right, up;
                   1069:        float           r, u;
                   1070:        vec3_t          offset;
                   1071:        int                     damage;
                   1072:        int                     kick = 2;
                   1073: 
                   1074:        if (deathmatch->value)
                   1075:                damage = 6;
                   1076:        else
                   1077:                damage = 8;
                   1078: 
                   1079:        if (ent->client->ps.gunframe == 5)
                   1080:                gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0);
                   1081: 
                   1082:        if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK))
                   1083:        {
                   1084:                ent->client->ps.gunframe = 32;
                   1085:                ent->client->weapon_sound = 0;
                   1086:                return;
                   1087:        }
                   1088:        else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK)
                   1089:                && ent->client->pers.inventory[ent->client->ammo_index])
                   1090:        {
                   1091:                ent->client->ps.gunframe = 15;
                   1092:        }
                   1093:        else
                   1094:        {
                   1095:                ent->client->ps.gunframe++;
                   1096:        }
                   1097: 
                   1098:        if (ent->client->ps.gunframe == 22)
                   1099:        {
                   1100:                ent->client->weapon_sound = 0;
                   1101:                gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0);
                   1102:        }
                   1103:        else
                   1104:        {
                   1105:                ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav");
                   1106:        }
                   1107: 
                   1108:        ent->client->anim_priority = ANIM_ATTACK;
                   1109:        if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                   1110:        {
                   1111:                ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1);
                   1112:                ent->client->anim_end = FRAME_crattak9;
                   1113:        }
                   1114:        else
                   1115:        {
                   1116:                ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1);
                   1117:                ent->client->anim_end = FRAME_attack8;
                   1118:        }
                   1119: 
                   1120:        if (ent->client->ps.gunframe <= 9)
                   1121:                shots = 1;
                   1122:        else if (ent->client->ps.gunframe <= 14)
                   1123:        {
                   1124:                if (ent->client->buttons & BUTTON_ATTACK)
                   1125:                        shots = 2;
                   1126:                else
                   1127:                        shots = 1;
                   1128:        }
                   1129:        else
                   1130:                shots = 3;
                   1131: 
                   1132:        if (ent->client->pers.inventory[ent->client->ammo_index] < shots)
                   1133:                shots = ent->client->pers.inventory[ent->client->ammo_index];
                   1134: 
                   1135:        if (!shots)
                   1136:        {
                   1137:                if (level.time >= ent->pain_debounce_time)
                   1138:                {
                   1139:                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
                   1140:                        ent->pain_debounce_time = level.time + 1;
                   1141:                }
                   1142:                NoAmmoWeaponChange (ent);
                   1143:                return;
                   1144:        }
                   1145: 
                   1146:        if (is_quad)
                   1147:        {
                   1148:                damage *= 4;
                   1149:                kick *= 4;
                   1150:        }
                   1151: 
                   1152:        for (i=0 ; i<3 ; i++)
                   1153:        {
                   1154:                ent->client->kick_origin[i] = crandom() * 0.35;
                   1155:                ent->client->kick_angles[i] = crandom() * 0.7;
                   1156:        }
                   1157: 
                   1158:        for (i=0 ; i<shots ; i++)
                   1159:        {
                   1160:                // get start / end positions
                   1161:                AngleVectors (ent->client->v_angle, forward, right, up);
                   1162:                r = 7 + crandom()*4;
                   1163:                u = crandom()*4;
                   1164:                VectorSet(offset, 0, r, u + ent->viewheight-8);
                   1165:                P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1166: 
                   1167:                fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN);
                   1168:        }
                   1169: 
                   1170:        // send muzzle flash
                   1171:        gi.WriteByte (svc_muzzleflash);
                   1172:        gi.WriteShort (ent-g_edicts);
                   1173:        gi.WriteByte ((MZ_CHAINGUN1 + shots - 1) | is_silenced);
                   1174:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                   1175: 
                   1176:        PlayerNoise(ent, start, PNOISE_WEAPON);
                   1177: 
                   1178:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1179:                ent->client->pers.inventory[ent->client->ammo_index] -= shots;
                   1180: }
                   1181: 
                   1182: 
                   1183: void Weapon_Chaingun (edict_t *ent)
                   1184: {
                   1185:        static int      pause_frames[]  = {38, 43, 51, 61, 0};
                   1186:        static int      fire_frames[]   = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0};
                   1187: 
                   1188:        Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire);
                   1189: }
                   1190: 
                   1191: 
                   1192: /*
                   1193: ======================================================================
                   1194: 
                   1195: SHOTGUN / SUPERSHOTGUN
                   1196: 
                   1197: ======================================================================
                   1198: */
                   1199: 
                   1200: void weapon_shotgun_fire (edict_t *ent)
                   1201: {
                   1202:        vec3_t          start;
                   1203:        vec3_t          forward, right;
                   1204:        vec3_t          offset;
                   1205:        int                     damage = 4;
                   1206:        int                     kick = 8;
                   1207: 
                   1208:        if (ent->client->ps.gunframe == 9)
                   1209:        {
                   1210:                ent->client->ps.gunframe++;
                   1211:                return;
                   1212:        }
                   1213: 
                   1214:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                   1215: 
                   1216:        VectorScale (forward, -2, ent->client->kick_origin);
                   1217:        ent->client->kick_angles[0] = -2;
                   1218: 
                   1219:        VectorSet(offset, 0, 8,  ent->viewheight-8);
                   1220:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1221: 
                   1222:        if (is_quad)
                   1223:        {
                   1224:                damage *= 4;
                   1225:                kick *= 4;
                   1226:        }
                   1227: 
                   1228:        if (deathmatch->value)
                   1229:                fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_DEATHMATCH_SHOTGUN_COUNT, MOD_SHOTGUN);
                   1230:        else
                   1231:                fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN);
                   1232: 
                   1233:        // send muzzle flash
                   1234:        gi.WriteByte (svc_muzzleflash);
                   1235:        gi.WriteShort (ent-g_edicts);
                   1236:        gi.WriteByte (MZ_SHOTGUN | is_silenced);
                   1237:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                   1238: 
                   1239:        ent->client->ps.gunframe++;
                   1240:        PlayerNoise(ent, start, PNOISE_WEAPON);
                   1241: 
                   1242:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1243:                ent->client->pers.inventory[ent->client->ammo_index]--;
                   1244: }
                   1245: 
                   1246: void Weapon_Shotgun (edict_t *ent)
                   1247: {
                   1248:        static int      pause_frames[]  = {22, 28, 34, 0};
                   1249:        static int      fire_frames[]   = {8, 9, 0};
                   1250: 
                   1251:        Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire);
                   1252: }
                   1253: 
                   1254: 
                   1255: void weapon_supershotgun_fire (edict_t *ent)
                   1256: {
                   1257:        vec3_t          start;
                   1258:        vec3_t          forward, right;
                   1259:        vec3_t          offset;
                   1260:        vec3_t          v;
                   1261:        int                     damage = 6;
                   1262:        int                     kick = 12;
                   1263: 
                   1264:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                   1265: 
                   1266:        VectorScale (forward, -2, ent->client->kick_origin);
                   1267:        ent->client->kick_angles[0] = -2;
                   1268: 
                   1269:        VectorSet(offset, 0, 8,  ent->viewheight-8);
                   1270:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1271: 
                   1272:        if (is_quad)
                   1273:        {
                   1274:                damage *= 4;
                   1275:                kick *= 4;
                   1276:        }
                   1277: 
                   1278:        v[PITCH] = ent->client->v_angle[PITCH];
                   1279:        v[YAW]   = ent->client->v_angle[YAW] - 5;
                   1280:        v[ROLL]  = ent->client->v_angle[ROLL];
                   1281:        AngleVectors (v, forward, NULL, NULL);
                   1282:        fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN);
                   1283:        v[YAW]   = ent->client->v_angle[YAW] + 5;
                   1284:        AngleVectors (v, forward, NULL, NULL);
                   1285:        fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN);
                   1286: 
                   1287:        // send muzzle flash
                   1288:        gi.WriteByte (svc_muzzleflash);
                   1289:        gi.WriteShort (ent-g_edicts);
                   1290:        gi.WriteByte (MZ_SSHOTGUN | is_silenced);
                   1291:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                   1292: 
                   1293:        ent->client->ps.gunframe++;
                   1294:        PlayerNoise(ent, start, PNOISE_WEAPON);
                   1295: 
                   1296:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1297:                ent->client->pers.inventory[ent->client->ammo_index] -= 2;
                   1298: }
                   1299: 
                   1300: void Weapon_SuperShotgun (edict_t *ent)
                   1301: {
                   1302:        static int      pause_frames[]  = {29, 42, 57, 0};
                   1303:        static int      fire_frames[]   = {7, 0};
                   1304: 
                   1305:        Weapon_Generic (ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire);
                   1306: }
                   1307: 
                   1308: 
                   1309: 
                   1310: /*
                   1311: ======================================================================
                   1312: 
                   1313: RAILGUN
                   1314: 
                   1315: ======================================================================
                   1316: */
                   1317: 
                   1318: void weapon_railgun_fire (edict_t *ent)
                   1319: {
                   1320:        vec3_t          start;
                   1321:        vec3_t          forward, right;
                   1322:        vec3_t          offset;
                   1323:        int                     damage;
                   1324:        int                     kick;
                   1325: 
                   1326:        if (deathmatch->value)
                   1327:        {       // normal damage is too extreme in dm
                   1328:                damage = 100;
                   1329:                kick = 200;
                   1330:        }
                   1331:        else
                   1332:        {
                   1333:                damage = 150;
                   1334:                kick = 250;
                   1335:        }
                   1336: 
                   1337:        if (is_quad)
                   1338:        {
                   1339:                damage *= 4;
                   1340:                kick *= 4;
                   1341:        }
                   1342: 
                   1343:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                   1344: 
                   1345:        VectorScale (forward, -3, ent->client->kick_origin);
                   1346:        ent->client->kick_angles[0] = -3;
                   1347: 
                   1348:        VectorSet(offset, 0, 7,  ent->viewheight-8);
                   1349:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1350:        fire_rail (ent, start, forward, damage, kick);
                   1351: 
                   1352:        // send muzzle flash
                   1353:        gi.WriteByte (svc_muzzleflash);
                   1354:        gi.WriteShort (ent-g_edicts);
                   1355:        gi.WriteByte (MZ_RAILGUN | is_silenced);
                   1356:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                   1357: 
                   1358:        ent->client->ps.gunframe++;
                   1359:        PlayerNoise(ent, start, PNOISE_WEAPON);
                   1360: 
                   1361:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1362:                ent->client->pers.inventory[ent->client->ammo_index]--;
                   1363: }
                   1364: 
                   1365: 
                   1366: void Weapon_Railgun (edict_t *ent)
                   1367: {
                   1368:        static int      pause_frames[]  = {56, 0};
                   1369:        static int      fire_frames[]   = {4, 0};
                   1370: 
                   1371:        Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire);
                   1372: }
                   1373: 
                   1374: 
                   1375: /*
                   1376: ======================================================================
                   1377: 
                   1378: BFG10K
                   1379: 
                   1380: ======================================================================
                   1381: */
                   1382: 
                   1383: void weapon_bfg_fire (edict_t *ent)
                   1384: {
                   1385:        vec3_t  offset, start;
                   1386:        vec3_t  forward, right;
                   1387:        int             damage;
                   1388:        float   damage_radius = 1000;
                   1389: 
                   1390:        if (deathmatch->value)
                   1391:                damage = 200;
                   1392:        else
                   1393:                damage = 500;
                   1394: 
                   1395:        if (ent->client->ps.gunframe == 9)
                   1396:        {
                   1397:                // send muzzle flash
                   1398:                gi.WriteByte (svc_muzzleflash);
                   1399:                gi.WriteShort (ent-g_edicts);
                   1400:                gi.WriteByte (MZ_BFG | is_silenced);
                   1401:                gi.multicast (ent->s.origin, MULTICAST_PVS);
                   1402: 
                   1403:                ent->client->ps.gunframe++;
                   1404: 
                   1405:                PlayerNoise(ent, start, PNOISE_WEAPON);
                   1406:                return;
                   1407:        }
                   1408: 
                   1409:        // cells can go down during windup (from power armor hits), so
                   1410:        // check again and abort firing if we don't have enough now
                   1411:        if (ent->client->pers.inventory[ent->client->ammo_index] < 50)
                   1412:        {
                   1413:                ent->client->ps.gunframe++;
                   1414:                return;
                   1415:        }
                   1416: 
                   1417:        if (is_quad)
                   1418:                damage *= 4;
                   1419: 
                   1420:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                   1421: 
                   1422:        VectorScale (forward, -2, ent->client->kick_origin);
                   1423: 
                   1424:        // make a big pitch kick with an inverse fall
                   1425:        ent->client->v_dmg_pitch = -40;
                   1426:        ent->client->v_dmg_roll = crandom()*8;
                   1427:        ent->client->v_dmg_time = level.time + DAMAGE_TIME;
                   1428: 
                   1429:        VectorSet(offset, 8, 8, ent->viewheight-8);
                   1430:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1431:        fire_bfg (ent, start, forward, damage, 400, damage_radius);
                   1432: 
                   1433:        ent->client->ps.gunframe++;
                   1434: 
                   1435:        PlayerNoise(ent, start, PNOISE_WEAPON);
                   1436: 
                   1437:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1438:                ent->client->pers.inventory[ent->client->ammo_index] -= 50;
                   1439: }
                   1440: 
                   1441: void Weapon_BFG (edict_t *ent)
                   1442: {
                   1443:        static int      pause_frames[]  = {39, 45, 50, 55, 0};
                   1444:        static int      fire_frames[]   = {9, 17, 0};
                   1445: 
                   1446:        Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire);
                   1447: }
                   1448: 
                   1449: 
                   1450: //======================================================================

unix.superglobalmegacorp.com

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