// ATST Main //--------------------------------------------------------- void WP_ATSTMainFire( gentity_t *ent ) //--------------------------------------------------------- { float vel = ATST_MAIN_VEL; // if ( ent->client && (ent->client->ps.eFlags & EF_IN_ATST )) // { // vel = 4500.0f; // } if ( !ent->s.number ) { // player shoots faster vel *= 1.6f; } WP_MissileTargetHint(ent, muzzle, forwardVec); gentity_t *missile = CreateMissile( muzzle, forwardVec, vel, 10000, ent ); missile->classname = "atst_main_proj"; missile->s.weapon = WP_ATST_MAIN; missile->damage = weaponData[WP_ATST_MAIN].damage; missile->dflags = DAMAGE_DEATH_KNOCKBACK|DAMAGE_HEAVY_WEAP_CLASS; missile->methodOfDeath = MOD_ENERGY; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; missile->owner = ent; VectorSet( missile->maxs, ATST_MAIN_SIZE, ATST_MAIN_SIZE, ATST_MAIN_SIZE ); VectorScale( missile->maxs, -1, missile->mins ); }
void WP_FireScepter( gentity_t *ent, qboolean alt_fire ) {//just a straight beam int damage = 1; vec3_t start, end; trace_t tr; gentity_t *traceEnt = NULL, *tent; float shotRange = 8192; qboolean render_impact = qtrue; VectorCopy( muzzle, start ); WP_TraceSetStart( ent, start, vec3_origin, vec3_origin ); WP_MissileTargetHint(ent, start, forwardVec); VectorMA( start, shotRange, forwardVec, end ); gi.trace( &tr, start, NULL, NULL, end, ent->s.number, MASK_SHOT, G2_RETURNONHIT, 10 ); traceEnt = &g_entities[tr.entityNum]; if ( tr.surfaceFlags & SURF_NOIMPACT ) { render_impact = qfalse; } // always render a shot beam, doing this the old way because I don't much feel like overriding the effect. tent = G_TempEntity( tr.endpos, EV_DISRUPTOR_MAIN_SHOT ); tent->svFlags |= SVF_BROADCAST; VectorCopy( muzzle, tent->s.origin2 ); if ( render_impact ) { if ( tr.entityNum < ENTITYNUM_WORLD && traceEnt->takedamage ) { // Create a simple impact type mark that doesn't last long in the world G_PlayEffect( G_EffectIndex( "disruptor/flesh_impact" ), tr.endpos, tr.plane.normal ); int hitLoc = G_GetHitLocFromTrace( &tr, MOD_DISRUPTOR ); G_Damage( traceEnt, ent, ent, forwardVec, tr.endpos, damage, DAMAGE_EXTRA_KNOCKBACK, MOD_DISRUPTOR, hitLoc ); } else { G_PlayEffect( G_EffectIndex( "disruptor/wall_impact" ), tr.endpos, tr.plane.normal ); } } /* shotDist = shotRange * tr.fraction; for ( dist = 0; dist < shotDist; dist += 64 ) { //FIXME: on a really long shot, this could make a LOT of alerts in one frame... VectorMA( start, dist, forwardVec, spot ); AddSightEvent( ent, spot, 256, AEL_DISCOVERED, 50 ); } VectorMA( start, shotDist-4, forwardVec, spot ); AddSightEvent( ent, spot, 256, AEL_DISCOVERED, 50 ); */ }
//--------------------------------------------------------- static void WP_BowcasterAltFire( gentity_t *ent ) //--------------------------------------------------------- { vec3_t start; int damage = weaponData[WP_BOWCASTER].altDamage; VectorCopy( muzzle, start ); WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall WP_MissileTargetHint(ent, start, forwardVec); gentity_t *missile = CreateMissile( start, forwardVec, BOWCASTER_VELOCITY, 10000, ent, qtrue ); missile->classname = "bowcaster_alt_proj"; missile->s.weapon = WP_BOWCASTER; // Do the damages if ( ent->s.number != 0 ) { if ( g_spskill->integer == 0 ) { damage = BOWCASTER_NPC_DAMAGE_EASY; } else if ( g_spskill->integer == 1 ) { damage = BOWCASTER_NPC_DAMAGE_NORMAL; } else { damage = BOWCASTER_NPC_DAMAGE_HARD; } } VectorSet( missile->maxs, BOWCASTER_SIZE, BOWCASTER_SIZE, BOWCASTER_SIZE ); VectorScale( missile->maxs, -1, missile->mins ); // if ( ent->client && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time ) // { // // in overcharge mode, so doing double damage // missile->flags |= FL_OVERCHARGED; // damage *= 2; // } missile->s.eFlags |= EF_BOUNCE; missile->bounceCount = 3; missile->damage = damage; missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_BOWCASTER_ALT; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; missile->splashDamage = weaponData[WP_BOWCASTER].altSplashDamage; missile->splashRadius = weaponData[WP_BOWCASTER].altSplashRadius; }
//--------------------------------------------------------- static void WP_DEMP2_MainFire( gentity_t *ent ) //--------------------------------------------------------- { vec3_t start; int damage = weaponData[WP_DEMP2].damage; VectorCopy( muzzle, start ); WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall WP_MissileTargetHint(ent, start, forwardVec); gentity_t *missile = CreateMissile( start, forwardVec, DEMP2_VELOCITY, 10000, ent ); missile->classname = "demp2_proj"; missile->s.weapon = WP_DEMP2; // Do the damages if ( ent->s.number != 0 ) { if ( g_spskill->integer == 0 ) { damage = DEMP2_NPC_DAMAGE_EASY; } else if ( g_spskill->integer == 1 ) { damage = DEMP2_NPC_DAMAGE_NORMAL; } else { damage = DEMP2_NPC_DAMAGE_HARD; } } VectorSet( missile->maxs, DEMP2_SIZE, DEMP2_SIZE, DEMP2_SIZE ); VectorScale( missile->maxs, -1, missile->mins ); // if ( ent->client && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time ) // { // // in overcharge mode, so doing double damage // missile->flags |= FL_OVERCHARGED; // damage *= 2; // } missile->damage = damage; missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_DEMP2; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; // we don't want it to ever bounce missile->bounceCount = 0; }
//--------------------------------------------------------- static void WP_DEMP2_AltFire( gentity_t *ent ) //--------------------------------------------------------- { int damage = weaponData[WP_REPEATER].altDamage; int count; vec3_t start; trace_t tr; VectorCopy( muzzle, start ); WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall count = ( level.time - ent->client->ps.weaponChargeTime ) / DEMP2_CHARGE_UNIT; if ( count < 1 ) { count = 1; } else if ( count > 3 ) { count = 3; } damage *= ( 1 + ( count * ( count - 1 )));// yields damage of 12,36,84...gives a higher bonus for longer charge // the shot can travel a whopping 4096 units in 1 second. Note that the shot will auto-detonate at 4096 units...we'll see if this looks cool or not WP_MissileTargetHint(ent, start, forwardVec); gentity_t *missile = CreateMissile( start, forwardVec, DEMP2_ALT_RANGE, 1000, ent, qtrue ); // letting it know what the charge size is. missile->count = count; // missile->speed = missile->nextthink; VectorCopy( tr.plane.normal, missile->pos1 ); missile->classname = "demp2_alt_proj"; missile->s.weapon = WP_DEMP2; missile->e_ThinkFunc = thinkF_DEMP2_AltDetonate; missile->splashDamage = missile->damage = damage; missile->splashMethodOfDeath = missile->methodOfDeath = MOD_DEMP2_ALT; missile->splashRadius = weaponData[WP_DEMP2].altSplashRadius; missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; // we don't want it to ever bounce missile->bounceCount = 0; }
// Emplaced Gun //--------------------------------------------------------- void WP_EmplacedFire( gentity_t *ent ) //--------------------------------------------------------- { float damage = weaponData[WP_EMPLACED_GUN].damage * ( ent->NPC ? 0.1f : 1.0f ); float vel = EMPLACED_VEL * ( ent->NPC ? 0.4f : 1.0f ); WP_MissileTargetHint(ent, muzzle, forwardVec); gentity_t *missile = CreateMissile( muzzle, forwardVec, vel, 10000, ent ); missile->classname = "emplaced_proj"; missile->s.weapon = WP_EMPLACED_GUN; missile->damage = damage; missile->dflags = DAMAGE_DEATH_KNOCKBACK | DAMAGE_HEAVY_WEAP_CLASS; missile->methodOfDeath = MOD_EMPLACED; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; // do some weird switchery on who the real owner is, we do this so the projectiles don't hit the gun object if ( ent && ent->client && !(ent->client->ps.eFlags&EF_LOCKED_TO_WEAPON) ) { missile->owner = ent; } else { missile->owner = ent->owner; } if ( missile->owner->e_UseFunc == useF_eweb_use ) { missile->alt_fire = qtrue; } VectorSet( missile->maxs, EMPLACED_SIZE, EMPLACED_SIZE, EMPLACED_SIZE ); VectorScale( missile->maxs, -1, missile->mins ); // alternate muzzles ent->fxID = !ent->fxID; }
//--------------------------------------------------------- void WP_FireTuskenRifle( gentity_t *ent ) //--------------------------------------------------------- { vec3_t start; VectorCopy( muzzle, start ); WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall if ( !(ent->client->ps.forcePowersActive&(1<<FP_SEE)) || ent->client->ps.forcePowerLevel[FP_SEE] < FORCE_LEVEL_2 ) {//force sight 2+ gives perfect aim //FIXME: maybe force sight level 3 autoaims some? if ( ent->NPC && ent->NPC->currentAim < 5 ) { vec3_t angs; vectoangles( forwardVec, angs ); if ( ent->client->NPC_class == CLASS_IMPWORKER ) {//*sigh*, hack to make impworkers less accurate without affecteing imperial officer accuracy angs[PITCH] += ( crandom() * (BLASTER_NPC_SPREAD+(6-ent->NPC->currentAim)*0.25f));//was 0.5f angs[YAW] += ( crandom() * (BLASTER_NPC_SPREAD+(6-ent->NPC->currentAim)*0.25f));//was 0.5f } else { angs[PITCH] += ( crandom() * ((5-ent->NPC->currentAim)*0.25f) ); angs[YAW] += ( crandom() * ((5-ent->NPC->currentAim)*0.25f) ); } AngleVectors( angs, forwardVec, NULL, NULL ); } } WP_MissileTargetHint(ent, start, forwardVec); gentity_t *missile = CreateMissile( start, forwardVec, TUSKEN_RIFLE_VEL, 10000, ent, qfalse ); missile->classname = "trifle_proj"; missile->s.weapon = WP_TUSKEN_RIFLE; if ( ent->s.number < MAX_CLIENTS || g_spskill->integer >= 2 ) { missile->damage = TUSKEN_RIFLE_DAMAGE_HARD; } else if ( g_spskill->integer > 0 ) { missile->damage = TUSKEN_RIFLE_DAMAGE_MEDIUM; } else { missile->damage = TUSKEN_RIFLE_DAMAGE_EASY; } missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_BRYAR;//??? missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; // we don't want it to bounce forever missile->bounceCount = 8; }
//--------------------------------------------------------- static void WP_BowcasterMainFire( gentity_t *ent ) //--------------------------------------------------------- { int damage = weaponData[WP_BOWCASTER].damage, count; float vel; vec3_t angs, dir, start; gentity_t *missile; VectorCopy( muzzle, start ); WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall // Do the damages if ( ent->s.number != 0 ) { if ( g_spskill->integer == 0 ) { damage = BOWCASTER_NPC_DAMAGE_EASY; } else if ( g_spskill->integer == 1 ) { damage = BOWCASTER_NPC_DAMAGE_NORMAL; } else { damage = BOWCASTER_NPC_DAMAGE_HARD; } } count = ( level.time - ent->client->ps.weaponChargeTime ) / BOWCASTER_CHARGE_UNIT; if ( count < 1 ) { count = 1; } else if ( count > 5 ) { count = 5; } if ( !(count & 1 )) { // if we aren't odd, knock us down a level count--; } // if ( ent->client && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time ) // { // // in overcharge mode, so doing double damage // damage *= 2; // } WP_MissileTargetHint(ent, start, forwardVec); for ( int i = 0; i < count; i++ ) { // create a range of different velocities vel = BOWCASTER_VELOCITY * ( crandom() * BOWCASTER_VEL_RANGE + 1.0f ); vectoangles( forwardVec, angs ); if ( !(ent->client->ps.forcePowersActive&(1<<FP_SEE)) || ent->client->ps.forcePowerLevel[FP_SEE] < FORCE_LEVEL_2 ) {//force sight 2+ gives perfect aim //FIXME: maybe force sight level 3 autoaims some? // add some slop to the fire direction angs[PITCH] += crandom() * BOWCASTER_ALT_SPREAD * 0.2f; angs[YAW] += ((i+0.5f) * BOWCASTER_ALT_SPREAD - count * 0.5f * BOWCASTER_ALT_SPREAD ); if ( ent->NPC ) { angs[PITCH] += ( crandom() * (BLASTER_NPC_SPREAD+(6-ent->NPC->currentAim)*0.25f) ); angs[YAW] += ( crandom() * (BLASTER_NPC_SPREAD+(6-ent->NPC->currentAim)*0.25f) ); } } AngleVectors( angs, dir, NULL, NULL ); missile = CreateMissile( start, dir, vel, 10000, ent ); missile->classname = "bowcaster_proj"; missile->s.weapon = WP_BOWCASTER; VectorSet( missile->maxs, BOWCASTER_SIZE, BOWCASTER_SIZE, BOWCASTER_SIZE ); VectorScale( missile->maxs, -1, missile->mins ); // if ( ent->client && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time ) // { // missile->flags |= FL_OVERCHARGED; // } missile->damage = damage; missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_BOWCASTER; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; missile->splashDamage = weaponData[WP_BOWCASTER].splashDamage; missile->splashRadius = weaponData[WP_BOWCASTER].splashRadius; // we don't want it to bounce missile->bounceCount = 0; ent->client->sess.missionStats.shotsFired++; } }
//--------------------------------------------------------- void WP_FireBryarPistol( gentity_t *ent, qboolean alt_fire ) //--------------------------------------------------------- { vec3_t start; int damage = !alt_fire ? weaponData[WP_BRYAR_PISTOL].damage : weaponData[WP_BRYAR_PISTOL].altDamage; VectorCopy( muzzle, start ); WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall if ( !(ent->client->ps.forcePowersActive&(1<<FP_SEE)) || ent->client->ps.forcePowerLevel[FP_SEE] < FORCE_LEVEL_2 ) {//force sight 2+ gives perfect aim //FIXME: maybe force sight level 3 autoaims some? if ( ent->NPC && ent->NPC->currentAim < 5 ) { vec3_t angs; vectoangles( forwardVec, angs ); if ( ent->client->NPC_class == CLASS_IMPWORKER ) {//*sigh*, hack to make impworkers less accurate without affecteing imperial officer accuracy angs[PITCH] += ( crandom() * (BLASTER_NPC_SPREAD+(6-ent->NPC->currentAim)*0.25f));//was 0.5f angs[YAW] += ( crandom() * (BLASTER_NPC_SPREAD+(6-ent->NPC->currentAim)*0.25f));//was 0.5f } else { angs[PITCH] += ( crandom() * ((5-ent->NPC->currentAim)*0.25f) ); angs[YAW] += ( crandom() * ((5-ent->NPC->currentAim)*0.25f) ); } AngleVectors( angs, forwardVec, NULL, NULL ); } } WP_MissileTargetHint(ent, start, forwardVec); gentity_t *missile = CreateMissile( start, forwardVec, BRYAR_PISTOL_VEL, 10000, ent, alt_fire ); missile->classname = "bryar_proj"; if ( ent->s.weapon == WP_BLASTER_PISTOL || ent->s.weapon == WP_JAWA ) {//*SIGH*... I hate our weapon system... missile->s.weapon = ent->s.weapon; } else { missile->s.weapon = WP_BRYAR_PISTOL; } if ( alt_fire ) { int count = ( level.time - ent->client->ps.weaponChargeTime ) / BRYAR_CHARGE_UNIT; if ( count < 1 ) { count = 1; } else if ( count > 5 ) { count = 5; } damage *= count; missile->count = count; // this will get used in the projectile rendering code to make a beefier effect } // if ( ent->client && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time ) // { // // in overcharge mode, so doing double damage // missile->flags |= FL_OVERCHARGED; // damage *= 2; // } missile->damage = damage; missile->dflags = DAMAGE_DEATH_KNOCKBACK; if ( alt_fire ) { missile->methodOfDeath = MOD_BRYAR_ALT; } else { missile->methodOfDeath = MOD_BRYAR; } missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; // we don't want it to bounce forever missile->bounceCount = 8; if ( ent->weaponModel[1] > 0 ) {//dual pistols, toggle the muzzle point back and forth between the two pistols each time he fires ent->count = (ent->count)?0:1; } }
//--------------------------------------------------------- void WP_FireNoghriStick( gentity_t *ent ) //--------------------------------------------------------- { vec3_t dir, angs; vectoangles( forwardVec, angs ); if ( !(ent->client->ps.forcePowersActive&(1<<FP_SEE)) || ent->client->ps.forcePowerLevel[FP_SEE] < FORCE_LEVEL_2 ) {//force sight 2+ gives perfect aim //FIXME: maybe force sight level 3 autoaims some? // add some slop to the main-fire direction angs[PITCH] += ( crandom() * (BLASTER_NPC_SPREAD+(6-ent->NPC->currentAim)*0.25f));//was 0.5f angs[YAW] += ( crandom() * (BLASTER_NPC_SPREAD+(6-ent->NPC->currentAim)*0.25f));//was 0.5f } AngleVectors( angs, dir, NULL, NULL ); // FIXME: if temp_org does not have clear trace to inside the bbox, don't shoot! int velocity = 1200; WP_TraceSetStart( ent, muzzle, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall WP_MissileTargetHint(ent, muzzle, dir); gentity_t *missile = CreateMissile( muzzle, dir, velocity, 10000, ent, qfalse ); missile->classname = "noghri_proj"; missile->s.weapon = WP_NOGHRI_STICK; // Do the damages if ( ent->s.number != 0 ) { if ( g_spskill->integer == 0 ) { missile->damage = 1; } else if ( g_spskill->integer == 1 ) { missile->damage = 5; } else { missile->damage = 10; } } // if ( ent->client ) // { // if ( ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time ) // { // // in overcharge mode, so doing double damage // missile->flags |= FL_OVERCHARGED; // damage *= 2; // } // } missile->dflags = DAMAGE_NO_KNOCKBACK; missile->methodOfDeath = MOD_BLASTER; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; missile->splashDamage = 0; missile->splashRadius = 100; missile->splashMethodOfDeath = MOD_GAS; //Hmm: maybe spew gas on impact? }
//--------------------------------------------------------- static void WP_RepeaterAltFire( gentity_t *ent ) //--------------------------------------------------------- { vec3_t start; int damage = weaponData[WP_REPEATER].altDamage; gentity_t *missile = NULL; VectorCopy( muzzle, start ); WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall if ( ent->client && ent->client->NPC_class == CLASS_GALAKMECH ) { missile = CreateMissile( start, ent->client->hiddenDir, ent->client->hiddenDist, 10000, ent, qtrue ); } else { WP_MissileTargetHint(ent, start, forwardVec); missile = CreateMissile( start, forwardVec, REPEATER_ALT_VELOCITY, 10000, ent, qtrue ); } missile->classname = "repeater_alt_proj"; missile->s.weapon = WP_REPEATER; missile->mass = 10; // Do the damages if ( ent->s.number != 0 ) { if ( g_spskill->integer == 0 ) { damage = REPEATER_ALT_NPC_DAMAGE_EASY; } else if ( g_spskill->integer == 1 ) { damage = REPEATER_ALT_NPC_DAMAGE_NORMAL; } else { damage = REPEATER_ALT_NPC_DAMAGE_HARD; } } VectorSet( missile->maxs, REPEATER_ALT_SIZE, REPEATER_ALT_SIZE, REPEATER_ALT_SIZE ); VectorScale( missile->maxs, -1, missile->mins ); missile->s.pos.trType = TR_GRAVITY; missile->s.pos.trDelta[2] += 40.0f; //give a slight boost in the upward direction // if ( ent->client && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time ) // { // // in overcharge mode, so doing double damage // missile->flags |= FL_OVERCHARGED; // damage *= 2; // } missile->damage = damage; missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_REPEATER_ALT; missile->splashMethodOfDeath = MOD_REPEATER_ALT; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; missile->splashDamage = weaponData[WP_REPEATER].altSplashDamage; missile->splashRadius = weaponData[WP_REPEATER].altSplashRadius; // we don't want it to bounce forever missile->bounceCount = 8; }
//--------------------------------------------------------- static void WP_FlechetteMainFire( gentity_t *ent ) //--------------------------------------------------------- { vec3_t fwd, angs, start; gentity_t *missile; float damage = weaponData[WP_FLECHETTE].damage, vel = FLECHETTE_VEL; VectorCopy( muzzle, start ); WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall // If we aren't the player, we will cut the velocity and damage of the shots if ( ent->s.number ) { damage *= 0.75f; vel *= 0.5f; } // if ( ent->client && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time ) // { // // in overcharge mode, so doing double damage // damage *= 2; // } for ( int i = 0; i < FLECHETTE_SHOTS; i++ ) { vectoangles( forwardVec, angs ); if ( i == 0 && ent->s.number == 0 ) { // do nothing on the first shot for the player, this one will hit the crosshairs } else { angs[PITCH] += Q_flrand(-1.0f, 1.0f) * FLECHETTE_SPREAD; angs[YAW] += Q_flrand(-1.0f, 1.0f) * FLECHETTE_SPREAD; } AngleVectors( angs, fwd, NULL, NULL ); WP_MissileTargetHint(ent, start, fwd); missile = CreateMissile( start, fwd, vel, 10000, ent ); missile->classname = "flech_proj"; missile->s.weapon = WP_FLECHETTE; VectorSet( missile->maxs, FLECHETTE_SIZE, FLECHETTE_SIZE, FLECHETTE_SIZE ); VectorScale( missile->maxs, -1, missile->mins ); missile->damage = damage; // if ( ent->client && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time ) // { // missile->flags |= FL_OVERCHARGED; // } missile->dflags = (DAMAGE_DEATH_KNOCKBACK|DAMAGE_EXTRA_KNOCKBACK); missile->methodOfDeath = MOD_FLECHETTE; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; // we don't want it to bounce forever missile->bounceCount = Q_irand(1,2); missile->s.eFlags |= EF_BOUNCE_SHRAPNEL; ent->client->sess.missionStats.shotsFired++; } }
//--------------------------------------------------------- static void WP_DisruptorMainFire( gentity_t *ent ) //--------------------------------------------------------- { int damage = weaponData[WP_DISRUPTOR].damage; qboolean render_impact = qtrue; vec3_t start, end, spot; trace_t tr; gentity_t *traceEnt = NULL, *tent; float dist, shotDist, shotRange = 8192; if ( ent->NPC ) { switch ( g_spskill->integer ) { case 0: damage = DISRUPTOR_NPC_MAIN_DAMAGE_EASY; break; case 1: damage = DISRUPTOR_NPC_MAIN_DAMAGE_MEDIUM; break; case 2: default: damage = DISRUPTOR_NPC_MAIN_DAMAGE_HARD; break; } } VectorCopy( muzzle, start ); WP_TraceSetStart( ent, start, vec3_origin, vec3_origin ); // if ( ent->client && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time ) // { // // in overcharge mode, so doing double damage // damage *= 2; // } WP_MissileTargetHint(ent, start, forwardVec); VectorMA( start, shotRange, forwardVec, end ); int ignore = ent->s.number; int traces = 0; while ( traces < 10 ) {//need to loop this in case we hit a Jedi who dodges the shot gi.trace( &tr, start, NULL, NULL, end, ignore, MASK_SHOT, G2_RETURNONHIT, 0 ); traceEnt = &g_entities[tr.entityNum]; if ( traceEnt && ( traceEnt->s.weapon == WP_SABER || (traceEnt->client && (traceEnt->client->NPC_class == CLASS_BOBAFETT||traceEnt->client->NPC_class == CLASS_REBORN) ) ) ) {//FIXME: need a more reliable way to know we hit a jedi? if ( Jedi_DodgeEvasion( traceEnt, ent, &tr, HL_NONE ) ) {//act like we didn't even hit him VectorCopy( tr.endpos, start ); ignore = tr.entityNum; traces++; continue; } } //a Jedi is not dodging this shot break; } if ( tr.surfaceFlags & SURF_NOIMPACT ) { render_impact = qfalse; } // always render a shot beam, doing this the old way because I don't much feel like overriding the effect. tent = G_TempEntity( tr.endpos, EV_DISRUPTOR_MAIN_SHOT ); tent->svFlags |= SVF_BROADCAST; VectorCopy( muzzle, tent->s.origin2 ); if ( render_impact ) { if ( tr.entityNum < ENTITYNUM_WORLD && traceEnt->takedamage ) { // Create a simple impact type mark that doesn't last long in the world G_PlayEffect( G_EffectIndex( "disruptor/flesh_impact" ), tr.endpos, tr.plane.normal ); if ( traceEnt->client && LogAccuracyHit( traceEnt, ent )) { ent->client->ps.persistant[PERS_ACCURACY_HITS]++; } int hitLoc = G_GetHitLocFromTrace( &tr, MOD_DISRUPTOR ); if ( traceEnt && traceEnt->client && traceEnt->client->NPC_class == CLASS_GALAKMECH ) {//hehe G_Damage( traceEnt, ent, ent, forwardVec, tr.endpos, 3, DAMAGE_DEATH_KNOCKBACK, MOD_DISRUPTOR, hitLoc ); } else { G_Damage( traceEnt, ent, ent, forwardVec, tr.endpos, damage, DAMAGE_DEATH_KNOCKBACK, MOD_DISRUPTOR, hitLoc ); } } else { G_PlayEffect( G_EffectIndex( "disruptor/wall_impact" ), tr.endpos, tr.plane.normal ); } } shotDist = shotRange * tr.fraction; for ( dist = 0; dist < shotDist; dist += 64 ) { //FIXME: on a really long shot, this could make a LOT of alerts in one frame... VectorMA( start, dist, forwardVec, spot ); AddSightEvent( ent, spot, 256, AEL_DISCOVERED, 50 ); } VectorMA( start, shotDist-4, forwardVec, spot ); AddSightEvent( ent, spot, 256, AEL_DISCOVERED, 50 ); }