1 #include "g_local.h"
2 void MatrixJabAndHook(edict_t *ent);
3 void MatrixCharge(edict_t *ent);
4 void swoosh (edict_t *ent);
5 
P_ProjectSource(gclient_t * client,vec3_t point,vec3_t distance,vec3_t forward,vec3_t right,vec3_t result)6 static void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
7 {
8 	vec3_t	_distance;
9 
10 	VectorCopy (distance, _distance);
11 	if (client->pers.hand == LEFT_HANDED)
12 		_distance[1] *= -1;
13 	else if (client->pers.hand == CENTER_HANDED)
14 		_distance[1] = 0;
15 	G_ProjectSource (point, _distance, forward, right, result);
16 }
17 
MatrixKungfu(edict_t * ent)18 void MatrixKungfu (edict_t *ent)
19 {
20 
21 	MatrixJabAndHook(ent);
22 	MatrixCharge(ent);
23 }
MatrixJabAndHook(edict_t * ent)24 void MatrixJabAndHook(edict_t *ent)
25 {
26 	vec3_t	forward, right;
27 	vec3_t  offset, start;
28     trace_t tr;
29     vec3_t end;
30 	int damage, kick, MOD, sum;
31 	edict_t	*target = NULL;
32 	edict_t *blip = NULL;
33 	vec3_t	targetdir, blipdir, dir, AngleToTarget;
34 	vec_t	speed;
35 	int		dist;
36 
37 	if(ent->client->ps.stats[STAT_SPECTATOR])
38 		return;
39 	//if(ent->client->weaponstate == WEAPON_FIRING)
40 	//	return;
41 	//might be cooler to be able to do kungfu and NOT wait for other shit.
42 
43 	if(ent->deadflag)
44 		return;
45 	if(ent->client->next_kungfu > level.framenum)
46 		return;
47 
48 
49 	while ((blip = findradius(blip, ent->s.origin, 100)) != NULL)
50 	{
51 		if (!(blip->svflags & SVF_MONSTER) && !blip->client)
52 			continue;
53 		if (blip == ent)
54 			continue;
55 		if (!blip->takedamage)
56 			continue;
57 		if (blip->health <= 0)
58 			continue;
59 		VectorSubtract(blip->s.origin, ent->s.origin, blipdir);
60 		blipdir[2] += 16;
61 		if ((target == NULL) || (VectorLength(blipdir) < VectorLength(targetdir)))
62 		{
63 			target = blip;
64 			VectorCopy(blipdir, targetdir);
65 		}
66 	}
67 	sum = fabs(ent->client->v_angle[YAW] - ent->oldvangles[YAW]);
68 
69 	if(sum > 180)
70 		sum = 360 - sum;
71 
72 
73 //	gi.cprintf (ent, PRINT_HIGH, "YAW = %i   ",sum);
74 //
75 	if (target != NULL)
76 	{
77 		VectorSubtract(target->s.origin, ent->s.origin, targetdir);
78 		VectorNormalize(targetdir);
79 		tr = gi.trace (ent->s.origin, NULL, NULL, target->s.origin, ent, MASK_MONSTERSOLID);
80 		MOD = MOD_KICK;
81 		damage = 60;
82 		kick = 300;
83 
84 		if(sum> 100)//if you spin far enough, do damage
85 		{
86 			target->velocity[2] +=100;
87 			T_Damage (target, ent, ent, targetdir, target->s.origin, target->s.origin, damage_spinkick->value, kick, 1, MOD_SWEEP);
88 			ent->matrixflip = KUNGFU;
89 			ent->KungFuAnim = SPINKICK;
90 			if(level.framenum < ent->LastHit + 15)
91 			{
92 				ent->CumulativeDamage += damage_spinkick->value;
93 				ent->HitStreak++;
94 				ent->LastHit = level.framenum;
95 			}
96 			else
97 			{
98 				ent->HitStreak = 1;
99 				ent->CumulativeDamage = damage_spinkick->value;
100 				ent->LastHit = level.framenum;
101 			}
102 			ent->KungFuAnim = SPINKICK;
103 			swoosh (ent);//swoosh noise
104 
105 			if (ent->solid != SOLID_NOT && sum> 100)
106 			{
107 				if(IsBlocking(target))
108 				gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf2.wav"), 1, ATTN_NORM, 0);
109 				else
110 				gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/kick1.wav"), 1, ATTN_NORM, 0);
111 				PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
112 
113 				ent->client->next_kungfu = level.framenum + reload_spinkick->value;
114 
115 				return;
116 			}
117 		}
118 
119 
120 
121 
122 	}
123 
124 
125     // don't need to check for water
126 
127 	if (ent->OLDvertbuttons <= 0 &&
128 		ent->vertbuttons>0 &&
129 		!ent->groundentity &&
130 		!ent->oldgroundentity) //hover kick must work even if no enemy in range.
131 			{
132 				MOD = MOD_KICK;
133 				damage = 20;
134 				kick = 1;
135 				swoosh (ent);//swoosh noise
136 
137 				if(target != NULL && tr.fraction < 1.0 && tr.ent->takedamage && !tr.ent->deadflag && !ent->deadflag)
138 				{
139 					T_Damage (target, ent, ent, targetdir, target->s.origin, target->s.origin, damage_hoverkick->value, kick, 1, MOD_HOVER);
140 					if(level.framenum < ent->LastHit + 15)
141 					{
142 					ent->CumulativeDamage += damage_hoverkick->value;
143 					ent->HitStreak++;
144 					ent->LastHit = level.framenum;
145 					}
146 					else
147 					{
148 					ent->HitStreak = 1;
149 					ent->CumulativeDamage = damage_hoverkick->value;
150 					ent->LastHit = level.framenum;
151 					}
152 					ent->KungFuAnim = HOVERKICK;
153 
154 					if (ent->solid != SOLID_NOT )
155 					{
156 						if(IsBlocking(target))
157 						{
158 							gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf2.wav"), 1, ATTN_NORM, 0);
159 
160 						}
161 						else
162 						gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf1.wav"), 1, ATTN_NORM, 0);
163 						PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
164 					}
165 
166 				}
167 				ent->client->next_kungfu = level.framenum + reload_hoverkick->value;
168 
169 
170 					if (ent->velocity[2] > 0)
171 						ent->velocity[2] += 100;
172 					else
173 						ent->velocity[2] += 120;
174 					ent->matrixflip = KUNGFU;
175 					ent->KungFuAnim = HOVERKICK;
176 			}
177 
178     AngleVectors (ent->client->v_angle, forward, right, NULL);
179     VectorScale (forward, 0, ent->client->kick_origin);
180     VectorSet(offset, 0, 0,  ent->viewheight-4);
181     P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
182 
183     VectorMA( start, 80, forward, end );
184 
185     tr = gi.trace (ent->s.origin, NULL, NULL, end, ent, MASK_MONSTERSOLID);
186 
187 	if (tr.fraction < 1.0 && tr.ent->takedamage && !tr.ent->deadflag && !ent->deadflag)
188     {
189 
190 			if(ent->forwardbuttons<0)
191 				return;
192 
193 			if (ent->OLDforwardbuttons == 0 && ent->forwardbuttons>0)
194 			{
195 				MOD = MOD_KICK;
196 				damage = 20;
197 				kick = 250;
198 					T_Damage (tr.ent, ent, ent, forward, tr.endpos, tr.plane.normal, damage_hook->value, kick, 1, MOD_HOOK);
199 					ent->matrixflip = KUNGFU;
200 					ent->KungFuAnim = HOOK;
201 					if(level.framenum < ent->LastHit + 15)
202 					{
203 					ent->CumulativeDamage += damage_hook->value;
204 					ent->HitStreak++;
205 					ent->LastHit = level.framenum;
206 					}
207 					else
208 					{
209 					ent->HitStreak = 1;
210 					ent->CumulativeDamage = damage_hook->value;
211 					ent->LastHit = level.framenum;
212 					}
213 					VectorClear(ent->velocity);
214 					swoosh (ent);//swoosh noise
215 					if (ent->solid != SOLID_NOT )
216 					if(IsBlocking(tr.ent))
217 						gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf2.wav"), 1, ATTN_NORM, 0);
218 						else
219 						gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/kick1.wav"), 1, ATTN_NORM, 0);
220 
221 					PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
222 					ent->client->next_kungfu = level.framenum + reload_hook->value;
223 					ent->client->kick_angles[0] = 16;
224 			}
225 			else
226 			if (ent->OLDstrafebuttons <= 0 && ent->strafebuttons>0 && ent->forwardbuttons == 0)
227 			{
228 				MOD = MOD_KICK;
229 				damage = 10;
230 				kick = 50;
231 					T_Damage (tr.ent, ent, ent, forward, tr.endpos, tr.plane.normal, damage_jab->value, kick, 1, MOD_JAB);
232 					ent->matrixflip = KUNGFU;
233 					ent->KungFuAnim = JAB;
234 					if(level.framenum < ent->LastHit + 15)
235 					{
236 					ent->CumulativeDamage += damage_jab->value;
237 					ent->HitStreak++;
238 					ent->LastHit = level.framenum;
239 					}
240 					else
241 					{
242 					ent->HitStreak = 1;
243 					ent->CumulativeDamage = damage_jab->value;
244 					ent->LastHit = level.framenum;
245 					}
246 					VectorClear(ent->velocity);
247 					swoosh (ent);//swoosh noise
248 					if (ent->solid != SOLID_NOT )
249 					if(IsBlocking(tr.ent))
250 						gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf2.wav"), 1, ATTN_NORM, 0);
251 						else
252 						gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/kick2.wav"), 1, ATTN_NORM, 0);
253 
254 					PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
255 					ent->client->next_kungfu = level.framenum + reload_jab->value;
256 					ent->client->kick_angles[2] = -15;
257 			}
258 			else
259 			if (ent->OLDstrafebuttons >= 0 && ent->strafebuttons<0 && ent->forwardbuttons == 0)
260 			{
261 				MOD = MOD_KICK;
262 				damage = 10;
263 				kick = 50;
264 					T_Damage (tr.ent, ent, ent, forward, tr.endpos, tr.plane.normal, damage_jab->value, kick, 1, MOD_JAB);
265 					ent->matrixflip = KUNGFU;
266 					ent->KungFuAnim = JAB;
267 					if(level.framenum < ent->LastHit + 15)
268 					{
269 					ent->CumulativeDamage += damage_jab->value;
270 					ent->HitStreak++;
271 					ent->LastHit = level.framenum;
272 					}
273 					else
274 					{
275 					ent->HitStreak = 1;
276 					ent->CumulativeDamage = damage_jab->value;
277 					ent->LastHit = level.framenum;
278 					}
279 					VectorClear(ent->velocity);
280 					swoosh (ent);//swoosh noise
281 
282 					if (ent->solid != SOLID_NOT )
283 					if(IsBlocking(tr.ent))
284 					gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf2.wav"), 1, ATTN_NORM, 0);
285 					else
286 					gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/kick.wav"), 1, ATTN_NORM, 0);
287 					PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
288 					ent->client->next_kungfu = level.framenum + reload_jab->value;
289 					ent->client->kick_angles[2] = 15;
290 			}
291 			else
292 			if (ent->OLDvertbuttons < 0 && ent->vertbuttons>=0 && ent->groundentity)
293 			{
294 				MOD = MOD_KICK;
295 				damage = 80;
296 				kick = 500;
297 					tr.ent->velocity[2] += 200;
298 					T_Damage (tr.ent, ent, ent, forward, tr.endpos, tr.plane.normal, damage_uppercut->value, kick, 1, MOD_UPPERCUT);
299 					ent->matrixflip = KUNGFU;
300 					ent->KungFuAnim = UPPERCUT;
301 					if(level.framenum < ent->LastHit + 15)
302 					{
303 					ent->CumulativeDamage += damage_uppercut->value;
304 					ent->HitStreak++;
305 					ent->LastHit = level.framenum;
306 					}
307 					else
308 					{
309 					ent->HitStreak = 1;
310 					ent->CumulativeDamage = damage_uppercut->value;
311 					ent->LastHit = level.framenum;
312 					}
313 					VectorClear(ent->velocity);
314 					swoosh (ent);//swoosh noise
315 
316 					if (ent->solid != SOLID_NOT )
317 						if(IsBlocking(tr.ent))
318 						gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf2.wav"), 1, ATTN_NORM, 0);
319 						else
320 						gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf1.wav"), 1, ATTN_NORM, 0);
321 
322 					PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
323 					ent->client->next_kungfu = level.framenum + reload_uppercut->value;
324 					ent->client->kick_angles[0] = -40;
325 			}
326 
327 
328 	}
329 
330 
331  VectorCopy(ent->client->v_angle, ent->oldvangles);//NB i am getting pissed off by this thing - WATCH IT.
332 }
333 
MatrixCharge(edict_t * ent)334 void MatrixCharge(edict_t *ent) // if you go fast and run into an opponent, you push them back (no damage, just a shoulder charge)
335 //this was a good idea in theory, but it means that people are pushed back before you can hit them.
336 {
337 
338 	/*vec3_t	forward, right;
339 	vec3_t  offset, start, speed;
340     trace_t tr;
341     vec3_t end;
342 
343 	AngleVectors (ent->client->v_angle, forward, right, NULL);
344     VectorScale (forward, 0, ent->client->kick_origin);
345     VectorSet(offset, 0, 0,  ent->viewheight-4);
346     P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
347 
348 	VectorCopy (ent->velocity, forward);
349 	VectorNormalize(forward);
350     VectorMA( start, 80, forward, end );
351 
352     tr = gi.trace (ent->s.origin, NULL, NULL, end, ent, MASK_MONSTERSOLID);
353 	//trace in direction of speed.
354 
355 	if(tr.fraction < 1.0 && tr.ent->takedamage && !tr.ent->deadflag && !ent->deadflag
356 		&& fabs(VectorLength(ent->velocity)) > 210
357 		&& fabs(VectorLength(tr.ent->velocity)) < 200)
358 	{
359 		VectorCopy(ent->velocity, speed);//temp speed
360 		VectorCopy(tr.ent->velocity, ent->velocity);//player takes on enemy's speed
361 		VectorMA(speed, 50, tr.ent->velocity, tr.ent->velocity);//player's original speed added onto enemie's
362 
363 	}
364 */
365 
366 }
swoosh(edict_t * ent)367 void swoosh (edict_t *ent)
368 {
369 	float	sound;
370 	sound = random() * 3;
371 			if (sound <= 1)
372 			{
373 				gi.sound(ent, CHAN_WEAPON, gi.soundindex("misc/throw.wav"), 1, ATTN_NORM, 0);
374 				PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
375 			}
376 			else if (sound <= 2)
377 			{
378 				gi.sound(ent, CHAN_WEAPON, gi.soundindex("misc/throw.wav"), 1, ATTN_NORM, 0);
379 				PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
380 			}
381 			else if(sound <= 3)
382 			{
383 				gi.sound(ent, CHAN_WEAPON, gi.soundindex("misc/swish.wav"), 1, ATTN_NORM, 0);
384 				PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
385 			}
386 }
387 
MatrixComboTally(edict_t * ent)388 void MatrixComboTally (edict_t *ent)
389 {
390 	char	string[1024];
391 
392 
393 	if(ent->HitStreak > 1 && ent->LastHit == level.framenum - 15)
394 	{
395 
396 
397 	// send the layout
398 	/*Com_sprintf (string, sizeof(string),
399 		"xv 160 yv 180 string2 \"%i Hit Combo\" ", 			//combo
400 		ent->HitStreak);
401 
402 	gi.WriteByte (svc_layout);
403 	gi.WriteString (string);
404 	gi.unicast (ent, true);*/
405 	if(combomessage->value)
406 	{
407 	gi.cprintf (ent, PRINT_CHAT, "%i Hit Combo: %i Damage Done\n", ent->HitStreak, (ent->CumulativeDamage * (2 + ent->damagelevel))/2);
408 	if(ent->CumulativeDamage >= 100)
409 	gi.sound(ent, CHAN_VOICE, gi.soundindex("frags/combo.wav"), 1, ATTN_NORM, 0);
410 	}
411 	if(ent->LastHit == level.framenum - 15)
412 	ent->HitStreak  = 0;
413 	ent->CumulativeDamage = 0;
414 	}
415 
416 	if(ent->HitStreak && ent->LastHit  < level.framenum - 15)
417 	{
418 		ent->HitStreak = 0;
419 		ent->CumulativeDamage = 0;
420 	}
421 
422 }
423 
IsBlocking(edict_t * ent)424 int IsBlocking (edict_t *ent)
425 {
426 	if(!ent->client)
427 		return false;
428 
429 	if(strcmp(ent->client->pers.weapon->classname, "weapon_fists") == 0  //if you're using fists or knoves you can block
430 	|| strcmp(ent->client->pers.weapon->classname, "weapon_knives") == 0)
431 		if(ent->forwardbuttons <= 0 && ent->strafebuttons == 0 && ent->client->next_kungfu <= level.framenum && ent->client->weaponstate != WEAPON_FIRING)
432 			return true;
433 	return false;
434 
435 
436 }
437 
438