1#include "hagar.qh"
2#ifndef IMPLEMENTATION
3CLASS(Hagar, Weapon)
4/* ammotype  */ ATTRIB(Hagar, ammo_field, .int, ammo_rockets);
5/* impulse   */ ATTRIB(Hagar, impulse, int, 8);
6/* flags     */ ATTRIB(Hagar, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
7/* rating    */ ATTRIB(Hagar, bot_pickupbasevalue, float, 6000);
8/* color     */ ATTRIB(Hagar, wpcolor, vector, '1 1 0.5');
9/* modelname */ ATTRIB(Hagar, mdl, string, "hagar");
10#ifdef GAMEQC
11/* model     */ ATTRIB(Hagar, m_model, Model, MDL_HAGAR_ITEM);
12#endif
13/* crosshair */ ATTRIB(Hagar, w_crosshair, string, "gfx/crosshairhagar");
14/* crosshair */ ATTRIB(Hagar, w_crosshair_size, float, 0.8);
15/* wepimg    */ ATTRIB(Hagar, model2, string, "weaponhagar");
16/* refname   */ ATTRIB(Hagar, netname, string, "hagar");
17/* wepname   */ ATTRIB(Hagar, m_name, string, _("Hagar"));
18
19#define X(BEGIN, P, END, class, prefix) \
20	BEGIN(class) \
21		P(class, prefix, ammo, float, BOTH) \
22        P(class, prefix, damageforcescale, float, BOTH) \
23        P(class, prefix, damage, float, BOTH) \
24        P(class, prefix, edgedamage, float, BOTH) \
25        P(class, prefix, force, float, BOTH) \
26        P(class, prefix, health, float, BOTH) \
27        P(class, prefix, lifetime, float, PRI) \
28        P(class, prefix, lifetime_min, float, SEC) \
29        P(class, prefix, lifetime_rand, float, SEC) \
30        P(class, prefix, load, float, SEC) \
31        P(class, prefix, load_abort, float, SEC) \
32        P(class, prefix, load_animtime, float, SEC) \
33        P(class, prefix, load_hold, float, SEC) \
34        P(class, prefix, load_linkexplode, float, SEC) \
35        P(class, prefix, load_max, float, SEC) \
36        P(class, prefix, load_releasedeath, float, SEC) \
37        P(class, prefix, load_speed, float, SEC) \
38        P(class, prefix, load_spread, float, SEC) \
39        P(class, prefix, load_spread_bias, float, SEC) \
40        P(class, prefix, radius, float, BOTH) \
41        P(class, prefix, refire, float, BOTH) \
42        P(class, prefix, reload_ammo, float, NONE) \
43        P(class, prefix, reload_time, float, NONE) \
44        P(class, prefix, secondary, float, NONE) \
45        P(class, prefix, speed, float, BOTH) \
46        P(class, prefix, spread, float, BOTH) \
47        P(class, prefix, switchdelay_drop, float, NONE) \
48        P(class, prefix, switchdelay_raise, float, NONE) \
49        P(class, prefix, weaponreplace, string,NONE) \
50        P(class, prefix, weaponstartoverride, float, NONE) \
51        P(class, prefix, weaponstart, float, NONE) \
52        P(class, prefix, weaponthrowable, float, NONE) \
53	END()
54    W_PROPS(X, Hagar, hagar)
55#undef X
56
57ENDCLASS(Hagar)
58REGISTER_WEAPON(HAGAR, hagar, NEW(Hagar));
59
60#endif
61#ifdef IMPLEMENTATION
62#ifdef SVQC
63spawnfunc(weapon_hagar) { weapon_defaultspawnfunc(this, WEP_HAGAR); }
64
65// NO bounce protection, as bounces are limited!
66
67void W_Hagar_Explode(entity this, entity directhitentity)
68{
69	this.event_damage = func_null;
70	RadiusDamage(this, this.realowner, WEP_CVAR_PRI(hagar, damage), WEP_CVAR_PRI(hagar, edgedamage), WEP_CVAR_PRI(hagar, radius), NULL, NULL, WEP_CVAR_PRI(hagar, force), this.projectiledeathtype, directhitentity);
71
72	delete(this);
73}
74
75void W_Hagar_Explode_use(entity this, entity actor, entity trigger)
76{
77	W_Hagar_Explode(this, trigger);
78}
79
80void W_Hagar_Explode2(entity this, entity directhitentity)
81{
82	this.event_damage = func_null;
83	RadiusDamage(this, this.realowner, WEP_CVAR_SEC(hagar, damage), WEP_CVAR_SEC(hagar, edgedamage), WEP_CVAR_SEC(hagar, radius), NULL, NULL, WEP_CVAR_SEC(hagar, force), this.projectiledeathtype, directhitentity);
84
85	delete(this);
86}
87
88void W_Hagar_Explode2_use(entity this, entity actor, entity trigger)
89{
90	W_Hagar_Explode2(this, trigger);
91}
92
93void W_Hagar_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
94{
95	if(this.health <= 0)
96		return;
97
98	float is_linkexplode = ( ((inflictor.owner != NULL) ? (inflictor.owner == this.owner) : true)
99		&& (inflictor.projectiledeathtype & HITTYPE_SECONDARY)
100		&& (this.projectiledeathtype & HITTYPE_SECONDARY));
101
102	if(is_linkexplode)
103		is_linkexplode = (is_linkexplode && WEP_CVAR_SEC(hagar, load_linkexplode));
104	else
105		is_linkexplode = -1; // not secondary load, so continue as normal without exception.
106
107	if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, is_linkexplode))
108		return; // g_projectiles_damage says to halt
109
110	this.health = this.health - damage;
111	this.angles = vectoangles(this.velocity);
112
113	if(this.health <= 0)
114		W_PrepareExplosionByDamage(this, attacker, getthink(this));
115}
116
117void W_Hagar_Touch(entity this, entity toucher)
118{
119	PROJECTILE_TOUCH(this, toucher);
120	this.use(this, NULL, toucher);
121}
122
123void W_Hagar_Touch2(entity this, entity toucher)
124{
125	PROJECTILE_TOUCH(this, toucher);
126
127	if(this.cnt > 0 || toucher.takedamage == DAMAGE_AIM) {
128		this.use(this, NULL, toucher);
129	} else {
130		this.cnt++;
131		Send_Effect(EFFECT_HAGAR_BOUNCE, this.origin, this.velocity, 1);
132		this.angles = vectoangles(this.velocity);
133		this.owner = NULL;
134		this.projectiledeathtype |= HITTYPE_BOUNCE;
135	}
136}
137
138void W_Hagar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
139{
140	entity missile;
141
142	W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(hagar, ammo), weaponentity);
143
144	W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage));
145
146	Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
147
148	missile = new(missile);
149	missile.owner = missile.realowner = actor;
150	missile.bot_dodge = true;
151	missile.bot_dodgerating = WEP_CVAR_PRI(hagar, damage);
152
153	missile.takedamage = DAMAGE_YES;
154	missile.health = WEP_CVAR_PRI(hagar, health);
155	missile.damageforcescale = WEP_CVAR_PRI(hagar, damageforcescale);
156	missile.event_damage = W_Hagar_Damage;
157	missile.damagedbycontents = true;
158	IL_PUSH(g_damagedbycontents, missile);
159
160	settouch(missile, W_Hagar_Touch);
161	missile.use = W_Hagar_Explode_use;
162	setthink(missile, adaptor_think2use_hittype_splash);
163	missile.nextthink = time + WEP_CVAR_PRI(hagar, lifetime);
164	PROJECTILE_MAKETRIGGER(missile);
165	missile.projectiledeathtype = WEP_HAGAR.m_id;
166	setorigin(missile, w_shotorg);
167	setsize(missile, '0 0 0', '0 0 0');
168
169	set_movetype(missile, MOVETYPE_FLY);
170	W_SetupProjVelocity_PRI(missile, hagar);
171
172	missile.angles = vectoangles(missile.velocity);
173	missile.flags = FL_PROJECTILE;
174	IL_PUSH(g_projectiles, missile);
175	IL_PUSH(g_bot_dodge, missile);
176	missile.missile_flags = MIF_SPLASH;
177
178	CSQCProjectile(missile, true, PROJECTILE_HAGAR, true);
179
180	MUTATOR_CALLHOOK(EditProjectile, actor, missile);
181}
182
183void W_Hagar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
184{
185	entity missile;
186
187	W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo), weaponentity);
188
189	W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
190
191	Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
192
193	missile = new(missile);
194	missile.owner = missile.realowner = actor;
195	missile.bot_dodge = true;
196	missile.bot_dodgerating = WEP_CVAR_SEC(hagar, damage);
197
198	missile.takedamage = DAMAGE_YES;
199	missile.health = WEP_CVAR_SEC(hagar, health);
200	missile.damageforcescale = WEP_CVAR_SEC(hagar, damageforcescale);
201	missile.event_damage = W_Hagar_Damage;
202	missile.damagedbycontents = true;
203	IL_PUSH(g_damagedbycontents, missile);
204
205	settouch(missile, W_Hagar_Touch2);
206	missile.cnt = 0;
207	missile.use = W_Hagar_Explode2_use;
208	setthink(missile, adaptor_think2use_hittype_splash);
209	missile.nextthink = time + WEP_CVAR_SEC(hagar, lifetime_min) + random() * WEP_CVAR_SEC(hagar, lifetime_rand);
210	PROJECTILE_MAKETRIGGER(missile);
211	missile.projectiledeathtype = WEP_HAGAR.m_id | HITTYPE_SECONDARY;
212	setorigin(missile, w_shotorg);
213	setsize(missile, '0 0 0', '0 0 0');
214
215	set_movetype(missile, MOVETYPE_BOUNCEMISSILE);
216	W_SetupProjVelocity_SEC(missile, hagar);
217
218	missile.angles = vectoangles(missile.velocity);
219	missile.flags = FL_PROJECTILE;
220	IL_PUSH(g_projectiles, missile);
221	IL_PUSH(g_bot_dodge, missile);
222	missile.missile_flags = MIF_SPLASH;
223
224	CSQCProjectile(missile, true, PROJECTILE_HAGAR_BOUNCING, true);
225
226	MUTATOR_CALLHOOK(EditProjectile, actor, missile);
227}
228
229.float hagar_loadstep, hagar_loadblock, hagar_loadbeep, hagar_warning;
230void W_Hagar_Attack2_Load_Release(entity actor, .entity weaponentity)
231{
232	// time to release the rockets we've loaded
233
234	entity missile;
235	float counter, shots, spread_pershot;
236	vector s;
237	vector forward, right, up;
238
239	if(!actor.(weaponentity).hagar_load)
240		return;
241
242	weapon_prepareattack_do(actor, weaponentity, true, WEP_CVAR_SEC(hagar, refire));
243
244	W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
245	Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
246
247	forward = v_forward;
248	right = v_right;
249	up = v_up;
250
251	shots = actor.(weaponentity).hagar_load;
252	missile = NULL;
253	for(counter = 0; counter < shots; ++counter)
254	{
255		missile = new(missile);
256		missile.owner = missile.realowner = actor;
257		missile.bot_dodge = true;
258		missile.bot_dodgerating = WEP_CVAR_SEC(hagar, damage);
259
260		missile.takedamage = DAMAGE_YES;
261		missile.health = WEP_CVAR_SEC(hagar, health);
262		missile.damageforcescale = WEP_CVAR_SEC(hagar, damageforcescale);
263		missile.event_damage = W_Hagar_Damage;
264		missile.damagedbycontents = true;
265		IL_PUSH(g_damagedbycontents, missile);
266
267		settouch(missile, W_Hagar_Touch); // not bouncy
268		missile.use = W_Hagar_Explode2_use;
269		setthink(missile, adaptor_think2use_hittype_splash);
270		missile.nextthink = time + WEP_CVAR_SEC(hagar, lifetime_min) + random() * WEP_CVAR_SEC(hagar, lifetime_rand);
271		PROJECTILE_MAKETRIGGER(missile);
272		missile.projectiledeathtype = WEP_HAGAR.m_id | HITTYPE_SECONDARY;
273		setorigin(missile, w_shotorg);
274		setsize(missile, '0 0 0', '0 0 0');
275		set_movetype(missile, MOVETYPE_FLY);
276		missile.missile_flags = MIF_SPLASH;
277
278		// per-shot spread calculation: the more shots there are, the less spread is applied (based on the bias cvar)
279		spread_pershot = ((shots - 1) / (WEP_CVAR_SEC(hagar, load_max) - 1));
280		spread_pershot = (1 - (spread_pershot * WEP_CVAR_SEC(hagar, load_spread_bias)));
281		spread_pershot = (WEP_CVAR_SEC(hagar, spread) * spread_pershot * g_weaponspreadfactor);
282
283		// pattern spread calculation
284		s = '0 0 0';
285		if(counter == 0)
286			s = '0 0 0';
287		else
288		{
289			makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1)));
290			s.y = v_forward.x;
291			s.z = v_forward.y;
292		}
293		s = s * WEP_CVAR_SEC(hagar, load_spread) * g_weaponspreadfactor;
294
295		W_SetupProjVelocity_Explicit(missile, w_shotdir + right * s.y + up * s.z, v_up, WEP_CVAR_SEC(hagar, speed), 0, 0, spread_pershot, false);
296
297		missile.angles = vectoangles(missile.velocity);
298		missile.flags = FL_PROJECTILE;
299		IL_PUSH(g_projectiles, missile);
300		IL_PUSH(g_bot_dodge, missile);
301
302		CSQCProjectile(missile, true, PROJECTILE_HAGAR, true);
303
304		MUTATOR_CALLHOOK(EditProjectile, actor, missile);
305	}
306
307	weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hagar, load_animtime), w_ready);
308	actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(hagar, refire) * W_WeaponRateFactor(actor);
309	actor.(weaponentity).hagar_load = 0;
310
311	if(weaponslot(weaponentity) == 0)
312		actor.hagar_load = 0;
313}
314
315void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
316{
317	// loadable hagar secondary attack, must always run each frame
318	if(round_handler_IsActive() && !round_handler_IsRoundStarted())
319		return;
320	if(time < game_starttime)
321		return;
322
323	bool loaded = actor.(weaponentity).hagar_load >= WEP_CVAR_SEC(hagar, load_max);
324
325	// this is different than WR_CHECKAMMO when it comes to reloading
326	bool enough_ammo;
327	if(actor.items & IT_UNLIMITED_WEAPON_AMMO)
328		enough_ammo = true;
329	else if(autocvar_g_balance_hagar_reload_ammo)
330		enough_ammo = actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
331	else
332		enough_ammo = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(hagar, ammo);
333
334	bool stopped = loaded || !enough_ammo;
335
336	if(PHYS_INPUT_BUTTON_ATCK2(actor))
337	{
338		if(PHYS_INPUT_BUTTON_ATCK(actor) && WEP_CVAR_SEC(hagar, load_abort))
339		{
340			if(actor.(weaponentity).hagar_load)
341			{
342				// if we pressed primary fire while loading, unload all rockets and abort
343				actor.(weaponentity).state = WS_READY;
344				W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo) * actor.(weaponentity).hagar_load * -1, weaponentity); // give back ammo
345				actor.(weaponentity).hagar_load = 0;
346				if(weaponslot(weaponentity) == 0)
347					actor.hagar_load = 0;
348				sound(actor, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
349
350				// pause until we can load rockets again, once we re-press the alt fire button
351				actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor(actor);
352
353				// require letting go of the alt fire button before we can load again
354				actor.(weaponentity).hagar_loadblock = true;
355			}
356		}
357		else
358		{
359			// check if we can attempt to load another rocket
360			if(!stopped)
361			{
362				if(!actor.(weaponentity).hagar_loadblock && actor.(weaponentity).hagar_loadstep < time)
363				{
364					W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo), weaponentity);
365					actor.(weaponentity).state = WS_INUSE;
366					actor.(weaponentity).hagar_load += 1;
367					sound(actor, CH_WEAPON_B, SND_HAGAR_LOAD, VOL_BASE * 0.8, ATTN_NORM); // sound is too loud according to most
368
369					if(actor.(weaponentity).hagar_load >= WEP_CVAR_SEC(hagar, load_max))
370						stopped = true;
371					else
372						actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor(actor);
373				}
374			}
375			if(stopped && !actor.(weaponentity).hagar_loadbeep && actor.(weaponentity).hagar_load) // prevents the beep from playing each frame
376			{
377				// if this is the last rocket we can load, play a beep sound to notify the player
378				sound(actor, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
379				actor.(weaponentity).hagar_loadbeep = true;
380				actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_hold) * W_WeaponRateFactor(actor);
381			}
382		}
383	}
384	else if(actor.(weaponentity).hagar_loadblock)
385	{
386		// the alt fire button has been released, so re-enable loading if blocked
387		actor.(weaponentity).hagar_loadblock = false;
388	}
389
390	if(actor.(weaponentity).hagar_load)
391	{
392		// play warning sound if we're about to release
393		if(stopped && actor.(weaponentity).hagar_loadstep - 0.5 < time && WEP_CVAR_SEC(hagar, load_hold) >= 0)
394		{
395			if(!actor.(weaponentity).hagar_warning) // prevents the beep from playing each frame
396			{
397				// we're about to automatically release after holding time, play a beep sound to notify the player
398				sound(actor, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
399				actor.(weaponentity).hagar_warning = true;
400			}
401		}
402
403		// release if player let go of button or if they've held it in too long
404		if(!PHYS_INPUT_BUTTON_ATCK2(actor) || (stopped && actor.(weaponentity).hagar_loadstep < time && WEP_CVAR_SEC(hagar, load_hold) >= 0))
405		{
406			actor.(weaponentity).state = WS_READY;
407			W_Hagar_Attack2_Load_Release(actor, weaponentity);
408		}
409	}
410	else
411	{
412		actor.(weaponentity).hagar_loadbeep = false;
413		actor.(weaponentity).hagar_warning = false;
414
415		// we aren't checking ammo during an attack, so we must do it here
416		if(!(thiswep.wr_checkammo1(thiswep, actor, weaponentity) + thiswep.wr_checkammo2(thiswep, actor, weaponentity)))
417		if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
418		{
419			// note: this doesn't force the switch
420			W_SwitchToOtherWeapon(actor, weaponentity);
421			return;
422		}
423	}
424}
425
426void W_Hagar_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity, int fire)
427{
428	if(!(fire & 1) || actor.(weaponentity).hagar_load || actor.(weaponentity).hagar_loadblock || actor.(weaponentity).m_switchweapon != WEP_HAGAR)
429	{
430		w_ready(thiswep, actor, weaponentity, fire);
431		return;
432	}
433
434	if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity))
435	if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
436	{
437		W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
438		w_ready(thiswep, actor, weaponentity, fire);
439		return;
440	}
441
442	W_Hagar_Attack(thiswep, actor, weaponentity);
443
444	int slot = weaponslot(weaponentity);
445	ATTACK_FINISHED(actor, slot) = time + WEP_CVAR_PRI(hagar, refire) * W_WeaponRateFactor(actor);
446	int theframe = WFRAME_FIRE1;
447	entity this = actor.(weaponentity);
448	if(this)
449	{
450		if(this.wframe == WFRAME_FIRE1)
451			theframe = WFRAME_DONTCHANGE;
452	}
453	weapon_thinkf(actor, weaponentity, theframe, WEP_CVAR_PRI(hagar, refire), W_Hagar_Attack_Auto);
454}
455
456METHOD(Hagar, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
457{
458    if(random()>0.15)
459        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
460    else // not using secondary_speed since these are only 15% and should cause some ricochets without re-aiming
461        PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
462}
463METHOD(Hagar, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
464{
465    float loadable_secondary;
466    loadable_secondary = (WEP_CVAR_SEC(hagar, load) && WEP_CVAR(hagar, secondary));
467    if(weaponslot(weaponentity) == 0)
468    	actor.hagar_load = actor.(weaponentity).hagar_load;
469
470    if(loadable_secondary)
471        W_Hagar_Attack2_Load(thiswep, actor, weaponentity); // must always run each frame
472    if(autocvar_g_balance_hagar_reload_ammo && actor.(weaponentity).clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) { // forced reload
473        thiswep.wr_reload(thiswep, actor, weaponentity);
474    }
475    else if((fire & 1) && !actor.(weaponentity).hagar_load && !actor.(weaponentity).hagar_loadblock) // not while secondary is loaded or awaiting reset
476	{
477		if(weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
478			W_Hagar_Attack_Auto(thiswep, actor, weaponentity, fire);
479	}
480    else if((fire & 2) && !loadable_secondary && WEP_CVAR(hagar, secondary))
481    {
482        if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(hagar, refire)))
483        {
484            W_Hagar_Attack2(thiswep, actor, weaponentity);
485            weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hagar, refire), w_ready);
486        }
487    }
488}
489METHOD(Hagar, wr_gonethink, void(entity thiswep, entity actor, .entity weaponentity))
490{
491    // we lost the weapon and want to prepare switching away
492    if(actor.(weaponentity).hagar_load)
493    {
494    	actor.(weaponentity).state = WS_READY;
495    	W_Hagar_Attack2_Load_Release(actor, weaponentity);
496    }
497}
498METHOD(Hagar, wr_setup, void(entity thiswep, entity actor, .entity weaponentity))
499{
500	actor.hagar_load = 0;
501    actor.(weaponentity).hagar_loadblock = false;
502    if(actor.(weaponentity).hagar_load)
503    {
504    	W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo) * actor.(weaponentity).hagar_load * -1, weaponentity); // give back ammo if necessary
505    	actor.(weaponentity).hagar_load = 0;
506    }
507}
508METHOD(Hagar, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
509{
510    float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(hagar, ammo);
511    ammo_amount += actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_PRI(hagar, ammo);
512    return ammo_amount;
513}
514METHOD(Hagar, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
515{
516    float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(hagar, ammo);
517    ammo_amount += actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
518    return ammo_amount;
519}
520METHOD(Hagar, wr_resetplayer, void(entity thiswep, entity actor))
521{
522    actor.hagar_load = 0;
523    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
524    {
525    	.entity weaponentity = weaponentities[slot];
526    	actor.(weaponentity).hagar_load = 0;
527    }
528}
529METHOD(Hagar, wr_playerdeath, void(entity thiswep, entity actor, .entity weaponentity))
530{
531    // if we have any rockets loaded when we die, release them
532    if(actor.(weaponentity).hagar_load && WEP_CVAR_SEC(hagar, load_releasedeath))
533    	W_Hagar_Attack2_Load_Release(actor, weaponentity);
534}
535METHOD(Hagar, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
536{
537    if(!actor.(weaponentity).hagar_load) // require releasing loaded rockets first
538        W_Reload(actor, weaponentity, min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo)), SND_RELOAD);
539}
540METHOD(Hagar, wr_suicidemessage, Notification(entity thiswep))
541{
542    return WEAPON_HAGAR_SUICIDE;
543}
544METHOD(Hagar, wr_killmessage, Notification(entity thiswep))
545{
546    if(w_deathtype & HITTYPE_SECONDARY)
547        return WEAPON_HAGAR_MURDER_BURST;
548    else
549        return WEAPON_HAGAR_MURDER_SPRAY;
550}
551
552#endif
553#ifdef CSQC
554
555METHOD(Hagar, wr_impacteffect, void(entity thiswep, entity actor))
556{
557    vector org2;
558    org2 = w_org + w_backoff * 6;
559    pointparticles(EFFECT_HAGAR_EXPLODE, org2, '0 0 0', 1);
560    if(!w_issilent)
561    {
562        if(w_random<0.15)
563            sound(actor, CH_SHOTS, SND_HAGEXP1, VOL_BASE, ATTN_NORM);
564        else if(w_random<0.7)
565            sound(actor, CH_SHOTS, SND_HAGEXP2, VOL_BASE, ATTN_NORM);
566        else
567            sound(actor, CH_SHOTS, SND_HAGEXP3, VOL_BASE, ATTN_NORM);
568    }
569}
570
571#endif
572#endif
573