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 #include "g_headers.h"
23
24 #include "b_local.h"
25 #include "g_local.h"
26 #include "wp_saber.h"
27 #include "w_local.h"
28 #include "g_functions.h"
29
30 //-------------------
31 // Wookiee Bowcaster
32 //-------------------
33
34 //---------------------------------------------------------
WP_BowcasterMainFire(gentity_t * ent)35 static void WP_BowcasterMainFire( gentity_t *ent )
36 //---------------------------------------------------------
37 {
38 int damage = weaponData[WP_BOWCASTER].damage, count;
39 float vel;
40 vec3_t angs, dir, start;
41 gentity_t *missile;
42
43 VectorCopy( wpMuzzle, start );
44 WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall
45
46 // Do the damages
47 if ( ent->s.number != 0 )
48 {
49 if ( g_spskill->integer == 0 )
50 {
51 damage = BOWCASTER_NPC_DAMAGE_EASY;
52 }
53 else if ( g_spskill->integer == 1 )
54 {
55 damage = BOWCASTER_NPC_DAMAGE_NORMAL;
56 }
57 else
58 {
59 damage = BOWCASTER_NPC_DAMAGE_HARD;
60 }
61 }
62
63 count = ( level.time - ent->client->ps.weaponChargeTime ) / BOWCASTER_CHARGE_UNIT;
64
65 if ( count < 1 )
66 {
67 count = 1;
68 }
69 else if ( count > 5 )
70 {
71 count = 5;
72 }
73
74 if ( !(count & 1 ))
75 {
76 // if we aren't odd, knock us down a level
77 count--;
78 }
79
80 // if ( ent->client && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time )
81 // {
82 // // in overcharge mode, so doing double damage
83 // damage *= 2;
84 // }
85
86 for ( int i = 0; i < count; i++ )
87 {
88 // create a range of different velocities
89 vel = BOWCASTER_VELOCITY * ( Q_flrand(-1.0f, 1.0f) * BOWCASTER_VEL_RANGE + 1.0f );
90
91 vectoangles( wpFwd, angs );
92
93 // add some slop to the fire direction
94 angs[PITCH] += Q_flrand(-1.0f, 1.0f) * BOWCASTER_ALT_SPREAD * 0.2f;
95 angs[YAW] += ((i+0.5f) * BOWCASTER_ALT_SPREAD - count * 0.5f * BOWCASTER_ALT_SPREAD );
96 if ( ent->NPC )
97 {
98 angs[PITCH] += ( Q_flrand(-1.0f, 1.0f) * (BLASTER_NPC_SPREAD+(6-ent->NPC->currentAim)*0.25f) );
99 angs[YAW] += ( Q_flrand(-1.0f, 1.0f) * (BLASTER_NPC_SPREAD+(6-ent->NPC->currentAim)*0.25f) );
100 }
101
102 AngleVectors( angs, dir, NULL, NULL );
103
104 missile = CreateMissile( start, dir, vel, 10000, ent );
105
106 missile->classname = "bowcaster_proj";
107 missile->s.weapon = WP_BOWCASTER;
108
109 VectorSet( missile->maxs, BOWCASTER_SIZE, BOWCASTER_SIZE, BOWCASTER_SIZE );
110 VectorScale( missile->maxs, -1, missile->mins );
111
112 // if ( ent->client && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time )
113 // {
114 // missile->flags |= FL_OVERCHARGED;
115 // }
116
117 missile->damage = damage;
118 missile->dflags = DAMAGE_DEATH_KNOCKBACK;
119 missile->methodOfDeath = MOD_BOWCASTER;
120 missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER;
121 missile->splashDamage = weaponData[WP_BOWCASTER].splashDamage;
122 missile->splashRadius = weaponData[WP_BOWCASTER].splashRadius;
123
124 // we don't want it to bounce
125 missile->bounceCount = 0;
126 ent->client->sess.missionStats.shotsFired++;
127 }
128 }
129
130 //---------------------------------------------------------
WP_BowcasterAltFire(gentity_t * ent)131 static void WP_BowcasterAltFire( gentity_t *ent )
132 //---------------------------------------------------------
133 {
134 vec3_t start;
135 int damage = weaponData[WP_BOWCASTER].altDamage;
136
137 VectorCopy( wpMuzzle, start );
138 WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall
139
140 gentity_t *missile = CreateMissile( start, wpFwd, BOWCASTER_VELOCITY, 10000, ent, qtrue );
141
142 missile->classname = "bowcaster_alt_proj";
143 missile->s.weapon = WP_BOWCASTER;
144
145 // Do the damages
146 if ( ent->s.number != 0 )
147 {
148 if ( g_spskill->integer == 0 )
149 {
150 damage = BOWCASTER_NPC_DAMAGE_EASY;
151 }
152 else if ( g_spskill->integer == 1 )
153 {
154 damage = BOWCASTER_NPC_DAMAGE_NORMAL;
155 }
156 else
157 {
158 damage = BOWCASTER_NPC_DAMAGE_HARD;
159 }
160 }
161
162 VectorSet( missile->maxs, BOWCASTER_SIZE, BOWCASTER_SIZE, BOWCASTER_SIZE );
163 VectorScale( missile->maxs, -1, missile->mins );
164
165 // if ( ent->client && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time )
166 // {
167 // // in overcharge mode, so doing double damage
168 // missile->flags |= FL_OVERCHARGED;
169 // damage *= 2;
170 // }
171
172 missile->s.eFlags |= EF_BOUNCE;
173 missile->bounceCount = 3;
174
175 missile->damage = damage;
176 missile->dflags = DAMAGE_DEATH_KNOCKBACK;
177 missile->methodOfDeath = MOD_BOWCASTER_ALT;
178 missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER;
179 missile->splashDamage = weaponData[WP_BOWCASTER].splashDamage;
180 missile->splashRadius = weaponData[WP_BOWCASTER].splashRadius;
181 }
182
183 //---------------------------------------------------------
WP_FireBowcaster(gentity_t * ent,qboolean alt_fire)184 void WP_FireBowcaster( gentity_t *ent, qboolean alt_fire )
185 //---------------------------------------------------------
186 {
187 if ( alt_fire )
188 {
189 WP_BowcasterAltFire( ent );
190 }
191 else
192 {
193 WP_BowcasterMainFire( ent );
194 }
195 }