예제 #1
0
/*
===============
FireWeapon3
===============
*/
void FireWeapon3( gentity_t *ent )
{
	if ( ent->client )
	{
		// set aiming directions
		AngleVectors( ent->client->ps.viewangles, forward, right, up );
		CalcMuzzlePoint( ent, forward, right, up, muzzle );
	}
	else
	{
		AngleVectors( ent->s.angles2, forward, right, up );
		VectorCopy( ent->s.pos.trBase, muzzle );
	}

	// fire the specific weapon
	switch ( ent->s.weapon )
	{
		case WP_ALEVEL3_UPG:
			bounceBallFire( ent );
			break;

		case WP_ABUILD2:
			slowBlobFire( ent );
			break;

		default:
			break;
	}
}
예제 #2
0
파일: g_weapon.c 프로젝트: wtfbbqhax/thz
/*
===============
areaZapFire
===============
*/
void areaZapFire( gentity_t *ent )
{
  trace_t   tr;
  vec3_t    end;
  gentity_t *traceEnt;
  vec3_t    mins, maxs;

  VectorSet( mins, -LEVEL2_AREAZAP_WIDTH, -LEVEL2_AREAZAP_WIDTH, -LEVEL2_AREAZAP_WIDTH );
  VectorSet( maxs, LEVEL2_AREAZAP_WIDTH, LEVEL2_AREAZAP_WIDTH, LEVEL2_AREAZAP_WIDTH );

  // set aiming directions
  AngleVectors( ent->client->ps.viewangles, forward, right, up );

  CalcMuzzlePoint( ent, forward, right, up, muzzle );

  VectorMA( muzzle, LEVEL2_AREAZAP_RANGE, forward, end );

  trap_Trace( &tr, muzzle, mins, maxs, end, ent->s.number, MASK_SHOT );

  if( tr.surfaceFlags & SURF_NOIMPACT )
    return;

  traceEnt = &g_entities[ tr.entityNum ];

  if( ( ( traceEnt->client && traceEnt->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ||
      ( traceEnt->s.eType == ET_BUILDABLE &&
        BG_FindTeamForBuildable( traceEnt->s.modelindex ) == BIT_HUMANS ) ) && traceEnt->health > 0 )
  {
    G_CreateNewZap( ent, traceEnt );
  }
}
예제 #3
0
/*
===============
CheckPounceAttack
===============
*/
qboolean CheckPounceAttack( gentity_t *ent )
{
  trace_t tr;
  gentity_t *traceEnt;
  int damage, timeMax, pounceRange, pounceWidth, payload;

  if( ent->client->pmext.pouncePayload <= 0 )
    return qfalse;

  // In case the goon lands on his target, he get's one shot after landing
  payload = ent->client->pmext.pouncePayload;
  if( !( ent->client->ps.pm_flags & PMF_CHARGE/* || ent->client->ps.weapon == WP_ALEVEL5 */) )
    ent->client->pmext.pouncePayload = 0;

  // Calculate muzzle point
  AngleVectors( ent->client->ps.viewangles, forward, right, up );
  CalcMuzzlePoint( ent, forward, right, up, muzzle );

  // Trace from muzzle to see what we hit
  if( ent->client->ps.weapon == WP_ALEVEL5)
  {
      pounceRange = LEVEL5_POUNCE_RANGE;
      pounceWidth = LEVEL5_POUNCE_WIDTH;
  }
  else
  {
      pounceRange = ent->client->ps.weapon == WP_ALEVEL3 ? LEVEL3_POUNCE_RANGE : LEVEL3_POUNCE_UPG_RANGE;
      pounceWidth = LEVEL3_POUNCE_WIDTH;
  }
  G_WideTrace( &tr, ent, pounceRange, pounceWidth, pounceWidth, &traceEnt );
  if( traceEnt == NULL )
    return qfalse;

  // Send blood impact
  if( traceEnt->takedamage )
    WideBloodSpurt( ent, traceEnt, &tr, MOD_LEVEL3_POUNCE );

  if( !traceEnt->takedamage )
    return qfalse;
    
  // Deal damage
  if( ent->client->ps.weapon == WP_ALEVEL5)
  {
    timeMax = LEVEL5_POUNCE_TIME;
    damage = payload * LEVEL5_POUNCE_DMG / timeMax;
    ent->client->pmext.pouncePayload = 0;
    G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage,
	      DAMAGE_NO_LOCDAMAGE, MOD_LEVEL5_POUNCE );
  }
  else
  {
    timeMax = ent->client->ps.weapon == WP_ALEVEL3 ? LEVEL3_POUNCE_TIME : LEVEL3_POUNCE_TIME_UPG;
    damage = payload * LEVEL3_POUNCE_DMG / timeMax;
    ent->client->pmext.pouncePayload = 0;
    G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage,
	      DAMAGE_NO_LOCDAMAGE, MOD_LEVEL3_POUNCE );
  }
  return qtrue;
}
예제 #4
0
/*
===============
G_MeleeFireCheck
===============
*/
qboolean G_MeleeFireCheck( gentity_t *ent ) {
	trace_t		tr;
	vec3_t		end;
	gentity_t	*tent;
	gentity_t	*traceEnt;

	// only living beeings can attack
	if ( ent->client->ps.stats[STAT_HEALTH] <= 0 ) {
		return qfalse;
	}

	// set aiming directions
	AngleVectors ( ent->client->ps.viewangles, forward, right, up);

	CalcMuzzlePoint ( ent, forward, right, up, muzzle );

	VectorMA (muzzle, 32, forward, end);

	// compensate for lag
	G_CalcLagTimeAndShiftAllClients( ent );

	trap_Trace (&tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT);

    // move the clients back to their proper positions
	if ( level.delagWeapons && ent->client && !(ent->r.svFlags & SVF_BOT) ) {
		G_UnTimeShiftAllClients( ent );
	}

	if ( tr.surfaceFlags & SURF_NOIMPACT ) {
		return qfalse;
	}

	traceEnt = &g_entities[ tr.entityNum ];

	// send blood impact
	if ( traceEnt->takedamage && traceEnt->client ) {
		// compensate for lag effects
		if ( level.delagWeapons && ent->client && !(ent->r.svFlags & SVF_BOT) ) {
			VectorSubtract( traceEnt->client->saved.currentOrigin, traceEnt->r.currentOrigin, end );
			VectorAdd( tr.endpos, end, tr.endpos );
		}
		// snap the endpos to integers, but nudged towards the line
		SnapVectorTowards( tr.endpos, muzzle );

		// create impact entity
		tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_FLESH );
		tent->s.eventParm = traceEnt->s.number;
	}

	if ( !traceEnt->takedamage) {
		return qfalse;
	}

	G_Damage( traceEnt, ent, ent, forward, tr.endpos,
		weLi[WP_SHOCKER].damage, 0, MOD_SHOCKER );

	return qtrue;
}
예제 #5
0
파일: g_weapon.c 프로젝트: wtfbbqhax/thz
/*
===============
CheckGrabAttack
===============
*/
void CheckGrabAttack( gentity_t *ent )
{
  trace_t   tr;
  vec3_t    end, dir;
  gentity_t *traceEnt;

  // set aiming directions
  AngleVectors( ent->client->ps.viewangles, forward, right, up );

  CalcMuzzlePoint( ent, forward, right, up, muzzle );

  VectorMA( muzzle, LEVEL1_GRAB_RANGE, forward, end );

  trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT );
  if( tr.surfaceFlags & SURF_NOIMPACT )
    return;

  traceEnt = &g_entities[ tr.entityNum ];

  if( !traceEnt->takedamage )
    return;

  if( traceEnt->client )
  {
    if( traceEnt->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
      return;

    if( traceEnt->client->ps.stats[ STAT_HEALTH ] <= 0 )
      return;

    if( !( traceEnt->client->ps.stats[ STAT_STATE ] & SS_GRABBED ) )
    {
      AngleVectors( traceEnt->client->ps.viewangles, dir, NULL, NULL );
      traceEnt->client->ps.stats[ STAT_VIEWLOCK ] = DirToByte( dir );

      //event for client side grab effect
      G_AddPredictableEvent( ent, EV_LEV1_GRAB, 0 );
    }

    traceEnt->client->ps.stats[ STAT_STATE ] |= SS_GRABBED;

    if( ent->client->ps.weapon == WP_ALEVEL1 )
      traceEnt->client->grabExpiryTime = level.time + LEVEL1_GRAB_TIME;
    else if( ent->client->ps.weapon == WP_ALEVEL1_UPG )
      traceEnt->client->grabExpiryTime = level.time + LEVEL1_GRAB_U_TIME;
  }
  else if( traceEnt->s.eType == ET_BUILDABLE &&
      traceEnt->s.modelindex == BA_H_MGTURRET )
  {
    if( !traceEnt->lev1Grabbed )
      G_AddPredictableEvent( ent, EV_LEV1_GRAB, 0 );

    traceEnt->lev1Grabbed = qtrue;
    traceEnt->lev1GrabTime = level.time;
  }
}
예제 #6
0
/*
===============
CheckVenomAttack
===============
*/
qboolean CheckVenomAttack( gentity_t *ent )
{
  trace_t   tr;
  gentity_t *traceEnt;
  int       damage = LEVEL0_BITE_DMG;

  if( ent->client->ps.weaponTime )
	return qfalse;

  // Calculate muzzle point
  AngleVectors( ent->client->ps.viewangles, forward, right, up );
  CalcMuzzlePoint( ent, forward, right, up, muzzle );

  G_WideTrace( &tr, ent, LEVEL0_BITE_RANGE, LEVEL0_BITE_WIDTH,
               LEVEL0_BITE_WIDTH, &traceEnt );

  if( traceEnt == NULL )
    return qfalse;

  if( !traceEnt->takedamage )
    return qfalse;

  if( traceEnt->health <= 0 )
      return qfalse;

  // only allow bites to work against buildings as they are constructing
  if( traceEnt->s.eType == ET_BUILDABLE )
  {
    if( traceEnt->buildableTeam == TEAM_ALIENS )
      return qfalse;

    if ( !( traceEnt->s.modelindex == BA_H_MGTURRET || traceEnt->s.modelindex == BA_H_MGTURRET2 || traceEnt->s.modelindex == BA_H_TESLAGEN || !traceEnt->spawned ) )
      damage = (int)(damage * g_DretchBuildingDamage.value);
    else
      damage = (int)(damage * g_DretchTurretDamage.value);

    if (damage <= 0)
      return qfalse;
  }

  if( traceEnt->client )
  {
    if( traceEnt->client->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
      return qfalse;
    if( traceEnt->client->ps.stats[ STAT_HEALTH ] <= 0 )
      return qfalse;
  }

  // send blood impact
  WideBloodSpurt( ent, traceEnt, &tr, MOD_LEVEL0_BITE );

  G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, MOD_LEVEL0_BITE );
  ent->client->ps.weaponTime += LEVEL0_BITE_REPEAT;
  return qtrue;
}
예제 #7
0
/*
===============
CheckGauntletAttack
===============
*/
qboolean CheckGauntletAttack( gentity_t *ent ) {
	trace_t		tr;
	vec3_t		end;
	gentity_t	*tent;
	gentity_t	*traceEnt;
	int			damage;

	// set aiming directions
	AngleVectors (ent->client->ps.viewangles, forward, right, up);

	CalcMuzzlePoint ( ent, forward, right, up, muzzle );

	VectorMA (muzzle, 32, forward, end);

	trap_Trace (&tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT);
	if ( tr.surfaceFlags & SURF_NOIMPACT ) {
		return qfalse;
	}

	if ( ent->client->noclip ) {
		return qfalse;
	}

	traceEnt = &g_entities[ tr.entityNum ];

	// send blood impact
	if ( traceEnt->takedamage && traceEnt->client ) {
		tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT );
		tent->s.otherEntityNum = traceEnt->s.number;
		tent->s.eventParm = DirToByte( tr.plane.normal );
		tent->s.weapon = ent->s.weapon;
	}

	if ( !traceEnt->takedamage) {
		return qfalse;
	}

	if (ent->client->ps.powerups[PW_QUAD] ) {
		G_AddEvent( ent, EV_POWERUP_QUAD, 0 );
		s_quadFactor = g_quadfactor.value;
	} else {
		s_quadFactor = 1;
	}
#if 1
	if( ent->client->persistantPowerup && ent->client->persistantPowerup->item && ent->client->persistantPowerup->item->giTag == PW_DOUBLER ) {
		s_quadFactor *= 2;
	}
#endif

	damage = 50 * s_quadFactor;
	G_Damage( traceEnt, ent, ent, forward, tr.endpos,
		damage, 0, MOD_GAUNTLET );

	return qtrue;
}
예제 #8
0
파일: weapon.c 프로젝트: icanhas/yantar
qbool
CheckGauntletAttack(Gentity *ent)
{
	Trace tr;
	Vec3	end;
	Gentity	*tent;
	Gentity	*traceEnt;
	int damage;

	/* set aiming directions */
	anglev3s (ent->client->ps.viewangles, forward, right, up);

	CalcMuzzlePoint (ent, forward, right, up, muzzle);

	saddv3 (muzzle, 32, forward, end);

	trap_Trace (&tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT);
	if(tr.surfaceFlags & SURF_NOIMPACT)
		return qfalse;
	if(ent->client->noclip)
		return qfalse;

	traceEnt = &g_entities[tr.entityNum];

	/* send blood impact */
	if(traceEnt->takedamage && traceEnt->client){
		tent = G_TempEntity(tr.endpos, EV_MISSILE_HIT);
		tent->s.otherEntityNum = traceEnt->s.number;
		tent->s.eventParm = DirToByte(tr.plane.normal);
		tent->s.weap[WSpri] = ent->s.weap[WSpri];
		tent->s.weap[WSsec] = ent->s.weap[WSsec];
		tent->s.weap[WShook] = ent->s.weap[WShook];
	}

	if(!traceEnt->takedamage)
		return qfalse;

	if(ent->client->ps.powerups[PW_QUAD]){
		G_AddEvent(ent, EV_POWERUP_QUAD, 0);
		s_quadFactor = g_quadfactor.value;
	}else
		s_quadFactor = 1;

#ifdef MISSIONPACK
	if(ent->client->persistantPowerup &&
	   ent->client->persistantPowerup->item &&
	   ent->client->persistantPowerup->item->tag == PW_DOUBLER)
	then
		s_quadFactor *= 2;
#endif

	damage = 50 * s_quadFactor;
	G_Damage(traceEnt, ent, ent, forward, tr.endpos, damage, 0, MOD_GAUNTLET);
	return qtrue;
}
예제 #9
0
/*
===============
FireWeapon2
===============
*/
void FireWeapon2( gentity_t *ent )
{
  if( ent->client )
  {
    // set aiming directions
    AngleVectors( ent->client->ps.viewangles, forward, right, up );
    CalcMuzzlePoint( ent, forward, right, up, muzzle );
  }
  else
  {
    AngleVectors( ent->s.angles2, forward, right, up );
    VectorCopy( ent->s.pos.trBase, muzzle );
  }

  // fire the specific weapon
  switch( ent->s.weapon )
  {
  
    case WP_MACHINEGUN:
      bulletFire( ent, RIFLE_SPREAD2, RIFLE_DMG2, MOD_MACHINEGUN );
      break;

    case WP_ALEVEL2_UPG:
      areaZapFire( ent );
      break;

    case WP_PAIN_SAW:
      painSawFire2( ent );
      break; 
	  
    case WP_LUCIFER_CANNON:
      LCChargeFire( ent, qtrue );
      break;
	  
    case WP_CHAINGUN:
      bulletFire( ent, CHAINGUN_SPREAD2, CHAINGUN_DMG2, MOD_CHAINGUN );
      break;

    case WP_LAS_GUN:
      lasGunFire2( ent );
      break;
	  
    case WP_PULSE_RIFLE:
      prifleStasisFire( ent );
      break;
	  
    case WP_ABUILD:
    case WP_HBUILD:
      cancelBuildFire( ent );
      break;
	  
    default:
      break;
  }
}
예제 #10
0
void Weapon_GrapplingHook_Fire (gentity_t *ent)
{
//freeze
	AngleVectors( ent->client->ps.viewangles, forward, right, up );
	CalcMuzzlePoint( ent, forward, right, up, muzzle );
//freeze
	if (!ent->client->fireHeld && !ent->client->hook)
		fire_grapple (ent, muzzle, forward);

	ent->client->fireHeld = qtrue;
}
예제 #11
0
void Weapon_GrapplingHook_Fire (gentity_t *ent)
{
	/* LQ3A: Take the direction from the viewangles. */
	AngleVectors(ent->client->ps.viewangles, forward, right, up);
	CalcMuzzlePoint(ent, forward, right, up, muzzle);

	if (!ent->client->fireHeld && !ent->client->hook)
		fire_grapple (ent, muzzle, forward);

	ent->client->fireHeld = qtrue;
}
예제 #12
0
/*
===============
Offhand_Grapple_Fire
===============
*/
void Offhand_Grapple_Fire(gentity_t *ent)
{
    AngleVectors(ent->client->ps.viewangles, forward, right, up);
    CalcMuzzlePoint(ent, forward, right, up, muzzle);

    if (!ent->client->fireHeld && !ent->client->hook)
        fire_grapple(ent, muzzle, forward);

    ent->client->hookhasbeenfired = qtrue;
    ent->client->fireHeld = qtrue;
}
예제 #13
0
/*
===============
FireWeapon2
===============
*/
void FireWeapon2( gentity_t *ent )
{
  if( ent->client )
  {
    // set aiming directions
    AngleVectors( ent->client->ps.viewangles, forward, right, up );
    CalcMuzzlePoint( ent, forward, right, up, muzzle );
  }
  else
  {
    AngleVectors( ent->s.angles2, forward, right, up );
    VectorCopy( ent->s.pos.trBase, muzzle );
  }

  // fire the specific weapon
  switch( ent->s.weapon )
  {
		/*case WP_ALEVEL1:
			//Blaster_ball( ent, 0);
			break;*/
			
    case WP_ALEVEL0:
        explodedretch( ent );
        break;
    case WP_ALEVEL1_UPG:
      poisonCloud( ent );
      break;
    case WP_ALEVEL2_UPG:
      areaZapFire( ent );
      break;

    case WP_LUCIFER_CANNON:
      LCChargeFire( ent, qtrue );
      break;

    case WP_ABUILD:
    case WP_ABUILD2:
    case WP_HBUILD:
    case WP_HBUILD2:
      cancelBuildFire( ent );
      break;
      
      case WP_BLASTER:
          detonate( ent );
          break;

    default:
      break;
  }
}
예제 #14
0
/*
===============
FireWeapon3
===============
*/
void FireWeapon3( gentity_t *ent )
{
  if( ent->client )
  {
    // set aiming directions
    AngleVectors( ent->client->ps.viewangles, forward, right, up );
    CalcMuzzlePoint( ent, forward, right, up, muzzle );
  }
  else
  {
    AngleVectors( ent->s.angles2, forward, right, up );
    VectorCopy( ent->s.pos.trBase, muzzle );
  }

  // fire the specific weapon
  switch( ent->s.weapon )
  {
    case WP_ALEVEL3_UPG:
      bounceBallFire( ent );
      break;

    case WP_ABUILD:
      slowBlobFire( ent );
      break;

   case WP_ALEVEL2_UPG:
      bounceBallFire_level2( ent );
      break;

  case WP_ALEVEL5:
      Prickles( ent );
      break;
	  
    case WP_ALEVEL4:
      // FireBreath_tyrant( ent );
      break;

    case WP_MASS_DRIVER:
      if(g_humanStage.integer == S5 && BG_InventoryContainsUpgrade( UP_BATTPACK, ent->client->ps.stats ))
      {
	  massDriverFire2( ent );
      }
      break;

    default:
      break;
  }
}
예제 #15
0
void painSawFire( gentity_t *ent )
{
  trace_t   tr;
  vec3_t    end;
  gentity_t *tent;
  gentity_t *traceEnt;

  // set aiming directions
  AngleVectors( ent->client->ps.viewangles, forward, right, up );

  CalcMuzzlePoint( ent, forward, right, up, muzzle );

  VectorMA( muzzle, PAINSAW_RANGE, forward, end );

  G_UnlaggedOn( ent, muzzle, PAINSAW_RANGE );
  trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT );
  G_UnlaggedOff( );

  if( tr.surfaceFlags & SURF_NOIMPACT )
    return;

  traceEnt = &g_entities[ tr.entityNum ];

  // send blood impact
  if( traceEnt->takedamage )
  {
    vec3_t  temp;

    //hack to get the particle system to line up with the weapon
    VectorCopy( tr.endpos, temp );
    temp[ 2 ] -= 10.0f;

    if( traceEnt->client )
    {
      tent = G_TempEntity( temp, EV_MISSILE_HIT );
      tent->s.otherEntityNum = traceEnt->s.number;
    }
    else
      tent = G_TempEntity( temp, EV_MISSILE_MISS );

    tent->s.eventParm = DirToByte( tr.plane.normal );
    tent->s.weapon = ent->s.weapon;
    tent->s.generic1 = ent->s.generic1; //weaponMode
  }

  if( traceEnt->takedamage )
    G_Damage( traceEnt, ent, ent, forward, tr.endpos, PAINSAW_DAMAGE, DAMAGE_NO_KNOCKBACK, MOD_PAINSAW );
}
예제 #16
0
void Rune_Phase_Use(gentity_t *ent)
{
	vec3_t oldmuzzle,muzzle,forward,right,up,end;
	trace_t trace, trace2;

	AngleVectors (ent->client->ps.viewangles, forward, right, up);
	CalcMuzzlePoint ( ent, forward, right, up, muzzle );

	if (ent->runetime<level.time)
	{
		VectorMA (muzzle, 250, forward, end);
		trap_Trace (&trace, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT );

		// we didn't hit anything, so exit
		if ( trace.fraction == 1)
			return;

		SnapVectorTowards( trace.endpos, muzzle );

        // prepare for firing through the wall
        VectorCopy (muzzle, oldmuzzle);
        VectorCopy (trace.endpos, muzzle);
        VectorMA (muzzle, 96, forward, muzzle);                

        if ( !( trap_PointContents( muzzle, -1 ) & CONTENTS_SOLID ))
        {
			// the point isn't inside a wall, so check to see if we are outside the bounds of the level
			VectorCopy(muzzle,end);
			end[2]=-10000;
			trap_Trace (&trace2, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT );

			// if we didn't hit anything after that big a trace, we are outside the level
			if (trace2.fraction==1)
				return;

			TeleportPlayer(ent,muzzle,ent->client->ps.viewangles, qtrue, qtrue);
			ent->runetime = level.time + RUNE_PHASE_RECHARGE;
        }


	}
	else
	{
		//trap_SendServerCommand( ent->s.clientNum, va("print \"Phase is recharging\n\""));
	}
}
예제 #17
0
//---------------------------------------------------------
static void WP_DropDetPack( gentity_t *self, vec3_t start, vec3_t dir ) 
//---------------------------------------------------------
{
	// Chucking a new one
	AngleVectors( self->client->ps.viewangles, forwardVec, vrightVec, up );
	CalcMuzzlePoint( self, forwardVec, vrightVec, up, muzzle, 0 );
	VectorNormalize( forwardVec );
	VectorMA( muzzle, -4, forwardVec, muzzle );

	VectorCopy( muzzle, start );
	WP_TraceSetStart( self, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall

	gentity_t	*missile = CreateMissile( start, forwardVec, 300, 10000, self, qfalse );

	missile->fxID = G_EffectIndex( "detpack/explosion" ); // if we set an explosion effect, explode death can use that instead

	missile->classname = "detpack";
	missile->s.weapon = WP_DET_PACK;

	missile->s.pos.trType = TR_GRAVITY;

	missile->s.eFlags |= EF_MISSILE_STICK;
	missile->e_TouchFunc = touchF_charge_stick;
	
	missile->damage = weaponData[WP_DET_PACK].damage;
	missile->methodOfDeath = MOD_DETPACK;

	missile->splashDamage = weaponData[WP_DET_PACK].splashDamage;
	missile->splashRadius = weaponData[WP_DET_PACK].splashRadius;
	missile->splashMethodOfDeath = MOD_DETPACK;// ?SPLASH;

	missile->clipmask = (CONTENTS_SOLID|CONTENTS_BODY|CONTENTS_SHOTCLIP);//MASK_SHOT;

	// we don't want it to ever bounce
	missile->bounceCount = 0;

	missile->s.radius = 30;
	VectorSet( missile->s.modelScale, 1.0f, 1.0f, 1.0f );
	gi.G2API_InitGhoul2Model( missile->ghoul2, weaponData[WP_DET_PACK].missileMdl, G_ModelIndex( weaponData[WP_DET_PACK].missileMdl ),
		NULL_HANDLE, NULL_HANDLE, 0, 0);

	AddSoundEvent( NULL, missile->currentOrigin, 128, AEL_MINOR, qtrue );
	AddSightEvent( NULL, missile->currentOrigin, 128, AEL_SUSPICIOUS, 10 );
}
예제 #18
0
/*
===============
FireWeapon3
===============
*/
void FireWeapon3( gentity_t *ent )
{
  if( ent->client )
  {
    // set aiming directions
    AngleVectors( ent->client->ps.viewangles, forward, right, up );
    CalcMuzzlePoint( ent, forward, right, up, muzzle );
  }
  else
  {
    AngleVectors( ent->s.angles2, forward, right, up );
    VectorCopy( ent->s.pos.trBase, muzzle );
  }

  // fire the specific weapon
  switch( ent->s.weapon )
  {
    case WP_ALEVEL3_UPG:
      bounceBallFire( ent );
      break;

    case WP_ABUILD2:
      slowBlobFire( ent );
      break;

//    case WP_ALEVEL4:
//      lockBlobLauncherFire( ent ); //thats right bitch, i'll trap you!
//N/B: Trap as in trap, not males dressing up as women.
      break;
/*
    case WP_HBUILD2:
      bulletFire( ent, 300, 1, MOD_TRIGGER_HURT );
      bulletFire( ent, 300, 1, MOD_TRIGGER_HURT );
      bulletFire( ent, 300, 1, MOD_TRIGGER_HURT );
      break;
	
*/
    default:
      break;
  }
}
예제 #19
0
/*
===============
meleeAttack
===============
*/
void meleeAttack( gentity_t *ent, float range, float width, int damage, meansOfDeath_t mod )
{
  trace_t   tr;
  vec3_t    end;
  gentity_t *tent;
  gentity_t *traceEnt;
  vec3_t    mins, maxs;

  VectorSet( mins, -width, -width, -width );
  VectorSet( maxs, width, width, width );

  // set aiming directions
  AngleVectors( ent->client->ps.viewangles, forward, right, up );

  CalcMuzzlePoint( ent, forward, right, up, muzzle );

  VectorMA( muzzle, range, forward, end );

  G_UnlaggedOn( ent, muzzle, range );
  trap_Trace( &tr, muzzle, mins, maxs, end, ent->s.number, MASK_SHOT );
  G_UnlaggedOff( );

  if( tr.surfaceFlags & SURF_NOIMPACT )
    return;

  traceEnt = &g_entities[ tr.entityNum ];

  // send blood impact
  if( traceEnt->takedamage && traceEnt->client )
  {
    tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT );
    tent->s.otherEntityNum = traceEnt->s.number;
    tent->s.eventParm = DirToByte( tr.plane.normal );
    tent->s.weapon = ent->s.weapon;
    tent->s.generic1 = ent->s.generic1; //weaponMode
  }

  if( traceEnt->takedamage )
    G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, mod );
}
예제 #20
0
/*
===============
G_MedkitTarget

Look for a possible healing target (a client) in the front.
===============
*/
gentity_t *G_MedkitTarget( gentity_t *ent )
{
  trace_t   tr;
  gentity_t *targetEnt = NULL;

  if( g_humanMedkitRange.value <= 0 ||
      g_humanMedkitWidth.value <= 0 )
    return NULL;

  // Calculate muzzle point
  AngleVectors( ent->client->ps.viewangles, forward, right, up );
  CalcMuzzlePoint( ent, forward, right, up, muzzle );

  G_WideTrace( &tr, ent, g_humanMedkitRange.value,
      g_humanMedkitWidth.value, g_humanMedkitWidth.value, &targetEnt );

  if( ( targetEnt != NULL ) &&
      ( targetEnt->client != NULL ) )
    return targetEnt;
  else
    return NULL;
}
예제 #21
0
/*
================
G_WideTrace

Trace a bounding box against entities, but not the world
Also check there is a line of sight between the start and end point
================
*/
static void G_WideTrace( trace_t *tr, gentity_t *ent, float range, float width, gentity_t **target )
{
  vec3_t    mins, maxs;
  vec3_t    end;

  VectorSet( mins, -width, -width, -width );
  VectorSet( maxs, width, width, width );

  *target = NULL;

  if( !ent->client )
    return;

  // Set aiming directions
  AngleVectors( ent->client->ps.viewangles, forward, right, up );
  CalcMuzzlePoint( ent, forward, right, up, muzzle );
  VectorMA( muzzle, range, forward, end );

  G_UnlaggedOn( ent, muzzle, range );

  // Trace against entities
  trap_Trace( tr, muzzle, mins, maxs, end, ent->s.number, CONTENTS_BODY );
  if( tr->entityNum != ENTITYNUM_NONE )
  {
    *target = &g_entities[ tr->entityNum ];

    // Set range to the trace length plus the width, so that the end of the
    // LOS trace is close to the exterior of the target's bounding box
    range = Distance( muzzle, tr->endpos ) + width;
    VectorMA( muzzle, range, forward, end );

    // Trace for line of sight against the world
    trap_Trace( tr, muzzle, NULL, NULL, end, 0, CONTENTS_SOLID );
    if( tr->fraction < 1.0f )
      *target = NULL;
  }

  G_UnlaggedOff( );
}
예제 #22
0
파일: g_weapon.cpp 프로젝트: BSzili/OpenJK
//---------------------------------------------------------
void FireWeapon( gentity_t *ent, qboolean alt_fire )
//---------------------------------------------------------
{
	float alert = 256;

	// track shots taken for accuracy tracking.
	ent->client->ps.persistant[PERS_ACCURACY_SHOTS]++;

	// set aiming directions
	if ( ent->s.weapon == WP_DISRUPTOR && alt_fire )
	{
		if ( ent->NPC )
		{
			//snipers must use the angles they actually did their shot trace with
			AngleVectors( ent->lastAngles, wpFwd, wpVright, wpUp );
		}
	}
	else if ( ent->s.weapon == WP_ATST_SIDE || ent->s.weapon == WP_ATST_MAIN )
	{
		vec3_t	delta1, enemy_org1, muzzle1;
		vec3_t	angleToEnemy1;

		VectorCopy( ent->client->renderInfo.muzzlePoint, muzzle1 );

		if ( !ent->s.number )
		{//player driving an AT-ST
			//SIGH... because we can't anticipate alt-fire, must calc muzzle here and now
			mdxaBone_t		boltMatrix;
			int				bolt;

			if ( ent->client->ps.weapon == WP_ATST_MAIN )
			{//FIXME: alt_fire should fire both barrels, but slower?
				if ( ent->alt_fire )
				{
					bolt = ent->handRBolt;
				}
				else
				{
					bolt = ent->handLBolt;
				}
			}
			else
			{// ATST SIDE weapons
				if ( ent->alt_fire )
				{
					if ( gi.G2API_GetSurfaceRenderStatus( &ent->ghoul2[ent->playerModel], "head_light_blaster_cann" ) )
					{//don't have it!
						return;
					}
					bolt = ent->genericBolt2;
				}
				else
				{
					if ( gi.G2API_GetSurfaceRenderStatus( &ent->ghoul2[ent->playerModel], "head_concussion_charger" ) )
					{//don't have it!
						return;
					}
					bolt = ent->genericBolt1;
				}
			}

			vec3_t yawOnlyAngles = {0, ent->currentAngles[YAW], 0};
			if ( ent->currentAngles[YAW] != ent->client->ps.legsYaw )
			{
				yawOnlyAngles[YAW] = ent->client->ps.legsYaw;
			}
			gi.G2API_GetBoltMatrix( ent->ghoul2, ent->playerModel, bolt, &boltMatrix, yawOnlyAngles, ent->currentOrigin, (cg.time?cg.time:level.time), NULL, ent->s.modelScale );

			// work the matrix axis stuff into the original axis and origins used.
			gi.G2API_GiveMeVectorFromMatrix( boltMatrix, ORIGIN, ent->client->renderInfo.muzzlePoint );
			gi.G2API_GiveMeVectorFromMatrix( boltMatrix, NEGATIVE_Y, ent->client->renderInfo.muzzleDir );
			ent->client->renderInfo.mPCalcTime = level.time;

			AngleVectors( ent->client->ps.viewangles, wpFwd, wpVright, wpUp );
			//CalcMuzzlePoint( ent, wpFwd, vright, wpUp, wpMuzzle, 0 );
		}
		else if ( !ent->enemy )
		{//an NPC with no enemy to auto-aim at
			VectorCopy( ent->client->renderInfo.muzzleDir, wpFwd );
		}
		else
		{//NPC, auto-aim at enemy
			CalcEntitySpot( ent->enemy, SPOT_HEAD, enemy_org1 );

			VectorSubtract (enemy_org1, muzzle1, delta1);

			vectoangles ( delta1, angleToEnemy1 );
			AngleVectors (angleToEnemy1, wpFwd, wpVright, wpUp);
		}
	}
	else if ( ent->s.weapon == WP_BOT_LASER && ent->enemy )
	{
		vec3_t	delta1, enemy_org1, muzzle1;
		vec3_t	angleToEnemy1;

		CalcEntitySpot( ent->enemy, SPOT_HEAD, enemy_org1 );
		CalcEntitySpot( ent, SPOT_WEAPON, muzzle1 );

		VectorSubtract (enemy_org1, muzzle1, delta1);

		vectoangles ( delta1, angleToEnemy1 );
		AngleVectors (angleToEnemy1, wpFwd, wpVright, wpUp);
	}
	else
	{
		AngleVectors( ent->client->ps.viewangles, wpFwd, wpVright, wpUp );
	}

	ent->alt_fire = alt_fire;
	CalcMuzzlePoint ( ent, wpFwd, wpVright, wpUp, wpMuzzle , 0);

	// fire the specific weapon
	switch( ent->s.weapon )
	{
	// Player weapons
	//-----------------
	case WP_SABER:
		return;
		break;

	case WP_BRYAR_PISTOL:
		WP_FireBryarPistol( ent, alt_fire );
		break;

	case WP_BLASTER:
		WP_FireBlaster( ent, alt_fire );
		break;

	case WP_DISRUPTOR:
		alert = 50; // if you want it to alert enemies, remove this
		WP_FireDisruptor( ent, alt_fire );
		break;

	case WP_BOWCASTER:
		WP_FireBowcaster( ent, alt_fire );
		break;

	case WP_REPEATER:
		WP_FireRepeater( ent, alt_fire );
		break;

	case WP_DEMP2:
		WP_FireDEMP2( ent, alt_fire );
		break;

	case WP_FLECHETTE:
		WP_FireFlechette( ent, alt_fire );
		break;

	case WP_ROCKET_LAUNCHER:
		WP_FireRocket( ent, alt_fire );
		break;

	case WP_THERMAL:
		WP_FireThermalDetonator( ent, alt_fire );
		break;

	case WP_TRIP_MINE:
		alert = 0; // if you want it to alert enemies, remove this
		WP_PlaceLaserTrap( ent, alt_fire );
		break;

	case WP_DET_PACK:
		alert = 0; // if you want it to alert enemies, remove this
		WP_FireDetPack( ent, alt_fire );
		break;

	case WP_BOT_LASER:
		WP_BotLaser( ent );
		break;

	case WP_EMPLACED_GUN:
		// doesn't care about whether it's alt-fire or not.  We can do an alt-fire if needed
		WP_EmplacedFire( ent );
		break;

	case WP_MELEE:
		alert = 0; // if you want it to alert enemies, remove this
		WP_Melee( ent );
		break;

	case WP_ATST_MAIN:
		WP_ATSTMainFire( ent );
		break;

	case WP_ATST_SIDE:

		// TEMP
		if ( alt_fire )
		{
//			WP_FireRocket( ent, qfalse );
			WP_ATSTSideAltFire(ent);
		}
		else
		{
			if ( ent->s.number == 0 && ent->client->ps.vehicleModel )
			{
				WP_ATSTMainFire( ent );
			}
			else
			{
				WP_ATSTSideFire(ent);
			}
		}
		break;

	case WP_TIE_FIGHTER:
		// TEMP
		WP_EmplacedFire( ent );
		break;

	case WP_RAPID_FIRE_CONC:
		// TEMP
		if ( alt_fire )
		{
			WP_FireRepeater( ent, alt_fire );
		}
		else
		{
			WP_EmplacedFire( ent );
		}
		break;

	case WP_STUN_BATON:
		WP_FireStunBaton( ent, alt_fire );
		break;

	case WP_BLASTER_PISTOL: // enemy version
		WP_FireBryarPistol( ent, qfalse ); // never an alt-fire?
		break;

//	case WP_TRICORDER:
//		WP_TricorderScan( ent, alt_fire );
//		break;

	default:
		return;
		break;
	}

	if ( !ent->s.number )
	{
		if ( ent->s.weapon == WP_FLECHETTE || (ent->s.weapon == WP_BOWCASTER && !alt_fire) )
		{//these can fire multiple shots, count them individually within the firing functions
		}
		else if ( W_AccuracyLoggableWeapon( ent->s.weapon, alt_fire, MOD_UNKNOWN ) )
		{
			ent->client->sess.missionStats.shotsFired++;
		}
	}
	// We should probably just use this as a default behavior, in special cases, just set alert to false.
	if ( ent->s.number == 0 && alert > 0 )
	{
		AddSoundEvent( ent, wpMuzzle, alert, AEL_DISCOVERED );
		AddSightEvent( ent, wpMuzzle, alert*2, AEL_DISCOVERED, 20 );
	}
}
예제 #23
0
void Bullet_Fire (gentity_t *ent, float spread, int damage ) {
	trace_t		tr;
	vec3_t		end;
#if 1
	vec3_t		impactpoint, bouncedir;
#endif
	float		r, f, d;
	float		u;
	gentity_t	*tent;
	gentity_t	*traceEnt;
	int			i, passent;

	vec3_t		forward, right, up;

	AngleVectors (ent->client->ps.viewangles, forward, right, up);
	CalcMuzzlePoint ( ent, forward, right, up, muzzle );
	ent->client->accuracy_shots++;
	f = ((float)(ent->client->accuracy_shots % SPIRAL_SIZE)) / SPIRAL_SIZE; // 0 >= f >= 1
	d = (f+(1/SPIRAL_SIZE)) * 2.0 * M_PI;

	damage *= s_quadFactor;

	//Com_Printf("f: %f, d: %f\n, a: %i", f, d, ent->client->accuracy_shots);

	u = sin(d) * (f * spread);
	r = cos(d) * (f * spread);

	//Com_Printf("end1 : [%f, %f, %f]\n", end[0], end[1], end[2]);

	VectorMA (muzzle, 8192, forward, end);

	//Com_Printf("end2 : [%f, %f, %f]\n", end[0], end[1], end[2]);
	//Com_Printf("right : [%f, %f, %f]\n", right[0], right[1], right[2]);
	VectorMA (end, r, right, end);

	//Com_Printf("end3 : [%f, %f, %f]\n", end[0], end[1], end[2]);
	//Com_Printf("up : [%f, %f, %f]\n", up[0], up[1], up[2]);

	VectorMA (end, u, up, end);

	//Com_Printf("end4 : [%f, %f, %f]\n", end[0], end[1], end[2]);

	passent = ent->s.number;
	for (i = 0; i < 10; i++) {

		trap_Trace (&tr, muzzle, NULL, NULL, end, passent, MASK_SHOT);
		if ( tr.surfaceFlags & SURF_NOIMPACT ) {
			return;
		}

		traceEnt = &g_entities[ tr.entityNum ];

		// snap the endpos to integers, but nudged towards the line
		SnapVectorTowards( tr.endpos, muzzle );

		// send bullet impact
		if ( traceEnt->takedamage && traceEnt->client ) {
			tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_FLESH );
			tent->s.eventParm = traceEnt->s.number;
			if( LogAccuracyHit( traceEnt, ent ) ) {
				ent->client->accuracy_hits++;
			}
		} else {
			tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_WALL );
			tent->s.eventParm = DirToByte( tr.plane.normal );
		}
		tent->s.otherEntityNum = ent->s.number;

		if ( traceEnt->takedamage) {
#if 1
			if ( traceEnt->client && traceEnt->client->invulnerabilityTime > level.time ) {
				if (G_InvulnerabilityEffect( traceEnt, forward, tr.endpos, impactpoint, bouncedir )) {
					G_BounceProjectile( muzzle, impactpoint, bouncedir, end );
					VectorCopy( impactpoint, muzzle );
					// the player can hit him/herself with the bounced rail
					passent = ENTITYNUM_NONE;
				}
				else {
					VectorCopy( tr.endpos, muzzle );
					passent = traceEnt->s.number;
				}
				continue;
			}
			else {
#endif
				G_Damage( traceEnt, ent, ent, forward, tr.endpos,
					damage, 0, MOD_MACHINEGUN);
#if 1
			}
#endif
		}
		break;
	}
}
예제 #24
0
void CalcEntitySpot ( const gentity_t *ent, const spot_t spot, vec3_t point ) 
{
	vec3_t	forward, up, right;
	vec3_t	start, end;
	trace_t	tr;

	if ( !ent )
	{
		return;
	}
	ViewHeightFix(ent);
	switch ( spot ) 
	{
	case SPOT_ORIGIN:
		if(VectorCompare(ent->currentOrigin, vec3_origin))
		{//brush
			VectorSubtract(ent->absmax, ent->absmin, point);//size
			VectorMA(ent->absmin, 0.5, point, point);
		}
		else
		{
			VectorCopy ( ent->currentOrigin, point );
		}
		break;

	case SPOT_CHEST:
	case SPOT_HEAD:
		if ( ent->client && VectorLengthSquared( ent->client->renderInfo.eyePoint ) && (ent->client->ps.viewEntity <= 0 || ent->client->ps.viewEntity >= ENTITYNUM_WORLD) )
		{//Actual tag_head eyespot!
			//FIXME: Stasis aliens may have a problem here...
			VectorCopy( ent->client->renderInfo.eyePoint, point );
			if ( ent->client->NPC_class == CLASS_ATST )
			{//adjust up some
				point[2] += 28;//magic number :)
			}
			if ( ent->NPC )
			{//always aim from the center of my bbox, so we don't wiggle when we lean forward or backwards
				point[0] = ent->currentOrigin[0];
				point[1] = ent->currentOrigin[1];
			}
			else if ( !ent->s.number )
			{
				SubtractLeanOfs( ent, point );
			}
		}
		else
		{
			VectorCopy ( ent->currentOrigin, point );
			if ( ent->client ) 
			{
				point[2] += ent->client->ps.viewheight;
			}
		}
		if ( spot == SPOT_CHEST && ent->client )
		{
			if ( ent->client->NPC_class != CLASS_ATST )
			{//adjust up some
				point[2] -= ent->maxs[2]*0.2f;
			}
		}
		break;

	case SPOT_HEAD_LEAN:
		if ( ent->client && VectorLengthSquared( ent->client->renderInfo.eyePoint ) && (ent->client->ps.viewEntity <= 0 || ent->client->ps.viewEntity >= ENTITYNUM_WORLD) )
		{//Actual tag_head eyespot!
			//FIXME: Stasis aliens may have a problem here...
			VectorCopy( ent->client->renderInfo.eyePoint, point );
			if ( ent->client->NPC_class == CLASS_ATST )
			{//adjust up some
				point[2] += 28;//magic number :)
			}
			if ( ent->NPC )
			{//always aim from the center of my bbox, so we don't wiggle when we lean forward or backwards
				point[0] = ent->currentOrigin[0];
				point[1] = ent->currentOrigin[1];
			}
			else if ( !ent->s.number )
			{
				SubtractLeanOfs( ent, point );
			}
			//NOTE: automatically takes leaning into account!
		}
		else
		{
			VectorCopy ( ent->currentOrigin, point );
			if ( ent->client ) 
			{
				point[2] += ent->client->ps.viewheight;
			}
			//AddLeanOfs ( ent, point );
		}
		break;

	//FIXME: implement...
	//case SPOT_CHEST:
		//Returns point 3/4 from tag_torso to tag_head?
		//break;

	case SPOT_LEGS:
		VectorCopy ( ent->currentOrigin, point );
		point[2] += (ent->mins[2] * 0.5);
		break;

	case SPOT_WEAPON:
		if( ent->NPC && !VectorCompare( ent->NPC->shootAngles, vec3_origin ) && !VectorCompare( ent->NPC->shootAngles, ent->client->ps.viewangles ))
		{
			AngleVectors( ent->NPC->shootAngles, forward, right, up );
		}
		else
		{
			AngleVectors( ent->client->ps.viewangles, forward, right, up );
		}
		CalcMuzzlePoint( (gentity_t*)ent, forward, right, up, point, 0 );
		//NOTE: automatically takes leaning into account!
		break;

	case SPOT_GROUND:
		// if entity is on the ground, just use it's absmin
		if ( ent->s.groundEntityNum != -1 ) 
		{
			VectorCopy( ent->currentOrigin, point );
			point[2] = ent->absmin[2];
			break;
		}

		// if it is reasonably close to the ground, give the point underneath of it
		VectorCopy( ent->currentOrigin, start );
		start[2] = ent->absmin[2];
		VectorCopy( start, end );
		end[2] -= 64;
		gi.trace( &tr, start, ent->mins, ent->maxs, end, ent->s.number, MASK_PLAYERSOLID, G2_NOCOLLIDE, 0 );
		if ( tr.fraction < 1.0 ) 
		{
			VectorCopy( tr.endpos, point);
			break;
		}

		// otherwise just use the origin
		VectorCopy( ent->currentOrigin, point );
		break;

	default:
		VectorCopy ( ent->currentOrigin, point );
		break;
	}
}
예제 #25
0
파일: AI_Sniper.cpp 프로젝트: kikili/OpenJK
void NPC_BSSniper_Attack( void )
{
	//Don't do anything if we're hurt
	if ( NPC->painDebounceTime > level.time )
	{
		NPC_UpdateAngles( qtrue, qtrue );
		return;
	}

	//NPC_CheckEnemy( qtrue, qfalse );
	//If we don't have an enemy, just idle
	if ( NPC_CheckEnemyExt() == qfalse )//!NPC->enemy )//
	{
		NPC->enemy = NULL;
		NPC_BSSniper_Patrol();//FIXME: or patrol?
		return;
	}

	if ( TIMER_Done( NPC, "flee" ) && NPC_CheckForDanger( NPC_CheckAlertEvents( qtrue, qtrue, -1, qfalse, AEL_DANGER ) ) )
	{//going to run
		NPC_UpdateAngles( qtrue, qtrue );
		return;
	}

	if ( !NPC->enemy )
	{//WTF?  somehow we lost our enemy?
		NPC_BSSniper_Patrol();//FIXME: or patrol?
		return;
	}

	enemyLOS = enemyCS = qfalse;
	AImove = qtrue;
	faceEnemy = qfalse;
	shoot = qfalse;
	enemyDist = DistanceSquared( NPC->currentOrigin, NPC->enemy->currentOrigin );
	if ( enemyDist < 16384 )//128 squared
	{//too close, so switch to primary fire
		if ( NPC->client->ps.weapon == WP_DISRUPTOR )
		{//sniping... should be assumed
			if ( NPCInfo->scriptFlags & SCF_ALT_FIRE )
			{//use primary fire
				trace_t	trace;
				gi.trace ( &trace, NPC->enemy->currentOrigin, NPC->enemy->mins, NPC->enemy->maxs, NPC->currentOrigin, NPC->enemy->s.number, NPC->enemy->clipmask, G2_NOCOLLIDE, 0 );
				if ( !trace.allsolid && !trace.startsolid && (trace.fraction == 1.0 || trace.entityNum == NPC->s.number ) )
				{//he can get right to me
					NPCInfo->scriptFlags &= ~SCF_ALT_FIRE;
					//reset fire-timing variables
					NPC_ChangeWeapon( WP_DISRUPTOR );
					NPC_UpdateAngles( qtrue, qtrue );
					return;
				}
			}
			//FIXME: switch back if he gets far away again?
		}
	}
	else if ( enemyDist > 65536 )//256 squared
	{
		if ( NPC->client->ps.weapon == WP_DISRUPTOR )
		{//sniping... should be assumed
			if ( !(NPCInfo->scriptFlags&SCF_ALT_FIRE) )
			{//use primary fire
				NPCInfo->scriptFlags |= SCF_ALT_FIRE;
				//reset fire-timing variables
				NPC_ChangeWeapon( WP_DISRUPTOR );
				NPC_UpdateAngles( qtrue, qtrue );
				return;
			}
		}
	}

	Sniper_UpdateEnemyPos();
	//can we see our target?
	if ( NPC_ClearLOS( NPC->enemy ) )//|| (NPCInfo->stats.aim >= 5 && gi.inPVS( NPC->client->renderInfo.eyePoint, NPC->enemy->currentOrigin )) )
	{
		NPCInfo->enemyLastSeenTime = level.time;
		VectorCopy( NPC->enemy->currentOrigin, NPCInfo->enemyLastSeenLocation );
		enemyLOS = qtrue;
		float maxShootDist = NPC_MaxDistSquaredForWeapon();
		if ( enemyDist < maxShootDist )
		{
			vec3_t fwd, right, up, muzzle, end;
			trace_t	tr;
			AngleVectors( NPC->client->ps.viewangles, fwd, right, up );
			CalcMuzzlePoint( NPC, fwd, right, up, muzzle, 0 );
			VectorMA( muzzle, 8192, fwd, end );
			gi.trace ( &tr, muzzle, NULL, NULL, end, NPC->s.number, MASK_SHOT, G2_RETURNONHIT, 0 );

			int hit = tr.entityNum;
			//can we shoot our target?
			if ( Sniper_EvaluateShot( hit ) )
			{
				enemyCS = qtrue;
			}
		}
	}
	/*
	else if ( gi.inPVS( NPC->enemy->currentOrigin, NPC->currentOrigin ) )
	{
		NPCInfo->enemyLastSeenTime = level.time;
		faceEnemy = qtrue;
	}
	*/

	if ( enemyLOS )
	{//FIXME: no need to face enemy if we're moving to some other goal and he's too far away to shoot?
		faceEnemy = qtrue;
	}
	if ( enemyCS )
	{
		shoot = qtrue;
	}
	else if ( level.time - NPCInfo->enemyLastSeenTime > 3000 )
	{//Hmm, have to get around this bastard... FIXME: this NPCInfo->enemyLastSeenTime builds up when ducked seems to make them want to run when they uncrouch
		Sniper_ResolveBlockedShot();
	}

	//Check for movement to take care of
	Sniper_CheckMoveState();

	//See if we should override shooting decision with any special considerations
	Sniper_CheckFireState();

	if ( AImove )
	{//move toward goal
		if ( NPCInfo->goalEntity )//&& ( NPCInfo->goalEntity != NPC->enemy || enemyDist > 10000 ) )//100 squared
		{
			AImove = Sniper_Move();
		}
		else
		{
			AImove = qfalse;
		}
	}

	if ( !AImove )
	{
		if ( !TIMER_Done( NPC, "duck" ) )
		{
			if ( TIMER_Done( NPC, "watch" ) )
			{//not while watching
				ucmd.upmove = -127;
			}
		}
		//FIXME: what about leaning?
		//FIXME: also, when stop ducking, start looking, if enemy can see me, chance of ducking back down again
	}
	else
	{//stop ducking!
		TIMER_Set( NPC, "duck", -1 );
	}

	if ( TIMER_Done( NPC, "duck" ) 
		&& TIMER_Done( NPC, "watch" ) 
		&& (TIMER_Get( NPC, "attackDelay" )-level.time) > 1000 
		&& NPC->attackDebounceTime < level.time )
	{
		if ( enemyLOS && (NPCInfo->scriptFlags&SCF_ALT_FIRE) )
		{
			if ( NPC->fly_sound_debounce_time < level.time )
			{
				NPC->fly_sound_debounce_time = level.time + 2000;
			}
		}
	}

	if ( !faceEnemy )
	{//we want to face in the dir we're running
		if ( AImove )
		{//don't run away and shoot
			NPCInfo->desiredYaw = NPCInfo->lastPathAngles[YAW];
			NPCInfo->desiredPitch = 0;
			shoot = qfalse;
		}
		NPC_UpdateAngles( qtrue, qtrue );
	}
	else// if ( faceEnemy )
	{//face the enemy
		Sniper_FaceEnemy();
	}

	if ( NPCInfo->scriptFlags&SCF_DONT_FIRE )
	{
		shoot = qfalse;
	}

	//FIXME: don't shoot right away!
	if ( shoot )
	{//try to shoot if it's time
		if ( TIMER_Done( NPC, "attackDelay" ) )
		{
			WeaponThink( qtrue );
			if ( ucmd.buttons&(BUTTON_ATTACK|BUTTON_ALT_ATTACK) )
			{
				G_SoundOnEnt( NPC, CHAN_WEAPON, "sound/null.wav" );
			}

			//took a shot, now hide
			if ( !(NPC->spawnflags&SPF_NO_HIDE) && !Q_irand( 0, 1 ) )
			{
				//FIXME: do this if in combat point and combat point has duck-type cover... also handle lean-type cover
				Sniper_StartHide();
			}
			else
			{
				TIMER_Set( NPC, "attackDelay", NPCInfo->shotTime-level.time );
			}
		}
	}
}
예제 #26
0
파일: AI_Sniper.cpp 프로젝트: kikili/OpenJK
void Sniper_FaceEnemy( void )
{
	//FIXME: the ones behind kill holes are facing some arbitrary direction and not firing
	//FIXME: If actually trying to hit enemy, don't fire unless enemy is at least in front of me?
	//FIXME: need to give designers option to make them not miss first few shots
	if ( NPC->enemy )
	{
		vec3_t	muzzle, target, angles, forward, right, up;
		//Get the positions
		AngleVectors( NPC->client->ps.viewangles, forward, right, up );
		CalcMuzzlePoint( NPC, forward, right, up, muzzle, 0 );
		//CalcEntitySpot( NPC, SPOT_WEAPON, muzzle );
		CalcEntitySpot( NPC->enemy, SPOT_ORIGIN, target );

		if ( enemyDist > 65536 && NPCInfo->stats.aim < 5 )//is 256 squared, was 16384 (128*128)
		{
			if ( NPC->count < (5-NPCInfo->stats.aim) )
			{//miss a few times first
				if ( shoot && TIMER_Done( NPC, "attackDelay" ) && level.time >= NPCInfo->shotTime )
				{//ready to fire again
					qboolean	aimError = qfalse;
					qboolean	hit = qtrue;
					int			tryMissCount = 0;
					trace_t		trace;

					GetAnglesForDirection( muzzle, target, angles );
					AngleVectors( angles, forward, right, up );

					while ( hit && tryMissCount < 10 )
					{
						tryMissCount++;
						if ( !Q_irand( 0, 1 ) )
						{
							aimError = qtrue;
							if ( !Q_irand( 0, 1 ) )
							{
								VectorMA( target, NPC->enemy->maxs[2]*Q_flrand(1.5, 4), right, target );
							}
							else
							{
								VectorMA( target, NPC->enemy->mins[2]*Q_flrand(1.5, 4), right, target );
							}
						}
						if ( !aimError || !Q_irand( 0, 1 ) )
						{
							if ( !Q_irand( 0, 1 ) )
							{
								VectorMA( target, NPC->enemy->maxs[2]*Q_flrand(1.5, 4), up, target );
							}
							else
							{
								VectorMA( target, NPC->enemy->mins[2]*Q_flrand(1.5, 4), up, target );
							}
						}
						gi.trace( &trace, muzzle, vec3_origin, vec3_origin, target, NPC->s.number, MASK_SHOT, G2_NOCOLLIDE, 0 );
						hit = Sniper_EvaluateShot( trace.entityNum );
					}
					NPC->count++;
				}
				else
				{
					if ( !enemyLOS )
					{
						NPC_UpdateAngles( qtrue, qtrue );
						return;
					}
				}
			}
			else
			{//based on distance, aim value, difficulty and enemy movement, miss
				//FIXME: incorporate distance as a factor?
				int missFactor = 8-(NPCInfo->stats.aim+g_spskill->integer) * 3;
				if ( missFactor > ENEMY_POS_LAG_STEPS )
				{
					missFactor = ENEMY_POS_LAG_STEPS;
				}
				else if ( missFactor < 0 )
				{//???
					missFactor = 0 ;
				}
				VectorCopy( NPCInfo->enemyLaggedPos[missFactor], target );
			}
			GetAnglesForDirection( muzzle, target, angles );
		}
		else
		{
			target[2] += Q_flrand( 0, NPC->enemy->maxs[2] );
			//CalcEntitySpot( NPC->enemy, SPOT_HEAD_LEAN, target );
			GetAnglesForDirection( muzzle, target, angles );
		}

		NPCInfo->desiredYaw		= AngleNormalize360( angles[YAW] );
		NPCInfo->desiredPitch	= AngleNormalize360( angles[PITCH] );
	}
	NPC_UpdateAngles( qtrue, qtrue );
}
예제 #27
0
/*
===============
FireWeapon
===============
*/
void FireWeapon( gentity_t *ent )
{
	if ( ent->client )
	{
		// set aiming directions
		AngleVectors( ent->client->ps.viewangles, forward, right, up );
		CalcMuzzlePoint( ent, forward, right, up, muzzle );
	}
	else
	{
		AngleVectors( ent->turretAim, forward, right, up );
		VectorCopy( ent->s.pos.trBase, muzzle );
	}

	// fire the specific weapon
	switch ( ent->s.weapon )
	{
		case WP_ALEVEL1:
			meleeAttack( ent, LEVEL1_CLAW_RANGE, LEVEL1_CLAW_WIDTH, LEVEL1_CLAW_WIDTH,
			             LEVEL1_CLAW_DMG, MOD_LEVEL1_CLAW );
			break;

		case WP_ALEVEL1_UPG:
			meleeAttack( ent, LEVEL1_CLAW_U_RANGE, LEVEL1_CLAW_WIDTH, LEVEL1_CLAW_WIDTH,
			             LEVEL1_CLAW_DMG, MOD_LEVEL1_CLAW );
			break;

		case WP_ALEVEL3:
			meleeAttack( ent, LEVEL3_CLAW_RANGE, LEVEL3_CLAW_WIDTH, LEVEL3_CLAW_WIDTH,
			             LEVEL3_CLAW_DMG, MOD_LEVEL3_CLAW );
			break;

		case WP_ALEVEL3_UPG:
			meleeAttack( ent, LEVEL3_CLAW_UPG_RANGE, LEVEL3_CLAW_WIDTH,
			             LEVEL3_CLAW_WIDTH, LEVEL3_CLAW_DMG, MOD_LEVEL3_CLAW );
			break;

		case WP_ALEVEL2:
			meleeAttack( ent, LEVEL2_CLAW_RANGE, LEVEL2_CLAW_WIDTH, LEVEL2_CLAW_WIDTH,
			             LEVEL2_CLAW_DMG, MOD_LEVEL2_CLAW );
			break;

		case WP_ALEVEL2_UPG:
			meleeAttack( ent, LEVEL2_CLAW_U_RANGE, LEVEL2_CLAW_WIDTH, LEVEL2_CLAW_WIDTH,
			             LEVEL2_CLAW_DMG, MOD_LEVEL2_CLAW );
			break;

		case WP_ALEVEL4:
			meleeAttack( ent, LEVEL4_CLAW_RANGE, LEVEL4_CLAW_WIDTH,
			             LEVEL4_CLAW_HEIGHT, LEVEL4_CLAW_DMG, MOD_LEVEL4_CLAW );
			break;

		case WP_BLASTER:
			blasterFire( ent );
			break;

		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;

		case WP_FLAMER:
			flamerFire( ent );
			break;

		case WP_PULSE_RIFLE:
			pulseRifleFire( ent );
			break;

		case WP_MASS_DRIVER:
			massDriverFire( ent );
			break;

		case WP_LUCIFER_CANNON:
			LCChargeFire( ent, qfalse );
			break;

		case WP_LAS_GUN:
			lasGunFire( ent );
			break;

		case WP_PAIN_SAW:
			painSawFire( ent );
			break;

		case WP_GRENADE:
			throwGrenade( ent );
			break;

		case WP_LOCKBLOB_LAUNCHER:
			lockBlobLauncherFire( ent );
			break;

		case WP_HIVE:
			hiveFire( ent );
			break;

		case WP_TESLAGEN:
			teslaFire( ent );
			break;

		case WP_MGTURRET:
			bulletFire( ent, MGTURRET_SPREAD, MGTURRET_DMG, MOD_MGTURRET );
			break;

		case WP_ABUILD:
		case WP_ABUILD2:
			buildFire( ent, MN_A_BUILD );
			break;

		case WP_HBUILD:
			buildFire( ent, MN_H_BUILD );
			break;

		default:
			break;
	}
}
예제 #28
0
/*
===============
CheckGrabAttack
===============
*/
void CheckGrabAttack( gentity_t *ent )
{
	trace_t   tr;
	vec3_t    end, dir;
	gentity_t *traceEnt;

	// set aiming directions
	AngleVectors( ent->client->ps.viewangles, forward, right, up );

	CalcMuzzlePoint( ent, forward, right, up, muzzle );

	if ( ent->client->ps.weapon == WP_ALEVEL1 )
	{
		VectorMA( muzzle, LEVEL1_GRAB_RANGE, forward, end );
	}
	else if ( ent->client->ps.weapon == WP_ALEVEL1_UPG )
	{
		VectorMA( muzzle, LEVEL1_GRAB_U_RANGE, forward, end );
	}

	trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT );

	if ( tr.surfaceFlags & SURF_NOIMPACT )
	{
		return;
	}

	traceEnt = &g_entities[ tr.entityNum ];

	if ( !traceEnt->takedamage )
	{
		return;
	}

	if ( traceEnt->client )
	{
		if ( traceEnt->client->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
		{
			return;
		}

		if ( traceEnt->client->ps.stats[ STAT_HEALTH ] <= 0 )
		{
			return;
		}

		if ( !( traceEnt->client->ps.stats[ STAT_STATE ] & SS_GRABBED ) )
		{
			AngleVectors( traceEnt->client->ps.viewangles, dir, NULL, NULL );
			traceEnt->client->ps.stats[ STAT_VIEWLOCK ] = DirToByte( dir );

			//event for client side grab effect
			G_AddPredictableEvent( ent, EV_LEV1_GRAB, 0 );
		}

		traceEnt->client->ps.stats[ STAT_STATE ] |= SS_GRABBED;

		if ( ent->client->ps.weapon == WP_ALEVEL1 )
		{
			traceEnt->client->grabExpiryTime = level.time + LEVEL1_GRAB_TIME;

			// Update the last combat time.
			ent->client->lastCombatTime = level.time + LEVEL1_GRAB_TIME;
			traceEnt->client->lastCombatTime = level.time + LEVEL1_GRAB_TIME;
		}
		else if ( ent->client->ps.weapon == WP_ALEVEL1_UPG )
		{
			traceEnt->client->grabExpiryTime = level.time + LEVEL1_GRAB_U_TIME;

			// Update the last combat time.
			ent->client->lastCombatTime = level.time + LEVEL1_GRAB_TIME;
			traceEnt->client->lastCombatTime = level.time + LEVEL1_GRAB_TIME;
		}
	}
}
예제 #29
0
파일: g_weapon.c 프로젝트: wtfbbqhax/thz
/*
===============
CheckPounceAttack
===============
*/
qboolean CheckPounceAttack( gentity_t *ent )
{
  trace_t   tr;
  vec3_t    end;
  gentity_t *tent;
  gentity_t *traceEnt;
  int       damage;
  vec3_t    mins, maxs;

  VectorSet( mins, -LEVEL3_POUNCE_WIDTH, -LEVEL3_POUNCE_WIDTH, -LEVEL3_POUNCE_WIDTH );
  VectorSet( maxs, LEVEL3_POUNCE_WIDTH, LEVEL3_POUNCE_WIDTH, LEVEL3_POUNCE_WIDTH );

  if( !ent->client->allowedToPounce )
    return qfalse;

  if( ent->client->ps.groundEntityNum != ENTITYNUM_NONE )
  {
    ent->client->allowedToPounce = qfalse;
    return qfalse;
  }

  if( ent->client->ps.weaponTime )
    return qfalse;

  // set aiming directions
  AngleVectors( ent->client->ps.viewangles, forward, right, up );

  CalcMuzzlePoint( ent, forward, right, up, muzzle );

  VectorMA( muzzle, LEVEL3_POUNCE_RANGE, forward, end );

  trap_Trace( &tr, ent->s.origin, mins, maxs, end, ent->s.number, MASK_SHOT );

  //miss
  if( tr.fraction >= 1.0 )
    return qfalse;

  if( tr.surfaceFlags & SURF_NOIMPACT )
    return qfalse;

  traceEnt = &g_entities[ tr.entityNum ];

  // send blood impact
  if( traceEnt->takedamage && traceEnt->client )
  {
    tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT );
    tent->s.otherEntityNum = traceEnt->s.number;
    tent->s.eventParm = DirToByte( tr.plane.normal );
    tent->s.weapon = ent->s.weapon;
    tent->s.generic1 = ent->s.generic1; //weaponMode
  }

  if( !traceEnt->takedamage )
    return qfalse;

  damage = (int)( ( (float)ent->client->pouncePayload / (float)LEVEL3_POUNCE_SPEED ) * LEVEL3_POUNCE_DMG );

  G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage,
      DAMAGE_NO_KNOCKBACK|DAMAGE_NO_LOCDAMAGE, MOD_LEVEL3_POUNCE );

  ent->client->ps.weaponTime += LEVEL3_POUNCE_TIME;
  ent->client->allowedToPounce = qfalse;

  return qtrue;
}
예제 #30
0
파일: g_weapon.c 프로젝트: wtfbbqhax/thz
/*
===============
CheckVenomAttack
===============
*/
qboolean CheckVenomAttack( gentity_t *ent )
{
  trace_t   tr;
  vec3_t    end;
  gentity_t *tent;
  gentity_t *traceEnt;
  vec3_t    mins, maxs;
  int       damage = LEVEL0_BITE_DMG;

  VectorSet( mins, -LEVEL0_BITE_WIDTH, -LEVEL0_BITE_WIDTH, -LEVEL0_BITE_WIDTH );
  VectorSet( maxs, LEVEL0_BITE_WIDTH, LEVEL0_BITE_WIDTH, LEVEL0_BITE_WIDTH );

  // set aiming directions
  AngleVectors( ent->client->ps.viewangles, forward, right, up );

  CalcMuzzlePoint( ent, forward, right, up, muzzle );

  VectorMA( muzzle, LEVEL0_BITE_RANGE, forward, end );

  trap_Trace( &tr, muzzle, mins, maxs, end, ent->s.number, MASK_SHOT );

  if( tr.surfaceFlags & SURF_NOIMPACT )
    return qfalse;

  traceEnt = &g_entities[ tr.entityNum ];

  if( !traceEnt->takedamage )
    return qfalse;

  if( !traceEnt->client && !traceEnt->s.eType == ET_BUILDABLE )
    return qfalse;

  //allow bites to work against defensive buildables only
  if( traceEnt->s.eType == ET_BUILDABLE )
  {
    if( traceEnt->s.modelindex != BA_H_MGTURRET &&
        traceEnt->s.modelindex != BA_H_TESLAGEN )
      return qfalse;

    //hackery
    damage *= 0.5f;
  }

  if( traceEnt->client )
  {
    if( traceEnt->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
      return qfalse;
    if( traceEnt->client->ps.stats[ STAT_HEALTH ] <= 0 )
      return qfalse;
  }

  // send blood impact
  if( traceEnt->takedamage && traceEnt->client )
  {
    tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT );
    tent->s.otherEntityNum = traceEnt->s.number;
    tent->s.eventParm = DirToByte( tr.plane.normal );
    tent->s.weapon = ent->s.weapon;
    tent->s.generic1 = ent->s.generic1; //weaponMode
  }

  G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, MOD_LEVEL0_BITE );

  return qtrue;
}