Annotation of quake2/xatrix/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: // RAFAEL
                      9: static qboolean is_quadfire;
                     10: static byte            is_silenced;
                     11: 
                     12: 
                     13: void weapon_grenade_fire (edict_t *ent, qboolean held);
                     14: // RAFAEL
                     15: void weapon_trap_fire (edict_t *ent, qboolean held);
                     16: 
                     17: 
                     18: static void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
                     19: {
                     20:        vec3_t  _distance;
                     21: 
                     22:        VectorCopy (distance, _distance);
                     23:        if (client->pers.hand == LEFT_HANDED)
                     24:                _distance[1] *= -1;
                     25:        else if (client->pers.hand == CENTER_HANDED)
                     26:                _distance[1] = 0;
                     27:        G_ProjectSource (point, _distance, forward, right, result);
                     28: }
                     29: 
                     30: 
                     31: /*
                     32: ===============
                     33: PlayerNoise
                     34: 
                     35: Each player can have two noise objects associated with it:
                     36: a personal noise (jumping, pain, weapon firing), and a weapon
                     37: target noise (bullet wall impacts)
                     38: 
                     39: Monsters that don't directly see the player can move
                     40: to a noise in hopes of seeing the player from there.
                     41: ===============
                     42: */
                     43: void PlayerNoise(edict_t *who, vec3_t where, int type)
                     44: {
                     45:        edict_t         *noise;
                     46: 
                     47:        if (type == PNOISE_WEAPON)
                     48:        {
                     49:                if (who->client->silencer_shots)
                     50:                {
                     51:                        who->client->silencer_shots--;
                     52:                        return;
                     53:                }
                     54:        }
                     55: 
                     56:        if (deathmatch->value)
                     57:                return;
                     58: 
                     59:        if (who->flags & FL_NOTARGET)
                     60:                return;
                     61: 
                     62: 
                     63:        if (!who->mynoise)
                     64:        {
                     65:                noise = G_Spawn();
                     66:                noise->classname = "player_noise";
                     67:                VectorSet (noise->mins, -8, -8, -8);
                     68:                VectorSet (noise->maxs, 8, 8, 8);
                     69:                noise->owner = who;
                     70:                noise->svflags = SVF_NOCLIENT;
                     71:                who->mynoise = noise;
                     72: 
                     73:                noise = G_Spawn();
                     74:                noise->classname = "player_noise";
                     75:                VectorSet (noise->mins, -8, -8, -8);
                     76:                VectorSet (noise->maxs, 8, 8, 8);
                     77:                noise->owner = who;
                     78:                noise->svflags = SVF_NOCLIENT;
                     79:                who->mynoise2 = noise;
                     80:        }
                     81: 
                     82:        if (type == PNOISE_SELF || type == PNOISE_WEAPON)
                     83:        {
                     84:                noise = who->mynoise;
                     85:                level.sound_entity = noise;
                     86:                level.sound_entity_framenum = level.framenum;
                     87:        }
                     88:        else // type == PNOISE_IMPACT
                     89:        {
                     90:                noise = who->mynoise2;
                     91:                level.sound2_entity = noise;
                     92:                level.sound2_entity_framenum = level.framenum;
                     93:        }
                     94: 
                     95:        VectorCopy (where, noise->s.origin);
                     96:        VectorSubtract (where, noise->maxs, noise->absmin);
                     97:        VectorAdd (where, noise->maxs, noise->absmax);
                     98:        noise->teleport_time = level.time;
                     99:        gi.linkentity (noise);
                    100: }
                    101: 
                    102: 
                    103: qboolean Pickup_Weapon (edict_t *ent, edict_t *other)
                    104: {
                    105:        int                     index;
                    106:        gitem_t         *ammo;
                    107: 
                    108:        index = ITEM_INDEX(ent->item);
                    109: 
                    110:        if ( ( ((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value) 
                    111:                && other->client->pers.inventory[index])
                    112:        {
                    113:                if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM) ) )
                    114:                        return false;   // leave the weapon for others to pickup
                    115:        }
                    116: 
                    117:        other->client->pers.inventory[index]++;
                    118: 
                    119:        if (!(ent->spawnflags & DROPPED_ITEM) )
                    120:        {
                    121:                // give them some ammo with it
                    122:                ammo = FindItem (ent->item->ammo);
                    123:                // Don't get infinite ammo with trap
                    124:                if ( ((int)dmflags->value & DF_INFINITE_AMMO) && Q_stricmp(ent->item->pickup_name, "ammo_trap") )
                    125:                        Add_Ammo (other, ammo, 1000);
                    126:                else
                    127:                        Add_Ammo (other, ammo, ammo->quantity);
                    128: 
                    129:                if (! (ent->spawnflags & DROPPED_PLAYER_ITEM) )
                    130:                {
                    131:                        if (deathmatch->value)
                    132:                        {
                    133:                                if ((int)(dmflags->value) & DF_WEAPONS_STAY)
                    134:                                        ent->flags |= FL_RESPAWN;
                    135:                                else
                    136:                                        SetRespawn (ent, 30);
                    137:                        }
                    138:                        if (coop->value)
                    139:                                ent->flags |= FL_RESPAWN;
                    140:                }
                    141:        }
                    142: 
                    143:        if (other->client->pers.weapon != ent->item && 
                    144:                (other->client->pers.inventory[index] == 1) &&
                    145:                ( !deathmatch->value || other->client->pers.weapon == FindItem("blaster") ) )
                    146:                other->client->newweapon = ent->item;
                    147: 
                    148:        return true;
                    149: }
                    150: 
                    151: 
                    152: /*
                    153: ===============
                    154: ChangeWeapon
                    155: 
                    156: The old weapon has been dropped all the way, so make the new one
                    157: current
                    158: ===============
                    159: */
                    160: void ChangeWeapon (edict_t *ent)
                    161: {
                    162:        if (ent->client->grenade_time)
                    163:        {
                    164:                ent->client->grenade_time = level.time;
                    165:                ent->client->weapon_sound = 0;
                    166:                weapon_grenade_fire (ent, false);
                    167:                ent->client->grenade_time = 0;
                    168:        }
                    169: 
                    170:        ent->client->pers.lastweapon = ent->client->pers.weapon;
                    171:        ent->client->pers.weapon = ent->client->newweapon;
                    172:        ent->client->newweapon = NULL;
                    173:        ent->client->machinegun_shots = 0;
                    174: 
                    175:        if (ent->client->pers.weapon && ent->client->pers.weapon->ammo)
                    176:                ent->client->ammo_index = ITEM_INDEX(FindItem(ent->client->pers.weapon->ammo));
                    177:        else
                    178:                ent->client->ammo_index = 0;
                    179: 
                    180:        if (!ent->client->pers.weapon)
                    181:        {       // dead
                    182:                ent->client->ps.gunindex = 0;
                    183:                return;
                    184:        }
                    185: 
                    186:        ent->client->weaponstate = WEAPON_ACTIVATING;
                    187:        ent->client->ps.gunframe = 0;
                    188:        ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model);
                    189: 
                    190:        ent->client->anim_priority = ANIM_PAIN;
                    191:        if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                    192:        {
                    193:                        ent->s.frame = FRAME_crpain1;
                    194:                        ent->client->anim_end = FRAME_crpain4;
                    195:        }
                    196:        else
                    197:        {
                    198:                        ent->s.frame = FRAME_pain301;
                    199:                        ent->client->anim_end = FRAME_pain304;
                    200:                        
                    201:        }
                    202: }
                    203: 
                    204: /*
                    205: =================
                    206: NoAmmoWeaponChange
                    207: =================
                    208: */
                    209: void NoAmmoWeaponChange (edict_t *ent)
                    210: {
                    211:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("slugs"))]
                    212:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("railgun"))] )
                    213:        {
                    214:                ent->client->newweapon = FindItem ("railgun");
                    215:                return;
                    216:        }
                    217:        // RAFAEL
                    218:        if ( ent->client->pers.inventory[ITEM_INDEX (FindItem ("mag slug"))]
                    219:                && ent->client->pers.inventory[ITEM_INDEX (FindItem ("phalanx"))])
                    220:        {
                    221:                ent->client->newweapon = FindItem ("phalanx");  
                    222:        }
                    223:        // RAFAEL
                    224:        if ( ent->client->pers.inventory[ITEM_INDEX (FindItem ("cells"))]
                    225:                && ent->client->pers.inventory[ITEM_INDEX (FindItem ("ionripper"))])
                    226:        {
                    227:                ent->client->newweapon = FindItem ("ionrippergun");     
                    228:        }
                    229:        
                    230:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))]
                    231:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("hyperblaster"))] )
                    232:        {
                    233:                ent->client->newweapon = FindItem ("hyperblaster");
                    234:                return;
                    235:        }
                    236:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
                    237:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("chaingun"))] )
                    238:        {
                    239:                ent->client->newweapon = FindItem ("chaingun");
                    240:                return;
                    241:        }
                    242:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
                    243:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("machinegun"))] )
                    244:        {
                    245:                ent->client->newweapon = FindItem ("machinegun");
                    246:                return;
                    247:        }
                    248:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))] > 1
                    249:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("super shotgun"))] )
                    250:        {
                    251:                ent->client->newweapon = FindItem ("super shotgun");
                    252:                return;
                    253:        }
                    254:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))]
                    255:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("shotgun"))] )
                    256:        {
                    257:                ent->client->newweapon = FindItem ("shotgun");
                    258:                return;
                    259:        }
                    260:        ent->client->newweapon = FindItem ("blaster");
                    261: }
                    262: 
                    263: /*
                    264: =================
                    265: Think_Weapon
                    266: 
                    267: Called by ClientBeginServerFrame and ClientThink
                    268: =================
                    269: */
                    270: void Think_Weapon (edict_t *ent)
                    271: {
                    272:        // if just died, put the weapon away
                    273:        if (ent->health < 1)
                    274:        {
                    275:                ent->client->newweapon = NULL;
                    276:                ChangeWeapon (ent);
                    277:        }
                    278: 
                    279:        // call active weapon think routine
                    280:        if (ent->client->pers.weapon && ent->client->pers.weapon->weaponthink)
                    281:        {
                    282:                is_quad = (ent->client->quad_framenum > level.framenum);
                    283:                // RAFAEL
                    284:                is_quadfire = (ent->client->quadfire_framenum > level.framenum);
                    285:                if (ent->client->silencer_shots)
                    286:                        is_silenced = MZ_SILENCED;
                    287:                else
                    288:                        is_silenced = 0;
                    289:                ent->client->pers.weapon->weaponthink (ent);
                    290:        }
                    291: }
                    292: 
                    293: 
                    294: /*
                    295: ================
                    296: Use_Weapon
                    297: 
                    298: Make the weapon ready if there is ammo
                    299: ================
                    300: */
                    301: void Use_Weapon (edict_t *ent, gitem_t *item)
                    302: {
                    303:        int                     ammo_index;
                    304:        gitem_t         *ammo_item;
                    305: 
                    306:        // see if we're already using it
                    307:        if (item == ent->client->pers.weapon)
                    308:                return;
                    309: 
                    310:        if (item->ammo && !g_select_empty->value && !(item->flags & IT_AMMO))
                    311:        {
                    312:                ammo_item = FindItem(item->ammo);
                    313:                ammo_index = ITEM_INDEX(ammo_item);
                    314: 
                    315:                if (!ent->client->pers.inventory[ammo_index])
                    316:                {
                    317:                        gi.cprintf (ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
                    318:                        return;
                    319:                }
                    320: 
                    321:                if (ent->client->pers.inventory[ammo_index] < item->quantity)
                    322:                {
                    323:                        gi.cprintf (ent, PRINT_HIGH, "Not enough %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
                    324:                        return;
                    325:                }
                    326:        }
                    327: 
                    328:        // change to this weapon when down
                    329:        ent->client->newweapon = item;
                    330: }
                    331: 
                    332: // RAFAEL 14-APR-98
                    333: void Use_Weapon2 (edict_t *ent, gitem_t *item)
                    334: {
                    335:        int                     ammo_index;
                    336:        gitem_t         *ammo_item;
                    337:        gitem_t         *nextitem;
                    338:        int                     index;
                    339: 
                    340:        if (strcmp (item->pickup_name, "HyperBlaster") == 0)
                    341:        {
                    342:                if (item == ent->client->pers.weapon)
                    343:                {
                    344:                        item = FindItem ("Ionripper");
                    345:                        index = ITEM_INDEX (item);
                    346:                        if (!ent->client->pers.inventory[index])
                    347:                        {
                    348:                                item = FindItem ("HyperBlaster");
                    349:                        }
                    350:                }
                    351:        }
                    352:        
                    353:        else if (strcmp (item->pickup_name, "Railgun") == 0)
                    354:        {
                    355:                ammo_item = FindItem(item->ammo);
                    356:                ammo_index = ITEM_INDEX(ammo_item);
                    357:                if (!ent->client->pers.inventory[ammo_index])
                    358:                {
                    359:                        nextitem = FindItem ("Phalanx");
                    360:                        ammo_item = FindItem(nextitem->ammo);
                    361:                        ammo_index = ITEM_INDEX(ammo_item);
                    362:                        if (ent->client->pers.inventory[ammo_index])
                    363:                        {
                    364:                                item = FindItem ("Phalanx");
                    365:                                index = ITEM_INDEX (item);
                    366:                                if (!ent->client->pers.inventory[index])
                    367:                                {
                    368:                                        item = FindItem ("Railgun");
                    369:                                }
                    370:                        }
                    371:                }
                    372:                else if (item == ent->client->pers.weapon)
                    373:                {
                    374:                        item = FindItem ("Phalanx");
                    375:                        index = ITEM_INDEX (item);
                    376:                        if (!ent->client->pers.inventory[index])
                    377:                        {
                    378:                                item = FindItem ("Railgun");
                    379:                        }
                    380:                }
                    381:                                
                    382:        }
                    383: 
                    384:        
                    385:        // see if we're already using it
                    386:        if (item == ent->client->pers.weapon)
                    387:                return;
                    388:        
                    389:        if (item->ammo)
                    390:        {
                    391:                ammo_item = FindItem(item->ammo);
                    392:                ammo_index = ITEM_INDEX(ammo_item);
                    393:                if (!ent->client->pers.inventory[ammo_index] && !g_select_empty->value)
                    394:                {
                    395:                        gi.cprintf (ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
                    396:                        return;
                    397:                }
                    398:        }
                    399: 
                    400:        // change to this weapon when down
                    401:        ent->client->newweapon = item;
                    402:        
                    403: }
                    404: // END 14-APR-98
                    405: 
                    406: /*
                    407: ================
                    408: Drop_Weapon
                    409: ================
                    410: */
                    411: void Drop_Weapon (edict_t *ent, gitem_t *item)
                    412: {
                    413:        int             index;
                    414: 
                    415:        if ((int)(dmflags->value) & DF_WEAPONS_STAY)
                    416:                return;
                    417: 
                    418:        index = ITEM_INDEX(item);
                    419:        // see if we're already using it
                    420:        if ( ((item == ent->client->pers.weapon) || (item == ent->client->newweapon))&& (ent->client->pers.inventory[index] == 1) )
                    421:        {
                    422:                gi.cprintf (ent, PRINT_HIGH, "Can't drop current weapon\n");
                    423:                return;
                    424:        }
                    425: 
                    426:        Drop_Item (ent, item);
                    427:        ent->client->pers.inventory[index]--;
                    428: }
                    429: 
                    430: 
                    431: /*
                    432: ================
                    433: Weapon_Generic
                    434: 
                    435: A generic function to handle the basics of weapon thinking
                    436: ================
                    437: */
                    438: #define FRAME_FIRE_FIRST               (FRAME_ACTIVATE_LAST + 1)
                    439: #define FRAME_IDLE_FIRST               (FRAME_FIRE_LAST + 1)
                    440: #define FRAME_DEACTIVATE_FIRST (FRAME_IDLE_LAST + 1)
                    441: 
                    442: 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))
                    443: {
                    444:        int             n;
                    445: 
                    446:        if (ent->client->weaponstate == WEAPON_DROPPING)
                    447:        {
                    448:                if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST)
                    449:                {
                    450:                        ChangeWeapon (ent);
                    451:                        return;
                    452:                }
                    453:                else if ((FRAME_DEACTIVATE_LAST - ent->client->ps.gunframe) == 4)
                    454:                {
                    455:                        ent->client->anim_priority = ANIM_REVERSE;
                    456:                        if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                    457:                        {
                    458:                                ent->s.frame = FRAME_crpain4+1;
                    459:                                ent->client->anim_end = FRAME_crpain1;
                    460:                        }
                    461:                        else
                    462:                        {
                    463:                                ent->s.frame = FRAME_pain304+1;
                    464:                                ent->client->anim_end = FRAME_pain301;
                    465:                                
                    466:                        }
                    467:                }
                    468: 
                    469:                ent->client->ps.gunframe++;
                    470:                return;
                    471:        }
                    472: 
                    473:        if (ent->client->weaponstate == WEAPON_ACTIVATING)
                    474:        {
                    475:                if (ent->client->ps.gunframe == FRAME_ACTIVATE_LAST)
                    476:                {
                    477:                        ent->client->weaponstate = WEAPON_READY;
                    478:                        ent->client->ps.gunframe = FRAME_IDLE_FIRST;
                    479:                        return;
                    480:                }
                    481: 
                    482:                ent->client->ps.gunframe++;
                    483:                return;
                    484:        }
                    485: 
                    486:        if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING))
                    487:        {
                    488:                ent->client->weaponstate = WEAPON_DROPPING;
                    489:                ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST;
                    490: 
                    491:                if ((FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < 4)
                    492:                {
                    493:                        ent->client->anim_priority = ANIM_REVERSE;
                    494:                        if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                    495:                        {
                    496:                                ent->s.frame = FRAME_crpain4+1;
                    497:                                ent->client->anim_end = FRAME_crpain1;
                    498:                        }
                    499:                        else
                    500:                        {
                    501:                                ent->s.frame = FRAME_pain304+1;
                    502:                                ent->client->anim_end = FRAME_pain301;
                    503:                                
                    504:                        }
                    505:                }
                    506:                return;
                    507:        }
                    508: 
                    509:        if (ent->client->weaponstate == WEAPON_READY)
                    510:        {
                    511:                if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) )
                    512:                {
                    513:                        ent->client->latched_buttons &= ~BUTTON_ATTACK;
                    514:                        if ((!ent->client->ammo_index) || 
                    515:                                ( ent->client->pers.inventory[ent->client->ammo_index] >= ent->client->pers.weapon->quantity))
                    516:                        {
                    517:                                ent->client->ps.gunframe = FRAME_FIRE_FIRST;
                    518:                                ent->client->weaponstate = WEAPON_FIRING;
                    519: 
                    520:                                // start the animation
                    521:                                ent->client->anim_priority = ANIM_ATTACK;
                    522:                                if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                    523:                                {
                    524:                                        ent->s.frame = FRAME_crattak1-1;
                    525:                                        ent->client->anim_end = FRAME_crattak9;
                    526:                                }
                    527:                                else
                    528:                                {
                    529:                                        ent->s.frame = FRAME_attack1-1;
                    530:                                        ent->client->anim_end = FRAME_attack8;
                    531:                                }
                    532:                        }
                    533:                        else
                    534:                        {
                    535:                                if (level.time >= ent->pain_debounce_time)
                    536:                                {
                    537:                                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
                    538:                                        ent->pain_debounce_time = level.time + 1;
                    539:                                }
                    540:                                NoAmmoWeaponChange (ent);
                    541:                        }
                    542:                }
                    543:                else
                    544:                {
                    545:                        if (ent->client->ps.gunframe == FRAME_IDLE_LAST)
                    546:                        {
                    547:                                ent->client->ps.gunframe = FRAME_IDLE_FIRST;
                    548:                                return;
                    549:                        }
                    550: 
                    551:                        if (pause_frames)
                    552:                        {
                    553:                                for (n = 0; pause_frames[n]; n++)
                    554:                                {
                    555:                                        if (ent->client->ps.gunframe == pause_frames[n])
                    556:                                        {
                    557:                                                if (rand()&15)
                    558:                                                        return;
                    559:                                        }
                    560:                                }
                    561:                        }
                    562: 
                    563:                        ent->client->ps.gunframe++;
                    564:                        return;
                    565:                }
                    566:        }
                    567: 
                    568:        if (ent->client->weaponstate == WEAPON_FIRING)
                    569:        {
                    570:                for (n = 0; fire_frames[n]; n++)
                    571:                {
                    572:                        if (ent->client->ps.gunframe == fire_frames[n])
                    573:                        {
                    574:                                if (ent->client->quad_framenum > level.framenum)
                    575:                                        gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0);
                    576: 
                    577:                                fire (ent);
                    578:                                break;
                    579:                        }
                    580:                }
                    581: 
                    582:                if (!fire_frames[n])
                    583:                        ent->client->ps.gunframe++;
                    584: 
                    585:                if (ent->client->ps.gunframe == FRAME_IDLE_FIRST+1)
                    586:                        ent->client->weaponstate = WEAPON_READY;
                    587:        }
                    588: }
                    589: 
                    590: 
                    591: /*
                    592: ======================================================================
                    593: 
                    594: GRENADE
                    595: 
                    596: ======================================================================
                    597: */
                    598: 
                    599: #define GRENADE_TIMER          3.0
                    600: #define GRENADE_MINSPEED       400
                    601: #define GRENADE_MAXSPEED       800
                    602: 
                    603: void weapon_grenade_fire (edict_t *ent, qboolean held)
                    604: {
                    605:        vec3_t  offset;
                    606:        vec3_t  forward, right;
                    607:        vec3_t  start;
                    608:        int             damage = 125;
                    609:        float   timer;
                    610:        int             speed;
                    611:        float   radius;
                    612: 
                    613:        radius = damage+40;
                    614:        if (is_quad)
                    615:                damage *= 4;
                    616: 
                    617:        VectorSet(offset, 8, 8, ent->viewheight-8);
                    618:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                    619:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                    620: 
                    621:        timer = ent->client->grenade_time - level.time;
                    622:        speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER);
                    623:        fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held);
                    624: 
                    625:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                    626:                ent->client->pers.inventory[ent->client->ammo_index]--;
                    627: 
                    628:        ent->client->grenade_time = level.time + 1.0;
                    629: 
                    630:        if (ent->health <= 0)
                    631:                return;
                    632: 
                    633:        if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                    634:        {
                    635:                ent->client->anim_priority = ANIM_ATTACK;
                    636:                ent->s.frame = FRAME_crattak1-1;
                    637:                ent->client->anim_end = FRAME_crattak3;
                    638:        }
                    639:        else
                    640:        {
                    641:                ent->client->anim_priority = ANIM_REVERSE;
                    642:                ent->s.frame = FRAME_wave08;
                    643:                ent->client->anim_end = FRAME_wave01;
                    644:        }
                    645: }
                    646: 
                    647: void Weapon_Grenade (edict_t *ent)
                    648: {
                    649:        if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY))
                    650:        {
                    651:                ChangeWeapon (ent);
                    652:                return;
                    653:        }
                    654: 
                    655:        if (ent->client->weaponstate == WEAPON_ACTIVATING)
                    656:        {
                    657:                ent->client->weaponstate = WEAPON_READY;
                    658:                ent->client->ps.gunframe = 16;
                    659:                return;
                    660:        }
                    661: 
                    662:        if (ent->client->weaponstate == WEAPON_READY)
                    663:        {
                    664:                if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) )
                    665:                {
                    666:                        ent->client->latched_buttons &= ~BUTTON_ATTACK;
                    667:                        if (ent->client->pers.inventory[ent->client->ammo_index])
                    668:                        {
                    669:                                ent->client->ps.gunframe = 1;
                    670:                                ent->client->weaponstate = WEAPON_FIRING;
                    671:                                ent->client->grenade_time = 0;
                    672:                        }
                    673:                        else
                    674:                        {
                    675:                                if (level.time >= ent->pain_debounce_time)
                    676:                                {
                    677:                                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
                    678:                                        ent->pain_debounce_time = level.time + 1;
                    679:                                }
                    680:                                NoAmmoWeaponChange (ent);
                    681:                        }
                    682:                        return;
                    683:                }
                    684: 
                    685:                if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48))
                    686:                {
                    687:                        if (rand()&15)
                    688:                                return;
                    689:                }
                    690: 
                    691:                if (++ent->client->ps.gunframe > 48)
                    692:                        ent->client->ps.gunframe = 16;
                    693:                return;
                    694:        }
                    695: 
                    696:        if (ent->client->weaponstate == WEAPON_FIRING)
                    697:        {
                    698:                if (ent->client->ps.gunframe == 5)
                    699:                        gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0);
                    700: 
                    701:                if (ent->client->ps.gunframe == 11)
                    702:                {
                    703:                        if (!ent->client->grenade_time)
                    704:                        {
                    705:                                ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2;
                    706:                                ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav");
                    707:                        }
                    708: 
                    709:                        // they waited too long, detonate it in their hand
                    710:                        if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time)
                    711:                        {
                    712:                                ent->client->weapon_sound = 0;
                    713:                                weapon_grenade_fire (ent, true);
                    714:                                ent->client->grenade_blew_up = true;
                    715:                        }
                    716: 
                    717:                        if (ent->client->buttons & BUTTON_ATTACK)
                    718:                                return;
                    719: 
                    720:                        if (ent->client->grenade_blew_up)
                    721:                        {
                    722:                                if (level.time >= ent->client->grenade_time)
                    723:                                {
                    724:                                        ent->client->ps.gunframe = 15;
                    725:                                        ent->client->grenade_blew_up = false;
                    726:                                }
                    727:                                else
                    728:                                {
                    729:                                        return;
                    730:                                }
                    731:                        }
                    732:                }
                    733: 
                    734:                if (ent->client->ps.gunframe == 12)
                    735:                {
                    736:                        ent->client->weapon_sound = 0;
                    737:                        weapon_grenade_fire (ent, false);
                    738:                }
                    739: 
                    740:                if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time))
                    741:                        return;
                    742: 
                    743:                ent->client->ps.gunframe++;
                    744: 
                    745:                if (ent->client->ps.gunframe == 16)
                    746:                {
                    747:                        ent->client->grenade_time = 0;
                    748:                        ent->client->weaponstate = WEAPON_READY;
                    749:                }
                    750:        }
                    751: }
                    752: 
                    753: /*
                    754: ======================================================================
                    755: 
                    756: GRENADE LAUNCHER
                    757: 
                    758: ======================================================================
                    759: */
                    760: 
                    761: void weapon_grenadelauncher_fire (edict_t *ent)
                    762: {
                    763:        vec3_t  offset;
                    764:        vec3_t  forward, right;
                    765:        vec3_t  start;
                    766:        int             damage = 120;
                    767:        float   radius;
                    768: 
                    769:        radius = damage+40;
                    770:        if (is_quad)
                    771:                damage *= 4;
                    772: 
                    773:        VectorSet(offset, 8, 8, ent->viewheight-8);
                    774:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                    775:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                    776: 
                    777:        VectorScale (forward, -2, ent->client->kick_origin);
                    778:        ent->client->kick_angles[0] = -1;
                    779: 
                    780:        fire_grenade (ent, start, forward, damage, 600, 2.5, radius);
                    781: 
                    782:        gi.WriteByte (svc_muzzleflash);
                    783:        gi.WriteShort (ent-g_edicts);
                    784:        gi.WriteByte (MZ_GRENADE | is_silenced);
                    785:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                    786: 
                    787:        ent->client->ps.gunframe++;
                    788: 
                    789:        PlayerNoise(ent, start, PNOISE_WEAPON);
                    790: 
                    791:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                    792:                ent->client->pers.inventory[ent->client->ammo_index]--;
                    793: }
                    794: 
                    795: void Weapon_GrenadeLauncher (edict_t *ent)
                    796: {
                    797:        static int      pause_frames[]  = {34, 51, 59, 0};
                    798:        static int      fire_frames[]   = {6, 0};
                    799: 
                    800:        Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire);
                    801: 
                    802:        // RAFAEL
                    803:        if (is_quadfire)
                    804:                Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire);
                    805: 
                    806: }
                    807: 
                    808: /*
                    809: ======================================================================
                    810: 
                    811: ROCKET
                    812: 
                    813: ======================================================================
                    814: */
                    815: 
                    816: void Weapon_RocketLauncher_Fire (edict_t *ent)
                    817: {
                    818:        vec3_t  offset, start;
                    819:        vec3_t  forward, right;
                    820:        int             damage;
                    821:        float   damage_radius;
                    822:        int             radius_damage;
                    823: 
                    824:        damage = 100 + (int)(random() * 20.0);
                    825:        radius_damage = 120;
                    826:        damage_radius = 120;
                    827:        if (is_quad)
                    828:        {
                    829:                damage *= 4;
                    830:                radius_damage *= 4;
                    831:        }
                    832: 
                    833:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                    834: 
                    835:        VectorScale (forward, -2, ent->client->kick_origin);
                    836:        ent->client->kick_angles[0] = -1;
                    837: 
                    838:        VectorSet(offset, 8, 8, ent->viewheight-8);
                    839:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                    840:        fire_rocket (ent, start, forward, damage, 650, damage_radius, radius_damage);
                    841: 
                    842:        // send muzzle flash
                    843:        gi.WriteByte (svc_muzzleflash);
                    844:        gi.WriteShort (ent-g_edicts);
                    845:        gi.WriteByte (MZ_ROCKET | is_silenced);
                    846:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                    847: 
                    848:        ent->client->ps.gunframe++;
                    849: 
                    850:        PlayerNoise(ent, start, PNOISE_WEAPON);
                    851: 
                    852:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                    853:                ent->client->pers.inventory[ent->client->ammo_index]--;
                    854: }
                    855: 
                    856: void Weapon_RocketLauncher (edict_t *ent)
                    857: {
                    858:        static int      pause_frames[]  = {25, 33, 42, 50, 0};
                    859:        static int      fire_frames[]   = {5, 0};
                    860: 
                    861:        Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire);
                    862: 
                    863:        
                    864:        // RAFAEL
                    865:        if (is_quadfire)
                    866:                Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire);
                    867:                
                    868: 
                    869: }
                    870: 
                    871: 
                    872: /*
                    873: ======================================================================
                    874: 
                    875: BLASTER / HYPERBLASTER
                    876: 
                    877: ======================================================================
                    878: */
                    879: 
                    880: void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect)
                    881: {
                    882:        vec3_t  forward, right;
                    883:        vec3_t  start;
                    884:        vec3_t  offset;
                    885: 
                    886:        if (is_quad)
                    887:                damage *= 4;
                    888:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                    889:        VectorSet(offset, 24, 8, ent->viewheight-8);
                    890:        VectorAdd (offset, g_offset, offset);
                    891:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                    892: 
                    893:        VectorScale (forward, -2, ent->client->kick_origin);
                    894:        ent->client->kick_angles[0] = -1;
                    895: 
                    896:        fire_blaster (ent, start, forward, damage, 1000, effect, hyper);
                    897: 
                    898:        // send muzzle flash
                    899:        gi.WriteByte (svc_muzzleflash);
                    900:        gi.WriteShort (ent-g_edicts);
                    901:        if (hyper)
                    902:                gi.WriteByte (MZ_HYPERBLASTER | is_silenced);
                    903:        else
                    904:                gi.WriteByte (MZ_BLASTER | is_silenced);
                    905:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                    906: 
                    907:        PlayerNoise(ent, start, PNOISE_WEAPON);
                    908: }
                    909: 
                    910: 
                    911: void Weapon_Blaster_Fire (edict_t *ent)
                    912: {
                    913:        int             damage;
                    914: 
                    915:        if (deathmatch->value)
                    916:                damage = 15;
                    917:        else
                    918:                damage = 10;
                    919:        Blaster_Fire (ent, vec3_origin, damage, false, EF_BLASTER);
                    920:        ent->client->ps.gunframe++;
                    921: }
                    922: 
                    923: void Weapon_Blaster (edict_t *ent)
                    924: {
                    925:        static int      pause_frames[]  = {19, 32, 0};
                    926:        static int      fire_frames[]   = {5, 0};
                    927: 
                    928:        Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire);
                    929: 
                    930:        // RAFAEL
                    931:        if (is_quadfire)
                    932:                Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire);
                    933:                
                    934: }
                    935: 
                    936: 
                    937: void Weapon_HyperBlaster_Fire (edict_t *ent)
                    938: {
                    939:        float   rotation;
                    940:        vec3_t  offset;
                    941:        int             effect;
                    942:        int             damage;
                    943: 
                    944:        ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav");
                    945: 
                    946:        if (!(ent->client->buttons & BUTTON_ATTACK))
                    947:        {
                    948:                ent->client->ps.gunframe++;
                    949:        }
                    950:        else
                    951:        {
                    952:                if (! ent->client->pers.inventory[ent->client->ammo_index] )
                    953:                {
                    954:                        if (level.time >= ent->pain_debounce_time)
                    955:                        {
                    956:                                gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
                    957:                                ent->pain_debounce_time = level.time + 1;
                    958:                        }
                    959:                        NoAmmoWeaponChange (ent);
                    960:                }
                    961:                else
                    962:                {
                    963:                        rotation = (ent->client->ps.gunframe - 5) * 2*M_PI/6;
                    964:                        offset[0] = -4 * sin(rotation);
                    965:                        offset[1] = 0;
                    966:                        offset[2] = 4 * cos(rotation);
                    967: 
                    968:                        if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9))
                    969:                                effect = EF_HYPERBLASTER;
                    970:                        else
                    971:                                effect = 0;
                    972:                        if (deathmatch->value)
                    973:                                damage = 15;
                    974:                        else
                    975:                                damage = 20;
                    976:                        Blaster_Fire (ent, offset, damage, true, effect);
                    977:                        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                    978:                                ent->client->pers.inventory[ent->client->ammo_index]--;
                    979: 
                    980:                        ent->client->anim_priority = ANIM_ATTACK;
                    981:                        if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                    982:                        {
                    983:                                ent->s.frame = FRAME_crattak1 - 1;
                    984:                                ent->client->anim_end = FRAME_crattak9;
                    985:                        }
                    986:                        else
                    987:                        {
                    988:                                ent->s.frame = FRAME_attack1 - 1;
                    989:                                ent->client->anim_end = FRAME_attack8;
                    990:                        }
                    991:                }
                    992: 
                    993:                ent->client->ps.gunframe++;
                    994:                if (ent->client->ps.gunframe == 12 && ent->client->pers.inventory[ent->client->ammo_index])
                    995:                        ent->client->ps.gunframe = 6;
                    996:        }
                    997: 
                    998:        if (ent->client->ps.gunframe == 12)
                    999:        {
                   1000:                gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0);
                   1001:                ent->client->weapon_sound = 0;
                   1002:        }
                   1003: 
                   1004: }
                   1005: 
                   1006: void Weapon_HyperBlaster (edict_t *ent)
                   1007: {
                   1008:        static int      pause_frames[]  = {0};
                   1009:        static int      fire_frames[]   = {6, 7, 8, 9, 10, 11, 0};
                   1010: 
                   1011:        Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire);
                   1012: 
                   1013:        
                   1014:        // RAFAEL
                   1015:        if (is_quadfire)
                   1016:                Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire);
                   1017:                
                   1018: }
                   1019: 
                   1020: /*
                   1021: ======================================================================
                   1022: 
                   1023: MACHINEGUN / CHAINGUN
                   1024: 
                   1025: ======================================================================
                   1026: */
                   1027: 
                   1028: void Machinegun_Fire (edict_t *ent)
                   1029: {
                   1030:        int     i;
                   1031:        vec3_t          start;
                   1032:        vec3_t          forward, right;
                   1033:        vec3_t          angles;
                   1034:        int                     damage = 8;
                   1035:        int                     kick = 2;
                   1036:        vec3_t          offset;
                   1037: 
                   1038:        if (!(ent->client->buttons & BUTTON_ATTACK))
                   1039:        {
                   1040:                ent->client->machinegun_shots = 0;
                   1041:                ent->client->ps.gunframe++;
                   1042:                return;
                   1043:        }
                   1044: 
                   1045:        if (ent->client->ps.gunframe == 5)
                   1046:                ent->client->ps.gunframe = 4;
                   1047:        else
                   1048:                ent->client->ps.gunframe = 5;
                   1049: 
                   1050:        if (ent->client->pers.inventory[ent->client->ammo_index] < 1)
                   1051:        {
                   1052:                ent->client->ps.gunframe = 6;
                   1053:                if (level.time >= ent->pain_debounce_time)
                   1054:                {
                   1055:                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
                   1056:                        ent->pain_debounce_time = level.time + 1;
                   1057:                }
                   1058:                NoAmmoWeaponChange (ent);
                   1059:                return;
                   1060:        }
                   1061: 
                   1062:        if (is_quad)
                   1063:        {
                   1064:                damage *= 4;
                   1065:                kick *= 4;
                   1066:        }
                   1067: 
                   1068:        for (i=1 ; i<3 ; i++)
                   1069:        {
                   1070:                ent->client->kick_origin[i] = crandom() * 0.35;
                   1071:                ent->client->kick_angles[i] = crandom() * 0.7;
                   1072:        }
                   1073:        ent->client->kick_origin[0] = crandom() * 0.35;
                   1074:        ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5;
                   1075: 
                   1076:        // raise the gun as it is firing
                   1077:        if (!deathmatch->value)
                   1078:        {
                   1079:                ent->client->machinegun_shots++;
                   1080:                if (ent->client->machinegun_shots > 9)
                   1081:                        ent->client->machinegun_shots = 9;
                   1082:        }
                   1083: 
                   1084:        // get start / end positions
                   1085:        VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles);
                   1086:        AngleVectors (angles, forward, right, NULL);
                   1087:        VectorSet(offset, 0, 8, ent->viewheight-8);
                   1088:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1089:        fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN);
                   1090: 
                   1091:        gi.WriteByte (svc_muzzleflash);
                   1092:        gi.WriteShort (ent-g_edicts);
                   1093:        gi.WriteByte (MZ_MACHINEGUN | is_silenced);
                   1094:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                   1095: 
                   1096:        PlayerNoise(ent, start, PNOISE_WEAPON);
                   1097: 
                   1098:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1099:                ent->client->pers.inventory[ent->client->ammo_index]--;
                   1100: 
                   1101:        ent->client->anim_priority = ANIM_ATTACK;
                   1102:        if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                   1103:        {
                   1104:                ent->s.frame = FRAME_crattak1 - (int) (random()+0.25);
                   1105:                ent->client->anim_end = FRAME_crattak9;
                   1106:        }
                   1107:        else
                   1108:        {
                   1109:                ent->s.frame = FRAME_attack1 - (int) (random()+0.25);
                   1110:                ent->client->anim_end = FRAME_attack8;
                   1111:        }
                   1112: }
                   1113: 
                   1114: void Weapon_Machinegun (edict_t *ent)
                   1115: {
                   1116:        static int      pause_frames[]  = {23, 45, 0};
                   1117:        static int      fire_frames[]   = {4, 5, 0};
                   1118: 
                   1119:        Weapon_Generic (ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire);
                   1120:        
                   1121:        // RAFAEL
                   1122:        if (is_quadfire)
                   1123:                Weapon_Generic (ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire);
                   1124:        
                   1125: }
                   1126: 
                   1127: void Chaingun_Fire (edict_t *ent)
                   1128: {
                   1129:        int                     i;
                   1130:        int                     shots;
                   1131:        vec3_t          start;
                   1132:        vec3_t          forward, right, up;
                   1133:        float           r, u;
                   1134:        vec3_t          offset;
                   1135:        int                     damage;
                   1136:        int                     kick = 2;
                   1137: 
                   1138:        if (deathmatch->value)
                   1139:                damage = 6;
                   1140:        else
                   1141:                damage = 8;
                   1142: 
                   1143:        if (ent->client->ps.gunframe == 5)
                   1144:                gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0);
                   1145: 
                   1146:        if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK))
                   1147:        {
                   1148:                ent->client->ps.gunframe = 32;
                   1149:                ent->client->weapon_sound = 0;
                   1150:                return;
                   1151:        }
                   1152:        else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK)
                   1153:                && ent->client->pers.inventory[ent->client->ammo_index])
                   1154:        {
                   1155:                ent->client->ps.gunframe = 15;
                   1156:        }
                   1157:        else
                   1158:        {
                   1159:                ent->client->ps.gunframe++;
                   1160:        }
                   1161: 
                   1162:        if (ent->client->ps.gunframe == 22)
                   1163:        {
                   1164:                ent->client->weapon_sound = 0;
                   1165:                gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0);
                   1166:        }
                   1167:        else
                   1168:        {
                   1169:                ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav");
                   1170:        }
                   1171: 
                   1172:        ent->client->anim_priority = ANIM_ATTACK;
                   1173:        if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
                   1174:        {
                   1175:                ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1);
                   1176:                ent->client->anim_end = FRAME_crattak9;
                   1177:        }
                   1178:        else
                   1179:        {
                   1180:                ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1);
                   1181:                ent->client->anim_end = FRAME_attack8;
                   1182:        }
                   1183: 
                   1184:        if (ent->client->ps.gunframe <= 9)
                   1185:                shots = 1;
                   1186:        else if (ent->client->ps.gunframe <= 14)
                   1187:        {
                   1188:                if (ent->client->buttons & BUTTON_ATTACK)
                   1189:                        shots = 2;
                   1190:                else
                   1191:                        shots = 1;
                   1192:        }
                   1193:        else
                   1194:                shots = 3;
                   1195: 
                   1196:        if (ent->client->pers.inventory[ent->client->ammo_index] < shots)
                   1197:                shots = ent->client->pers.inventory[ent->client->ammo_index];
                   1198: 
                   1199:        if (!shots)
                   1200:        {
                   1201:                if (level.time >= ent->pain_debounce_time)
                   1202:                {
                   1203:                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
                   1204:                        ent->pain_debounce_time = level.time + 1;
                   1205:                }
                   1206:                NoAmmoWeaponChange (ent);
                   1207:                return;
                   1208:        }
                   1209: 
                   1210:        if (is_quad)
                   1211:        {
                   1212:                damage *= 4;
                   1213:                kick *= 4;
                   1214:        }
                   1215: 
                   1216:        for (i=0 ; i<3 ; i++)
                   1217:        {
                   1218:                ent->client->kick_origin[i] = crandom() * 0.35;
                   1219:                ent->client->kick_angles[i] = crandom() * 0.7;
                   1220:        }
                   1221: 
                   1222:        for (i=0 ; i<shots ; i++)
                   1223:        {
                   1224:                // get start / end positions
                   1225:                AngleVectors (ent->client->v_angle, forward, right, up);
                   1226:                r = 7 + crandom()*4;
                   1227:                u = crandom()*4;
                   1228:                VectorSet(offset, 0, r, u + ent->viewheight-8);
                   1229:                P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1230: 
                   1231:                fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN);
                   1232:        }
                   1233: 
                   1234:        // send muzzle flash
                   1235:        gi.WriteByte (svc_muzzleflash);
                   1236:        gi.WriteShort (ent-g_edicts);
                   1237:        gi.WriteByte ((MZ_CHAINGUN1 + shots - 1) | is_silenced);
                   1238:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                   1239: 
                   1240:        PlayerNoise(ent, start, PNOISE_WEAPON);
                   1241: 
                   1242:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1243:                ent->client->pers.inventory[ent->client->ammo_index] -= shots;
                   1244: }
                   1245: 
                   1246: 
                   1247: void Weapon_Chaingun (edict_t *ent)
                   1248: {
                   1249:        static int      pause_frames[]  = {38, 43, 51, 61, 0};
                   1250:        static int      fire_frames[]   = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0};
                   1251: 
                   1252:        Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire);
                   1253: 
                   1254:        
                   1255:        // RAFAEL
                   1256:        if (is_quadfire)
                   1257:                Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire);
                   1258: 
                   1259: }
                   1260: 
                   1261: 
                   1262: /*
                   1263: ======================================================================
                   1264: 
                   1265: SHOTGUN / SUPERSHOTGUN
                   1266: 
                   1267: ======================================================================
                   1268: */
                   1269: 
                   1270: void weapon_shotgun_fire (edict_t *ent)
                   1271: {
                   1272:        vec3_t          start;
                   1273:        vec3_t          forward, right;
                   1274:        vec3_t          offset;
                   1275:        int                     damage = 4;
                   1276:        int                     kick = 8;
                   1277: 
                   1278:        if (ent->client->ps.gunframe == 9)
                   1279:        {
                   1280:                ent->client->ps.gunframe++;
                   1281:                return;
                   1282:        }
                   1283: 
                   1284:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                   1285: 
                   1286:        VectorScale (forward, -2, ent->client->kick_origin);
                   1287:        ent->client->kick_angles[0] = -2;
                   1288: 
                   1289:        VectorSet(offset, 0, 8,  ent->viewheight-8);
                   1290:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1291: 
                   1292:        if (is_quad)
                   1293:        {
                   1294:                damage *= 4;
                   1295:                kick *= 4;
                   1296:        }
                   1297: 
                   1298:        if (deathmatch->value)
                   1299:                fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_DEATHMATCH_SHOTGUN_COUNT, MOD_SHOTGUN);
                   1300:        else
                   1301:                fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN);
                   1302: 
                   1303:        // send muzzle flash
                   1304:        gi.WriteByte (svc_muzzleflash);
                   1305:        gi.WriteShort (ent-g_edicts);
                   1306:        gi.WriteByte (MZ_SHOTGUN | is_silenced);
                   1307:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                   1308: 
                   1309:        ent->client->ps.gunframe++;
                   1310:        PlayerNoise(ent, start, PNOISE_WEAPON);
                   1311: 
                   1312:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1313:                ent->client->pers.inventory[ent->client->ammo_index]--;
                   1314: }
                   1315: 
                   1316: void Weapon_Shotgun (edict_t *ent)
                   1317: {
                   1318:        static int      pause_frames[]  = {22, 28, 34, 0};
                   1319:        static int      fire_frames[]   = {8, 9, 0};
                   1320: 
                   1321:        Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire);
                   1322: 
                   1323:        
                   1324:        // RAFAEL
                   1325:        if (is_quadfire)
                   1326:                Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire);
                   1327: }
                   1328: 
                   1329: 
                   1330: void weapon_supershotgun_fire (edict_t *ent)
                   1331: {
                   1332:        vec3_t          start;
                   1333:        vec3_t          forward, right;
                   1334:        vec3_t          offset;
                   1335:        vec3_t          v;
                   1336:        int                     damage = 6;
                   1337:        int                     kick = 12;
                   1338: 
                   1339:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                   1340: 
                   1341:        VectorScale (forward, -2, ent->client->kick_origin);
                   1342:        ent->client->kick_angles[0] = -2;
                   1343: 
                   1344:        VectorSet(offset, 0, 8,  ent->viewheight-8);
                   1345:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1346: 
                   1347:        if (is_quad)
                   1348:        {
                   1349:                damage *= 4;
                   1350:                kick *= 4;
                   1351:        }
                   1352: 
                   1353:        v[PITCH] = ent->client->v_angle[PITCH];
                   1354:        v[YAW]   = ent->client->v_angle[YAW] - 5;
                   1355:        v[ROLL]  = ent->client->v_angle[ROLL];
                   1356:        AngleVectors (v, forward, NULL, NULL);
                   1357:        fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN);
                   1358:        v[YAW]   = ent->client->v_angle[YAW] + 5;
                   1359:        AngleVectors (v, forward, NULL, NULL);
                   1360:        fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN);
                   1361: 
                   1362:        // send muzzle flash
                   1363:        gi.WriteByte (svc_muzzleflash);
                   1364:        gi.WriteShort (ent-g_edicts);
                   1365:        gi.WriteByte (MZ_SSHOTGUN | is_silenced);
                   1366:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                   1367: 
                   1368:        ent->client->ps.gunframe++;
                   1369:        PlayerNoise(ent, start, PNOISE_WEAPON);
                   1370: 
                   1371:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1372:                ent->client->pers.inventory[ent->client->ammo_index] -= 2;
                   1373: }
                   1374: 
                   1375: void Weapon_SuperShotgun (edict_t *ent)
                   1376: {
                   1377:        static int      pause_frames[]  = {29, 42, 57, 0};
                   1378:        static int      fire_frames[]   = {7, 0};
                   1379: 
                   1380:        Weapon_Generic (ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire);
                   1381: 
                   1382:        
                   1383:        // RAFAEL
                   1384:        if (is_quadfire)
                   1385:                Weapon_Generic (ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire);
                   1386: }
                   1387: 
                   1388: 
                   1389: 
                   1390: /*
                   1391: ======================================================================
                   1392: 
                   1393: RAILGUN
                   1394: 
                   1395: ======================================================================
                   1396: */
                   1397: 
                   1398: void weapon_railgun_fire (edict_t *ent)
                   1399: {
                   1400:        vec3_t          start;
                   1401:        vec3_t          forward, right;
                   1402:        vec3_t          offset;
                   1403:        int                     damage;
                   1404:        int                     kick;
                   1405: 
                   1406:        if (deathmatch->value)
                   1407:        {       // normal damage is too extreme in dm
                   1408:                damage = 100;
                   1409:                kick = 200;
                   1410:        }
                   1411:        else
                   1412:        {
                   1413:                damage = 150;
                   1414:                kick = 250;
                   1415:        }
                   1416: 
                   1417:        if (is_quad)
                   1418:        {
                   1419:                damage *= 4;
                   1420:                kick *= 4;
                   1421:        }
                   1422: 
                   1423:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                   1424: 
                   1425:        VectorScale (forward, -3, ent->client->kick_origin);
                   1426:        ent->client->kick_angles[0] = -3;
                   1427: 
                   1428:        VectorSet(offset, 0, 7,  ent->viewheight-8);
                   1429:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1430:        fire_rail (ent, start, forward, damage, kick);
                   1431: 
                   1432:        // send muzzle flash
                   1433:        gi.WriteByte (svc_muzzleflash);
                   1434:        gi.WriteShort (ent-g_edicts);
                   1435:        gi.WriteByte (MZ_RAILGUN | is_silenced);
                   1436:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                   1437: 
                   1438:        ent->client->ps.gunframe++;
                   1439:        PlayerNoise(ent, start, PNOISE_WEAPON);
                   1440: 
                   1441:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1442:                ent->client->pers.inventory[ent->client->ammo_index]--;
                   1443: }
                   1444: 
                   1445: 
                   1446: void Weapon_Railgun (edict_t *ent)
                   1447: {
                   1448:        static int      pause_frames[]  = {56, 0};
                   1449:        static int      fire_frames[]   = {4, 0};
                   1450: 
                   1451:        Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire);
                   1452: 
                   1453:        
                   1454:        // RAFAEL
                   1455:        if (is_quadfire)
                   1456:                Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire);
                   1457: }
                   1458: 
                   1459: 
                   1460: /*
                   1461: ======================================================================
                   1462: 
                   1463: BFG10K
                   1464: 
                   1465: ======================================================================
                   1466: */
                   1467: 
                   1468: void weapon_bfg_fire (edict_t *ent)
                   1469: {
                   1470:        vec3_t  offset, start;
                   1471:        vec3_t  forward, right;
                   1472:        int             damage;
                   1473:        float   damage_radius = 1000;
                   1474: 
                   1475:        if (deathmatch->value)
                   1476:                damage = 200;
                   1477:        else
                   1478:                damage = 500;
                   1479: 
                   1480:        if (ent->client->ps.gunframe == 9)
                   1481:        {
                   1482:                // send muzzle flash
                   1483:                gi.WriteByte (svc_muzzleflash);
                   1484:                gi.WriteShort (ent-g_edicts);
                   1485:                gi.WriteByte (MZ_BFG | is_silenced);
                   1486:                gi.multicast (ent->s.origin, MULTICAST_PVS);
                   1487: 
                   1488:                ent->client->ps.gunframe++;
                   1489: 
                   1490:                PlayerNoise(ent, start, PNOISE_WEAPON);
                   1491:                return;
                   1492:        }
                   1493: 
                   1494:        // cells can go down during windup (from power armor hits), so
                   1495:        // check again and abort firing if we don't have enough now
                   1496:        if (ent->client->pers.inventory[ent->client->ammo_index] < 50)
                   1497:        {
                   1498:                ent->client->ps.gunframe++;
                   1499:                return;
                   1500:        }
                   1501: 
                   1502:        if (is_quad)
                   1503:                damage *= 4;
                   1504: 
                   1505:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                   1506: 
                   1507:        VectorScale (forward, -2, ent->client->kick_origin);
                   1508: 
                   1509:        // make a big pitch kick with an inverse fall
                   1510:        ent->client->v_dmg_pitch = -40;
                   1511:        ent->client->v_dmg_roll = crandom()*8;
                   1512:        ent->client->v_dmg_time = level.time + DAMAGE_TIME;
                   1513: 
                   1514:        VectorSet(offset, 8, 8, ent->viewheight-8);
                   1515:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1516:        fire_bfg (ent, start, forward, damage, 400, damage_radius);
                   1517: 
                   1518:        ent->client->ps.gunframe++;
                   1519: 
                   1520:        PlayerNoise(ent, start, PNOISE_WEAPON);
                   1521: 
                   1522:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1523:                ent->client->pers.inventory[ent->client->ammo_index] -= 50;
                   1524: }
                   1525: 
                   1526: void Weapon_BFG (edict_t *ent)
                   1527: {
                   1528:        static int      pause_frames[]  = {39, 45, 50, 55, 0};
                   1529:        static int      fire_frames[]   = {9, 17, 0};
                   1530: 
                   1531:        Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire);
                   1532: 
                   1533:        // RAFAEL
                   1534:        if (is_quadfire)
                   1535:                Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire);
                   1536: }
                   1537: 
                   1538: 
                   1539: //======================================================================
                   1540: 
                   1541: 
                   1542: // RAFAEL
                   1543: /*
                   1544:        RipperGun
                   1545: */
                   1546: 
                   1547: void weapon_ionripper_fire (edict_t *ent)
                   1548: {
                   1549:        vec3_t  start;
                   1550:        vec3_t  forward, right;
                   1551:        vec3_t  offset;
                   1552:        vec3_t  tempang;
                   1553:        int             damage;
                   1554:        int             kick;
                   1555: 
                   1556:        if (deathmatch->value)
                   1557:        {
                   1558:                // tone down for deathmatch
                   1559:                damage = 30;
                   1560:                kick = 40;
                   1561:        }
                   1562:        else
                   1563:        {
                   1564:                damage = 50;
                   1565:                kick = 60;
                   1566:        }
                   1567:        
                   1568:        if (is_quad)
                   1569:        {
                   1570:                damage *= 4;
                   1571:                kick *= 4;
                   1572:        }
                   1573: 
                   1574:        VectorCopy (ent->client->v_angle, tempang);
                   1575:        tempang[YAW] += crandom();
                   1576: 
                   1577:        AngleVectors (tempang, forward, right, NULL);
                   1578:        
                   1579:        VectorScale (forward, -3, ent->client->kick_origin);
                   1580:        ent->client->kick_angles[0] = -3;
                   1581: 
                   1582:        // VectorSet (offset, 0, 7, ent->viewheight - 8);
                   1583:        VectorSet (offset, 16, 7, ent->viewheight - 8);
                   1584: 
                   1585:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1586: 
                   1587:        fire_ionripper (ent, start, forward, damage, 500, EF_IONRIPPER);
                   1588: 
                   1589:        // send muzzle flash
                   1590:        gi.WriteByte (svc_muzzleflash);
                   1591:        gi.WriteShort (ent - g_edicts);
                   1592:        gi.WriteByte (MZ_IONRIPPER | is_silenced);
                   1593:        gi.multicast (ent->s.origin, MULTICAST_PVS);
                   1594: 
                   1595:        ent->client->ps.gunframe++;
                   1596:        PlayerNoise (ent, start, PNOISE_WEAPON);
                   1597: 
                   1598:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1599:                ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity;
                   1600:        
                   1601:        if (ent->client->pers.inventory[ent->client->ammo_index] < 0)
                   1602:                ent->client->pers.inventory[ent->client->ammo_index] = 0;
                   1603: }
                   1604: 
                   1605: 
                   1606: void Weapon_Ionripper (edict_t *ent)
                   1607: {
                   1608:        static int pause_frames[] = {36, 0};
                   1609:        static int fire_frames[] = {5, 0};
                   1610: 
                   1611:        Weapon_Generic (ent, 4, 6, 36, 39, pause_frames, fire_frames, weapon_ionripper_fire);
                   1612: 
                   1613:        if (is_quadfire)
                   1614:                Weapon_Generic (ent, 4, 6, 36, 39, pause_frames, fire_frames, weapon_ionripper_fire);
                   1615: }
                   1616: 
                   1617: 
                   1618: // 
                   1619: //     Phalanx
                   1620: //
                   1621: 
                   1622: void weapon_phalanx_fire (edict_t *ent)
                   1623: {
                   1624:        vec3_t          start;
                   1625:        vec3_t          forward, right, up;
                   1626:        vec3_t          offset;
                   1627:        vec3_t          v;
                   1628:        int                     kick = 12;
                   1629:        int                     damage;
                   1630:        float           damage_radius;
                   1631:        int                     radius_damage;
                   1632: 
                   1633:        damage = 70 + (int)(random() * 10.0);
                   1634:        radius_damage = 120;
                   1635:        damage_radius = 120;
                   1636:        
                   1637:        if (is_quad)
                   1638:        {
                   1639:                damage *= 4;
                   1640:                radius_damage *= 4;
                   1641:        }
                   1642: 
                   1643:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                   1644: 
                   1645:        VectorScale (forward, -2, ent->client->kick_origin);
                   1646:        ent->client->kick_angles[0] = -2;
                   1647: 
                   1648:        VectorSet(offset, 0, 8,  ent->viewheight-8);
                   1649:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1650: 
                   1651:        if (ent->client->ps.gunframe == 8)
                   1652:        {
                   1653:                v[PITCH] = ent->client->v_angle[PITCH];
                   1654:                v[YAW]   = ent->client->v_angle[YAW] - 1.5;
                   1655:                v[ROLL]  = ent->client->v_angle[ROLL];
                   1656:                AngleVectors (v, forward, right, up);
                   1657:                
                   1658:                radius_damage = 30;
                   1659:                damage_radius = 120;
                   1660:        
                   1661:                fire_plasma (ent, start, forward, damage, 725, damage_radius, radius_damage);
                   1662: 
                   1663:                if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1664:                        ent->client->pers.inventory[ent->client->ammo_index]--;
                   1665:        }
                   1666:        else
                   1667:        {
                   1668:                v[PITCH] = ent->client->v_angle[PITCH];
                   1669:                v[YAW]   = ent->client->v_angle[YAW] + 1.5;
                   1670:                v[ROLL]  = ent->client->v_angle[ROLL];
                   1671:                AngleVectors (v, forward, right, up);
                   1672:                fire_plasma (ent, start, forward, damage, 725, damage_radius, radius_damage);
                   1673: 
                   1674:                // send muzzle flash
                   1675:                gi.WriteByte (svc_muzzleflash);
                   1676:                gi.WriteShort (ent-g_edicts);
                   1677:                gi.WriteByte (MZ_PHALANX | is_silenced);
                   1678:                gi.multicast (ent->s.origin, MULTICAST_PVS);
                   1679:                
                   1680:                PlayerNoise(ent, start, PNOISE_WEAPON);
                   1681:        }
                   1682:        
                   1683:        ent->client->ps.gunframe++;
                   1684:        
                   1685: }
                   1686: 
                   1687: void Weapon_Phalanx (edict_t *ent)
                   1688: {
                   1689:        static int      pause_frames[]  = {29, 42, 55, 0};
                   1690:        static int      fire_frames[]   = {7, 8, 0};
                   1691: 
                   1692:        Weapon_Generic (ent, 5, 20, 58, 63, pause_frames, fire_frames, weapon_phalanx_fire);
                   1693: 
                   1694:        if (is_quadfire)
                   1695:                Weapon_Generic (ent, 5, 20, 58, 63, pause_frames, fire_frames, weapon_phalanx_fire);
                   1696:        
                   1697: }
                   1698: 
                   1699: /*
                   1700: ======================================================================
                   1701: 
                   1702: TRAP
                   1703: 
                   1704: ======================================================================
                   1705: */
                   1706: 
                   1707: #define TRAP_TIMER                     5.0
                   1708: #define TRAP_MINSPEED          300
                   1709: #define TRAP_MAXSPEED          700
                   1710: 
                   1711: void weapon_trap_fire (edict_t *ent, qboolean held)
                   1712: {
                   1713:        vec3_t  offset;
                   1714:        vec3_t  forward, right;
                   1715:        vec3_t  start;
                   1716:        int             damage = 125;
                   1717:        float   timer;
                   1718:        int             speed;
                   1719:        float   radius;
                   1720: 
                   1721:        radius = damage+40;
                   1722:        if (is_quad)
                   1723:                damage *= 4;
                   1724: 
                   1725:        VectorSet(offset, 8, 8, ent->viewheight-8);
                   1726:        AngleVectors (ent->client->v_angle, forward, right, NULL);
                   1727:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
                   1728: 
                   1729:        timer = ent->client->grenade_time - level.time;
                   1730:        speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER);
                   1731:        // fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held);
                   1732:        fire_trap (ent, start, forward, damage, speed, timer, radius, held);
                   1733:        
                   1734: // you don't get infinite traps!  ZOID
                   1735: //     if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
                   1736: 
                   1737:        ent->client->pers.inventory[ent->client->ammo_index]--;
                   1738: 
                   1739:        ent->client->grenade_time = level.time + 1.0;
                   1740: }
                   1741: 
                   1742: void Weapon_Trap (edict_t *ent)
                   1743: {
                   1744:        if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY))
                   1745:        {
                   1746:                ChangeWeapon (ent);
                   1747:                return;
                   1748:        }
                   1749: 
                   1750:        if (ent->client->weaponstate == WEAPON_ACTIVATING)
                   1751:        {
                   1752:                ent->client->weaponstate = WEAPON_READY;
                   1753:                ent->client->ps.gunframe = 16;
                   1754:                return;
                   1755:        }
                   1756: 
                   1757:        if (ent->client->weaponstate == WEAPON_READY)
                   1758:        {
                   1759:                if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) )
                   1760:                {
                   1761:                        ent->client->latched_buttons &= ~BUTTON_ATTACK;
                   1762:                        if (ent->client->pers.inventory[ent->client->ammo_index])
                   1763:                        {
                   1764:                                ent->client->ps.gunframe = 1;
                   1765:                                ent->client->weaponstate = WEAPON_FIRING;
                   1766:                                ent->client->grenade_time = 0;
                   1767:                        }
                   1768:                        else
                   1769:                        {
                   1770:                                if (level.time >= ent->pain_debounce_time)
                   1771:                                {
                   1772:                                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
                   1773:                                        ent->pain_debounce_time = level.time + 1;
                   1774:                                }
                   1775:                                NoAmmoWeaponChange (ent);
                   1776:                        }
                   1777:                        return;
                   1778:                }
                   1779: 
                   1780:                if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48))
                   1781:                {
                   1782:                        if (rand()&15)
                   1783:                                return;
                   1784:                }
                   1785: 
                   1786:                if (++ent->client->ps.gunframe > 48)
                   1787:                        ent->client->ps.gunframe = 16;
                   1788:                return;
                   1789:        }
                   1790: 
                   1791:        if (ent->client->weaponstate == WEAPON_FIRING)
                   1792:        {
                   1793:                if (ent->client->ps.gunframe == 5)
                   1794:                        // RAFAEL 16-APR-98
                   1795:                        // gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0);
                   1796:                        gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/trapcock.wav"), 1, ATTN_NORM, 0);
                   1797:                        // END 16-APR-98
                   1798: 
                   1799:                if (ent->client->ps.gunframe == 11)
                   1800:                {
                   1801:                        if (!ent->client->grenade_time)
                   1802:                        {
                   1803:                                ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2;
                   1804:                                // RAFAEL 16-APR-98
                   1805:                                ent->client->weapon_sound = gi.soundindex("weapons/traploop.wav");
                   1806:                                // END 16-APR-98
                   1807:                        }
                   1808: 
                   1809:                        // they waited too long, detonate it in their hand
                   1810:                        if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time)
                   1811:                        {
                   1812:                                ent->client->weapon_sound = 0;
                   1813:                                weapon_trap_fire (ent, true);
                   1814:                                ent->client->grenade_blew_up = true;
                   1815:                        }
                   1816: 
                   1817:                        if (ent->client->buttons & BUTTON_ATTACK)
                   1818:                                return;
                   1819: 
                   1820:                        if (ent->client->grenade_blew_up)
                   1821:                        {
                   1822:                                if (level.time >= ent->client->grenade_time)
                   1823:                                {
                   1824:                                        ent->client->ps.gunframe = 15;
                   1825:                                        ent->client->grenade_blew_up = false;
                   1826:                                }
                   1827:                                else
                   1828:                                {
                   1829:                                        return;
                   1830:                                }
                   1831:                        }
                   1832:                }
                   1833: 
                   1834:                if (ent->client->ps.gunframe == 12)
                   1835:                {
                   1836:                        ent->client->weapon_sound = 0;
                   1837:                        weapon_trap_fire (ent, false);
                   1838:                        if (ent->client->pers.inventory[ent->client->ammo_index] == 0)
                   1839:                                NoAmmoWeaponChange (ent);
                   1840:                }
                   1841: 
                   1842:                if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time))
                   1843:                        return;
                   1844: 
                   1845:                ent->client->ps.gunframe++;
                   1846: 
                   1847:                if (ent->client->ps.gunframe == 16)
                   1848:                {
                   1849:                        ent->client->grenade_time = 0;
                   1850:                        ent->client->weaponstate = WEAPON_READY;
                   1851:                }
                   1852:        }
                   1853: }

unix.superglobalmegacorp.com

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