Annotation of quake2/rogue/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: static byte            is_silenced;
        !             9: 
        !            10: //PGM
        !            11: static byte            damage_multiplier;
        !            12: //PGM
        !            13: 
        !            14: void weapon_grenade_fire (edict_t *ent, qboolean held);
        !            15: 
        !            16: //========
        !            17: //ROGUE
        !            18: byte P_DamageModifier(edict_t *ent)
        !            19: {
        !            20:        is_quad = 0;
        !            21:        damage_multiplier = 1;
        !            22: 
        !            23:        if(ent->client->quad_framenum > level.framenum)
        !            24:        {
        !            25:                damage_multiplier *= 4;
        !            26:                is_quad = 1;
        !            27: 
        !            28:                // if we're quad and DF_NO_STACK_DOUBLE is on, return now.
        !            29:                if(((int)(dmflags->value) & DF_NO_STACK_DOUBLE))
        !            30:                        return damage_multiplier;
        !            31:        }
        !            32:        if(ent->client->double_framenum > level.framenum)
        !            33:        {
        !            34:                if ((deathmatch->value) || (damage_multiplier == 1))
        !            35:                {
        !            36:                        damage_multiplier *= 2;
        !            37:                        is_quad = 1;
        !            38:                }
        !            39:        }
        !            40:        
        !            41:        return damage_multiplier;
        !            42: }
        !            43: //ROGUE
        !            44: //========
        !            45: 
        !            46: static void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
        !            47: {
        !            48:        vec3_t  _distance;
        !            49: 
        !            50:        VectorCopy (distance, _distance);
        !            51:        if (client->pers.hand == LEFT_HANDED)
        !            52:                _distance[1] *= -1;
        !            53:        else if (client->pers.hand == CENTER_HANDED)
        !            54:                _distance[1] = 0;
        !            55:        G_ProjectSource (point, _distance, forward, right, result);
        !            56: }
        !            57: 
        !            58: static void P_ProjectSource2 (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, 
        !            59:                                                          vec3_t right, vec3_t up, vec3_t result)
        !            60: {
        !            61:        vec3_t  _distance;
        !            62: 
        !            63:        VectorCopy (distance, _distance);
        !            64:        if (client->pers.hand == LEFT_HANDED)
        !            65:                _distance[1] *= -1;
        !            66:        else if (client->pers.hand == CENTER_HANDED)
        !            67:                _distance[1] = 0;
        !            68:        G_ProjectSource2 (point, _distance, forward, right, up, result);
        !            69: }
        !            70: 
        !            71: /*
        !            72: ===============
        !            73: PlayerNoise
        !            74: 
        !            75: Each player can have two noise objects associated with it:
        !            76: a personal noise (jumping, pain, weapon firing), and a weapon
        !            77: target noise (bullet wall impacts)
        !            78: 
        !            79: Monsters that don't directly see the player can move
        !            80: to a noise in hopes of seeing the player from there.
        !            81: ===============
        !            82: */
        !            83: void PlayerNoise(edict_t *who, vec3_t where, int type)
        !            84: {
        !            85:        edict_t         *noise;
        !            86: 
        !            87:        if (type == PNOISE_WEAPON)
        !            88:        {
        !            89:                if (who->client->silencer_shots)
        !            90:                {
        !            91:                        who->client->silencer_shots--;
        !            92:                        return;
        !            93:                }
        !            94:        }
        !            95: 
        !            96:        if (deathmatch->value)
        !            97:                return;
        !            98: 
        !            99:        if (who->flags & FL_NOTARGET)
        !           100:                return;
        !           101: 
        !           102:        if (who->flags & FL_DISGUISED)
        !           103:        {
        !           104:                if (type == PNOISE_WEAPON)
        !           105:                {
        !           106:                        level.disguise_violator = who;
        !           107:                        level.disguise_violation_framenum = level.framenum + 5;
        !           108:                }
        !           109:                else
        !           110:                        return;
        !           111:        }
        !           112: 
        !           113:        if (!who->mynoise)
        !           114:        {
        !           115:                noise = G_Spawn();
        !           116:                noise->classname = "player_noise";
        !           117:                VectorSet (noise->mins, -8, -8, -8);
        !           118:                VectorSet (noise->maxs, 8, 8, 8);
        !           119:                noise->owner = who;
        !           120:                noise->svflags = SVF_NOCLIENT;
        !           121:                who->mynoise = noise;
        !           122: 
        !           123:                noise = G_Spawn();
        !           124:                noise->classname = "player_noise";
        !           125:                VectorSet (noise->mins, -8, -8, -8);
        !           126:                VectorSet (noise->maxs, 8, 8, 8);
        !           127:                noise->owner = who;
        !           128:                noise->svflags = SVF_NOCLIENT;
        !           129:                who->mynoise2 = noise;
        !           130:        }
        !           131: 
        !           132:        if (type == PNOISE_SELF || type == PNOISE_WEAPON)
        !           133:        {
        !           134:                noise = who->mynoise;
        !           135:                level.sound_entity = noise;
        !           136:                level.sound_entity_framenum = level.framenum;
        !           137:        }
        !           138:        else // type == PNOISE_IMPACT
        !           139:        {
        !           140:                noise = who->mynoise2;
        !           141:                level.sound2_entity = noise;
        !           142:                level.sound2_entity_framenum = level.framenum;
        !           143:        }
        !           144: 
        !           145:        VectorCopy (where, noise->s.origin);
        !           146:        VectorSubtract (where, noise->maxs, noise->absmin);
        !           147:        VectorAdd (where, noise->maxs, noise->absmax);
        !           148:        noise->teleport_time = level.time;
        !           149:        gi.linkentity (noise);
        !           150: }
        !           151: 
        !           152: 
        !           153: qboolean Pickup_Weapon (edict_t *ent, edict_t *other)
        !           154: {
        !           155:        int                     index;
        !           156:        gitem_t         *ammo;
        !           157: 
        !           158:        index = ITEM_INDEX(ent->item);
        !           159: 
        !           160:        if ( ( ((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value) 
        !           161:                && other->client->pers.inventory[index])
        !           162:        {
        !           163:                if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM) ) )
        !           164:                        return false;   // leave the weapon for others to pickup
        !           165:        }
        !           166: 
        !           167:        other->client->pers.inventory[index]++;
        !           168: 
        !           169:        if (!(ent->spawnflags & DROPPED_ITEM) )
        !           170:        {
        !           171:                // give them some ammo with it
        !           172:                // PGM -- IF APPROPRIATE!
        !           173:                if(ent->item->ammo)                     //PGM
        !           174:                {
        !           175:                        ammo = FindItem (ent->item->ammo);
        !           176:                        if ( (int)dmflags->value & DF_INFINITE_AMMO )
        !           177:                                Add_Ammo (other, ammo, 1000);
        !           178:                        else
        !           179:                                Add_Ammo (other, ammo, ammo->quantity);
        !           180:                }
        !           181: 
        !           182:                if (! (ent->spawnflags & DROPPED_PLAYER_ITEM) )
        !           183:                {
        !           184:                        if (deathmatch->value)
        !           185:                        {
        !           186:                                if ((int)(dmflags->value) & DF_WEAPONS_STAY)
        !           187:                                        ent->flags |= FL_RESPAWN;
        !           188:                                else
        !           189:                                        SetRespawn (ent, 30);
        !           190:                        }
        !           191:                        if (coop->value)
        !           192:                                ent->flags |= FL_RESPAWN;
        !           193:                }
        !           194:        }
        !           195: 
        !           196:        if (other->client->pers.weapon != ent->item && 
        !           197:                (other->client->pers.inventory[index] == 1) &&
        !           198:                ( !deathmatch->value || other->client->pers.weapon == FindItem("blaster") ) )
        !           199:                other->client->newweapon = ent->item;
        !           200: 
        !           201:        return true;
        !           202: }
        !           203: 
        !           204: 
        !           205: /*
        !           206: ===============
        !           207: ChangeWeapon
        !           208: 
        !           209: The old weapon has been dropped all the way, so make the new one
        !           210: current
        !           211: ===============
        !           212: */
        !           213: void ChangeWeapon (edict_t *ent)
        !           214: {
        !           215:        int i;
        !           216: 
        !           217:        if (ent->client->grenade_time)
        !           218:        {
        !           219:                ent->client->grenade_time = level.time;
        !           220:                ent->client->weapon_sound = 0;
        !           221:                weapon_grenade_fire (ent, false);
        !           222:                ent->client->grenade_time = 0;
        !           223:        }
        !           224: 
        !           225:        ent->client->pers.lastweapon = ent->client->pers.weapon;
        !           226:        ent->client->pers.weapon = ent->client->newweapon;
        !           227:        ent->client->newweapon = NULL;
        !           228:        ent->client->machinegun_shots = 0;
        !           229: 
        !           230:        // set visible model
        !           231:        if (ent->s.modelindex == 255)
        !           232:        {
        !           233:                if (ent->client->pers.weapon)
        !           234:                        i = ((ent->client->pers.weapon->weapmodel & 0xff) << 8);
        !           235:                else
        !           236:                        i = 0;
        !           237:                ent->s.skinnum = (ent - g_edicts - 1) | i;
        !           238:        }
        !           239: 
        !           240:        if (ent->client->pers.weapon && ent->client->pers.weapon->ammo)
        !           241:                ent->client->ammo_index = ITEM_INDEX(FindItem(ent->client->pers.weapon->ammo));
        !           242:        else
        !           243:                ent->client->ammo_index = 0;
        !           244: 
        !           245:        if (!ent->client->pers.weapon)
        !           246:        {       // dead
        !           247:                ent->client->ps.gunindex = 0;
        !           248:                return;
        !           249:        }
        !           250: 
        !           251:        ent->client->weaponstate = WEAPON_ACTIVATING;
        !           252:        ent->client->ps.gunframe = 0;
        !           253:        ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model);
        !           254: 
        !           255:        ent->client->anim_priority = ANIM_PAIN;
        !           256:        if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
        !           257:        {
        !           258:                        ent->s.frame = FRAME_crpain1;
        !           259:                        ent->client->anim_end = FRAME_crpain4;
        !           260:        }
        !           261:        else
        !           262:        {
        !           263:                        ent->s.frame = FRAME_pain301;
        !           264:                        ent->client->anim_end = FRAME_pain304;
        !           265:                        
        !           266:        }
        !           267: }
        !           268: 
        !           269: /*
        !           270: =================
        !           271: NoAmmoWeaponChange
        !           272: =================
        !           273: */
        !           274: 
        !           275: // PMM - added rogue weapons to the list
        !           276: 
        !           277: void NoAmmoWeaponChange (edict_t *ent)
        !           278: {
        !           279:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("slugs"))]
        !           280:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("railgun"))] )
        !           281:        {
        !           282:                ent->client->newweapon = FindItem ("railgun");
        !           283:                return;
        !           284:        }
        !           285:        // ROGUE
        !           286:        if ( (ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))] >= 2)
        !           287:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("Plasma Beam"))] )
        !           288:        {
        !           289:                ent->client->newweapon = FindItem ("Plasma Beam");
        !           290:                return;
        !           291:        }
        !           292:        // -ROGUE
        !           293:        /*
        !           294:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))]
        !           295:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("hyperblaster"))] )
        !           296:        {
        !           297:                ent->client->newweapon = FindItem ("hyperblaster");
        !           298:                return;
        !           299:        }
        !           300:        */
        !           301:        // ROGUE
        !           302:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("flechettes"))]
        !           303:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("etf rifle"))] )
        !           304:        {
        !           305:                ent->client->newweapon = FindItem ("etf rifle");
        !           306:                return;
        !           307:        }
        !           308:        // -ROGUE
        !           309:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
        !           310:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("chaingun"))] )
        !           311:        {
        !           312:                ent->client->newweapon = FindItem ("chaingun");
        !           313:                return;
        !           314:        }
        !           315:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
        !           316:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("machinegun"))] )
        !           317:        {
        !           318:                ent->client->newweapon = FindItem ("machinegun");
        !           319:                return;
        !           320:        }
        !           321:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))] > 1
        !           322:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("super shotgun"))] )
        !           323:        {
        !           324:                ent->client->newweapon = FindItem ("super shotgun");
        !           325:                return;
        !           326:        }
        !           327:        if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))]
        !           328:                &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("shotgun"))] )
        !           329:        {
        !           330:                ent->client->newweapon = FindItem ("shotgun");
        !           331:                return;
        !           332:        }
        !           333:        ent->client->newweapon = FindItem ("blaster");
        !           334: }
        !           335: 
        !           336: /*
        !           337: =================
        !           338: Think_Weapon
        !           339: 
        !           340: Called by ClientBeginServerFrame and ClientThink
        !           341: =================
        !           342: */
        !           343: void Think_Weapon (edict_t *ent)
        !           344: {
        !           345:        // if just died, put the weapon away
        !           346:        if (ent->health < 1)
        !           347:        {
        !           348:                ent->client->newweapon = NULL;
        !           349:                ChangeWeapon (ent);
        !           350:        }
        !           351: 
        !           352:        // call active weapon think routine
        !           353:        if (ent->client->pers.weapon && ent->client->pers.weapon->weaponthink)
        !           354:        {
        !           355: //PGM
        !           356:                P_DamageModifier(ent);  
        !           357: //             is_quad = (ent->client->quad_framenum > level.framenum);
        !           358: //PGM
        !           359:                if (ent->client->silencer_shots)
        !           360:                        is_silenced = MZ_SILENCED;
        !           361:                else
        !           362:                        is_silenced = 0;
        !           363:                ent->client->pers.weapon->weaponthink (ent);
        !           364:        }
        !           365: }
        !           366: 
        !           367: 
        !           368: /*
        !           369: ================
        !           370: Use_Weapon
        !           371: 
        !           372: Make the weapon ready if there is ammo
        !           373: ================
        !           374: */
        !           375: void Use_Weapon (edict_t *ent, gitem_t *item)
        !           376: {
        !           377:        int                     ammo_index;
        !           378:        gitem_t         *ammo_item;
        !           379: 
        !           380:        // see if we're already using it
        !           381:        if (item == ent->client->pers.weapon)
        !           382:                return;
        !           383: 
        !           384:        if (item->ammo && !g_select_empty->value && !(item->flags & IT_AMMO))
        !           385:        {
        !           386:                ammo_item = FindItem(item->ammo);
        !           387:                ammo_index = ITEM_INDEX(ammo_item);
        !           388: 
        !           389:                if (!ent->client->pers.inventory[ammo_index])
        !           390:                {
        !           391:                        gi.cprintf (ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
        !           392:                        return;
        !           393:                }
        !           394: 
        !           395:                if (ent->client->pers.inventory[ammo_index] < item->quantity)
        !           396:                {
        !           397:                        gi.cprintf (ent, PRINT_HIGH, "Not enough %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
        !           398:                        return;
        !           399:                }
        !           400:        }
        !           401: 
        !           402:        // change to this weapon when down
        !           403:        ent->client->newweapon = item;
        !           404: }
        !           405: 
        !           406: 
        !           407: 
        !           408: /*
        !           409: ================
        !           410: Drop_Weapon
        !           411: ================
        !           412: */
        !           413: void Drop_Weapon (edict_t *ent, gitem_t *item)
        !           414: {
        !           415:        int             index;
        !           416: 
        !           417:        if ((int)(dmflags->value) & DF_WEAPONS_STAY)
        !           418:                return;
        !           419: 
        !           420:        index = ITEM_INDEX(item);
        !           421:        // see if we're already using it
        !           422:        if ( ((item == ent->client->pers.weapon) || (item == ent->client->newweapon))&& (ent->client->pers.inventory[index] == 1) )
        !           423:        {
        !           424:                gi.cprintf (ent, PRINT_HIGH, "Can't drop current weapon\n");
        !           425:                return;
        !           426:        }
        !           427: 
        !           428:        Drop_Item (ent, item);
        !           429:        ent->client->pers.inventory[index]--;
        !           430: }
        !           431: 
        !           432: 
        !           433: /*
        !           434: ================
        !           435: Weapon_Generic
        !           436: 
        !           437: A generic function to handle the basics of weapon thinking
        !           438: ================
        !           439: */
        !           440: #define FRAME_FIRE_FIRST               (FRAME_ACTIVATE_LAST + 1)
        !           441: #define FRAME_IDLE_FIRST               (FRAME_FIRE_LAST + 1)
        !           442: #define FRAME_DEACTIVATE_FIRST (FRAME_IDLE_LAST + 1)
        !           443: 
        !           444: 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))
        !           445: {
        !           446:        int             n;
        !           447: 
        !           448:        if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses
        !           449:        {
        !           450:                return;
        !           451:        }
        !           452: 
        !           453:        if (ent->client->weaponstate == WEAPON_DROPPING)
        !           454:        {
        !           455:                if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST)
        !           456:                {
        !           457:                        ChangeWeapon (ent);
        !           458:                        return;
        !           459:                }
        !           460:                else if ((FRAME_DEACTIVATE_LAST - ent->client->ps.gunframe) == 4)
        !           461:                {
        !           462:                        ent->client->anim_priority = ANIM_REVERSE;
        !           463:                        if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
        !           464:                        {
        !           465:                                ent->s.frame = FRAME_crpain4+1;
        !           466:                                ent->client->anim_end = FRAME_crpain1;
        !           467:                        }
        !           468:                        else
        !           469:                        {
        !           470:                                ent->s.frame = FRAME_pain304+1;
        !           471:                                ent->client->anim_end = FRAME_pain301;
        !           472:                                
        !           473:                        }
        !           474:                }
        !           475: 
        !           476:                ent->client->ps.gunframe++;
        !           477:                return;
        !           478:        }
        !           479: 
        !           480:        if (ent->client->weaponstate == WEAPON_ACTIVATING)
        !           481:        {
        !           482:                if (ent->client->ps.gunframe == FRAME_ACTIVATE_LAST)
        !           483:                {
        !           484:                        ent->client->weaponstate = WEAPON_READY;
        !           485:                        ent->client->ps.gunframe = FRAME_IDLE_FIRST;
        !           486:                        return;
        !           487:                }
        !           488: 
        !           489:                ent->client->ps.gunframe++;
        !           490:                return;
        !           491:        }
        !           492: 
        !           493:        if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING))
        !           494:        {
        !           495:                ent->client->weaponstate = WEAPON_DROPPING;
        !           496:                ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST;
        !           497: 
        !           498:                if ((FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < 4)
        !           499:                {
        !           500:                        ent->client->anim_priority = ANIM_REVERSE;
        !           501:                        if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
        !           502:                        {
        !           503:                                ent->s.frame = FRAME_crpain4+1;
        !           504:                                ent->client->anim_end = FRAME_crpain1;
        !           505:                        }
        !           506:                        else
        !           507:                        {
        !           508:                                ent->s.frame = FRAME_pain304+1;
        !           509:                                ent->client->anim_end = FRAME_pain301;
        !           510:                                
        !           511:                        }
        !           512:                }
        !           513:                return;
        !           514:        }
        !           515: 
        !           516:        if (ent->client->weaponstate == WEAPON_READY)
        !           517:        {
        !           518:                if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) )
        !           519:                {
        !           520:                        ent->client->latched_buttons &= ~BUTTON_ATTACK;
        !           521:                        if ((!ent->client->ammo_index) || 
        !           522:                                ( ent->client->pers.inventory[ent->client->ammo_index] >= ent->client->pers.weapon->quantity))
        !           523:                        {
        !           524:                                ent->client->ps.gunframe = FRAME_FIRE_FIRST;
        !           525:                                ent->client->weaponstate = WEAPON_FIRING;
        !           526: 
        !           527:                                // start the animation
        !           528:                                ent->client->anim_priority = ANIM_ATTACK;
        !           529:                                if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
        !           530:                                {
        !           531:                                        ent->s.frame = FRAME_crattak1-1;
        !           532:                                        ent->client->anim_end = FRAME_crattak9;
        !           533:                                }
        !           534:                                else
        !           535:                                {
        !           536:                                        ent->s.frame = FRAME_attack1-1;
        !           537:                                        ent->client->anim_end = FRAME_attack8;
        !           538:                                }
        !           539:                        }
        !           540:                        else
        !           541:                        {
        !           542:                                if (level.time >= ent->pain_debounce_time)
        !           543:                                {
        !           544:                                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
        !           545:                                        ent->pain_debounce_time = level.time + 1;
        !           546:                                }
        !           547:                                NoAmmoWeaponChange (ent);
        !           548:                        }
        !           549:                }
        !           550:                else
        !           551:                {
        !           552:                        if (ent->client->ps.gunframe == FRAME_IDLE_LAST)
        !           553:                        {
        !           554:                                ent->client->ps.gunframe = FRAME_IDLE_FIRST;
        !           555:                                return;
        !           556:                        }
        !           557: 
        !           558:                        if (pause_frames)
        !           559:                        {
        !           560:                                for (n = 0; pause_frames[n]; n++)
        !           561:                                {
        !           562:                                        if (ent->client->ps.gunframe == pause_frames[n])
        !           563:                                        {
        !           564:                                                if (rand()&15)
        !           565:                                                        return;
        !           566:                                        }
        !           567:                                }
        !           568:                        }
        !           569: 
        !           570:                        ent->client->ps.gunframe++;
        !           571:                        return;
        !           572:                }
        !           573:        }
        !           574: 
        !           575:        if (ent->client->weaponstate == WEAPON_FIRING)
        !           576:        {
        !           577:                for (n = 0; fire_frames[n]; n++)
        !           578:                {
        !           579:                        if (ent->client->ps.gunframe == fire_frames[n])
        !           580:                        {
        !           581:                                // FIXME - double should use different sound
        !           582:                                if ((ent->client->quad_framenum > level.framenum) || (ent->client->double_framenum > level.framenum))
        !           583:                                        gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0);
        !           584: 
        !           585:                                fire (ent);
        !           586:                                break;
        !           587:                        }
        !           588:                }
        !           589: 
        !           590:                if (!fire_frames[n])
        !           591:                        ent->client->ps.gunframe++;
        !           592: 
        !           593:                if (ent->client->ps.gunframe == FRAME_IDLE_FIRST+1)
        !           594:                        ent->client->weaponstate = WEAPON_READY;
        !           595:        }
        !           596: }
        !           597: 
        !           598: 
        !           599: /*
        !           600: ======================================================================
        !           601: 
        !           602: GRENADE
        !           603: 
        !           604: ======================================================================
        !           605: */
        !           606: 
        !           607: #define GRENADE_TIMER          3.0
        !           608: #define GRENADE_MINSPEED       400
        !           609: #define GRENADE_MAXSPEED       800
        !           610: 
        !           611: void weapon_grenade_fire (edict_t *ent, qboolean held)
        !           612: {
        !           613:        vec3_t  offset;
        !           614:        vec3_t  forward, right, up;
        !           615:        vec3_t  start;
        !           616:        int             damage = 125;
        !           617:        float   timer;
        !           618:        int             speed;
        !           619:        float   radius;
        !           620: 
        !           621:        radius = damage+40;
        !           622:        if (is_quad)
        !           623: //             damage *= 4;
        !           624:                damage *= damage_multiplier;            // PGM
        !           625: 
        !           626:        AngleVectors (ent->client->v_angle, forward, right, up);
        !           627:        if (ent->client->pers.weapon->tag == AMMO_TESLA)
        !           628:        {
        !           629: //             VectorSet(offset, 0, -12, ent->viewheight-26);
        !           630:                VectorSet(offset, 0, -4, ent->viewheight-22);
        !           631:        }
        !           632:        else
        !           633:        {
        !           634: //             VectorSet(offset, 8, 8, ent->viewheight-8);
        !           635:                VectorSet(offset, 2, 6, ent->viewheight-14);
        !           636:        }
        !           637:        P_ProjectSource2 (ent->client, ent->s.origin, offset, forward, right, up, start);
        !           638: 
        !           639:        timer = ent->client->grenade_time - level.time;
        !           640:        speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER);
        !           641:        if (speed > GRENADE_MAXSPEED)
        !           642:                speed = GRENADE_MAXSPEED;
        !           643: 
        !           644: //     fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held);
        !           645: 
        !           646: // ============
        !           647: // PGM
        !           648:        switch(ent->client->pers.weapon->tag)
        !           649:        {
        !           650:                case AMMO_GRENADES:
        !           651:                        fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held);
        !           652:                        break;
        !           653:                case AMMO_TESLA:
        !           654:                        fire_tesla (ent, start, forward, damage_multiplier, speed);
        !           655:                        break;
        !           656:                default:
        !           657:                        fire_prox (ent, start, forward, damage_multiplier, speed);
        !           658:                        break;
        !           659:        }
        !           660: // PGM
        !           661: // ============
        !           662: 
        !           663:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
        !           664:                ent->client->pers.inventory[ent->client->ammo_index]--;
        !           665: 
        !           666:        ent->client->grenade_time = level.time + 1.0;
        !           667: 
        !           668:        if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses
        !           669:        {
        !           670:                return;
        !           671:        }
        !           672: 
        !           673:        if (ent->health <= 0)
        !           674:                return;
        !           675: 
        !           676:        if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
        !           677:        {
        !           678:                ent->client->anim_priority = ANIM_ATTACK;
        !           679:                ent->s.frame = FRAME_crattak1-1;
        !           680:                ent->client->anim_end = FRAME_crattak3;
        !           681:        }
        !           682:        else
        !           683:        {
        !           684:                ent->client->anim_priority = ANIM_REVERSE;
        !           685:                ent->s.frame = FRAME_wave08;
        !           686:                ent->client->anim_end = FRAME_wave01;
        !           687:        }
        !           688: }
        !           689: /*
        !           690: void Weapon_Grenade (edict_t *ent)
        !           691: {
        !           692:        if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY))
        !           693:        {
        !           694:                ChangeWeapon (ent);
        !           695:                return;
        !           696:        }
        !           697: 
        !           698:        if (ent->client->weaponstate == WEAPON_ACTIVATING)
        !           699:        {
        !           700:                ent->client->weaponstate = WEAPON_READY;
        !           701:                ent->client->ps.gunframe = 16;
        !           702:                return;
        !           703:        }
        !           704: 
        !           705:        if (ent->client->weaponstate == WEAPON_READY)
        !           706:        {
        !           707:                if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) )
        !           708:                {
        !           709:                        ent->client->latched_buttons &= ~BUTTON_ATTACK;
        !           710:                        if (ent->client->pers.inventory[ent->client->ammo_index])
        !           711:                        {
        !           712:                                ent->client->ps.gunframe = 1;
        !           713:                                ent->client->weaponstate = WEAPON_FIRING;
        !           714:                                ent->client->grenade_time = 0;
        !           715:                        }
        !           716:                        else
        !           717:                        {
        !           718:                                if (level.time >= ent->pain_debounce_time)
        !           719:                                {
        !           720:                                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
        !           721:                                        ent->pain_debounce_time = level.time + 1;
        !           722:                                }
        !           723:                                NoAmmoWeaponChange (ent);
        !           724:                        }
        !           725:                        return;
        !           726:                }
        !           727: 
        !           728:                if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48))
        !           729:                {
        !           730:                        if (rand()&15)
        !           731:                                return;
        !           732:                }
        !           733: 
        !           734:                if (++ent->client->ps.gunframe > 48)
        !           735:                        ent->client->ps.gunframe = 16;
        !           736:                return;
        !           737:        }
        !           738: 
        !           739:        if (ent->client->weaponstate == WEAPON_FIRING)
        !           740:        {
        !           741:                if (ent->client->ps.gunframe == 5)
        !           742:                        gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0);
        !           743: 
        !           744:                if (ent->client->ps.gunframe == 11)
        !           745:                {
        !           746:                        if (!ent->client->grenade_time)
        !           747:                        {
        !           748:                                ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2;
        !           749:                                ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav");
        !           750:                        }
        !           751: 
        !           752:                        // they waited too long, detonate it in their hand
        !           753:                        if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time)
        !           754:                        {
        !           755:                                ent->client->weapon_sound = 0;
        !           756:                                weapon_grenade_fire (ent, true);
        !           757:                                ent->client->grenade_blew_up = true;
        !           758:                        }
        !           759: 
        !           760:                        if (ent->client->buttons & BUTTON_ATTACK)
        !           761:                                return;
        !           762: 
        !           763:                        if (ent->client->grenade_blew_up)
        !           764:                        {
        !           765:                                if (level.time >= ent->client->grenade_time)
        !           766:                                {
        !           767:                                        ent->client->ps.gunframe = 15;
        !           768:                                        ent->client->grenade_blew_up = false;
        !           769:                                }
        !           770:                                else
        !           771:                                {
        !           772:                                        return;
        !           773:                                }
        !           774:                        }
        !           775:                }
        !           776: 
        !           777:                if (ent->client->ps.gunframe == 12)
        !           778:                {
        !           779:                        ent->client->weapon_sound = 0;
        !           780:                        weapon_grenade_fire (ent, false);
        !           781:                }
        !           782: 
        !           783:                if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time))
        !           784:                        return;
        !           785: 
        !           786:                ent->client->ps.gunframe++;
        !           787: 
        !           788:                if (ent->client->ps.gunframe == 16)
        !           789:                {
        !           790:                        ent->client->grenade_time = 0;
        !           791:                        ent->client->weaponstate = WEAPON_READY;
        !           792:                }
        !           793:        }
        !           794: }
        !           795: */
        !           796: 
        !           797: #define FRAME_IDLE_FIRST               (FRAME_FIRE_LAST + 1)
        !           798: 
        !           799: //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))
        !           800: //                                                                     15                      48                                              5                                               11                                      12                              29,34,39,48
        !           801: void Throw_Generic (edict_t *ent, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_THROW_SOUND,
        !           802:                                        int FRAME_THROW_HOLD, int FRAME_THROW_FIRE, int *pause_frames, int EXPLODE,
        !           803:                                        void (*fire)(edict_t *ent, qboolean held))
        !           804: {
        !           805:        int n;
        !           806: 
        !           807:        if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY))
        !           808:        {
        !           809:                ChangeWeapon (ent);
        !           810:                return;
        !           811:        }
        !           812: 
        !           813:        if (ent->client->weaponstate == WEAPON_ACTIVATING)
        !           814:        {
        !           815:                ent->client->weaponstate = WEAPON_READY;
        !           816:                ent->client->ps.gunframe = FRAME_IDLE_FIRST;
        !           817:                return;
        !           818:        }
        !           819: 
        !           820:        if (ent->client->weaponstate == WEAPON_READY)
        !           821:        {
        !           822:                if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) )
        !           823:                {
        !           824:                        ent->client->latched_buttons &= ~BUTTON_ATTACK;
        !           825:                        if (ent->client->pers.inventory[ent->client->ammo_index])
        !           826:                        {
        !           827:                                ent->client->ps.gunframe = 1;
        !           828:                                ent->client->weaponstate = WEAPON_FIRING;
        !           829:                                ent->client->grenade_time = 0;
        !           830:                        }
        !           831:                        else
        !           832:                        {
        !           833:                                if (level.time >= ent->pain_debounce_time)
        !           834:                                {
        !           835:                                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
        !           836:                                        ent->pain_debounce_time = level.time + 1;
        !           837:                                }
        !           838:                                NoAmmoWeaponChange (ent);
        !           839:                        }
        !           840:                        return;
        !           841:                }
        !           842: 
        !           843:                if (ent->client->ps.gunframe == FRAME_IDLE_LAST)
        !           844:                {
        !           845:                        ent->client->ps.gunframe = FRAME_IDLE_FIRST;
        !           846:                        return;
        !           847:                }
        !           848: 
        !           849:                if (pause_frames)
        !           850:                {
        !           851:                        for (n = 0; pause_frames[n]; n++)
        !           852:                        {
        !           853:                                if (ent->client->ps.gunframe == pause_frames[n])
        !           854:                                {
        !           855:                                        if (rand()&15)
        !           856:                                                return;
        !           857:                                }
        !           858:                        }
        !           859:                }
        !           860: 
        !           861:                ent->client->ps.gunframe++;
        !           862:                return;
        !           863:        }
        !           864: 
        !           865:        if (ent->client->weaponstate == WEAPON_FIRING)
        !           866:        {
        !           867:                if (ent->client->ps.gunframe == FRAME_THROW_SOUND)
        !           868:                        gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0);
        !           869: 
        !           870:                if (ent->client->ps.gunframe == FRAME_THROW_HOLD)
        !           871:                {
        !           872:                        if (!ent->client->grenade_time)
        !           873:                        {
        !           874:                                ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2;
        !           875:                                switch(ent->client->pers.weapon->tag)
        !           876:                                {
        !           877:                                        case AMMO_GRENADES:
        !           878:                                                ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav");
        !           879:                                                break;
        !           880:                                }
        !           881:                        }
        !           882: 
        !           883:                        // they waited too long, detonate it in their hand
        !           884:                        if (EXPLODE && !ent->client->grenade_blew_up && level.time >= ent->client->grenade_time)
        !           885:                        {
        !           886:                                ent->client->weapon_sound = 0;
        !           887:                                fire (ent, true);
        !           888:                                ent->client->grenade_blew_up = true;
        !           889:                        }
        !           890: 
        !           891:                        if (ent->client->buttons & BUTTON_ATTACK)
        !           892:                                return;
        !           893: 
        !           894:                        if (ent->client->grenade_blew_up)
        !           895:                        {
        !           896:                                if (level.time >= ent->client->grenade_time)
        !           897:                                {
        !           898:                                        ent->client->ps.gunframe = FRAME_FIRE_LAST;
        !           899:                                        ent->client->grenade_blew_up = false;
        !           900:                                }
        !           901:                                else
        !           902:                                {
        !           903:                                        return;
        !           904:                                }
        !           905:                        }
        !           906:                }
        !           907: 
        !           908:                if (ent->client->ps.gunframe == FRAME_THROW_FIRE)
        !           909:                {
        !           910:                        ent->client->weapon_sound = 0;
        !           911:                        fire (ent, true);
        !           912:                }
        !           913: 
        !           914:                if ((ent->client->ps.gunframe == FRAME_FIRE_LAST) && (level.time < ent->client->grenade_time))
        !           915:                        return;
        !           916: 
        !           917:                ent->client->ps.gunframe++;
        !           918: 
        !           919:                if (ent->client->ps.gunframe == FRAME_IDLE_FIRST)
        !           920:                {
        !           921:                        ent->client->grenade_time = 0;
        !           922:                        ent->client->weaponstate = WEAPON_READY;
        !           923:                }
        !           924:        }
        !           925: }
        !           926: 
        !           927: //void Throw_Generic (edict_t *ent, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_THROW_SOUND,
        !           928: //                                             int FRAME_THROW_HOLD, int FRAME_THROW_FIRE, int *pause_frames, 
        !           929: //                                             int EXPLOSION_TIME, void (*fire)(edict_t *ent))
        !           930: 
        !           931: void Weapon_Grenade (edict_t *ent)
        !           932: {
        !           933:        static int      pause_frames[]  = {29,34,39,48,0};
        !           934: 
        !           935:        Throw_Generic (ent, 15, 48, 5, 11, 12, pause_frames, GRENADE_TIMER, weapon_grenade_fire);
        !           936: }
        !           937: 
        !           938: void Weapon_Prox (edict_t *ent)
        !           939: {
        !           940:        static int      pause_frames[]  = {22, 29, 0};
        !           941: 
        !           942:        Throw_Generic (ent, 7, 27, 99, 2, 4, pause_frames, 0, weapon_grenade_fire);
        !           943: }
        !           944: 
        !           945: void Weapon_Tesla (edict_t *ent)
        !           946: {
        !           947:        static int      pause_frames[]  = {21, 0};
        !           948: 
        !           949:        if ((ent->client->ps.gunframe > 1) && (ent->client->ps.gunframe < 9))
        !           950:        {
        !           951:                ent->client->ps.gunindex = gi.modelindex  ("models/weapons/v_tesla2/tris.md2");
        !           952:        }
        !           953:        else
        !           954:        {
        !           955:                ent->client->ps.gunindex = gi.modelindex  ("models/weapons/v_tesla/tris.md2");
        !           956:        }
        !           957: 
        !           958:        Throw_Generic (ent, 8, 32, 99, 1, 2, pause_frames, 0, weapon_grenade_fire);
        !           959: }
        !           960: 
        !           961: 
        !           962: 
        !           963: /*
        !           964: ======================================================================
        !           965: 
        !           966: GRENADE LAUNCHER
        !           967: 
        !           968: ======================================================================
        !           969: */
        !           970: 
        !           971: void weapon_grenadelauncher_fire (edict_t *ent)
        !           972: {
        !           973:        vec3_t  offset;
        !           974:        vec3_t  forward, right;
        !           975:        vec3_t  start;
        !           976: //     int             damage = 120;
        !           977:        int             damage;                 // PGM
        !           978:        float   radius;
        !           979: 
        !           980: // =====
        !           981: // PGM
        !           982:        switch(ent->client->pers.weapon->tag)
        !           983:        {
        !           984:                case AMMO_PROX:
        !           985:                        damage = 90;
        !           986:                        break;
        !           987:                default:
        !           988:                        damage = 120;
        !           989:                        break;
        !           990:        }
        !           991: // PGM
        !           992: // =====
        !           993: 
        !           994:        radius = damage+40;
        !           995:        if (is_quad)
        !           996: //             damage *= 4;
        !           997:                damage *= damage_multiplier;            //pgm
        !           998: 
        !           999:        VectorSet(offset, 8, 8, ent->viewheight-8);
        !          1000:        AngleVectors (ent->client->v_angle, forward, right, NULL);
        !          1001:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
        !          1002: 
        !          1003:        VectorScale (forward, -2, ent->client->kick_origin);
        !          1004:        ent->client->kick_angles[0] = -1;
        !          1005: 
        !          1006: //     fire_grenade (ent, start, forward, damage, 600, 2.5, radius);
        !          1007: // =====
        !          1008: // PGM
        !          1009:        switch(ent->client->pers.weapon->tag)
        !          1010:        {
        !          1011:                case AMMO_PROX:
        !          1012:                        fire_prox (ent, start, forward, damage_multiplier, 600);
        !          1013:                        break;
        !          1014:                default:
        !          1015:                        fire_grenade (ent, start, forward, damage, 600, 2.5, radius);
        !          1016:                        break;
        !          1017:        }
        !          1018: // PGM
        !          1019: // =====
        !          1020: 
        !          1021:        gi.WriteByte (svc_muzzleflash);
        !          1022:        gi.WriteShort (ent-g_edicts);
        !          1023:        gi.WriteByte (MZ_GRENADE | is_silenced);
        !          1024:        gi.multicast (ent->s.origin, MULTICAST_PVS);
        !          1025: 
        !          1026:        ent->client->ps.gunframe++;
        !          1027: 
        !          1028:        PlayerNoise(ent, start, PNOISE_WEAPON);
        !          1029: 
        !          1030:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
        !          1031:                ent->client->pers.inventory[ent->client->ammo_index]--;
        !          1032: }
        !          1033: 
        !          1034: void Weapon_GrenadeLauncher (edict_t *ent)
        !          1035: {
        !          1036:        static int      pause_frames[]  = {34, 51, 59, 0};
        !          1037:        static int      fire_frames[]   = {6, 0};
        !          1038: 
        !          1039:        Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire);
        !          1040: }
        !          1041: 
        !          1042: //==========
        !          1043: //PGM
        !          1044: void Weapon_ProxLauncher (edict_t *ent)
        !          1045: {
        !          1046:        static int      pause_frames[]  = {34, 51, 59, 0};
        !          1047:        static int      fire_frames[]   = {6, 0};
        !          1048: 
        !          1049:        Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire);
        !          1050: }
        !          1051: //PGM
        !          1052: //==========
        !          1053: 
        !          1054: /*
        !          1055: ======================================================================
        !          1056: 
        !          1057: ROCKET
        !          1058: 
        !          1059: ======================================================================
        !          1060: */
        !          1061: 
        !          1062: void Weapon_RocketLauncher_Fire (edict_t *ent)
        !          1063: {
        !          1064:        vec3_t  offset, start;
        !          1065:        vec3_t  forward, right;
        !          1066:        int             damage;
        !          1067:        float   damage_radius;
        !          1068:        int             radius_damage;
        !          1069: 
        !          1070:        damage = 100 + (int)(random() * 20.0);
        !          1071:        radius_damage = 120;
        !          1072:        damage_radius = 120;
        !          1073:        if (is_quad)
        !          1074:        {
        !          1075: //PGM
        !          1076: //             damage *= 4;
        !          1077:                damage *= damage_multiplier;
        !          1078: //             radius_damage *= 4;
        !          1079:                radius_damage *= damage_multiplier;
        !          1080: //PGM
        !          1081:        }
        !          1082: 
        !          1083:        AngleVectors (ent->client->v_angle, forward, right, NULL);
        !          1084: 
        !          1085:        VectorScale (forward, -2, ent->client->kick_origin);
        !          1086:        ent->client->kick_angles[0] = -1;
        !          1087: 
        !          1088:        VectorSet(offset, 8, 8, ent->viewheight-8);
        !          1089:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
        !          1090:        fire_rocket (ent, start, forward, damage, 650, damage_radius, radius_damage);
        !          1091: 
        !          1092:        // send muzzle flash
        !          1093:        gi.WriteByte (svc_muzzleflash);
        !          1094:        gi.WriteShort (ent-g_edicts);
        !          1095:        gi.WriteByte (MZ_ROCKET | is_silenced);
        !          1096:        gi.multicast (ent->s.origin, MULTICAST_PVS);
        !          1097: 
        !          1098:        ent->client->ps.gunframe++;
        !          1099: 
        !          1100:        PlayerNoise(ent, start, PNOISE_WEAPON);
        !          1101: 
        !          1102:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
        !          1103:                ent->client->pers.inventory[ent->client->ammo_index]--;
        !          1104: }
        !          1105: 
        !          1106: void Weapon_RocketLauncher (edict_t *ent)
        !          1107: {
        !          1108:        static int      pause_frames[]  = {25, 33, 42, 50, 0};
        !          1109:        static int      fire_frames[]   = {5, 0};
        !          1110: 
        !          1111:        Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire);
        !          1112: }
        !          1113: 
        !          1114: 
        !          1115: /*
        !          1116: ======================================================================
        !          1117: 
        !          1118: BLASTER / HYPERBLASTER
        !          1119: 
        !          1120: ======================================================================
        !          1121: */
        !          1122: 
        !          1123: void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect)
        !          1124: {
        !          1125:        vec3_t  forward, right;
        !          1126:        vec3_t  start;
        !          1127:        vec3_t  offset;
        !          1128: 
        !          1129:        if (is_quad)
        !          1130: //             damage *= 4;            
        !          1131:                damage *= damage_multiplier;            //pgm
        !          1132: 
        !          1133:        AngleVectors (ent->client->v_angle, forward, right, NULL);
        !          1134:        VectorSet(offset, 24, 8, ent->viewheight-8);
        !          1135:        VectorAdd (offset, g_offset, offset);
        !          1136:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
        !          1137: 
        !          1138:        VectorScale (forward, -2, ent->client->kick_origin);
        !          1139:        ent->client->kick_angles[0] = -1;
        !          1140: 
        !          1141:        fire_blaster (ent, start, forward, damage, 1000, effect, hyper);
        !          1142: 
        !          1143:        // send muzzle flash
        !          1144:        gi.WriteByte (svc_muzzleflash);
        !          1145:        gi.WriteShort (ent-g_edicts);
        !          1146:        if (hyper)
        !          1147:                gi.WriteByte (MZ_HYPERBLASTER | is_silenced);
        !          1148:        else
        !          1149:                gi.WriteByte (MZ_BLASTER | is_silenced);
        !          1150:        gi.multicast (ent->s.origin, MULTICAST_PVS);
        !          1151: 
        !          1152:        PlayerNoise(ent, start, PNOISE_WEAPON);
        !          1153: }
        !          1154: 
        !          1155: 
        !          1156: void Weapon_Blaster_Fire (edict_t *ent)
        !          1157: {
        !          1158:        int             damage;
        !          1159: 
        !          1160:        if (deathmatch->value)
        !          1161:                damage = 15;
        !          1162:        else
        !          1163:                damage = 10;
        !          1164:        Blaster_Fire (ent, vec3_origin, damage, false, EF_BLASTER);
        !          1165:        ent->client->ps.gunframe++;
        !          1166: }
        !          1167: 
        !          1168: void Weapon_Blaster (edict_t *ent)
        !          1169: {
        !          1170:        static int      pause_frames[]  = {19, 32, 0};
        !          1171:        static int      fire_frames[]   = {5, 0};
        !          1172: 
        !          1173:        Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire);
        !          1174: }
        !          1175: 
        !          1176: 
        !          1177: void Weapon_HyperBlaster_Fire (edict_t *ent)
        !          1178: {
        !          1179:        float   rotation;
        !          1180:        vec3_t  offset;
        !          1181:        int             effect;
        !          1182:        int             damage;
        !          1183: 
        !          1184:        ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav");
        !          1185: 
        !          1186:        if (!(ent->client->buttons & BUTTON_ATTACK))
        !          1187:        {
        !          1188:                ent->client->ps.gunframe++;
        !          1189:        }
        !          1190:        else
        !          1191:        {
        !          1192:                if (! ent->client->pers.inventory[ent->client->ammo_index] )
        !          1193:                {
        !          1194:                        if (level.time >= ent->pain_debounce_time)
        !          1195:                        {
        !          1196:                                gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
        !          1197:                                ent->pain_debounce_time = level.time + 1;
        !          1198:                        }
        !          1199:                        NoAmmoWeaponChange (ent);
        !          1200:                }
        !          1201:                else
        !          1202:                {
        !          1203:                        rotation = (ent->client->ps.gunframe - 5) * 2*M_PI/6;
        !          1204:                        offset[0] = -4 * sin(rotation);
        !          1205:                        offset[1] = 0;
        !          1206:                        offset[2] = 4 * cos(rotation);
        !          1207: 
        !          1208:                        if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9))
        !          1209:                                effect = EF_HYPERBLASTER;
        !          1210:                        else
        !          1211:                                effect = 0;
        !          1212:                        if (deathmatch->value)
        !          1213:                                damage = 15;
        !          1214:                        else
        !          1215:                                damage = 20;
        !          1216:                        Blaster_Fire (ent, offset, damage, true, effect);
        !          1217:                        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
        !          1218:                                ent->client->pers.inventory[ent->client->ammo_index]--;
        !          1219: 
        !          1220:                        ent->client->anim_priority = ANIM_ATTACK;
        !          1221:                        if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
        !          1222:                        {
        !          1223:                                ent->s.frame = FRAME_crattak1 - 1;
        !          1224:                                ent->client->anim_end = FRAME_crattak9;
        !          1225:                        }
        !          1226:                        else
        !          1227:                        {
        !          1228:                                ent->s.frame = FRAME_attack1 - 1;
        !          1229:                                ent->client->anim_end = FRAME_attack8;
        !          1230:                        }
        !          1231:                }
        !          1232: 
        !          1233:                ent->client->ps.gunframe++;
        !          1234:                if (ent->client->ps.gunframe == 12 && ent->client->pers.inventory[ent->client->ammo_index])
        !          1235:                        ent->client->ps.gunframe = 6;
        !          1236:        }
        !          1237: 
        !          1238:        if (ent->client->ps.gunframe == 12)
        !          1239:        {
        !          1240:                gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0);
        !          1241:                ent->client->weapon_sound = 0;
        !          1242:        }
        !          1243: 
        !          1244: }
        !          1245: 
        !          1246: void Weapon_HyperBlaster (edict_t *ent)
        !          1247: {
        !          1248:        static int      pause_frames[]  = {0};
        !          1249:        static int      fire_frames[]   = {6, 7, 8, 9, 10, 11, 0};
        !          1250: 
        !          1251:        Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire);
        !          1252: }
        !          1253: 
        !          1254: /*
        !          1255: ======================================================================
        !          1256: 
        !          1257: MACHINEGUN / CHAINGUN
        !          1258: 
        !          1259: ======================================================================
        !          1260: */
        !          1261: 
        !          1262: void Machinegun_Fire (edict_t *ent)
        !          1263: {
        !          1264:        int     i;
        !          1265:        vec3_t          start;
        !          1266:        vec3_t          forward, right;
        !          1267:        vec3_t          angles;
        !          1268:        int                     damage = 8;
        !          1269:        int                     kick = 2;
        !          1270:        vec3_t          offset;
        !          1271: 
        !          1272:        if (!(ent->client->buttons & BUTTON_ATTACK))
        !          1273:        {
        !          1274:                ent->client->machinegun_shots = 0;
        !          1275:                ent->client->ps.gunframe++;
        !          1276:                return;
        !          1277:        }
        !          1278: 
        !          1279:        if (ent->client->ps.gunframe == 5)
        !          1280:                ent->client->ps.gunframe = 4;
        !          1281:        else
        !          1282:                ent->client->ps.gunframe = 5;
        !          1283: 
        !          1284:        if (ent->client->pers.inventory[ent->client->ammo_index] < 1)
        !          1285:        {
        !          1286:                ent->client->ps.gunframe = 6;
        !          1287:                if (level.time >= ent->pain_debounce_time)
        !          1288:                {
        !          1289:                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
        !          1290:                        ent->pain_debounce_time = level.time + 1;
        !          1291:                }
        !          1292:                NoAmmoWeaponChange (ent);
        !          1293:                return;
        !          1294:        }
        !          1295: 
        !          1296:        if (is_quad)
        !          1297:        {
        !          1298: //PGM
        !          1299: //             damage *= 4;
        !          1300:                damage *= damage_multiplier;
        !          1301: //             kick *= 4;
        !          1302:                kick *= damage_multiplier;
        !          1303: //PGM
        !          1304:        }
        !          1305: 
        !          1306:        for (i=1 ; i<3 ; i++)
        !          1307:        {
        !          1308:                ent->client->kick_origin[i] = crandom() * 0.35;
        !          1309:                ent->client->kick_angles[i] = crandom() * 0.7;
        !          1310:        }
        !          1311:        ent->client->kick_origin[0] = crandom() * 0.35;
        !          1312:        ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5;
        !          1313: 
        !          1314:        // raise the gun as it is firing
        !          1315:        if (!deathmatch->value)
        !          1316:        {
        !          1317:                ent->client->machinegun_shots++;
        !          1318:                if (ent->client->machinegun_shots > 9)
        !          1319:                        ent->client->machinegun_shots = 9;
        !          1320:        }
        !          1321: 
        !          1322:        // get start / end positions
        !          1323:        VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles);
        !          1324:        AngleVectors (angles, forward, right, NULL);
        !          1325:        VectorSet(offset, 0, 8, ent->viewheight-8);
        !          1326:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
        !          1327:        fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN);
        !          1328: 
        !          1329:        gi.WriteByte (svc_muzzleflash);
        !          1330:        gi.WriteShort (ent-g_edicts);
        !          1331:        gi.WriteByte (MZ_MACHINEGUN | is_silenced);
        !          1332:        gi.multicast (ent->s.origin, MULTICAST_PVS);
        !          1333: 
        !          1334:        PlayerNoise(ent, start, PNOISE_WEAPON);
        !          1335: 
        !          1336:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
        !          1337:                ent->client->pers.inventory[ent->client->ammo_index]--;
        !          1338: 
        !          1339:        ent->client->anim_priority = ANIM_ATTACK;
        !          1340:        if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
        !          1341:        {
        !          1342:                ent->s.frame = FRAME_crattak1 - (int) (random()+0.25);
        !          1343:                ent->client->anim_end = FRAME_crattak9;
        !          1344:        }
        !          1345:        else
        !          1346:        {
        !          1347:                ent->s.frame = FRAME_attack1 - (int) (random()+0.25);
        !          1348:                ent->client->anim_end = FRAME_attack8;
        !          1349:        }
        !          1350: }
        !          1351: 
        !          1352: void Weapon_Machinegun (edict_t *ent)
        !          1353: {
        !          1354:        static int      pause_frames[]  = {23, 45, 0};
        !          1355:        static int      fire_frames[]   = {4, 5, 0};
        !          1356: 
        !          1357:        Weapon_Generic (ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire);
        !          1358: }
        !          1359: 
        !          1360: void Chaingun_Fire (edict_t *ent)
        !          1361: {
        !          1362:        int                     i;
        !          1363:        int                     shots;
        !          1364:        vec3_t          start;
        !          1365:        vec3_t          forward, right, up;
        !          1366:        float           r, u;
        !          1367:        vec3_t          offset;
        !          1368:        int                     damage;
        !          1369:        int                     kick = 2;
        !          1370: 
        !          1371:        if (deathmatch->value)
        !          1372:                damage = 6;
        !          1373:        else
        !          1374:                damage = 8;
        !          1375: 
        !          1376:        if (ent->client->ps.gunframe == 5)
        !          1377:                gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0);
        !          1378: 
        !          1379:        if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK))
        !          1380:        {
        !          1381:                ent->client->ps.gunframe = 32;
        !          1382:                ent->client->weapon_sound = 0;
        !          1383:                return;
        !          1384:        }
        !          1385:        else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK)
        !          1386:                && ent->client->pers.inventory[ent->client->ammo_index])
        !          1387:        {
        !          1388:                ent->client->ps.gunframe = 15;
        !          1389:        }
        !          1390:        else
        !          1391:        {
        !          1392:                ent->client->ps.gunframe++;
        !          1393:        }
        !          1394: 
        !          1395:        if (ent->client->ps.gunframe == 22)
        !          1396:        {
        !          1397:                ent->client->weapon_sound = 0;
        !          1398:                gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0);
        !          1399:        }
        !          1400:        else
        !          1401:        {
        !          1402:                ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav");
        !          1403:        }
        !          1404: 
        !          1405:        ent->client->anim_priority = ANIM_ATTACK;
        !          1406:        if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
        !          1407:        {
        !          1408:                ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1);
        !          1409:                ent->client->anim_end = FRAME_crattak9;
        !          1410:        }
        !          1411:        else
        !          1412:        {
        !          1413:                ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1);
        !          1414:                ent->client->anim_end = FRAME_attack8;
        !          1415:        }
        !          1416: 
        !          1417:        if (ent->client->ps.gunframe <= 9)
        !          1418:                shots = 1;
        !          1419:        else if (ent->client->ps.gunframe <= 14)
        !          1420:        {
        !          1421:                if (ent->client->buttons & BUTTON_ATTACK)
        !          1422:                        shots = 2;
        !          1423:                else
        !          1424:                        shots = 1;
        !          1425:        }
        !          1426:        else
        !          1427:                shots = 3;
        !          1428: 
        !          1429:        if (ent->client->pers.inventory[ent->client->ammo_index] < shots)
        !          1430:                shots = ent->client->pers.inventory[ent->client->ammo_index];
        !          1431: 
        !          1432:        if (!shots)
        !          1433:        {
        !          1434:                if (level.time >= ent->pain_debounce_time)
        !          1435:                {
        !          1436:                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
        !          1437:                        ent->pain_debounce_time = level.time + 1;
        !          1438:                }
        !          1439:                NoAmmoWeaponChange (ent);
        !          1440:                return;
        !          1441:        }
        !          1442: 
        !          1443:        if (is_quad)
        !          1444:        {
        !          1445: //PGM
        !          1446: //             damage *= 4;
        !          1447:                damage *= damage_multiplier;
        !          1448: //             kick *= 4;
        !          1449:                kick *= damage_multiplier;
        !          1450: //PGM
        !          1451:        }
        !          1452: 
        !          1453:        for (i=0 ; i<3 ; i++)
        !          1454:        {
        !          1455:                ent->client->kick_origin[i] = crandom() * 0.35;
        !          1456:                ent->client->kick_angles[i] = crandom() * 0.7;
        !          1457:        }
        !          1458: 
        !          1459:        for (i=0 ; i<shots ; i++)
        !          1460:        {
        !          1461:                // get start / end positions
        !          1462:                AngleVectors (ent->client->v_angle, forward, right, up);
        !          1463:                r = 7 + crandom()*4;
        !          1464:                u = crandom()*4;
        !          1465:                VectorSet(offset, 0, r, u + ent->viewheight-8);
        !          1466:                P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
        !          1467: 
        !          1468:                fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN);
        !          1469:        }
        !          1470: 
        !          1471:        // send muzzle flash
        !          1472:        gi.WriteByte (svc_muzzleflash);
        !          1473:        gi.WriteShort (ent-g_edicts);
        !          1474:        gi.WriteByte ((MZ_CHAINGUN1 + shots - 1) | is_silenced);
        !          1475:        gi.multicast (ent->s.origin, MULTICAST_PVS);
        !          1476: 
        !          1477:        PlayerNoise(ent, start, PNOISE_WEAPON);
        !          1478: 
        !          1479:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
        !          1480:                ent->client->pers.inventory[ent->client->ammo_index] -= shots;
        !          1481: }
        !          1482: 
        !          1483: 
        !          1484: void Weapon_Chaingun (edict_t *ent)
        !          1485: {
        !          1486:        static int      pause_frames[]  = {38, 43, 51, 61, 0};
        !          1487:        static int      fire_frames[]   = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0};
        !          1488: 
        !          1489:        Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire);
        !          1490: }
        !          1491: 
        !          1492: 
        !          1493: /*
        !          1494: ======================================================================
        !          1495: 
        !          1496: SHOTGUN / SUPERSHOTGUN
        !          1497: 
        !          1498: ======================================================================
        !          1499: */
        !          1500: 
        !          1501: void weapon_shotgun_fire (edict_t *ent)
        !          1502: {
        !          1503:        vec3_t          start;
        !          1504:        vec3_t          forward, right;
        !          1505:        vec3_t          offset;
        !          1506:        int                     damage = 4;
        !          1507:        int                     kick = 8;
        !          1508: 
        !          1509:        if (ent->client->ps.gunframe == 9)
        !          1510:        {
        !          1511:                ent->client->ps.gunframe++;
        !          1512:                return;
        !          1513:        }
        !          1514: 
        !          1515:        AngleVectors (ent->client->v_angle, forward, right, NULL);
        !          1516: 
        !          1517:        VectorScale (forward, -2, ent->client->kick_origin);
        !          1518:        ent->client->kick_angles[0] = -2;
        !          1519: 
        !          1520:        VectorSet(offset, 0, 8,  ent->viewheight-8);
        !          1521:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
        !          1522: 
        !          1523:        if (is_quad)
        !          1524:        {
        !          1525: //PGM
        !          1526: //             damage *= 4;
        !          1527:                damage *= damage_multiplier;
        !          1528: //             kick *= 4;
        !          1529:                kick *= damage_multiplier;
        !          1530: //PGM
        !          1531:        }
        !          1532: 
        !          1533:        if (deathmatch->value)
        !          1534:                fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_DEATHMATCH_SHOTGUN_COUNT, MOD_SHOTGUN);
        !          1535:        else
        !          1536:                fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN);
        !          1537: 
        !          1538:        // send muzzle flash
        !          1539:        gi.WriteByte (svc_muzzleflash);
        !          1540:        gi.WriteShort (ent-g_edicts);
        !          1541:        gi.WriteByte (MZ_SHOTGUN | is_silenced);
        !          1542:        gi.multicast (ent->s.origin, MULTICAST_PVS);
        !          1543: 
        !          1544:        ent->client->ps.gunframe++;
        !          1545:        PlayerNoise(ent, start, PNOISE_WEAPON);
        !          1546: 
        !          1547:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
        !          1548:                ent->client->pers.inventory[ent->client->ammo_index]--;
        !          1549: }
        !          1550: 
        !          1551: void Weapon_Shotgun (edict_t *ent)
        !          1552: {
        !          1553:        static int      pause_frames[]  = {22, 28, 34, 0};
        !          1554:        static int      fire_frames[]   = {8, 9, 0};
        !          1555: 
        !          1556:        Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire);
        !          1557: }
        !          1558: 
        !          1559: 
        !          1560: void weapon_supershotgun_fire (edict_t *ent)
        !          1561: {
        !          1562:        vec3_t          start;
        !          1563:        vec3_t          forward, right;
        !          1564:        vec3_t          offset;
        !          1565:        vec3_t          v;
        !          1566:        int                     damage = 6;
        !          1567:        int                     kick = 12;
        !          1568: 
        !          1569:        AngleVectors (ent->client->v_angle, forward, right, NULL);
        !          1570: 
        !          1571:        VectorScale (forward, -2, ent->client->kick_origin);
        !          1572:        ent->client->kick_angles[0] = -2;
        !          1573: 
        !          1574:        VectorSet(offset, 0, 8,  ent->viewheight-8);
        !          1575:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
        !          1576: 
        !          1577:        if (is_quad)
        !          1578:        {
        !          1579: //PGM
        !          1580: //             damage *= 4;
        !          1581:                damage *= damage_multiplier;
        !          1582: //             kick *= 4;
        !          1583:                kick *= damage_multiplier;
        !          1584: //PGM
        !          1585:        }
        !          1586: 
        !          1587:        v[PITCH] = ent->client->v_angle[PITCH];
        !          1588:        v[YAW]   = ent->client->v_angle[YAW] - 5;
        !          1589:        v[ROLL]  = ent->client->v_angle[ROLL];
        !          1590:        AngleVectors (v, forward, NULL, NULL);
        !          1591:        fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN);
        !          1592:        v[YAW]   = ent->client->v_angle[YAW] + 5;
        !          1593:        AngleVectors (v, forward, NULL, NULL);
        !          1594:        fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN);
        !          1595: 
        !          1596:        // send muzzle flash
        !          1597:        gi.WriteByte (svc_muzzleflash);
        !          1598:        gi.WriteShort (ent-g_edicts);
        !          1599:        gi.WriteByte (MZ_SSHOTGUN | is_silenced);
        !          1600:        gi.multicast (ent->s.origin, MULTICAST_PVS);
        !          1601: 
        !          1602:        ent->client->ps.gunframe++;
        !          1603:        PlayerNoise(ent, start, PNOISE_WEAPON);
        !          1604: 
        !          1605:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
        !          1606:                ent->client->pers.inventory[ent->client->ammo_index] -= 2;
        !          1607: }
        !          1608: 
        !          1609: void Weapon_SuperShotgun (edict_t *ent)
        !          1610: {
        !          1611:        static int      pause_frames[]  = {29, 42, 57, 0};
        !          1612:        static int      fire_frames[]   = {7, 0};
        !          1613: 
        !          1614:        Weapon_Generic (ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire);
        !          1615: }
        !          1616: 
        !          1617: 
        !          1618: 
        !          1619: /*
        !          1620: ======================================================================
        !          1621: 
        !          1622: RAILGUN
        !          1623: 
        !          1624: ======================================================================
        !          1625: */
        !          1626: 
        !          1627: void weapon_railgun_fire (edict_t *ent)
        !          1628: {
        !          1629:        vec3_t          start;
        !          1630:        vec3_t          forward, right;
        !          1631:        vec3_t          offset;
        !          1632:        int                     damage;
        !          1633:        int                     kick;
        !          1634: 
        !          1635:        if (deathmatch->value)
        !          1636:        {       // normal damage is too extreme in dm
        !          1637:                damage = 100;
        !          1638:                kick = 200;
        !          1639:        }
        !          1640:        else
        !          1641:        {
        !          1642:                damage = 150;
        !          1643:                kick = 250;
        !          1644:        }
        !          1645: 
        !          1646:        if (is_quad)
        !          1647:        {
        !          1648: //PGM
        !          1649: //             damage *= 4;
        !          1650:                damage *= damage_multiplier;
        !          1651: //             kick *= 4;
        !          1652:                kick *= damage_multiplier;
        !          1653: //PGM
        !          1654:        }
        !          1655: 
        !          1656:        AngleVectors (ent->client->v_angle, forward, right, NULL);
        !          1657: 
        !          1658:        VectorScale (forward, -3, ent->client->kick_origin);
        !          1659:        ent->client->kick_angles[0] = -3;
        !          1660: 
        !          1661:        VectorSet(offset, 0, 7,  ent->viewheight-8);
        !          1662:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
        !          1663:        fire_rail (ent, start, forward, damage, kick);
        !          1664: 
        !          1665:        // send muzzle flash
        !          1666:        gi.WriteByte (svc_muzzleflash);
        !          1667:        gi.WriteShort (ent-g_edicts);
        !          1668:        gi.WriteByte (MZ_RAILGUN | is_silenced);
        !          1669:        gi.multicast (ent->s.origin, MULTICAST_PVS);
        !          1670: 
        !          1671:        ent->client->ps.gunframe++;
        !          1672:        PlayerNoise(ent, start, PNOISE_WEAPON);
        !          1673: 
        !          1674:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
        !          1675:                ent->client->pers.inventory[ent->client->ammo_index]--;
        !          1676: }
        !          1677: 
        !          1678: 
        !          1679: void Weapon_Railgun (edict_t *ent)
        !          1680: {
        !          1681:        static int      pause_frames[]  = {56, 0};
        !          1682:        static int      fire_frames[]   = {4, 0};
        !          1683: 
        !          1684:        Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire);
        !          1685: }
        !          1686: 
        !          1687: 
        !          1688: /*
        !          1689: ======================================================================
        !          1690: 
        !          1691: BFG10K
        !          1692: 
        !          1693: ======================================================================
        !          1694: */
        !          1695: 
        !          1696: void weapon_bfg_fire (edict_t *ent)
        !          1697: {
        !          1698:        vec3_t  offset, start;
        !          1699:        vec3_t  forward, right;
        !          1700:        int             damage;
        !          1701:        float   damage_radius = 1000;
        !          1702: 
        !          1703:        if (deathmatch->value)
        !          1704:                damage = 200;
        !          1705:        else
        !          1706:                damage = 500;
        !          1707: 
        !          1708:        if (ent->client->ps.gunframe == 9)
        !          1709:        {
        !          1710:                // send muzzle flash
        !          1711:                gi.WriteByte (svc_muzzleflash);
        !          1712:                gi.WriteShort (ent-g_edicts);
        !          1713:                gi.WriteByte (MZ_BFG | is_silenced);
        !          1714:                gi.multicast (ent->s.origin, MULTICAST_PVS);
        !          1715: 
        !          1716:                ent->client->ps.gunframe++;
        !          1717: 
        !          1718:                PlayerNoise(ent, start, PNOISE_WEAPON);
        !          1719:                return;
        !          1720:        }
        !          1721: 
        !          1722:        // cells can go down during windup (from power armor hits), so
        !          1723:        // check again and abort firing if we don't have enough now
        !          1724:        if (ent->client->pers.inventory[ent->client->ammo_index] < 50)
        !          1725:        {
        !          1726:                ent->client->ps.gunframe++;
        !          1727:                return;
        !          1728:        }
        !          1729: 
        !          1730:        if (is_quad)
        !          1731: //PGM
        !          1732: //             damage *= 4;
        !          1733:                damage *= damage_multiplier;
        !          1734: //PGM
        !          1735: 
        !          1736:        AngleVectors (ent->client->v_angle, forward, right, NULL);
        !          1737: 
        !          1738:        VectorScale (forward, -2, ent->client->kick_origin);
        !          1739: 
        !          1740:        // make a big pitch kick with an inverse fall
        !          1741:        ent->client->v_dmg_pitch = -40;
        !          1742:        ent->client->v_dmg_roll = crandom()*8;
        !          1743:        ent->client->v_dmg_time = level.time + DAMAGE_TIME;
        !          1744: 
        !          1745:        VectorSet(offset, 8, 8, ent->viewheight-8);
        !          1746:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
        !          1747:        fire_bfg (ent, start, forward, damage, 400, damage_radius);
        !          1748: 
        !          1749:        ent->client->ps.gunframe++;
        !          1750: 
        !          1751:        PlayerNoise(ent, start, PNOISE_WEAPON);
        !          1752: 
        !          1753:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
        !          1754:                ent->client->pers.inventory[ent->client->ammo_index] -= 50;
        !          1755: }
        !          1756: 
        !          1757: void Weapon_BFG (edict_t *ent)
        !          1758: {
        !          1759:        static int      pause_frames[]  = {39, 45, 50, 55, 0};
        !          1760:        static int      fire_frames[]   = {9, 17, 0};
        !          1761: 
        !          1762:        Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire);
        !          1763: }
        !          1764: 
        !          1765: 
        !          1766: //======================================================================
        !          1767: // ROGUE MODS BELOW
        !          1768: //======================================================================
        !          1769: 
        !          1770: 
        !          1771: //
        !          1772: // CHAINFIST
        !          1773: //
        !          1774: #define CHAINFIST_REACH 64
        !          1775: 
        !          1776: void weapon_chainfist_fire (edict_t *ent)
        !          1777: {
        !          1778:        vec3_t  offset;
        !          1779:        vec3_t  forward, right, up;
        !          1780:        vec3_t  start;
        !          1781:        int             damage;
        !          1782: 
        !          1783:        damage = 15;
        !          1784:        if(deathmatch->value)
        !          1785:                damage = 30;
        !          1786: 
        !          1787:        if (is_quad)
        !          1788:                damage *= damage_multiplier;
        !          1789: 
        !          1790:        AngleVectors (ent->client->v_angle, forward, right, up);
        !          1791: 
        !          1792:        // kick back
        !          1793:        VectorScale (forward, -2, ent->client->kick_origin);
        !          1794:        ent->client->kick_angles[0] = -1;
        !          1795: 
        !          1796:        // set start point
        !          1797:        VectorSet(offset, 0, 8, ent->viewheight-4);
        !          1798:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
        !          1799: 
        !          1800:        fire_player_melee (ent, start, forward, CHAINFIST_REACH, damage, 100, 1, MOD_CHAINFIST);
        !          1801: 
        !          1802:        PlayerNoise(ent, start, PNOISE_WEAPON);
        !          1803: 
        !          1804:        ent->client->ps.gunframe++;
        !          1805:        ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity;
        !          1806: }
        !          1807: 
        !          1808: // this spits out some smoke from the motor. it's a two-stroke, you know.
        !          1809: void chainfist_smoke (edict_t *ent)
        !          1810: {
        !          1811:        vec3_t  tempVec, forward, right, up;
        !          1812:        vec3_t  offset;
        !          1813: 
        !          1814:        AngleVectors(ent->client->v_angle, forward, right, up);
        !          1815:        VectorSet(offset, 8, 8, ent->viewheight -4);
        !          1816:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, tempVec);
        !          1817: 
        !          1818:        gi.WriteByte (svc_temp_entity);
        !          1819:        gi.WriteByte (TE_CHAINFIST_SMOKE);
        !          1820:        gi.WritePosition (tempVec);
        !          1821:        gi.unicast (ent, 0);
        !          1822:        // FIXME - this should probably only go to the owner unless we decide to
        !          1823:        //              add the visible weapons patch
        !          1824: }
        !          1825: 
        !          1826: #define HOLD_FRAMES                    0
        !          1827: 
        !          1828: void Weapon_ChainFist (edict_t *ent)
        !          1829: {
        !          1830:        static int      pause_frames[]  = {0};
        !          1831:        static int      fire_frames[]   = {8, 9, 16, 17, 18, 30, 31, 0};
        !          1832: 
        !          1833:        // these are caches for the sound index. there's probably a better way to do this.
        !          1834: //     static int      idle_index;
        !          1835: //     static int      attack_index;
        !          1836:        float           chance;
        !          1837:        int                     last_sequence;
        !          1838:        
        !          1839:        last_sequence = 0;
        !          1840: 
        !          1841:        // load chainsaw sounds and store the indexes for later use.
        !          1842: //     if(!idle_index && !attack_index)
        !          1843: //     {
        !          1844: //             idle_index = gi.soundindex("weapons/sawidle.wav");
        !          1845: //             attack_index = gi.soundindex("weapons/sawhit.wav");
        !          1846: //     }
        !          1847: 
        !          1848:        if(ent->client->ps.gunframe == 13 ||
        !          1849:                ent->client->ps.gunframe == 23)                 // end of attack, go idle
        !          1850:                ent->client->ps.gunframe = 32;
        !          1851: 
        !          1852: #if HOLD_FRAMES
        !          1853:        else if(ent->client->ps.gunframe == 9 && ((ent->client->buttons) & BUTTON_ATTACK))
        !          1854:                ent->client->ps.gunframe = 7;
        !          1855:        else if(ent->client->ps.gunframe == 18 && ((ent->client->buttons) & BUTTON_ATTACK))
        !          1856:                ent->client->ps.gunframe = 16;
        !          1857: #endif
        !          1858: 
        !          1859:        // holds for idle sequence
        !          1860:        else if(ent->client->ps.gunframe == 42 && (rand()&7))
        !          1861:        {
        !          1862:                if((ent->client->pers.hand != CENTER_HANDED) && random() < 0.4)
        !          1863:                        chainfist_smoke(ent);
        !          1864: //             ent->client->ps.gunframe = 40;
        !          1865:        }
        !          1866:        else if(ent->client->ps.gunframe == 51 && (rand()&7))
        !          1867:        {
        !          1868:                if((ent->client->pers.hand != CENTER_HANDED) && random() < 0.4)
        !          1869:                        chainfist_smoke(ent);
        !          1870: //             ent->client->ps.gunframe = 49;
        !          1871:        }       
        !          1872: 
        !          1873:        // set the appropriate weapon sound.
        !          1874:        if(ent->client->weaponstate == WEAPON_FIRING)
        !          1875: //             ent->client->weapon_sound = attack_index;
        !          1876:                ent->client->weapon_sound = gi.soundindex("weapons/sawhit.wav");
        !          1877:        else if(ent->client->weaponstate == WEAPON_DROPPING)
        !          1878:                ent->client->weapon_sound = 0;
        !          1879:        else
        !          1880: //             ent->client->weapon_sound = idle_index;
        !          1881:                ent->client->weapon_sound = gi.soundindex("weapons/sawidle.wav");
        !          1882: 
        !          1883:        Weapon_Generic (ent, 4, 32, 57, 60, pause_frames, fire_frames, weapon_chainfist_fire);
        !          1884: 
        !          1885: //     gi.dprintf("chainfist %d\n", ent->client->ps.gunframe);
        !          1886:        if((ent->client->buttons) & BUTTON_ATTACK)
        !          1887:        {
        !          1888:                if(ent->client->ps.gunframe == 13 ||
        !          1889:                        ent->client->ps.gunframe == 23 ||
        !          1890:                        ent->client->ps.gunframe == 32)
        !          1891:                {
        !          1892:                        last_sequence = ent->client->ps.gunframe;
        !          1893:                        ent->client->ps.gunframe = 6;
        !          1894:                }
        !          1895:        }
        !          1896: 
        !          1897:        if (ent->client->ps.gunframe == 6)
        !          1898:        {
        !          1899:                chance = random();
        !          1900:                if(last_sequence == 13)                 // if we just did sequence 1, do 2 or 3.
        !          1901:                        chance -= 0.34;
        !          1902:                else if(last_sequence == 23)    // if we just did sequence 2, do 1 or 3
        !          1903:                        chance += 0.33;
        !          1904:                else if(last_sequence == 32)    // if we just did sequence 3, do 1 or 2
        !          1905:                {
        !          1906:                        if(chance >= 0.33)
        !          1907:                                chance += 0.34;
        !          1908:                }
        !          1909: 
        !          1910:                if(chance < 0.33)
        !          1911:                        ent->client->ps.gunframe = 14;
        !          1912:                else if(chance < 0.66)
        !          1913:                        ent->client->ps.gunframe = 24;
        !          1914:        }
        !          1915: 
        !          1916: }
        !          1917: 
        !          1918: //
        !          1919: // Disintegrator
        !          1920: //
        !          1921: 
        !          1922: void weapon_tracker_fire (edict_t *self)
        !          1923: {
        !          1924:        vec3_t          forward, right;
        !          1925:        vec3_t          start;
        !          1926:        vec3_t          end;
        !          1927:        vec3_t          offset;
        !          1928:        edict_t         *enemy;
        !          1929:        trace_t         tr;
        !          1930:        int                     damage;
        !          1931:        vec3_t          mins, maxs;
        !          1932: 
        !          1933:        // PMM - felt a little high at 25
        !          1934:        if(deathmatch->value)
        !          1935:                damage = 30;
        !          1936:        else
        !          1937:                damage = 45;
        !          1938: 
        !          1939:        if (is_quad)
        !          1940:                damage *= damage_multiplier;            //pgm
        !          1941: 
        !          1942:        VectorSet(mins, -16, -16, -16);
        !          1943:        VectorSet(maxs, 16, 16, 16);
        !          1944:        AngleVectors (self->client->v_angle, forward, right, NULL);
        !          1945:        VectorSet(offset, 24, 8, self->viewheight-8);
        !          1946:        P_ProjectSource (self->client, self->s.origin, offset, forward, right, start);
        !          1947: 
        !          1948:        // FIXME - can we shorten this? do we need to?
        !          1949:        VectorMA (start, 8192, forward, end);
        !          1950:        enemy = NULL;
        !          1951:        //PMM - doing two traces .. one point and one box.  
        !          1952:        tr = gi.trace (start, vec3_origin, vec3_origin, end, self, MASK_SHOT);
        !          1953:        if(tr.ent != world)
        !          1954:        {
        !          1955:                if(tr.ent->svflags & SVF_MONSTER || tr.ent->client || tr.ent->svflags & SVF_DAMAGEABLE)
        !          1956:                {
        !          1957:                        if(tr.ent->health > 0)
        !          1958:                                enemy = tr.ent;
        !          1959:                }
        !          1960:        }
        !          1961:        else
        !          1962:        {
        !          1963:                tr = gi.trace (start, mins, maxs, end, self, MASK_SHOT);
        !          1964:                if(tr.ent != world)
        !          1965:                {
        !          1966:                        if(tr.ent->svflags & SVF_MONSTER || tr.ent->client || tr.ent->svflags & SVF_DAMAGEABLE)
        !          1967:                        {
        !          1968:                                if(tr.ent->health > 0)
        !          1969:                                        enemy = tr.ent;
        !          1970:                        }
        !          1971:                }
        !          1972:        }
        !          1973: 
        !          1974:        VectorScale (forward, -2, self->client->kick_origin);
        !          1975:        self->client->kick_angles[0] = -1;
        !          1976: 
        !          1977:        fire_tracker (self, start, forward, damage, 1000, enemy);
        !          1978: 
        !          1979:        // send muzzle flash
        !          1980:        gi.WriteByte (svc_muzzleflash);
        !          1981:        gi.WriteShort (self-g_edicts);
        !          1982:        gi.WriteByte (MZ_TRACKER);
        !          1983:        gi.multicast (self->s.origin, MULTICAST_PVS);
        !          1984: 
        !          1985:        PlayerNoise(self, start, PNOISE_WEAPON);
        !          1986: 
        !          1987:        self->client->ps.gunframe++;
        !          1988:        self->client->pers.inventory[self->client->ammo_index] -= self->client->pers.weapon->quantity;
        !          1989: }
        !          1990: 
        !          1991: void Weapon_Disintegrator (edict_t *ent)
        !          1992: {
        !          1993:        static int      pause_frames[]  = {14, 19, 23, 0};
        !          1994: //     static int      fire_frames[]   = {7, 0};
        !          1995:        static int      fire_frames[]   = {5, 0};
        !          1996: 
        !          1997:        Weapon_Generic (ent, 4, 9, 29, 34, pause_frames, fire_frames, weapon_tracker_fire);
        !          1998: }
        !          1999: 
        !          2000: /*
        !          2001: ======================================================================
        !          2002: 
        !          2003: ETF RIFLE
        !          2004: 
        !          2005: ======================================================================
        !          2006: */
        !          2007: void weapon_etf_rifle_fire (edict_t *ent)
        !          2008: {
        !          2009:        vec3_t  forward, right, up;
        !          2010:        vec3_t  start, tempPt;
        !          2011:        int             damage = 8;
        !          2012:        int             kick = 3;
        !          2013:        int             i;
        !          2014:        vec3_t  angles;
        !          2015:        vec3_t  offset;
        !          2016: 
        !          2017:        // PGM - adjusted to use the quantity entry in the weapon structure.
        !          2018:        if(ent->client->pers.inventory[ent->client->ammo_index] < ent->client->pers.weapon->quantity)
        !          2019:        {
        !          2020:                VectorClear (ent->client->kick_origin);
        !          2021:                VectorClear (ent->client->kick_angles);
        !          2022:                ent->client->ps.gunframe = 8;
        !          2023: 
        !          2024:                if (level.time >= ent->pain_debounce_time)
        !          2025:                {
        !          2026:                        gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
        !          2027:                        ent->pain_debounce_time = level.time + 1;
        !          2028:                }
        !          2029:                NoAmmoWeaponChange (ent);
        !          2030:                return;
        !          2031:        }
        !          2032: 
        !          2033:        if (is_quad)
        !          2034:        {
        !          2035:                damage *= damage_multiplier;
        !          2036:                kick *= damage_multiplier;
        !          2037:        }
        !          2038: 
        !          2039:        for(i=0;i<3;i++)
        !          2040:        {
        !          2041:                ent->client->kick_origin[i] = crandom() * 0.85;
        !          2042:                ent->client->kick_angles[i] = crandom() * 0.85;
        !          2043:        }
        !          2044: 
        !          2045:        // get start / end positions
        !          2046:        VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles);
        !          2047: //     AngleVectors (angles, forward, right, NULL);
        !          2048: //     gi.dprintf("v_angle: %s\n", vtos(ent->client->v_angle));
        !          2049:        AngleVectors (ent->client->v_angle, forward, right, up);
        !          2050: 
        !          2051:        // FIXME - set correct frames for different offsets.
        !          2052: 
        !          2053:        if(ent->client->ps.gunframe == 6)                                       // right barrel
        !          2054:        {
        !          2055: //             gi.dprintf("right\n");
        !          2056:                VectorSet(offset, 15, 8, -8);
        !          2057:        }
        !          2058:        else                                                                            // left barrel
        !          2059:        {
        !          2060: //             gi.dprintf("left\n");
        !          2061:                VectorSet(offset, 15, 6, -8);
        !          2062:        }
        !          2063:        
        !          2064:        VectorCopy (ent->s.origin, tempPt);
        !          2065:        tempPt[2] += ent->viewheight;
        !          2066:        P_ProjectSource2 (ent->client, tempPt, offset, forward, right, up, start);
        !          2067: //     gi.dprintf("start: %s\n", vtos(start));
        !          2068:        fire_flechette (ent, start, forward, damage, 750, kick);
        !          2069: 
        !          2070:        // send muzzle flash
        !          2071:        gi.WriteByte (svc_muzzleflash);
        !          2072:        gi.WriteShort (ent-g_edicts);
        !          2073:        gi.WriteByte (MZ_ETF_RIFLE);
        !          2074:        gi.multicast (ent->s.origin, MULTICAST_PVS);
        !          2075: 
        !          2076:        PlayerNoise(ent, start, PNOISE_WEAPON);
        !          2077: 
        !          2078:        ent->client->ps.gunframe++;
        !          2079:        ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity;
        !          2080: }
        !          2081: 
        !          2082: void Weapon_ETF_Rifle (edict_t *ent)
        !          2083: {
        !          2084:        static int      pause_frames[]  = {18, 28, 0};
        !          2085:        static int      fire_frames[]   = {6, 7, 0};
        !          2086: //     static int      idle_seq;
        !          2087: 
        !          2088:        // note - if you change the fire frame number, fix the offset in weapon_etf_rifle_fire.
        !          2089: 
        !          2090: //     if (!(ent->client->buttons & BUTTON_ATTACK))
        !          2091: //             ent->client->machinegun_shots = 0;
        !          2092: 
        !          2093:        if (ent->client->weaponstate == WEAPON_FIRING)
        !          2094:        {
        !          2095:                if (ent->client->pers.inventory[ent->client->ammo_index] <= 0)
        !          2096:                        ent->client->ps.gunframe = 8;
        !          2097:        }
        !          2098: 
        !          2099:        Weapon_Generic (ent, 4, 7, 37, 41, pause_frames, fire_frames, weapon_etf_rifle_fire);
        !          2100: 
        !          2101:        if(ent->client->ps.gunframe == 8 && (ent->client->buttons & BUTTON_ATTACK))
        !          2102:                ent->client->ps.gunframe = 6;
        !          2103: 
        !          2104: //     gi.dprintf("etf rifle %d\n", ent->client->ps.gunframe);
        !          2105: }
        !          2106: 
        !          2107: // pgm - this now uses ent->client->pers.weapon->quantity like all the other weapons
        !          2108: //#define HEATBEAM_AMMO_USE            2               
        !          2109: #define        HEATBEAM_DM_DMG                 15
        !          2110: #define HEATBEAM_SP_DMG                        15
        !          2111: 
        !          2112: void Heatbeam_Fire (edict_t *ent)
        !          2113: {
        !          2114:        vec3_t          start;
        !          2115:        vec3_t          forward, right, up;
        !          2116:        vec3_t          offset;
        !          2117:        int                     damage;
        !          2118:        int                     kick;
        !          2119: 
        !          2120:        // for comparison, the hyperblaster is 15/20
        !          2121:        // jim requested more damage, so try 15/15 --- PGM 07/23/98
        !          2122:        if (deathmatch->value)
        !          2123:                damage = HEATBEAM_DM_DMG;
        !          2124:        else
        !          2125:                damage = HEATBEAM_SP_DMG;
        !          2126: 
        !          2127:        if (deathmatch->value)  // really knock 'em around in deathmatch
        !          2128:                kick = 75;
        !          2129:        else
        !          2130:                kick = 30;
        !          2131: 
        !          2132: //     if(ent->client->pers.inventory[ent->client->ammo_index] < HEATBEAM_AMMO_USE)
        !          2133: //     {
        !          2134: //             NoAmmoWeaponChange (ent);
        !          2135: //             return;
        !          2136: //     }
        !          2137: 
        !          2138:        ent->client->ps.gunframe++;
        !          2139:        ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_beamer2/tris.md2");
        !          2140: 
        !          2141:        if (is_quad)
        !          2142:        {
        !          2143:                damage *= damage_multiplier;
        !          2144:                kick *= damage_multiplier;
        !          2145:        }
        !          2146: 
        !          2147:        VectorClear (ent->client->kick_origin);
        !          2148:        VectorClear (ent->client->kick_angles);
        !          2149: 
        !          2150:        // get start / end positions
        !          2151:        AngleVectors (ent->client->v_angle, forward, right, up);
        !          2152: 
        !          2153: // This offset is the "view" offset for the beam start (used by trace)
        !          2154:        
        !          2155:        VectorSet(offset, 7, 2, ent->viewheight-3);
        !          2156:        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
        !          2157: 
        !          2158:        // This offset is the entity offset
        !          2159:        VectorSet(offset, 2, 7, -3);
        !          2160: 
        !          2161:        fire_heat (ent, start, forward, offset, damage, kick, false);
        !          2162: 
        !          2163:        // send muzzle flash
        !          2164:        gi.WriteByte (svc_muzzleflash);
        !          2165:        gi.WriteShort (ent-g_edicts);
        !          2166:        gi.WriteByte (MZ_HEATBEAM | is_silenced);
        !          2167:        gi.multicast (ent->s.origin, MULTICAST_PVS);
        !          2168: 
        !          2169:        PlayerNoise(ent, start, PNOISE_WEAPON);
        !          2170: 
        !          2171:        if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
        !          2172:                ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity;
        !          2173: 
        !          2174: }
        !          2175: 
        !          2176: void Weapon_Heatbeam (edict_t *ent)
        !          2177: {
        !          2178: //     static int      pause_frames[]  = {38, 43, 51, 61, 0};
        !          2179: //     static int      fire_frames[]   = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0};
        !          2180:        static int      pause_frames[]  = {35, 0};
        !          2181: //     static int      fire_frames[]   = {9, 0};
        !          2182:        static int      fire_frames[]   = {9, 10, 11, 12, 0};
        !          2183: //     static int      attack_index;
        !          2184: //     static int  off_model, on_model;
        !          2185: 
        !          2186: //     if ((g_showlogic) && (g_showlogic->value)) {
        !          2187: //             gi.dprintf ("Frame %d, skin %d\n", ent->client->ps.gunframe, ent->client->ps.gunskin);
        !          2188: //     }
        !          2189:        
        !          2190: //     if (!attack_index)
        !          2191: //     {
        !          2192: //             attack_index = gi.soundindex ("weapons/bfg__l1a.wav");
        !          2193: //             off_model = gi.modelindex ("models/weapons/v_beamer/tris.md2");
        !          2194: //             on_model = gi.modelindex ("models/weapons/v_beamer2/tris.md2");
        !          2195:                //ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model);
        !          2196: //     }
        !          2197: 
        !          2198:        if (ent->client->weaponstate == WEAPON_FIRING)
        !          2199:        {
        !          2200: //             ent->client->weapon_sound = attack_index;
        !          2201:                ent->client->weapon_sound = gi.soundindex ("weapons/bfg__l1a.wav");
        !          2202:                if ((ent->client->pers.inventory[ent->client->ammo_index] >= 2) && ((ent->client->buttons) & BUTTON_ATTACK))
        !          2203:                {
        !          2204: //                     if(ent->client->ps.gunframe >= 9 && ((ent->client->buttons) & BUTTON_ATTACK))
        !          2205: //                     if(ent->client->ps.gunframe >= 12 && ((ent->client->buttons) & BUTTON_ATTACK))
        !          2206:                        if(ent->client->ps.gunframe >= 13)
        !          2207:                        {
        !          2208:                                ent->client->ps.gunframe = 9;
        !          2209: //                             ent->client->ps.gunframe = 8;
        !          2210: //                             ent->client->ps.gunskin = 0;
        !          2211: //                             ent->client->ps.gunindex = on_model;
        !          2212:                                ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_beamer2/tris.md2");
        !          2213:                        }
        !          2214:                        else
        !          2215:                        {
        !          2216: //                             ent->client->ps.gunskin = 1;
        !          2217: //                             ent->client->ps.gunindex = on_model;
        !          2218:                                ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_beamer2/tris.md2");
        !          2219:                        }
        !          2220:                }
        !          2221:                else
        !          2222:                {
        !          2223: //                     ent->client->ps.gunframe = 10;
        !          2224:                        ent->client->ps.gunframe = 13;
        !          2225: //                     ent->client->ps.gunskin = 1;
        !          2226: //                     ent->client->ps.gunindex = off_model;
        !          2227:                        ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_beamer/tris.md2");
        !          2228:                }
        !          2229:        }
        !          2230:        else
        !          2231:        {
        !          2232: //             ent->client->ps.gunskin = 1;
        !          2233: //             ent->client->ps.gunindex = off_model;
        !          2234:                ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_beamer/tris.md2");
        !          2235:                ent->client->weapon_sound = 0;
        !          2236:        }
        !          2237: 
        !          2238: //     Weapon_Generic (ent, 8, 9, 39, 44, pause_frames, fire_frames, Heatbeam_Fire);
        !          2239:        Weapon_Generic (ent, 8, 12, 39, 44, pause_frames, fire_frames, Heatbeam_Fire);
        !          2240: }

unix.superglobalmegacorp.com

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