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 }