1 /*
2 ===========================================================================
3 Copyright (C) 2000 - 2013, Raven Software, Inc.
4 Copyright (C) 2001 - 2013, Activision, Inc.
5 Copyright (C) 2013 - 2015, OpenJK contributors
6 
7 This file is part of the OpenJK source code.
8 
9 OpenJK is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, see <http://www.gnu.org/licenses/>.
20 ===========================================================================
21 */
22 
23 #include "g_local.h"
24 #include "b_local.h"
25 #include "g_functions.h"
26 #include "wp_saber.h"
27 #include "w_local.h"
28 
29 
30 //---------------
31 //	Blaster
32 //---------------
33 
34 //---------------------------------------------------------
WP_FireBlasterMissile(gentity_t * ent,vec3_t start,vec3_t dir,qboolean altFire)35 void WP_FireBlasterMissile( gentity_t *ent, vec3_t start, vec3_t dir, qboolean altFire )
36 //---------------------------------------------------------
37 {
38 	int velocity	= BLASTER_VELOCITY;
39 	int	damage		= altFire ? weaponData[WP_BLASTER].altDamage : weaponData[WP_BLASTER].damage;
40 
41 	if ( ent && ent->client && ent->client->NPC_class == CLASS_VEHICLE )
42 	{
43 		damage *= 3;
44 		velocity = ATST_MAIN_VEL + ent->client->ps.speed;
45 	}
46 	else
47 	{
48 		// If an enemy is shooting at us, lower the velocity so you have a chance to evade
49 		if ( ent->client && ent->client->ps.clientNum != 0 && ent->client->NPC_class != CLASS_BOBAFETT )
50 		{
51 			if ( g_spskill->integer < 2 )
52 			{
53 				velocity *= BLASTER_NPC_VEL_CUT;
54 			}
55 			else
56 			{
57 				velocity *= BLASTER_NPC_HARD_VEL_CUT;
58 			}
59 		}
60 	}
61 
62 	WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall
63 
64 	WP_MissileTargetHint(ent, start, dir);
65 
66 	gentity_t *missile = CreateMissile( start, dir, velocity, 10000, ent, altFire );
67 
68 	missile->classname = "blaster_proj";
69 	missile->s.weapon = WP_BLASTER;
70 
71 	// Do the damages
72 	if ( ent->s.number != 0 && ent->client->NPC_class != CLASS_BOBAFETT )
73 	{
74 		if ( g_spskill->integer == 0 )
75 		{
76 			damage = BLASTER_NPC_DAMAGE_EASY;
77 		}
78 		else if ( g_spskill->integer == 1 )
79 		{
80 			damage = BLASTER_NPC_DAMAGE_NORMAL;
81 		}
82 		else
83 		{
84 			damage = BLASTER_NPC_DAMAGE_HARD;
85 		}
86 	}
87 
88 //	if ( ent->client )
89 //	{
90 //		if ( ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time )
91 //		{
92 //			// in overcharge mode, so doing double damage
93 //			missile->flags |= FL_OVERCHARGED;
94 //			damage *= 2;
95 //		}
96 //	}
97 
98 	missile->damage = damage;
99 	missile->dflags = DAMAGE_DEATH_KNOCKBACK;
100 	if ( altFire )
101 	{
102 		missile->methodOfDeath = MOD_BLASTER_ALT;
103 	}
104 	else
105 	{
106 		missile->methodOfDeath = MOD_BLASTER;
107 	}
108 	missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER;
109 
110 	// we don't want it to bounce forever
111 	missile->bounceCount = 8;
112 }
113 
114 //---------------------------------------------------------
WP_FireBlaster(gentity_t * ent,qboolean alt_fire)115 void WP_FireBlaster( gentity_t *ent, qboolean alt_fire )
116 //---------------------------------------------------------
117 {
118 	vec3_t	dir, angs;
119 
120 	vectoangles( forwardVec, angs );
121 
122 	if ( ent->client && ent->client->NPC_class == CLASS_VEHICLE )
123 	{//no inherent aim screw up
124 	}
125 	else if ( !(ent->client->ps.forcePowersActive&(1<<FP_SEE))
126 		|| ent->client->ps.forcePowerLevel[FP_SEE] < FORCE_LEVEL_2 )
127 	{//force sight 2+ gives perfect aim
128 		//FIXME: maybe force sight level 3 autoaims some?
129 		if ( alt_fire )
130 		{
131 			// add some slop to the alt-fire direction
132 			angs[PITCH] += Q_flrand(-1.0f, 1.0f) * BLASTER_ALT_SPREAD;
133 			angs[YAW]	+= Q_flrand(-1.0f, 1.0f) * BLASTER_ALT_SPREAD;
134 		}
135 		else
136 		{
137 			// Troopers use their aim values as well as the gun's inherent inaccuracy
138 			// so check for all classes of stormtroopers and anyone else that has aim error
139 			if ( ent->client && ent->NPC &&
140 				( ent->client->NPC_class == CLASS_STORMTROOPER ||
141 				ent->client->NPC_class == CLASS_SWAMPTROOPER ) )
142 			{
143 				angs[PITCH] += ( Q_flrand(-1.0f, 1.0f) * (BLASTER_NPC_SPREAD+(6-ent->NPC->currentAim)*0.25f));//was 0.5f
144 				angs[YAW]	+= ( Q_flrand(-1.0f, 1.0f) * (BLASTER_NPC_SPREAD+(6-ent->NPC->currentAim)*0.25f));//was 0.5f
145 			}
146 			else
147 			{
148 				// add some slop to the main-fire direction
149 				angs[PITCH] += Q_flrand(-1.0f, 1.0f) * BLASTER_MAIN_SPREAD;
150 				angs[YAW]	+= Q_flrand(-1.0f, 1.0f) * BLASTER_MAIN_SPREAD;
151 			}
152 		}
153 	}
154 
155 	AngleVectors( angs, dir, NULL, NULL );
156 
157 	// FIXME: if temp_org does not have clear trace to inside the bbox, don't shoot!
158 	WP_FireBlasterMissile( ent, muzzle, dir, alt_fire );
159 }