diff options
author | Tim Angus <tim@ngus.net> | 2004-01-05 02:25:11 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2004-01-05 02:25:11 +0000 |
commit | 77eec9985622a5f029c5647b83b274c561448f3d (patch) | |
tree | ae5265ce761395e5801494c2b5061be48de2440d /src | |
parent | 5fbfe75aa0cdf3a38b0e30a23156fa5affc33996 (diff) |
* Added shotgun
* Fixed particle system destruction bug with muzzle systems
* Fixed armoury retriggering bug
Diffstat (limited to 'src')
-rw-r--r-- | src/cgame/cg_event.c | 5 | ||||
-rw-r--r-- | src/cgame/cg_local.h | 1 | ||||
-rw-r--r-- | src/cgame/cg_weapons.c | 177 | ||||
-rw-r--r-- | src/game/bg_misc.c | 117 | ||||
-rw-r--r-- | src/game/bg_public.h | 13 | ||||
-rw-r--r-- | src/game/g_cmds.c | 51 | ||||
-rw-r--r-- | src/game/g_weapon.c | 63 | ||||
-rw-r--r-- | src/game/tremulous.h | 10 | ||||
-rw-r--r-- | src/ui/ui_main.c | 8 |
9 files changed, 284 insertions, 161 deletions
diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c index 83d95424..4833346d 100644 --- a/src/cgame/cg_event.c +++ b/src/cgame/cg_event.c @@ -736,6 +736,11 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qtrue, es->eventParm ); break; + case EV_SHOTGUN: + DEBUGNAME( "EV_SHOTGUN" ); + CG_ShotgunFire( es ); + break; + case EV_GENERAL_SOUND: DEBUGNAME( "EV_GENERAL_SOUND" ); if( cgs.gameSounds[ es->eventParm ] ) diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index b9df770d..2dd28bf2 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -1607,6 +1607,7 @@ void CG_MissileHitWall( weapon_t weapon, weaponMode_t weaponMode, int cli vec3_t origin, vec3_t dir, impactSound_t soundType ); void CG_MissileHitPlayer( weapon_t weapon, weaponMode_t weaponMode, vec3_t origin, vec3_t dir, int entityNum ); void CG_Bullet( vec3_t origin, int sourceEntityNum, vec3_t normal, qboolean flesh, int fleshEntityNum ); +void CG_ShotgunFire( entityState_t *es ); void CG_TeslaTrail( vec3_t start, vec3_t end, int srcENum, int destENum ); void CG_AlienZap( vec3_t start, vec3_t end, int srcENum, int destENum ); diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c index 4f5235b2..9af1a76b 100644 --- a/src/cgame/cg_weapons.c +++ b/src/cgame/cg_weapons.c @@ -90,6 +90,75 @@ static void CG_MachineGunEjectBrass( centity_t *cent ) /* ========================== +CG_ShotgunEjectBrass +========================== +*/ +static void CG_ShotgunEjectBrass( centity_t *cent ) +{ + localEntity_t *le; + refEntity_t *re; + vec3_t velocity, xvelocity; + vec3_t offset, xoffset; + vec3_t v[ 3 ]; + float waterScale = 1.0f; + + if( cg_brassTime.integer <= 0 ) + return; + + le = CG_AllocLocalEntity( ); + re = &le->refEntity; + + velocity[ 0 ] = 60 + 60 * crandom( ); + velocity[ 1 ] = 40 + 10 * crandom( ); + velocity[ 2 ] = 100 + 50 * crandom( ); + + le->leType = LE_FRAGMENT; + le->startTime = cg.time; + le->endTime = le->startTime + cg_brassTime.integer * 3 + cg_brassTime.integer * random( ); + + le->pos.trType = TR_GRAVITY; + le->pos.trTime = cg.time; + + AnglesToAxis( cent->lerpAngles, v ); + + offset[ 0 ] = 8; + offset[ 1 ] = 0; + offset[ 2 ] = 24; + + xoffset[ 0 ] = offset[ 0 ] * v[ 0 ][ 0 ] + offset[ 1 ] * v[ 1 ][ 0 ] + offset[ 2 ] * v[ 2 ][ 0 ]; + xoffset[ 1 ] = offset[ 0 ] * v[ 0 ][ 1 ] + offset[ 1 ] * v[ 1 ][ 1 ] + offset[ 2 ] * v[ 2 ][ 1 ]; + xoffset[ 2 ] = offset[ 0 ] * v[ 0 ][ 2 ] + offset[ 1 ] * v[ 1 ][ 2 ] + offset[ 2 ] * v[ 2 ][ 2 ]; + VectorAdd( cent->lerpOrigin, xoffset, re->origin ); + VectorCopy( re->origin, le->pos.trBase ); + + if( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) + waterScale = 0.10f; + + xvelocity[ 0 ] = velocity[ 0 ] * v[ 0 ][ 0 ] + velocity[ 1 ] * v[ 1 ][ 0 ] + velocity[ 2 ] * v[ 2 ][ 0 ]; + xvelocity[ 1 ] = velocity[ 0 ] * v[ 0 ][ 1 ] + velocity[ 1 ] * v[ 1 ][ 1 ] + velocity[ 2 ] * v[ 2 ][ 1 ]; + xvelocity[ 2 ] = velocity[ 0 ] * v[ 0 ][ 2 ] + velocity[ 1 ] * v[ 1 ][ 2 ] + velocity[ 2 ] * v[ 2 ][ 2 ]; + VectorScale( xvelocity, waterScale, le->pos.trDelta ); + + AxisCopy( axisDefault, re->axis ); + re->hModel = cgs.media.shotgunBrassModel; + le->bounceFactor = 0.3f; + + le->angles.trType = TR_LINEAR; + le->angles.trTime = cg.time; + le->angles.trBase[ 0 ] = rand( )&31; + le->angles.trBase[ 1 ] = rand( )&31; + le->angles.trBase[ 2 ] = rand( )&31; + le->angles.trDelta[ 0 ] = 1; + le->angles.trDelta[ 1 ] = 0.5; + le->angles.trDelta[ 2 ] = 0; + + le->leFlags = LEF_TUMBLE; + le->leBounceSoundType = LEBS_BRASS; + le->leMarkType = LEMT_NONE; +} + +/* +========================== CG_TeslaTrail ========================== */ @@ -758,6 +827,10 @@ void CG_RegisterWeapon( int weaponNum ) case WP_CHAINGUN: weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass; break; + + case WP_SHOTGUN: + weaponInfo->ejectBrassFunc = CG_ShotgunEjectBrass; + break; } } @@ -1032,13 +1105,10 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent CG_SetParticleSystemTag( cent->muzzlePS, gun, weapon->weaponModel, "tag_flash" ); } - //FIXME: this leaves open the possibility for keep a persistent muzzle system going - // by hopping between firing buttons -- currently nothing with a persistent - // muzzle system has multiple fire modes however //if the PS is infinite disable it when not firing - if( !( cent->currentState.eFlags & EF_FIRING ) && - !( cent->currentState.eFlags & EF_FIRING2 ) && - !( cent->currentState.eFlags & EF_FIRING3 ) && + if( ( ( !( cent->currentState.eFlags & EF_FIRING ) && weaponMode == WPM_PRIMARY ) || + ( !( cent->currentState.eFlags & EF_FIRING2 ) && weaponMode == WPM_SECONDARY ) || + ( !( cent->currentState.eFlags & EF_FIRING3 ) && weaponMode == WPM_TERTIARY ) ) && CG_IsParticleSystemInfinite( cent->muzzlePS ) ) { CG_DestroyParticleSystem( cent->muzzlePS ); @@ -1845,7 +1915,6 @@ Renders bullet effects. void CG_Bullet( vec3_t end, int sourceEntityNum, vec3_t normal, qboolean flesh, int fleshEntityNum ) { trace_t trace; - int sourceContentType, destContentType; vec3_t start; // if the shooter is currently valid, calc a source point and possibly @@ -1854,26 +1923,8 @@ void CG_Bullet( vec3_t end, int sourceEntityNum, vec3_t normal, qboolean flesh, { if( CG_CalcMuzzlePoint( sourceEntityNum, start ) ) { - sourceContentType = trap_CM_PointContents( start, 0 ); - destContentType = trap_CM_PointContents( end, 0 ); - - // do a complete bubble trail if necessary - if( ( sourceContentType == destContentType ) && ( sourceContentType & CONTENTS_WATER ) ) - CG_BubbleTrail( start, end, 32 ); + CG_BubbleTrail( start, end, 32 ); - // bubble trail from water into air - else if( ( sourceContentType & CONTENTS_WATER ) ) - { - trap_CM_BoxTrace( &trace, end, start, NULL, NULL, 0, CONTENTS_WATER ); - CG_BubbleTrail( start, trace.endpos, 32 ); - } - // bubble trail from air into water - else if( ( destContentType & CONTENTS_WATER ) ) - { - trap_CM_BoxTrace( &trace, start, end, NULL, NULL, 0, CONTENTS_WATER ); - CG_BubbleTrail( trace.endpos, end, 32 ); - } - // draw a tracer if( random( ) < cg_tracerChance.value ) CG_Tracer( start, end ); @@ -1886,3 +1937,77 @@ void CG_Bullet( vec3_t end, int sourceEntityNum, vec3_t normal, qboolean flesh, else CG_MissileHitWall( WP_MACHINEGUN, WPM_PRIMARY, 0, end, normal, IMPACTSOUND_DEFAULT ); } + +/* +============================================================================ + +SHOTGUN TRACING + +============================================================================ +*/ + +/* +================ +CG_ShotgunPattern + +Perform the same traces the server did to locate the +hit splashes +================ +*/ +static void CG_ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, int otherEntNum ) +{ + int i; + float r, u; + vec3_t end; + vec3_t forward, right, up; + trace_t tr; + + // derive the right and up vectors from the forward vector, because + // the client won't have any other information + VectorNormalize2( origin2, forward ); + PerpendicularVector( right, forward ); + CrossProduct( forward, right, up ); + + // generate the "random" spread pattern + for( i = 0; i < SHOTGUN_PELLETS; i++ ) + { + r = Q_crandom( &seed ) * SHOTGUN_SPREAD * 16; + u = Q_crandom( &seed ) * SHOTGUN_SPREAD * 16; + VectorMA( origin, 8192 * 16, forward, end ); + VectorMA( end, r, right, end ); + VectorMA( end, u, up, end ); + + CG_Trace( &tr, origin, NULL, NULL, end, otherEntNum, MASK_SHOT ); + CG_BubbleTrail( origin, end, 32 ); + + if( !( tr.surfaceFlags & SURF_NOIMPACT ) ) + { + if( cg_entities[ tr.entityNum ].currentState.eType == ET_PLAYER ) + CG_MissileHitPlayer( WP_SHOTGUN, WPM_PRIMARY, tr.endpos, tr.plane.normal, tr.entityNum ); + else if( tr.surfaceFlags & SURF_METALSTEPS ) + CG_MissileHitWall( WP_SHOTGUN, WPM_PRIMARY, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_METAL ); + else + CG_MissileHitWall( WP_SHOTGUN, WPM_PRIMARY, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_DEFAULT ); + } + } +} + +/* +============== +CG_ShotgunFire +============== +*/ +void CG_ShotgunFire( entityState_t *es ) +{ + vec3_t up; + vec3_t v; + int contents; + + VectorSubtract( es->origin2, es->pos.trBase, v ); + VectorNormalize( v ); + VectorScale( v, 32, v ); + VectorAdd( es->pos.trBase, v, v ); + + CG_ShotgunPattern( es->pos.trBase, es->origin2, es->eventParm, es->otherEntityNum ); +} + diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index 185d58b7..aea70b2b 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -2852,6 +2852,28 @@ weaponAttributes_t bg_weapons[ ] = WUT_HUMANS //WUTeam_t team; }, { + WP_SHOTGUN, //int weaponNum; + SHOTGUN_PRICE, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "shotgun", //char *weaponName; + "Shotgun", //char *weaponHumanName; + SHOTGUN_SHELLS, //int quan; + SHOTGUN_SPAWNCLIPS, //int clips; + SHOTGUN_MAXCLIPS, //int maxClips; + qfalse, //int infiniteAmmo; + qfalse, //int usesEnergy; + SHOTGUN_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + SHOTGUN_RELOAD, //int reloadTime; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qtrue, //qboolean purchasable; + 0, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { WP_FLAMER, //int weaponNum; FLAMER_PRICE, //int price; ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages @@ -3733,9 +3755,6 @@ upgradeAttributes_t bg_upgrades[ ] = "larmour", //char *upgradeName; "Light Armour", //char *upgradeHumanName; "icons/iconu_larmour", - WP_NONE, //weapon_t weaponAmmo; - 0, //int ammo; - 0, //int clips; WUT_HUMANS //WUTeam_t team; }, { @@ -3746,9 +3765,6 @@ upgradeAttributes_t bg_upgrades[ ] = "helmet", //char *upgradeName; "Helmet", //char *upgradeHumanName; "icons/iconu_helmet", - WP_NONE, //weapon_t weaponAmmo; - 0, //int ammo; - 0, //int clips; WUT_HUMANS //WUTeam_t team; }, { @@ -3759,9 +3775,6 @@ upgradeAttributes_t bg_upgrades[ ] = "atoxin", //char *upgradeName; "Anti-toxin", //char *upgradeHumanName; "icons/iconu_atoxin", - WP_NONE, //weapon_t weaponAmmo; - 0, //int ammo; - 0, //int clips; WUT_HUMANS //WUTeam_t team; }, { @@ -3772,9 +3785,6 @@ upgradeAttributes_t bg_upgrades[ ] = "battpack", //char *upgradeName; "Battery Pack", //char *upgradeHumanName; "icons/iconu_battpack", - WP_NONE, //weapon_t weaponAmmo; - 0, //int ammo; - 0, //int clips; WUT_HUMANS //WUTeam_t team; }, { @@ -3785,9 +3795,6 @@ upgradeAttributes_t bg_upgrades[ ] = "jetpack", //char *upgradeName; "Jet Pack", //char *upgradeHumanName; "icons/iconu_jetpack", - WP_NONE, //weapon_t weaponAmmo; - 0, //int ammo; - 0, //int clips; WUT_HUMANS //WUTeam_t team; }, { @@ -3798,48 +3805,16 @@ upgradeAttributes_t bg_upgrades[ ] = "bsuit", //char *upgradeName; "Battlesuit", //char *upgradeHumanName; "icons/iconu_bsuit", - WP_NONE, //weapon_t weaponAmmo; - 0, //int ammo; - 0, //int clips; WUT_HUMANS //WUTeam_t team; }, { - UP_MGCLIP, //int upgradeNum; - MGCLIP_PRICE, //int price; + UP_AMMO, //int upgradeNum; + 0, //int price; ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages SLOT_NONE, //int slots; - "mgclip", //char *upgradeName; - "1 Rifle Clip", //char *upgradeHumanName; + "ammo", //char *upgradeName; + "Ammunition", //char *upgradeHumanName; 0, - WP_MACHINEGUN, //weapon_t weaponAmmo; - 0, //int ammo; - 1, //int clips; - WUT_HUMANS //WUTeam_t team; - }, - { - UP_CGAMMO, //int upgradeNum; - CGAMMO_PRICE, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages - SLOT_NONE, //int slots; - "cgammo", //char *upgradeName; - "Chaingun bullets", //char *upgradeHumanName; - 0, - WP_CHAINGUN, //weapon_t weaponAmmo; - 100, //int ammo; - 0, //int clips; - WUT_HUMANS //WUTeam_t team; - }, - { - UP_GAS, //int upgradeNum; - GAS_PRICE, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages - SLOT_NONE, //int slots; - "gas", //char *upgradeName; - "Flamer gas", //char *upgradeHumanName; - 0, - WP_FLAMER, //weapon_t weaponAmmo; - 200, //int ammo; - 0, //int clips; WUT_HUMANS //WUTeam_t team; } }; @@ -3987,46 +3962,6 @@ char *BG_FindIconForUpgrade( int upgrade ) /* ============== -BG_FindWeaponAmmoForUpgrade -============== -*/ -weapon_t BG_FindWeaponAmmoForUpgrade( int upgrade ) -{ - int i; - - for( i = 0; i < bg_numUpgrades; i++ ) - { - if( bg_upgrades[ i ].upgradeNum == upgrade ) - return bg_upgrades[ i ].weaponAmmo; - } - - return WP_NONE; -} - -/* -============== -BG_FindAmmoForUpgrade -============== -*/ -void BG_FindAmmoForUpgrade( int upgrade, int *ammo, int *clips ) -{ - int i; - - for( i = 0; i < bg_numUpgrades; i++ ) - { - if( bg_upgrades[ i ].upgradeNum == upgrade ) - { - if( ammo != NULL ) - *ammo = bg_upgrades[ i ].ammo; - - if( clips != NULL ) - *clips = bg_upgrades[ i ].clips; - } - } -} - -/* -============== BG_FindTeamForUpgrade ============== */ diff --git a/src/game/bg_public.h b/src/game/bg_public.h index ade44adf..49165a49 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -339,6 +339,7 @@ typedef enum WP_BLASTER, WP_MACHINEGUN, + WP_SHOTGUN, WP_CHAINGUN, WP_FLAMER, WP_MASS_DRIVER, @@ -373,9 +374,7 @@ typedef enum UP_JETPACK, UP_BATTLESUIT, - UP_MGCLIP, - UP_CGAMMO, - UP_GAS, + UP_AMMO, UP_NUM_UPGRADES } upgrade_t; @@ -521,6 +520,8 @@ typedef enum EV_BULLET_HIT_FLESH, EV_BULLET_HIT_WALL, + EV_SHOTGUN, + EV_MISSILE_HIT, EV_MISSILE_MISS, EV_MISSILE_MISS_METAL, @@ -1045,10 +1046,6 @@ typedef struct char *icon; - weapon_t weaponAmmo; - int ammo; - int clips; - WUTeam_t team; } upgradeAttributes_t; @@ -1164,8 +1161,6 @@ char *BG_FindNameForUpgrade( int upgrade ); int BG_FindUpgradeNumForName( char *name ); char *BG_FindHumanNameForUpgrade( int upgrade ); char *BG_FindIconForUpgrade( int upgrade ); -weapon_t BG_FindWeaponAmmoForBuildable( int upgrade ); -void BG_FindAmmoForUpgrade( int upgrade, int *ammo, int *clips ); WUTeam_t BG_FindTeamForUpgrade( int upgrade ); // content masks diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index 6bc84ed9..3662a8ab 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -1338,7 +1338,6 @@ void Cmd_Buy_f( gentity_t *ent ) } else if( upgrade != UP_NONE ) { - int maxAmmo, newAmmo, newClips; weapon_t weaponAmmo; //already got this? @@ -1382,33 +1381,11 @@ void Cmd_Buy_f( gentity_t *ent ) return; } - BG_FindAmmoForUpgrade( upgrade, &newAmmo, &newClips ); - - if( newAmmo || newClips ) - { - //get current ammo for the weapon in question - weaponAmmo = BG_FindWeaponAmmoForUpgrade( upgrade ); - BG_unpackAmmoArray( weaponAmmo, ent->client->ps.ammo, ent->client->ps.powerups, - &quan, &clips, &maxClips ); + weaponAmmo = ent->client->ps.weapon; - BG_FindAmmoForWeapon( weaponAmmo, &maxAmmo, NULL, NULL ); - - //this ammo package would exceed max ammo - if( clips + newClips > maxClips ) - { - //FIXME: different dialog? - G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOSLOTS ); - return; - } - else - clips += newClips; - - if( quan + newAmmo > maxAmmo ) - quan = maxAmmo; - else - quan += newAmmo; - - //updata ammo count + if( upgrade == UP_AMMO && !BG_FindUsesEnergyForWeapon( weaponAmmo ) ) + { + BG_FindAmmoForWeapon( weaponAmmo, &quan, &clips, &maxClips ); BG_packAmmoArray( weaponAmmo, ent->client->ps.ammo, ent->client->ps.powerups, quan, clips, maxClips ); } @@ -1430,8 +1407,14 @@ void Cmd_Buy_f( gentity_t *ent ) if( numItems == 0 ) G_AddEvent( ent, EV_NEXT_WEAPON, ent->client->ps.clientNum ); - //retrigger the armoury menu - ent->client->retriggerArmouryMenu = level.framenum + RAM_FRAMES; + if( trap_Argc( ) >= 2 ) + { + trap_Argv( 2, s, sizeof( s ) ); + + //retrigger the armoury menu + if( !Q_stricmp( s, "retrigger" ) ) + ent->client->retriggerArmouryMenu = level.framenum + RAM_FRAMES; + } //update ClientInfo ClientUserinfoChanged( ent->client->ps.clientNum ); @@ -1506,8 +1489,14 @@ void Cmd_Sell_f( gentity_t *ent ) else trap_SendServerCommand( ent-g_entities, va( "print \"Unknown item\n\"" ) ); - //retrigger the armoury menu - ent->client->retriggerArmouryMenu = level.framenum + RAM_FRAMES; + if( trap_Argc( ) >= 2 ) + { + trap_Argv( 2, s, sizeof( s ) ); + + //retrigger the armoury menu + if( !Q_stricmp( s, "retrigger" ) ) + ent->client->retriggerArmouryMenu = level.framenum + RAM_FRAMES; + } //update ClientInfo ClientUserinfoChanged( ent->client->ps.clientNum ); diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c index 4dd1d67e..107128b5 100644 --- a/src/game/g_weapon.c +++ b/src/game/g_weapon.c @@ -159,6 +159,66 @@ void bulletFire( gentity_t *ent, float spread, int damage, int mod ) /* ====================================================================== +SHOTGUN + +====================================================================== +*/ + +// this should match CG_ShotgunPattern +void ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, gentity_t *ent ) +{ + int i; + float r, u; + vec3_t end; + vec3_t forward, right, up; + trace_t tr; + gentity_t *traceEnt; + + // derive the right and up vectors from the forward vector, because + // the client won't have any other information + VectorNormalize2( origin2, forward ); + PerpendicularVector( right, forward ); + CrossProduct( forward, right, up ); + + // generate the "random" spread pattern + for( i = 0; i < SHOTGUN_PELLETS; i++ ) + { + r = Q_crandom( &seed ) * SHOTGUN_SPREAD * 16; + u = Q_crandom( &seed ) * SHOTGUN_SPREAD * 16; + VectorMA( origin, 8192 * 16, forward, end ); + VectorMA( end, r, right, end ); + VectorMA( end, u, up, end ); + + trap_Trace( &tr, origin, NULL, NULL, end, ent->s.number, MASK_SHOT ); + traceEnt = &g_entities[ tr.entityNum ]; + + // send bullet impact + if( !( tr.surfaceFlags & SURF_NOIMPACT ) ) + { + if( traceEnt->takedamage ) + G_Damage( traceEnt, ent, ent, forward, tr.endpos, SHOTGUN_DMG, 0, MOD_SHOTGUN ); + } + } +} + + +void shotgunFire( gentity_t *ent ) +{ + gentity_t *tent; + + // send shotgun blast + tent = G_TempEntity( muzzle, EV_SHOTGUN ); + VectorScale( forward, 4096, tent->s.origin2 ); + SnapVector( tent->s.origin2 ); + tent->s.eventParm = rand() & 255; // seed for spread pattern + tent->s.otherEntityNum = ent->s.number; + + ShotgunPattern( tent->s.pos.trBase, tent->s.origin2, tent->s.eventParm, ent ); +} + +/* +====================================================================== + MASS DRIVER ====================================================================== @@ -1120,6 +1180,9 @@ void FireWeapon( gentity_t *ent ) case WP_MACHINEGUN: bulletFire( ent, RIFLE_SPREAD, RIFLE_DMG, MOD_MACHINEGUN ); break; + case WP_SHOTGUN: + shotgunFire( ent ); + break; case WP_CHAINGUN: bulletFire( ent, CHAINGUN_SPREAD, CHAINGUN_DMG, MOD_CHAINGUN ); break; diff --git a/src/game/tremulous.h b/src/game/tremulous.h index ca7c48d8..7694887d 100644 --- a/src/game/tremulous.h +++ b/src/game/tremulous.h @@ -291,6 +291,16 @@ #define RIFLE_SPREAD 200 #define RIFLE_DMG HDM(5) +#define SHOTGUN_SHELLS 8 +#define SHOTGUN_PELLETS 8 //used to sync server and client side +#define SHOTGUN_SPAWNCLIPS 3 +#define SHOTGUN_MAXCLIPS 3 +#define SHOTGUN_REPEAT 1200 +#define SHOTGUN_RELOAD 2000 +#define SHOTGUN_PRICE 150 +#define SHOTGUN_SPREAD 900 +#define SHOTGUN_DMG HDM(5) + #define CHAINGUN_BULLETS 300 #define CHAINGUN_REPEAT 50 #define CHAINGUN_PRICE 200 diff --git a/src/ui/ui_main.c b/src/ui/ui_main.c index bf32f974..5a98d881 100644 --- a/src/ui/ui_main.c +++ b/src/ui/ui_main.c @@ -3486,7 +3486,7 @@ static void UI_LoadTremHumanArmouryBuys( ) uiInfo.tremHumanArmouryBuyList[ j ].text = String_Alloc( BG_FindHumanNameForWeapon( i ) ); uiInfo.tremHumanArmouryBuyList[ j ].cmd = - String_Alloc( va( "cmd buy %s", BG_FindNameForWeapon( i ) ) ); + String_Alloc( va( "cmd buy %s retrigger", BG_FindNameForWeapon( i ) ) ); uiInfo.tremHumanArmouryBuyList[ j ].infopane = UI_FindInfoPaneByName( va( "%sitem", BG_FindNameForWeapon( i ) ) ); @@ -3506,7 +3506,7 @@ static void UI_LoadTremHumanArmouryBuys( ) uiInfo.tremHumanArmouryBuyList[ j ].text = String_Alloc( BG_FindHumanNameForUpgrade( i ) ); uiInfo.tremHumanArmouryBuyList[ j ].cmd = - String_Alloc( va( "cmd buy %s", BG_FindNameForUpgrade( i ) ) ); + String_Alloc( va( "cmd buy %s retrigger", BG_FindNameForUpgrade( i ) ) ); uiInfo.tremHumanArmouryBuyList[ j ].infopane = UI_FindInfoPaneByName( va( "%sitem", BG_FindNameForUpgrade( i ) ) ); @@ -3536,7 +3536,7 @@ static void UI_LoadTremHumanArmourySells( ) { uiInfo.tremHumanArmourySellList[ j ].text = String_Alloc( BG_FindHumanNameForWeapon( i ) ); uiInfo.tremHumanArmourySellList[ j ].cmd = - String_Alloc( va( "cmd sell %s", BG_FindNameForWeapon( i ) ) ); + String_Alloc( va( "cmd sell %s retrigger", BG_FindNameForWeapon( i ) ) ); uiInfo.tremHumanArmourySellList[ j ].infopane = UI_FindInfoPaneByName( va( "%sitem", BG_FindNameForWeapon( i ) ) ); @@ -3552,7 +3552,7 @@ static void UI_LoadTremHumanArmourySells( ) { uiInfo.tremHumanArmourySellList[ j ].text = String_Alloc( BG_FindHumanNameForUpgrade( i ) ); uiInfo.tremHumanArmourySellList[ j ].cmd = - String_Alloc( va( "cmd sell %s", BG_FindNameForUpgrade( i ) ) ); + String_Alloc( va( "cmd sell %s retrigger", BG_FindNameForUpgrade( i ) ) ); uiInfo.tremHumanArmourySellList[ j ].infopane = UI_FindInfoPaneByName( va( "%sitem", BG_FindNameForUpgrade( i ) ) ); |