Annotation of quake2/xatrix/p_weapon.c, revision 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.