1 /*-------------------------------------------------------------------------------
2 
3 	BARONY
4 	File: acthudweapon.cpp
5 	Desc: behavior function for hud weapon (first person models)
6 
7 	Copyright 2013-2016 (c) Turning Wheel LLC, all rights reserved.
8 	See LICENSE for details.
9 
10 -------------------------------------------------------------------------------*/
11 
12 #include "main.hpp"
13 #include "game.hpp"
14 #include "stat.hpp"
15 #include "items.hpp"
16 #include "sound.hpp"
17 #include "magic/magic.hpp"
18 #include "interface/interface.hpp"
19 #include "net.hpp"
20 #include "collision.hpp"
21 #include "player.hpp"
22 #include "scores.hpp"
23 
24 Entity* hudweapon = nullptr;
25 Entity* hudarm = nullptr;
26 bool weaponSwitch = false;
27 bool shieldSwitch = false;
28 
29 Sint32 throwGimpTimer = 0; // player cannot throw objects unless zero
30 Sint32 pickaxeGimpTimer = 0; // player cannot swap weapons immediately after using pickaxe
31 							 // due to multiplayer weapon degrade lag... equipping new weapon before degrade
32 							// message hits can degrade the wrong weapon.
33 Sint32 swapWeaponGimpTimer = 0; // player cannot swap weapons unless zero
34 Sint32 bowGimpTimer = 0; // can't draw bow unless zero.
35 
36 /*-------------------------------------------------------------------------------
37 
38 	act*
39 
40 	The following function describes an entity behavior. The function
41 	takes a pointer to the entity that uses it as an argument.
42 
43 -------------------------------------------------------------------------------*/
44 
45 #define HUD_SHAPESHIFT_HIDE my->skill[12]
46 #define HUD_LASTSHAPESHIFT_FORM my->skill[13]
47 
actHudArm(Entity * my)48 void actHudArm(Entity* my)
49 {
50 	hudarm = my;
51 	Entity* parent = hudweapon;
52 
53 	if (players[clientnum] == nullptr || players[clientnum]->entity == nullptr)
54 	{
55 		hudarm = nullptr;
56 		list_RemoveNode(my->mynode);
57 		return;
58 	}
59 
60 	if (stats[clientnum]->HP <= 0)
61 	{
62 		hudarm = nullptr;
63 		list_RemoveNode(my->mynode);
64 		return;
65 	}
66 
67 	if (parent == nullptr)
68 	{
69 		hudarm = nullptr;
70 		list_RemoveNode(my->mynode);
71 		return;
72 	}
73 
74 	// sprite
75 	my->scalex = 1.f;
76 	my->scaley = 1.f;
77 	my->scalez = 1.f;
78 	// position
79 	my->x = parent->x;
80 	my->y = parent->y;
81 	my->z = parent->z - 2.5;
82 
83 	Monster playerRace = players[clientnum]->entity->getMonsterFromPlayerRace(stats[clientnum]->playerRace);
84 	int playerAppearance = stats[clientnum]->appearance;
85 	if ( players[clientnum]->entity->effectShapeshift != NOTHING )
86 	{
87 		playerRace = static_cast<Monster>(players[clientnum]->entity->effectShapeshift);
88 		if ( playerRace == RAT || playerRace == SPIDER )
89 		{
90 			HUD_SHAPESHIFT_HIDE = 1;
91 		}
92 	}
93 	else if ( players[clientnum]->entity->effectPolymorph != NOTHING )
94 	{
95 		if ( players[clientnum]->entity->effectPolymorph > NUMMONSTERS )
96 		{
97 			playerRace = HUMAN;
98 			playerAppearance = players[clientnum]->entity->effectPolymorph - 100;
99 		}
100 		else
101 		{
102 			playerRace = static_cast<Monster>(players[clientnum]->entity->effectPolymorph);
103 		}
104 	}
105 
106 	// when reverting form, render main limb as invisible for 1 tick as it's position needs to settle.
107 	if ( HUD_LASTSHAPESHIFT_FORM != playerRace )
108 	{
109 		if ( HUD_SHAPESHIFT_HIDE > 0 )
110 		{
111 			my->flags[INVISIBLE] = true;
112 			--HUD_SHAPESHIFT_HIDE;
113 		}
114 	}
115 	HUD_LASTSHAPESHIFT_FORM = playerRace;
116 
117 	bool noGloves = false;
118 	bool hideWeapon = false;
119 	if (stats[clientnum]->gloves == nullptr
120 		|| playerRace == SPIDER
121 		|| playerRace == RAT
122 		|| playerRace == CREATURE_IMP
123 		|| playerRace == TROLL )
124 	{
125 		noGloves = true;
126 		hideWeapon = true;
127 	}
128 	else
129 	{
130 		if ( stats[clientnum]->gloves->type == GLOVES || stats[clientnum]->gloves->type == GLOVES_DEXTERITY )
131 		{
132 			my->sprite = 637;
133 		}
134 		else if ( stats[clientnum]->gloves->type == BRACERS || stats[clientnum]->gloves->type == BRACERS_CONSTITUTION )
135 		{
136 			my->sprite = 638;
137 		}
138 		else if ( stats[clientnum]->gloves->type == GAUNTLETS || stats[clientnum]->gloves->type == GAUNTLETS_STRENGTH )
139 		{
140 			my->sprite = 639;
141 		}
142 		else if ( stats[clientnum]->gloves->type == BRASS_KNUCKLES )
143 		{
144 			my->sprite = 640;
145 		}
146 		else if ( stats[clientnum]->gloves->type == IRON_KNUCKLES )
147 		{
148 			my->sprite = 641;
149 		}
150 		else if ( stats[clientnum]->gloves->type == SPIKED_GAUNTLETS )
151 		{
152 			my->sprite = 642;
153 		}
154 		else if ( stats[clientnum]->gloves->type == CRYSTAL_GLOVES )
155 		{
156 			my->sprite = 591;
157 		}
158 		else if ( stats[clientnum]->gloves->type == ARTIFACT_GLOVES )
159 		{
160 			my->sprite = 590;
161 		}
162 		else if ( stats[clientnum]->gloves->type == SUEDE_GLOVES )
163 		{
164 			my->sprite = 802;
165 		}
166 		if ( stats[clientnum]->weapon == nullptr )
167 		{
168 			my->scalex = 0.5f;
169 			my->scaley = 0.5f;
170 			my->scalez = 0.5f;
171 			my->z -= 0.75;
172 			//my->x += 0.5 * cos(parent->yaw);
173 			//my->y += 0.5 * sin(parent->yaw);
174 		}
175 	}
176 
177 	if ( noGloves )
178 	{
179 		switch ( playerRace )
180 		{
181 			case SKELETON:
182 				my->sprite = 774;
183 				break;
184 			case INCUBUS:
185 				my->sprite = 776;
186 				break;
187 			case SUCCUBUS:
188 				my->sprite = 778;
189 				break;
190 			case GOBLIN:
191 				my->sprite = 780;
192 				break;
193 			case AUTOMATON:
194 				my->sprite = 782;
195 				break;
196 			case INSECTOID:
197 				if ( stats[clientnum]->sex == FEMALE )
198 				{
199 					my->sprite = 786;
200 				}
201 				else
202 				{
203 					my->sprite = 784;
204 				}
205 				break;
206 			case GOATMAN:
207 				my->sprite = 788;
208 				break;
209 			case VAMPIRE:
210 				my->sprite = 790;
211 				break;
212 			case HUMAN:
213 				if ( playerAppearance / 6 == 0 )
214 				{
215 					my->sprite = 634;
216 				}
217 				else if ( playerAppearance / 6 == 1 )
218 				{
219 					my->sprite = 635;
220 				}
221 				else
222 				{
223 					my->sprite = 636;
224 				}
225 				break;
226 			case TROLL:
227 				my->sprite = 855;
228 				break;
229 			case SPIDER:
230 				my->sprite = 853;
231 				break;
232 			case CREATURE_IMP:
233 				my->sprite = 857;
234 				break;
235 			case RAT:
236 				my->sprite = 859;
237 				break;
238 			default:
239 				my->sprite = 634;
240 				break;
241 		}
242 
243 		if ( stats[clientnum]->weapon == nullptr || hideWeapon )
244 		{
245 			my->scalex = 0.5f;
246 			my->scaley = 0.5f;
247 			my->scalez = 0.5f;
248 			my->z -= 0.75;
249 			//my->x += 0.5 * cos(parent->yaw);
250 			//my->y += 0.5 * sin(parent->yaw);
251 		}
252 	}
253 
254 	// rotation
255 	//my->yaw = atan2( my->y-camera.y*16, my->x-camera.x*16 );
256 	//my->fskill[0] = sqrt( pow(my->x-camera.x*16,2) + pow(my->y-camera.y*16,2) );
257 	//my->pitch = atan2( my->z-camera.z*.5, my->fskill[0] );
258 	//messagePlayer(0, "my y: %f, my z: %f", my->y, my->z);
259 	my->focalx = 0;
260 	my->focaly = 0;
261 	my->focalz = -1.5;
262 	if ( playerRace == RAT )
263 	{
264 		my->pitch = 0.f;
265 		my->yaw = parent->yaw + players[clientnum]->entity->fskill[10]; // PLAYER_SIDEBOB
266 		my->scalex = 1.f;
267 		my->scaley = 1.f;
268 		my->scalez = 1.f;
269 		my->x += -4.f;
270 		my->y += -3.f;
271 		my->z += 5.5;
272 	}
273 	else if ( playerRace == SPIDER )
274 	{
275 		my->pitch = parent->pitch;
276 		my->yaw = parent->yaw + players[clientnum]->entity->fskill[10];
277 		my->scalex = 1.f;
278 		my->scaley = 1.f;
279 		my->scalez = 1.f;
280 		my->x += 1;
281 		my->y += 1;
282 		my->z += 2;
283 		my->focalz = -1;
284 	}
285 	else
286 	{
287 		my->yaw = -2 * PI / 32;
288 		my->pitch = -17 * PI / 32;
289 	}
290 }
291 
292 bool bowFire = false;
293 bool bowIsBeingDrawn = false;
294 Uint32 bowStartDrawingTick = 0;
295 Uint32 bowDrawBaseTicks = 50;
296 #ifdef USE_FMOD
297 	FMOD_CHANNEL* bowDrawingSoundChannel = NULL;
298 	FMOD_BOOL bowDrawingSoundPlaying = 0;
299 #elif defined USE_OPENAL
300 	OPENAL_SOUND* bowDrawingSoundChannel = NULL;
301 	ALboolean bowDrawingSoundPlaying = 0;
302 #endif
303 
304 #define HUDWEAPON_CHOP my->skill[0]
305 #define HUDWEAPON_INIT my->skill[1]
306 #define HUDWEAPON_CHARGE my->skill[3]
307 #define HUDWEAPON_OVERCHARGE my->skill[4]
308 #define HUDWEAPON_WHIP_ANGLE my->skill[5]
309 #define HUDWEAPON_HIDEWEAPON my->skill[6]
310 #define HUDWEAPON_SHOOTING_RANGED_WEAPON my->skill[7]
311 #define HUDWEAPON_CROSSBOW_RELOAD_ANIMATION my->skill[8]
312 #define HUDWEAPON_BOW_HAS_QUIVER my->skill[9]
313 #define HUDWEAPON_BOW_FORCE_RELOAD my->skill[10]
314 #define HUDWEAPON_PLAYERNUM my->skill[11]
315 #define HUDWEAPON_MOVEX my->fskill[0]
316 #define HUDWEAPON_MOVEY my->fskill[1]
317 #define HUDWEAPON_MOVEZ my->fskill[2]
318 #define HUDWEAPON_YAW my->fskill[3]
319 #define HUDWEAPON_PITCH my->fskill[4]
320 #define HUDWEAPON_ROLL my->fskill[5]
321 #define HUDWEAPON_OLDVIBRATEX my->fskill[6]
322 #define HUDWEAPON_OLDVIBRATEY my->fskill[7]
323 #define HUDWEAPON_OLDVIBRATEZ my->fskill[8]
324 
325 enum CrossbowAnimState : int
326 {
327 	CROSSBOW_ANIM_NONE,
328 	CROSSBOW_ANIM_SHOOT,
329 	CROSSBOW_ANIM_RELOAD_START,
330 	CROSSBOW_ANIM_RELOAD_END,
331 	CROSSBOW_ANIM_SWAPPED_WEAPON,
332 	CROSSBOW_ANIM_HEAVY_RELOAD_MIDPOINT
333 };
334 
335 enum RangedWeaponAnimState : int
336 {
337 	RANGED_ANIM_IDLE,
338 	RANGED_ANIM_BEING_DRAWN,
339 	RANGED_ANIM_FIRED
340 };
341 
342 enum CrossbowHudweaponChop : int
343 {
344 	CROSSBOW_CHOP_RELOAD_START = 16,
345 	CROSSBOW_CHOP_RELOAD_ENDING = 17
346 };
347 
348 Uint32 hudweaponuid = 0;
actHudWeapon(Entity * my)349 void actHudWeapon(Entity* my)
350 {
351 	double result = 0;
352 	ItemType type;
353 	bool wearingring = false;
354 	Entity* entity;
355 	Entity* parent = hudarm;
356 
357 	auto& camera_shakex = cameravars[HUDWEAPON_PLAYERNUM].shakex;
358 	auto& camera_shakey = cameravars[HUDWEAPON_PLAYERNUM].shakey;
359 	auto& camera_shakex2 = cameravars[HUDWEAPON_PLAYERNUM].shakex2;
360 	auto& camera_shakey2 = cameravars[HUDWEAPON_PLAYERNUM].shakey2;
361 
362 	// isn't active during intro/menu sequence
363 	if ( intro == true )
364 	{
365 		my->flags[INVISIBLE] = true;
366 		return;
367 	}
368 
369 	if ( multiplayer == CLIENT )
370 	{
371 		if ( stats[clientnum]->HP <= 0 )
372 		{
373 			my->flags[INVISIBLE] = true;
374 			return;
375 		}
376 	}
377 
378 	// initialize
379 	if ( !HUDWEAPON_INIT )
380 	{
381 		HUDWEAPON_INIT = 1;
382 		hudweapon = my;
383 		hudweaponuid = my->getUID();
384 		entity = newEntity(109, 1, map.entities, nullptr); // malearmright.vox
385 		entity->focalz = -1.5;
386 		entity->parent = my->getUID();
387 		my->parent = entity->getUID(); // just an easy way to refer to eachother, doesn't mean much
388 		hudarm = entity;
389 		parent = hudarm;
390 		entity->behavior = &actHudArm;
391 		entity->flags[OVERDRAW] = true;
392 		entity->flags[PASSABLE] = true;
393 		entity->flags[NOUPDATE] = true;
394 	}
395 
396 	if ( players[clientnum] == nullptr || players[clientnum]->entity == nullptr
397 		|| (players[clientnum]->entity && players[clientnum]->entity->playerCreatedDeathCam != 0) )
398 	{
399 		hudweapon = nullptr; //PLAYER DED. NULLIFY THIS.
400 		list_RemoveNode(my->mynode);
401 		return;
402 	}
403 
404 	// reduce throwGimpTimer (allows player to throw items again)
405 	if ( throwGimpTimer > 0 )
406 	{
407 		--throwGimpTimer;
408 	}
409 	if ( pickaxeGimpTimer > 0 )
410 	{
411 		//messagePlayer(clientnum, "%d", pickaxeGimpTimer);
412 		--pickaxeGimpTimer;
413 	}
414 	if ( swapWeaponGimpTimer > 0 )
415 	{
416 		--swapWeaponGimpTimer;
417 	}
418 	if ( bowGimpTimer > 0 )
419 	{
420 		--bowGimpTimer;
421 	}
422 
423 	// check levitating value
424 	bool levitating = isLevitating(stats[clientnum]);
425 
426 	// swimming
427 	if (players[clientnum] && players[clientnum]->entity)
428 	{
429 		if ( isPlayerSwimming(players[clientnum]->entity) || players[clientnum]->entity->skill[13] != 0 )  //skill[13] PLAYER_INWATER
430 		{
431 			my->flags[INVISIBLE] = true;
432 			if (parent)
433 			{
434 				parent->flags[INVISIBLE] = true;
435 			}
436 			return;
437 		}
438 	}
439 
440 	Monster playerRace = players[clientnum]->entity->getMonsterFromPlayerRace(stats[clientnum]->playerRace);
441 	int playerAppearance = stats[clientnum]->appearance;
442 	if ( players[clientnum]->entity->effectShapeshift != NOTHING )
443 	{
444 		playerRace = static_cast<Monster>(players[clientnum]->entity->effectShapeshift);
445 	}
446 	else if ( players[clientnum]->entity->effectPolymorph != NOTHING )
447 	{
448 		if ( players[clientnum]->entity->effectPolymorph > NUMMONSTERS )
449 		{
450 			playerRace = HUMAN;
451 			playerAppearance = players[clientnum]->entity->effectPolymorph - 100;
452 		}
453 		else
454 		{
455 			playerRace = static_cast<Monster>(players[clientnum]->entity->effectPolymorph);
456 		}
457 	}
458 
459 	if ( playerRace == RAT || playerRace == SPIDER )
460 	{
461 		HUD_SHAPESHIFT_HIDE = std::min(2, HUD_SHAPESHIFT_HIDE + 1);
462 	}
463 
464 	bool hideWeapon = false;
465 	if ( playerRace == SPIDER
466 		|| playerRace == RAT
467 		|| playerRace == CREATURE_IMP
468 		|| playerRace == TROLL )
469 	{
470 		hideWeapon = true;
471 		if ( playerRace == CREATURE_IMP && stats[clientnum]->weapon && itemCategory(stats[clientnum]->weapon) == MAGICSTAFF )
472 		{
473 			hideWeapon = false;
474 		}
475 	}
476 	else
477 	{
478 		if ( HUD_SHAPESHIFT_HIDE > 0 )
479 		{
480 			--HUD_SHAPESHIFT_HIDE;
481 		}
482 	}
483 
484 	HUDWEAPON_HIDEWEAPON = hideWeapon;
485 	HUDWEAPON_SHOOTING_RANGED_WEAPON = RANGED_ANIM_IDLE;
486 
487 	bool rangedweapon = false;
488 	if ( stats[clientnum]->weapon && !hideWeapon )
489 	{
490 		if ( isRangedWeapon(*stats[clientnum]->weapon) )
491 		{
492 			rangedweapon = true;
493 		}
494 	}
495 
496 	// select model
497 	if ( stats[clientnum]->ring != nullptr )
498 	{
499 		if ( stats[clientnum]->ring->type == RING_INVISIBILITY )
500 		{
501 			wearingring = true;
502 		}
503 	}
504 	if ( stats[clientnum]->cloak != nullptr )
505 	{
506 		if ( stats[clientnum]->cloak->type == CLOAK_INVISIBILITY )
507 		{
508 			wearingring = true;
509 		}
510 	}
511 	if ( players[clientnum]->entity->skill[3] == 1 || players[clientnum]->entity->isInvisible() )   // debug cam or player invisible
512 	{
513 		my->flags[INVISIBLE] = true;
514 		if (parent != nullptr)
515 		{
516 			parent->flags[INVISIBLE] = true;
517 		}
518 	}
519 	else
520 	{
521 		if ( stats[clientnum]->weapon == nullptr || hideWeapon )
522 		{
523 			my->flags[INVISIBLE] = true;
524 			if (parent != nullptr)
525 			{
526 				parent->flags[INVISIBLE] = false;
527 			}
528 		}
529 		else
530 		{
531 			if ( stats[clientnum]->weapon )
532 			{
533 				if ( stats[clientnum]->weapon->type == TOOL_WHIP )
534 				{
535 					my->scalex = 0.6;
536 					my->scaley = 0.6;
537 					my->scalez = 0.6;
538 				}
539 				else if ( stats[clientnum]->weapon->type == TOOL_DECOY
540 					|| stats[clientnum]->weapon->type == TOOL_DUMMYBOT )
541 				{
542 					my->scalex = 0.8;
543 					my->scaley = 0.8;
544 					my->scalez = 0.8;
545 				}
546 				else if ( stats[clientnum]->weapon->type == TOOL_SENTRYBOT
547 					|| stats[clientnum]->weapon->type == TOOL_SPELLBOT )
548 				{
549 					my->scalex = 0.7;
550 					my->scaley = 0.7;
551 					my->scalez = 0.7;
552 				}
553 				else if ( (stats[clientnum]->weapon->type >= TOOL_BOMB && stats[clientnum]->weapon->type <= TOOL_TELEPORT_BOMB)
554 					|| stats[clientnum]->weapon->type == FOOD_CREAMPIE )
555 				{
556 					my->scalex = 1.f;
557 					my->scaley = 1.f;
558 					my->scalez = 1.f;
559 				}
560 				else if ( itemModelFirstperson(stats[clientnum]->weapon) != itemModel(stats[clientnum]->weapon) )
561 				{
562 					my->scalex = 0.5f;
563 					my->scaley = 0.5f;
564 					my->scalez = 0.5f;
565 				}
566 				else
567 				{
568 					my->scalex = 1.f;
569 					my->scaley = 1.f;
570 					my->scalez = 1.f;
571 				}
572 			}
573 			my->sprite = itemModelFirstperson(stats[clientnum]->weapon);
574 
575 			if ( bowIsBeingDrawn && !(stats[clientnum]->weapon && stats[clientnum]->weapon->type == HEAVY_CROSSBOW) )
576 			{
577 				HUDWEAPON_SHOOTING_RANGED_WEAPON = RANGED_ANIM_BEING_DRAWN;
578 				if ( (my->ticks - bowStartDrawingTick) >= bowDrawBaseTicks / 4 )
579 				{
580 					if ( rangedweapon )
581 					{
582 						if ( stats[clientnum]->weapon
583 							&& stats[clientnum]->weapon->type != CROSSBOW )
584 						{
585 							my->sprite++;
586 						}
587 						HUDWEAPON_SHOOTING_RANGED_WEAPON = RANGED_ANIM_FIRED;
588 					}
589 				}
590 			}
591 			else if ( stats[clientnum]->weapon && (stats[clientnum]->weapon->type == CROSSBOW || stats[clientnum]->weapon->type == HEAVY_CROSSBOW) )
592 			{
593 				HUDWEAPON_SHOOTING_RANGED_WEAPON = RANGED_ANIM_BEING_DRAWN;
594 				if ( rangedWeaponUseQuiverOnAttack(stats[clientnum]) )
595 				{
596 					HUDWEAPON_BOW_HAS_QUIVER = 1;
597 				}
598 				else
599 				{
600 					if ( HUDWEAPON_BOW_HAS_QUIVER == 1 )
601 					{
602 						// force a reload animation.
603 						HUDWEAPON_CROSSBOW_RELOAD_ANIMATION = CROSSBOW_ANIM_RELOAD_START;
604 						HUDWEAPON_CHOP = CROSSBOW_CHOP_RELOAD_START;
605 						if ( stats[clientnum]->weapon->type == HEAVY_CROSSBOW )
606 						{
607 #ifdef SOUND
608 							bowDrawingSoundChannel = playSound(410, 64);
609 #endif
610 						}
611 						HUDWEAPON_MOVEX = -1;
612 					}
613 					HUDWEAPON_BOW_HAS_QUIVER = 0;
614 				}
615 				if ( HUDWEAPON_CHOP != 0 )
616 				{
617 					if ( HUDWEAPON_CHOP == CROSSBOW_CHOP_RELOAD_START )
618 					{
619 						if ( stats[clientnum]->weapon->type == CROSSBOW )
620 						{
621 							my->sprite = 975; // model has been "fired" and the bowstring not pulled back
622 						}
623 						else if ( stats[clientnum]->weapon->type == HEAVY_CROSSBOW )
624 						{
625 							my->sprite = 987;
626 						}
627 					}
628 					else if ( HUDWEAPON_CHOP == CROSSBOW_CHOP_RELOAD_ENDING )
629 					{
630 						if ( stats[clientnum]->weapon->type == HEAVY_CROSSBOW )
631 						{
632 							if ( HUDWEAPON_CROSSBOW_RELOAD_ANIMATION == CROSSBOW_ANIM_HEAVY_RELOAD_MIDPOINT )
633 							{
634 								my->sprite = 985;
635 							}
636 						}
637 					}
638 					HUDWEAPON_SHOOTING_RANGED_WEAPON = RANGED_ANIM_FIRED;
639 				}
640 			}
641 
642 			if ( itemCategory(stats[clientnum]->weapon) == SPELLBOOK )
643 			{
644 				my->flags[INVISIBLE] = true;
645 				if ( parent != NULL )
646 				{
647 					parent->flags[INVISIBLE] = false;
648 				}
649 			}
650 			else
651 			{
652 				my->flags[INVISIBLE] = false;
653 				if ( parent != NULL )
654 				{
655 					parent->flags[INVISIBLE] = true;
656 				}
657 			}
658 		}
659 	}
660 
661 	// when transitioning from rat/spider to normal, need a tick to make invisible while camera/limb positions settle.
662 	if ( HUD_SHAPESHIFT_HIDE > 0 && HUD_SHAPESHIFT_HIDE < 2 )
663 	{
664 		my->flags[INVISIBLE] = true;
665 		if ( parent != NULL )
666 		{
667 			parent->flags[INVISIBLE] = true;
668 		}
669 	}
670 
671 	if ( cast_animation.active || cast_animation.active_spellbook )
672 	{
673 		if ( playerRace != RAT )
674 		{
675 			my->flags[INVISIBLE] = true;
676 			if (parent != NULL)
677 			{
678 				parent->flags[INVISIBLE] = true;
679 			}
680 		}
681 	}
682 
683 	bool swingweapon = false;
684 	if ( players[clientnum]->entity
685 		&& (*inputPressed(impulses[IN_ATTACK]) || (shootmode && *inputPressed(joyimpulses[INJOY_GAME_ATTACK])))
686 		&& shootmode
687 		&& !gamePaused
688 		&& players[clientnum]->entity->isMobile()
689 		&& !(*inputPressed(impulses[IN_DEFEND]) && stats[clientnum]->defending || (shootmode && *inputPressed(joyimpulses[INJOY_GAME_DEFEND]) && stats[clientnum]->defending))
690 		&& HUDWEAPON_OVERCHARGE < MAXCHARGE )
691 	{
692 		swingweapon = true;
693 	}
694 	else if ( (*inputPressed(impulses[IN_ATTACK]) || (shootmode && *inputPressed(joyimpulses[INJOY_GAME_ATTACK]))) &&
695 		(*inputPressed(impulses[IN_DEFEND]) && stats[clientnum]->defending || (shootmode && *inputPressed(joyimpulses[INJOY_GAME_DEFEND]) && stats[clientnum]->defending)) )
696 	{
697 		if ( stats[clientnum]->shield && stats[clientnum]->shield->type == TOOL_TINKERING_KIT )
698 		{
699 			if ( !GenericGUI.isGUIOpen() )
700 			{
701 				*inputPressed(impulses[IN_ATTACK]) = 0;
702 				*inputPressed(joyimpulses[INJOY_GAME_ATTACK]) = 0;
703 				GenericGUI.openGUI(GUI_TYPE_TINKERING, stats[clientnum]->shield);
704 				swapWeaponGimpTimer = 20;
705 				return;
706 			}
707 		}
708 	}
709 
710 	bool thrownWeapon = stats[clientnum]->weapon
711 		&& (itemCategory(stats[clientnum]->weapon) == THROWN || itemCategory(stats[clientnum]->weapon) == GEM
712 			|| stats[clientnum]->weapon->type == FOOD_CREAMPIE);
713 	bool castStrikeAnimation = (players[clientnum]->entity->skill[9] == MONSTER_POSE_SPECIAL_WINDUP1);
714 
715 	// weapon switch animation
716 	if ( weaponSwitch )
717 	{
718 		weaponSwitch = false;
719 		if ( !hideWeapon )
720 		{
721 			if ( stats[clientnum]->weapon && (stats[clientnum]->weapon->type == CROSSBOW || stats[clientnum]->weapon->type == HEAVY_CROSSBOW) )
722 			{
723 				swingweapon = false;
724 				HUDWEAPON_CHARGE = 0;
725 				HUDWEAPON_OVERCHARGE = 0;
726 				HUDWEAPON_CHOP = 0;
727 				throwGimpTimer = std::max(throwGimpTimer, 20);
728 
729 				HUDWEAPON_MOVEY = 0;
730 				HUDWEAPON_PITCH = 0;
731 				HUDWEAPON_YAW = -0.1;
732 				HUDWEAPON_MOVEZ = 0;
733 
734 				if ( rangedWeaponUseQuiverOnAttack(stats[clientnum]) )
735 				{
736 					if ( stats[clientnum]->weapon->type == HEAVY_CROSSBOW )
737 					{
738 #ifdef SOUND
739 						bowDrawingSoundChannel = playSound(410, 64);
740 #endif
741 					}
742 					HUDWEAPON_CROSSBOW_RELOAD_ANIMATION = CROSSBOW_ANIM_SWAPPED_WEAPON;
743 					if ( swingweapon )
744 					{
745 						swapWeaponGimpTimer = 20; // gimp timer for quivers and ranged weapons.
746 					}
747 					else
748 					{
749 						// let go of attack button, if the animation is the post-attack portion, then quickly fade the timer.
750 						if ( swapWeaponGimpTimer > 5 )
751 						{
752 							swapWeaponGimpTimer = 5;
753 						}
754 					}
755 					swingweapon = false;
756 				}
757 				else
758 				{
759 					HUDWEAPON_CROSSBOW_RELOAD_ANIMATION = CROSSBOW_ANIM_RELOAD_START;
760 					HUDWEAPON_CHOP = CROSSBOW_CHOP_RELOAD_START;
761 					HUDWEAPON_MOVEX = -1;
762 					if ( stats[clientnum]->weapon->type == HEAVY_CROSSBOW )
763 					{
764 #ifdef SOUND
765 						bowDrawingSoundChannel = playSound(410, 64);
766 #endif
767 					}
768 				}
769 			}
770 			else if ( HUDWEAPON_CHOP == CROSSBOW_CHOP_RELOAD_START || HUDWEAPON_CHOP == CROSSBOW_CHOP_RELOAD_ENDING )
771 			{
772 				// non-crossbow, if we're in these unique crossbow states then reset the chop.
773 				HUDWEAPON_CHOP = 0;
774 			}
775 
776 			if ( thrownWeapon && HUDWEAPON_CHOP > 3 )
777 			{
778 				// prevent thrown weapon rapid firing.
779 				swingweapon = false;
780 				HUDWEAPON_CHARGE = 0;
781 				HUDWEAPON_OVERCHARGE = 0;
782 				HUDWEAPON_CHOP = 0;
783 				throwGimpTimer = std::max(throwGimpTimer, 5);
784 			}
785 
786 			if ( rangedweapon && stats[clientnum]->weapon
787 				&& stats[clientnum]->weapon->type != CROSSBOW
788 				&& stats[clientnum]->weapon->type != HEAVY_CROSSBOW
789 				)
790 			{
791 				HUDWEAPON_BOW_FORCE_RELOAD = 1;
792 				if ( HUDWEAPON_BOW_HAS_QUIVER == 1 )
793 				{
794 					// reequiped bow, force a reload.
795 					bowGimpTimer = std::max(bowGimpTimer, 3);
796 				}
797 			}
798 
799 			if ( !HUDWEAPON_CHOP )
800 			{
801 				HUDWEAPON_MOVEZ = 2;
802 				HUDWEAPON_MOVEX = -.5;
803 				HUDWEAPON_ROLL = -PI / 2;
804 			}
805 		}
806 	}
807 
808 	// all items (e.g weapons) have swap equipment gimp timer in multiplayer.
809 	if ( HUDWEAPON_CHOP > 0 && swingweapon )
810 	{
811 		swapWeaponGimpTimer = 20;
812 	}
813 	else if ( HUDWEAPON_CHOP != 0 && HUDWEAPON_CHOP != 1 && HUDWEAPON_CHOP != 4 && HUDWEAPON_CHOP != 7 && !swingweapon )
814 	{
815 		// let go of attack button, if the animation is the post-attack portion, then quickly fade the timer.
816 		if ( swapWeaponGimpTimer > 5 )
817 		{
818 			swapWeaponGimpTimer = 5;
819 		}
820 	}
821 
822 	if ( HUDWEAPON_CROSSBOW_RELOAD_ANIMATION == CROSSBOW_ANIM_SWAPPED_WEAPON )
823 	{
824 		swapWeaponGimpTimer = 20;
825 	}
826 
827 	Uint32 bowFireRate = bowDrawBaseTicks;
828 	bool shakeRangedWeapon = false;
829 	if ( rangedweapon && stats[clientnum]->weapon
830 		&& stats[clientnum]->weapon->type != CROSSBOW
831 		&& stats[clientnum]->weapon->type != HEAVY_CROSSBOW
832 		&& !hideWeapon )
833 	{
834 		bowFireRate = bowDrawBaseTicks * (rangedAttackGetSpeedModifier(stats[clientnum]));
835 		if ( rangedWeaponUseQuiverOnAttack(stats[clientnum]) )
836 		{
837 			HUDWEAPON_BOW_HAS_QUIVER = 1;
838 		}
839 		else
840 		{
841 			if ( HUDWEAPON_BOW_HAS_QUIVER == 1 )
842 			{
843 				// unequipped quiver, force a reload.
844 				HUDWEAPON_BOW_FORCE_RELOAD = 1;
845 				bowGimpTimer = std::max(bowGimpTimer, 12);
846 			}
847 			HUDWEAPON_BOW_HAS_QUIVER = 0;
848 		}
849 
850 		if ( (swingweapon && HUDWEAPON_CHOP != 0) || HUDWEAPON_BOW_FORCE_RELOAD == 1 )
851 		{
852 			if ( HUDWEAPON_BOW_FORCE_RELOAD == 1 )
853 			{
854 				if ( HUDWEAPON_SHOOTING_RANGED_WEAPON == RANGED_ANIM_FIRED )
855 				{
856 					HUDWEAPON_SHOOTING_RANGED_WEAPON = RANGED_ANIM_IDLE;
857 				}
858 				// don't undo swing weapon.
859 			}
860 			else
861 			{
862 				swingweapon = false;
863 			}
864 			HUDWEAPON_BOW_FORCE_RELOAD = 0;
865 			HUDWEAPON_CHARGE = 0;
866 			HUDWEAPON_OVERCHARGE = 0;
867 			HUDWEAPON_CHOP = 0;
868 			bowIsBeingDrawn = false;
869 		}
870 		else if ( rangedWeaponUseQuiverOnAttack(stats[clientnum]) )
871 		{
872 			if ( swingweapon )
873 			{
874 				swapWeaponGimpTimer = 20; // gimp timer for quivers and ranged weapons.
875 			}
876 			else
877 			{
878 				// let go of attack button, if the animation is the post-attack portion, then quickly fade the timer.
879 				if ( swapWeaponGimpTimer > 5 )
880 				{
881 					swapWeaponGimpTimer = 5;
882 				}
883 			}
884 		}
885 	}
886 	// check bow drawing attack and if defending/not firing cancel the SFX.
887 	if ( rangedweapon && bowIsBeingDrawn && !stats[clientnum]->defending && !hideWeapon )
888 	{
889 		if ( stats[clientnum]->weapon->type == HEAVY_CROSSBOW )
890 		{
891 			bowFireRate = bowDrawBaseTicks * (rangedAttackGetSpeedModifier(stats[clientnum]));
892 		}
893 
894 		if ( (my->ticks - bowStartDrawingTick) < bowFireRate )
895 		{
896 			bowFire = false;
897 		}
898 		else
899 		{
900 			bowIsBeingDrawn = false;
901 			bowFire = true; // ready to fire!
902 		}
903 #ifdef SOUND
904 #ifdef USE_OPENAL
905 		if ( bowDrawingSoundChannel )
906 		{
907 			OPENAL_Channel_IsPlaying(bowDrawingSoundChannel, &bowDrawingSoundPlaying);
908 		}
909 #else
910 		if ( bowDrawingSoundChannel )
911 		{
912 			FMOD_Channel_IsPlaying(bowDrawingSoundChannel, &bowDrawingSoundPlaying);
913 		}
914 #endif
915 #endif // SOUND
916 	}
917 	else
918 	{
919 		bowFire = false;
920 		bowIsBeingDrawn = false;
921 		bool stopSound = true;
922 		if ( stats[clientnum]->weapon && stats[clientnum]->weapon->type == HEAVY_CROSSBOW
923 			&& !stats[clientnum]->defending && !hideWeapon )
924 		{
925 #ifdef SOUND
926 #ifdef USE_OPENAL
927 			if ( bowDrawingSoundChannel )
928 			{
929 				OPENAL_Channel_IsPlaying(bowDrawingSoundChannel, &bowDrawingSoundPlaying);
930 			}
931 #else
932 			if ( bowDrawingSoundChannel )
933 			{
934 				FMOD_Channel_IsPlaying(bowDrawingSoundChannel, &bowDrawingSoundPlaying);
935 			}
936 #endif
937 #endif // SOUND
938 
939 			stopSound = false;
940 			if ( HUDWEAPON_CROSSBOW_RELOAD_ANIMATION == CROSSBOW_ANIM_NONE )
941 			{
942 				stopSound = true;
943 			}
944 		}
945 
946 		if ( stopSound )
947 		{
948 #ifdef SOUND
949 			if ( bowDrawingSoundPlaying && bowDrawingSoundChannel )
950 			{
951 #ifdef USE_OPENAL
952 				OPENAL_Channel_Stop(bowDrawingSoundChannel);
953 #else
954 				FMOD_Channel_Stop(bowDrawingSoundChannel);
955 #endif
956 				bowDrawingSoundPlaying = 0;
957 				bowDrawingSoundChannel = NULL;
958 			}
959 #endif
960 		}
961 	}
962 
963 	bool whip = stats[clientnum]->weapon && stats[clientnum]->weapon->type == TOOL_WHIP;
964 
965 	// main animation
966 	if ( HUDWEAPON_CHOP == 0 )
967 	{
968 		if ( HUDWEAPON_CROSSBOW_RELOAD_ANIMATION != CROSSBOW_ANIM_SWAPPED_WEAPON )
969 		{
970 			// CROSSBOW_ANIM_SWAPPED_WEAPON requires the weapon to not be in the swapping animation to finish.
971 			// otherwise, the animation sets HUDWEAPON_CHOP to 0 so it has finished.
972 			HUDWEAPON_CROSSBOW_RELOAD_ANIMATION = CROSSBOW_ANIM_NONE;
973 		}
974 		bool ignoreAttack = false;
975 		if ( swingweapon && throwGimpTimer > 0 && stats[clientnum]->weapon &&
976 			( stats[clientnum]->weapon->type == CROSSBOW
977 				|| itemCategory(stats[clientnum]->weapon) == POTION
978 				|| itemCategory(stats[clientnum]->weapon) == GEM
979 				|| itemCategory(stats[clientnum]->weapon) == THROWN
980 				|| stats[clientnum]->weapon->type == FOOD_CREAMPIE )
981 			)
982 		{
983 			ignoreAttack = true;
984 		}
985 		else if ( swingweapon && bowGimpTimer > 0 && rangedweapon && stats[clientnum]->weapon
986 			&& stats[clientnum]->weapon->type != CROSSBOW
987 			&& stats[clientnum]->weapon->type != HEAVY_CROSSBOW
988 			&& !hideWeapon )
989 		{
990 			ignoreAttack = true;
991 		}
992 
993 		if ( !ignoreAttack && (swingweapon || castStrikeAnimation) )
994 		{
995 			if ( cast_animation.active || cast_animation.active_spellbook )
996 			{
997 				messagePlayer(clientnum, language[1301]);
998 				spellcastingAnimationManager_deactivate(&cast_animation);
999 			}
1000 			if ( castStrikeAnimation )
1001 			{
1002 				HUDWEAPON_CHOP = 10; // special punch
1003 			}
1004 			else if ( stats[clientnum]->weapon == NULL || hideWeapon )
1005 			{
1006 				HUDWEAPON_CHOP = 7; // punch
1007 			}
1008 			else
1009 			{
1010 				if ( conductGameChallenges[CONDUCT_BRAWLER] || achievementBrawlerMode )
1011 				{
1012 					if ( itemCategory(stats[clientnum]->weapon) == WEAPON
1013 						|| rangedweapon
1014 						|| itemCategory(stats[clientnum]->weapon) == THROWN
1015 						|| stats[clientnum]->weapon->type == FOOD_CREAMPIE
1016 						|| itemCategory(stats[clientnum]->weapon) == MAGICSTAFF
1017 						|| itemCategory(stats[clientnum]->weapon) == GEM
1018 						|| stats[clientnum]->weapon->type == TOOL_PICKAXE )
1019 					{
1020 						if ( achievementBrawlerMode && conductGameChallenges[CONDUCT_BRAWLER] )
1021 						{
1022 							messagePlayer(clientnum, language[2997]); // prevent attack.
1023 							return;
1024 						}
1025 						if ( achievementBrawlerMode )
1026 						{
1027 							messagePlayer(clientnum, language[2998]); // notify no longer eligible for achievement but still atk.
1028 						}
1029 						conductGameChallenges[CONDUCT_BRAWLER] = 0;
1030 					}
1031 				}
1032 
1033 				if ( itemCategory(stats[clientnum]->weapon) == WEAPON || stats[clientnum]->weapon->type == TOOL_PICKAXE )
1034 				{
1035 					if ( stats[clientnum]->weapon->type == TOOL_PICKAXE )
1036 					{
1037 						pickaxeGimpTimer = 40;
1038 					}
1039 					if ( stats[clientnum]->weapon->type == IRON_SPEAR || stats[clientnum]->weapon->type == ARTIFACT_SPEAR )
1040 					{
1041 						HUDWEAPON_CHOP = 7; // spear lunges
1042 					}
1043 					else if ( whip )
1044 					{
1045 						HUDWEAPON_CHOP = 4;
1046 						pickaxeGimpTimer = 20;
1047 					}
1048 					else if ( rangedweapon )
1049 					{
1050 						if ( stats[clientnum]->weapon->type == SLING
1051 							|| stats[clientnum]->weapon->type == SHORTBOW
1052 							|| stats[clientnum]->weapon->type == ARTIFACT_BOW
1053 							|| stats[clientnum]->weapon->type == LONGBOW
1054 							|| stats[clientnum]->weapon->type == COMPOUND_BOW )
1055 						{
1056 							if ( !stats[clientnum]->defending && !throwGimpTimer )
1057 							{
1058 								// bows need to be drawn back
1059 								if ( !bowIsBeingDrawn )
1060 								{
1061 									if ( bowFire )
1062 									{
1063 										bowFire = false;
1064 
1065 										bool artifactBowSaveAmmo = false;
1066 										if ( stats[clientnum]->weapon->type == ARTIFACT_BOW /*&& rangedWeaponUseQuiverOnAttack(stats[clientnum])*/ )
1067 										{
1068 											real_t amount = 0.f;
1069 											real_t percent = getArtifactWeaponEffectChance(ARTIFACT_BOW, *(stats[clientnum]), &amount);
1070 											if ( (rand() % 100 < static_cast<int>(percent)) )
1071 											{
1072 												artifactBowSaveAmmo = true;
1073 											}
1074 										}
1075 
1076 										if ( artifactBowSaveAmmo )
1077 										{
1078 											players[clientnum]->entity->attack(MONSTER_POSE_RANGED_SHOOT2, 0, nullptr);
1079 										}
1080 										else
1081 										{
1082 											players[clientnum]->entity->attack(MONSTER_POSE_RANGED_SHOOT1, 0, nullptr);
1083 										}
1084 										HUDWEAPON_MOVEX = 3;
1085 										throwGimpTimer = TICKS_PER_SECOND / 4;
1086 
1087 										if ( multiplayer == CLIENT )
1088 										{
1089 											if ( rangedWeaponUseQuiverOnAttack(stats[clientnum]) && !artifactBowSaveAmmo )
1090 											{
1091 												Item* quiver = stats[clientnum]->shield;
1092 												quiver->count--;
1093 												if ( quiver->count <= 0 )
1094 												{
1095 													if ( quiver->node )
1096 													{
1097 														list_RemoveNode(quiver->node);
1098 													}
1099 													else
1100 													{
1101 														free(quiver);
1102 													}
1103 													stats[clientnum]->shield = NULL;
1104 												}
1105 											}
1106 										}
1107 									}
1108 									else
1109 									{
1110 										bowStartDrawingTick = my->ticks;
1111 										bowIsBeingDrawn = true;
1112 #ifdef SOUND
1113 										bowDrawingSoundChannel = playSound(246, 64);
1114 #endif
1115 									}
1116 								}
1117 
1118 								real_t targety = -1.0;
1119 								if ( HUDWEAPON_MOVEX > 0 )
1120 								{
1121 									if ( HUDWEAPON_MOVEX > 1 )
1122 									{
1123 										HUDWEAPON_MOVEX = std::max<real_t>(HUDWEAPON_MOVEX - 1, 0.0);
1124 									}
1125 									else
1126 									{
1127 										HUDWEAPON_MOVEX = std::max<real_t>(HUDWEAPON_MOVEX - 0.2, 0.0);
1128 									}
1129 								}
1130 								else if ( HUDWEAPON_MOVEX < 0 )
1131 								{
1132 									HUDWEAPON_MOVEX = std::min<real_t>(HUDWEAPON_MOVEX + 1, 0.0);
1133 								}
1134 								if ( HUDWEAPON_MOVEY > targety )
1135 								{
1136 									HUDWEAPON_MOVEY = std::max<real_t>(HUDWEAPON_MOVEY - 1, targety);
1137 								}
1138 								else if ( HUDWEAPON_MOVEY < targety )
1139 								{
1140 									HUDWEAPON_MOVEY = std::min<real_t>(HUDWEAPON_MOVEY + 1, targety);
1141 								}
1142 								if ( HUDWEAPON_MOVEZ > 0 )
1143 								{
1144 									HUDWEAPON_MOVEZ = std::max<real_t>(HUDWEAPON_MOVEZ - 1, 0.0);
1145 								}
1146 								else if ( HUDWEAPON_MOVEZ < 0 )
1147 								{
1148 									HUDWEAPON_MOVEZ = std::min<real_t>(HUDWEAPON_MOVEZ + 1, 0.0);
1149 								}
1150 								if ( HUDWEAPON_YAW > -.1 )
1151 								{
1152 									HUDWEAPON_YAW = std::max<real_t>(HUDWEAPON_YAW - .1, -.1);
1153 								}
1154 								else if ( HUDWEAPON_YAW < -.1 )
1155 								{
1156 									HUDWEAPON_YAW = std::min<real_t>(HUDWEAPON_YAW + .1, -.1);
1157 								}
1158 								if ( HUDWEAPON_PITCH > 0 )
1159 								{
1160 									HUDWEAPON_PITCH = std::max<real_t>(HUDWEAPON_PITCH - .1, 0.0);
1161 								}
1162 								else if ( HUDWEAPON_PITCH < 0 )
1163 								{
1164 									HUDWEAPON_PITCH = std::min<real_t>(HUDWEAPON_PITCH + .1, 0.0);
1165 								}
1166 								if ( HUDWEAPON_ROLL > 0 )
1167 								{
1168 									HUDWEAPON_ROLL = std::max<real_t>(HUDWEAPON_ROLL - .1, 0.0);
1169 								}
1170 								else if ( HUDWEAPON_ROLL < 0 )
1171 								{
1172 									HUDWEAPON_ROLL = std::min<real_t>(HUDWEAPON_ROLL + .1, 0.0);
1173 								}
1174 							}
1175 						}
1176 						else
1177 						{
1178 							// crossbows
1179 							bool doAttack = false;
1180 							if ( throwGimpTimer == 0 )
1181 							{
1182 								doAttack = true;
1183 								bool heavyCrossbow = stats[clientnum]->weapon && stats[clientnum]->weapon->type == HEAVY_CROSSBOW;
1184 
1185 								if ( heavyCrossbow )
1186 								{
1187 									doAttack = false;
1188 									// need to charge up.
1189 									if ( !bowIsBeingDrawn )
1190 									{
1191 										if ( bowFire )
1192 										{
1193 											bowFire = false;
1194 											doAttack = true;
1195 										}
1196 										else
1197 										{
1198 											bowStartDrawingTick = my->ticks;
1199 											bowIsBeingDrawn = true;
1200 										}
1201 									}
1202 									else
1203 									{
1204 										shakeRangedWeapon = true;
1205 									}
1206 								}
1207 
1208 								if ( doAttack )
1209 								{
1210 									players[clientnum]->entity->attack(MONSTER_POSE_RANGED_SHOOT1, 0, nullptr);
1211 									HUDWEAPON_MOVEX = -4;
1212 
1213 									// set delay before crossbow can fire again
1214 									throwGimpTimer = 40;
1215 
1216 									HUDWEAPON_CHOP = CROSSBOW_CHOP_RELOAD_START;
1217 									HUDWEAPON_CROSSBOW_RELOAD_ANIMATION = CROSSBOW_ANIM_SHOOT;
1218 
1219 									if ( heavyCrossbow )
1220 									{
1221 										players[clientnum]->entity->playerStrafeVelocity = 0.3;
1222 										players[clientnum]->entity->playerStrafeDir = players[clientnum]->entity->yaw + PI;
1223 										if ( multiplayer != CLIENT )
1224 										{
1225 											players[clientnum]->entity->setEffect(EFF_KNOCKBACK, true, 30, false);
1226 										}
1227 										if ( players[clientnum]->entity->skill[3] == 0 )   // debug cam OFF
1228 										{
1229 											camera_shakex += .06;
1230 											camera_shakey += 6;
1231 										}
1232 									}
1233 
1234 									if ( multiplayer == CLIENT )
1235 									{
1236 										if ( rangedWeaponUseQuiverOnAttack(stats[clientnum]) )
1237 										{
1238 											Item* quiver = stats[clientnum]->shield;
1239 											quiver->count--;
1240 											if ( quiver->count <= 0 )
1241 											{
1242 												if ( quiver->node )
1243 												{
1244 													list_RemoveNode(quiver->node);
1245 												}
1246 												else
1247 												{
1248 													free(quiver);
1249 												}
1250 												stats[clientnum]->shield = NULL;
1251 											}
1252 										}
1253 									}
1254 								}
1255 							}
1256 
1257 							if ( !doAttack )
1258 							{
1259 								// reset animation - this is for weaponswitch animation code to complete while holding attack.
1260 								if ( HUDWEAPON_MOVEX > 0 )
1261 								{
1262 									HUDWEAPON_MOVEX = std::max<real_t>(HUDWEAPON_MOVEX - 1, 0.0);
1263 								}
1264 								else if ( HUDWEAPON_MOVEX < 0 )
1265 								{
1266 									HUDWEAPON_MOVEX = std::min<real_t>(HUDWEAPON_MOVEX + 1, 0.0);
1267 								}
1268 								if ( HUDWEAPON_MOVEY > 0 )
1269 								{
1270 									HUDWEAPON_MOVEY = std::max<real_t>(HUDWEAPON_MOVEY - 1, 0.0);
1271 								}
1272 								else if ( HUDWEAPON_MOVEY < 0 )
1273 								{
1274 									HUDWEAPON_MOVEY = std::min<real_t>(HUDWEAPON_MOVEY + 1, 0.0);
1275 								}
1276 								if ( HUDWEAPON_MOVEZ > 0 )
1277 								{
1278 									HUDWEAPON_MOVEZ = std::max<real_t>(HUDWEAPON_MOVEZ - 1, 0.0);
1279 								}
1280 								else if ( HUDWEAPON_MOVEZ < 0 )
1281 								{
1282 									HUDWEAPON_MOVEZ = std::min<real_t>(HUDWEAPON_MOVEZ + 1, 0.0);
1283 								}
1284 								if ( HUDWEAPON_YAW > -.1 )
1285 								{
1286 									HUDWEAPON_YAW = std::max<real_t>(HUDWEAPON_YAW - .1, -.1);
1287 								}
1288 								else if ( HUDWEAPON_YAW < -.1 )
1289 								{
1290 									HUDWEAPON_YAW = std::min<real_t>(HUDWEAPON_YAW + .1, -.1);
1291 								}
1292 								if ( HUDWEAPON_ROLL > 0 )
1293 								{
1294 									HUDWEAPON_ROLL = std::max<real_t>(HUDWEAPON_ROLL - .1, 0.0);
1295 								}
1296 								else if ( HUDWEAPON_ROLL < 0 )
1297 								{
1298 									HUDWEAPON_ROLL = std::min<real_t>(HUDWEAPON_ROLL + .1, 0.0);
1299 								}
1300 								if ( HUDWEAPON_PITCH > 0 )
1301 								{
1302 									HUDWEAPON_PITCH = std::max<real_t>(HUDWEAPON_PITCH - .1, 0.0);
1303 								}
1304 								else if ( HUDWEAPON_PITCH < 0 )
1305 								{
1306 									HUDWEAPON_PITCH = std::min<real_t>(HUDWEAPON_PITCH + .1, 0.0);
1307 								}
1308 							}
1309 						}
1310 					}
1311 					else
1312 					{
1313 						HUDWEAPON_CHOP = 1;
1314 					}
1315 				}
1316 				else
1317 				{
1318 					Item* item = stats[clientnum]->weapon;
1319 					if (item)
1320 					{
1321 						if (itemCategory(item) == SPELLBOOK)
1322 						{
1323 							mousestatus[SDL_BUTTON_LEFT] = 0;
1324 							players[clientnum]->entity->attack(2, 0, nullptr); // will need to add some delay to this so you can't rapid fire spells
1325 						}
1326 						else if ( itemIsThrowableTinkerTool(item) )
1327 						{
1328 							HUDWEAPON_CHOP = 13;
1329 						}
1330 						else if (itemCategory(item) == MAGICSTAFF)
1331 						{
1332 							HUDWEAPON_CHOP = 7; // magicstaffs lunge
1333 						}
1334 						else if ( itemCategory(item) == THROWN || itemCategory(item) == GEM || item->type == FOOD_CREAMPIE )
1335 						{
1336 							if ( !throwGimpTimer )
1337 							{
1338 								throwGimpTimer = TICKS_PER_SECOND / 2; // limits how often you can throw objects
1339 								HUDWEAPON_CHOP = 1; // thrown normal swing
1340 							}
1341 						}
1342 						else if (item->type == TOOL_LOCKPICK || item->type == TOOL_SKELETONKEY )
1343 						{
1344 							// keys and lockpicks
1345 							HUDWEAPON_MOVEX = 5;
1346 							HUDWEAPON_CHOP = 3;
1347 							Entity* player = players[clientnum]->entity;
1348 							bool foundBomb = false;
1349 							if ( stats[clientnum]->weapon )
1350 							{
1351 								bool clickedOnGUI = false;
1352 								int tmpmousex = omousex;
1353 								int tmpmousey = omousey;
1354 								omousex = xres / 2; // pretend move the mouse to the centre of screen.
1355 								omousey = yres / 2;
1356 								Entity* clickedOn = entityClicked(&clickedOnGUI, true, HUDWEAPON_PLAYERNUM); // using objects
1357 								omousex = tmpmousex;
1358 								omousey = tmpmousey;
1359 								if ( clickedOn && clickedOn->behavior == &actBomb && entityDist(clickedOn, players[clientnum]->entity) < STRIKERANGE )
1360 								{
1361 									// found something
1362 									stats[clientnum]->weapon->apply(clientnum, clickedOn);
1363 									foundBomb = true;
1364 								}
1365 							}
1366 							if ( !foundBomb )
1367 							{
1368 								real_t dist = lineTrace(player, player->x, player->y, player->yaw, STRIKERANGE, 0, false);
1369 								if ( hit.entity && stats[clientnum]->weapon )
1370 								{
1371 									stats[clientnum]->weapon->apply(clientnum, hit.entity);
1372 								}
1373 								else
1374 								{
1375 									bool foundWall = false;
1376 									if ( dist < STRIKERANGE
1377 										&& !hit.entity && hit.mapx >= 0 && hit.mapx < map.width && hit.mapy >= 0 && hit.mapy < map.height )
1378 									{
1379 										// arrow traps
1380 										if ( map.tiles[OBSTACLELAYER + hit.mapy * MAPLAYERS + hit.mapx * MAPLAYERS * map.height] == 53 )
1381 										{
1382 											foundWall = true;
1383 											stats[clientnum]->weapon->applyLockpickToWall(clientnum, hit.mapx, hit.mapy);
1384 										}
1385 									}
1386 									if ( !foundWall )
1387 									{
1388 										messagePlayer(clientnum, language[503], item->getName());
1389 									}
1390 								}
1391 							}
1392 						}
1393 						else if ( item->type >= ARTIFACT_ORB_BLUE && item->type <= ARTIFACT_ORB_GREEN )
1394 						{
1395 							HUDWEAPON_MOVEX = 5;
1396 							HUDWEAPON_CHOP = 3;
1397 							Entity* player = players[clientnum]->entity;
1398 							lineTrace(player, player->x, player->y, player->yaw, STRIKERANGE, 0, false);
1399 							if ( hit.entity && stats[clientnum]->weapon )
1400 							{
1401 								stats[clientnum]->weapon->apply(clientnum, hit.entity);
1402 							}
1403 							else
1404 							{
1405 								if ( statGetINT(stats[clientnum], player) <= 10 )
1406 								{
1407 									messagePlayer(clientnum, language[2373], item->getName());
1408 								}
1409 								else
1410 								{
1411 									messagePlayer(clientnum, language[2372], item->getName());
1412 								}
1413 							}
1414 						}
1415 						else if ( item->type == POTION_EMPTY )
1416 						{
1417 							if ( throwGimpTimer == 0 )
1418 							{
1419 								HUDWEAPON_MOVEX = 5;
1420 								HUDWEAPON_CHOP = 3;
1421 								Entity* player = players[clientnum]->entity;
1422 								lineTrace(player, player->x, player->y, player->yaw, STRIKERANGE, 0, false);
1423 								if ( hit.entity && stats[clientnum]->weapon )
1424 								{
1425 									stats[clientnum]->weapon->apply(clientnum, hit.entity);
1426 								}
1427 								else
1428 								{
1429 									messagePlayer(clientnum, language[3336]);
1430 								}
1431 								throwGimpTimer = TICKS_PER_SECOND / 2;
1432 							}
1433 						}
1434 						else if ((itemCategory(item) == POTION || itemCategory(item) == GEM || itemCategory(item) == THROWN || item->type == FOOD_CREAMPIE )
1435 							&& !throwGimpTimer)
1436 						{
1437 							if ( itemCategory(item) == THROWN )
1438 							{
1439 								// possibility to change to be unique.
1440 								throwGimpTimer = TICKS_PER_SECOND / 2; // limits how often you can throw objects
1441 							}
1442 							else
1443 							{
1444 								throwGimpTimer = TICKS_PER_SECOND / 2; // limits how often you can throw objects
1445 							}
1446 							HUDWEAPON_MOVEZ = 3;
1447 							HUDWEAPON_CHOP = 3;
1448 							players[clientnum]->entity->attack(1, 0, nullptr);
1449 							if (multiplayer == CLIENT)
1450 							{
1451 								item->count--;
1452 								if (item->count <= 0)
1453 								{
1454 									if (item->node)
1455 									{
1456 										list_RemoveNode(item->node);
1457 									}
1458 									else
1459 									{
1460 										free(item);
1461 									}
1462 									stats[clientnum]->weapon = NULL;
1463 								}
1464 							}
1465 						}
1466 					}
1467 				}
1468 			}
1469 		}
1470 		else
1471 		{
1472 			if ( !stats[clientnum]->defending )
1473 			{
1474 				if ( stats[clientnum]->weapon || hideWeapon )
1475 				{
1476 					if ( !hideWeapon &&
1477 						(stats[clientnum]->weapon->type == SLING
1478 							|| stats[clientnum]->weapon->type == SHORTBOW
1479 							|| stats[clientnum]->weapon->type == ARTIFACT_BOW
1480 							|| stats[clientnum]->weapon->type == LONGBOW
1481 							|| stats[clientnum]->weapon->type == COMPOUND_BOW) )
1482 					{
1483 						// not drawing bow anymore, reset.
1484 						bowIsBeingDrawn = false;
1485 #ifdef SOUND
1486 						if ( bowDrawingSoundPlaying && bowDrawingSoundChannel )
1487 						{
1488 #ifdef USE_OPENAL
1489 							OPENAL_Channel_Stop(bowDrawingSoundChannel);
1490 #else
1491 							FMOD_Channel_Stop(bowDrawingSoundChannel);
1492 #endif
1493 							bowDrawingSoundPlaying = 0;
1494 							bowDrawingSoundChannel = NULL;
1495 						}
1496 #endif
1497 
1498 						if ( HUDWEAPON_MOVEX > 0 )
1499 						{
1500 							HUDWEAPON_MOVEX = std::max<real_t>(HUDWEAPON_MOVEX - 1, 0.0);
1501 						}
1502 						else if ( HUDWEAPON_MOVEX < 0 )
1503 						{
1504 							HUDWEAPON_MOVEX = std::min<real_t>(HUDWEAPON_MOVEX + 1, 0.0);
1505 						}
1506 						if ( HUDWEAPON_MOVEY > 1 )
1507 						{
1508 							HUDWEAPON_MOVEY = std::max<real_t>(HUDWEAPON_MOVEY - 1, 1.0);
1509 						}
1510 						else if ( HUDWEAPON_MOVEY < 1 )
1511 						{
1512 							HUDWEAPON_MOVEY = std::min<real_t>(HUDWEAPON_MOVEY + 1, 1.0);
1513 						}
1514 						if ( HUDWEAPON_MOVEZ > 0 )
1515 						{
1516 							HUDWEAPON_MOVEZ = std::max<real_t>(HUDWEAPON_MOVEZ - 1, 0.0);
1517 						}
1518 						else if ( HUDWEAPON_MOVEZ < 0 )
1519 						{
1520 							HUDWEAPON_MOVEZ = std::min<real_t>(HUDWEAPON_MOVEZ + 1, 0.0);
1521 						}
1522 						if ( HUDWEAPON_YAW > -.1 )
1523 						{
1524 							HUDWEAPON_YAW = std::max<real_t>(HUDWEAPON_YAW - .1, -.1);
1525 						}
1526 						else if ( HUDWEAPON_YAW < -.1 )
1527 						{
1528 							HUDWEAPON_YAW = std::min<real_t>(HUDWEAPON_YAW + .1, -.1);
1529 						}
1530 						if ( HUDWEAPON_PITCH > 0 )
1531 						{
1532 							HUDWEAPON_PITCH = std::max<real_t>(HUDWEAPON_PITCH - .1, 0.0);
1533 						}
1534 						else if ( HUDWEAPON_PITCH < 0 )
1535 						{
1536 							HUDWEAPON_PITCH = std::min<real_t>(HUDWEAPON_PITCH + .1, 0.0);
1537 						}
1538 						if ( HUDWEAPON_ROLL > -PI / 3 )
1539 						{
1540 							HUDWEAPON_ROLL = std::max<real_t>(HUDWEAPON_ROLL - .1, -PI / 3);
1541 						}
1542 						else if ( HUDWEAPON_ROLL < -PI / 3 )
1543 						{
1544 							HUDWEAPON_ROLL = std::min<real_t>(HUDWEAPON_ROLL + .1, -PI / 3);
1545 						}
1546 					}
1547 					else
1548 					{
1549 						if ( HUDWEAPON_MOVEX > 0 )
1550 						{
1551 							HUDWEAPON_MOVEX = std::max<real_t>(HUDWEAPON_MOVEX - 1, 0.0);
1552 						}
1553 						else if ( HUDWEAPON_MOVEX < 0 )
1554 						{
1555 							HUDWEAPON_MOVEX = std::min<real_t>(HUDWEAPON_MOVEX + 1, 0.0);
1556 						}
1557 						if ( HUDWEAPON_MOVEY > 0 )
1558 						{
1559 							HUDWEAPON_MOVEY = std::max<real_t>(HUDWEAPON_MOVEY - 1, 0.0);
1560 						}
1561 						else if ( HUDWEAPON_MOVEY < 0 )
1562 						{
1563 							HUDWEAPON_MOVEY = std::min<real_t>(HUDWEAPON_MOVEY + 1, 0.0);
1564 						}
1565 						if ( HUDWEAPON_MOVEZ > 0 )
1566 						{
1567 							HUDWEAPON_MOVEZ = std::max<real_t>(HUDWEAPON_MOVEZ - 1, 0.0);
1568 						}
1569 						else if ( HUDWEAPON_MOVEZ < 0 )
1570 						{
1571 							HUDWEAPON_MOVEZ = std::min<real_t>(HUDWEAPON_MOVEZ + 1, 0.0);
1572 						}
1573 						if ( HUDWEAPON_YAW > -.1 )
1574 						{
1575 							HUDWEAPON_YAW = std::max<real_t>(HUDWEAPON_YAW - .1, -.1);
1576 						}
1577 						else if ( HUDWEAPON_YAW < -.1 )
1578 						{
1579 							HUDWEAPON_YAW = std::min<real_t>(HUDWEAPON_YAW + .1, -.1);
1580 						}
1581 						if ( HUDWEAPON_PITCH > 0 )
1582 						{
1583 							HUDWEAPON_PITCH = std::max<real_t>(HUDWEAPON_PITCH - .1, 0.0);
1584 						}
1585 						else if ( HUDWEAPON_PITCH < 0 )
1586 						{
1587 							HUDWEAPON_PITCH = std::min<real_t>(HUDWEAPON_PITCH + .1, 0.0);
1588 						}
1589 						if ( HUDWEAPON_ROLL > 0 )
1590 						{
1591 							HUDWEAPON_ROLL = std::max<real_t>(HUDWEAPON_ROLL - .1, 0.0);
1592 						}
1593 						else if ( HUDWEAPON_ROLL < 0 )
1594 						{
1595 							HUDWEAPON_ROLL = std::min<real_t>(HUDWEAPON_ROLL + .1, 0.0);
1596 						}
1597 					}
1598 				}
1599 				else
1600 				{
1601 					// fix for fists not resetting position after blocking.
1602 					if ( HUDWEAPON_MOVEY > 0 )
1603 					{
1604 						HUDWEAPON_MOVEY = std::max<real_t>(HUDWEAPON_MOVEY - 1, 0.0);
1605 					}
1606 					else if ( HUDWEAPON_MOVEY < 0 )
1607 					{
1608 						HUDWEAPON_MOVEY = std::min<real_t>(HUDWEAPON_MOVEY + 1, 0.0);
1609 					}
1610 					if ( HUDWEAPON_MOVEZ > 0 )
1611 					{
1612 						HUDWEAPON_MOVEZ = std::max<real_t>(HUDWEAPON_MOVEZ - 1, 0.0);
1613 					}
1614 					else if ( HUDWEAPON_MOVEZ < 0 )
1615 					{
1616 						HUDWEAPON_MOVEZ = std::min<real_t>(HUDWEAPON_MOVEZ + 1, 0.0);
1617 					}
1618 				}
1619 			}
1620 			else
1621 			{
1622 				if ( HUDWEAPON_MOVEX > 0 )
1623 				{
1624 					HUDWEAPON_MOVEX = std::max<real_t>(HUDWEAPON_MOVEX - 1, 0.0);
1625 				}
1626 				else if ( HUDWEAPON_MOVEX < 0 )
1627 				{
1628 					HUDWEAPON_MOVEX = std::min<real_t>(HUDWEAPON_MOVEX + 1, 0.0);
1629 				}
1630 				if ( HUDWEAPON_MOVEY > 1 )
1631 				{
1632 					HUDWEAPON_MOVEY = std::max<real_t>(HUDWEAPON_MOVEY - 1, 1.0);
1633 				}
1634 				else if ( HUDWEAPON_MOVEY < 1 )
1635 				{
1636 					HUDWEAPON_MOVEY = std::min<real_t>(HUDWEAPON_MOVEY + 1, 1.0);
1637 				}
1638 				if ( HUDWEAPON_MOVEZ > 1 )
1639 				{
1640 					HUDWEAPON_MOVEZ = std::max<real_t>(HUDWEAPON_MOVEZ - 1, 1.0);
1641 				}
1642 				else if ( HUDWEAPON_MOVEZ < 1 )
1643 				{
1644 					HUDWEAPON_MOVEZ = std::min<real_t>(HUDWEAPON_MOVEZ + 1, 1.0);
1645 				}
1646 				if ( HUDWEAPON_YAW > .1 )
1647 				{
1648 					HUDWEAPON_YAW = std::max<real_t>(HUDWEAPON_YAW - .1, .1);
1649 				}
1650 				else if ( HUDWEAPON_YAW < .1 )
1651 				{
1652 					HUDWEAPON_YAW = std::min<real_t>(HUDWEAPON_YAW + .1, .1);
1653 				}
1654 				if ( HUDWEAPON_PITCH > PI / 6 )
1655 				{
1656 					HUDWEAPON_PITCH = std::max<real_t>(HUDWEAPON_PITCH - .1, PI / 6);
1657 				}
1658 				else if ( HUDWEAPON_PITCH < PI / 6 )
1659 				{
1660 					HUDWEAPON_PITCH = std::min<real_t>(HUDWEAPON_PITCH + .1, PI / 6);
1661 				}
1662 				if ( HUDWEAPON_ROLL > PI / 6 )
1663 				{
1664 					HUDWEAPON_ROLL = std::max<real_t>(HUDWEAPON_ROLL - .1, PI / 6);
1665 				}
1666 				else if ( HUDWEAPON_ROLL < PI / 6 )
1667 				{
1668 					HUDWEAPON_ROLL = std::min<real_t>(HUDWEAPON_ROLL + .1, PI / 6);
1669 				}
1670 			}
1671 		}
1672 	}
1673 	else if ( HUDWEAPON_CHOP == 1 )     // prepare for first swing
1674 	{
1675 		HUDWEAPON_YAW -= .25;
1676 		if ( HUDWEAPON_YAW < 0 )
1677 		{
1678 			HUDWEAPON_YAW = 0;
1679 		}
1680 		HUDWEAPON_PITCH -= .1;
1681 		if ( HUDWEAPON_PITCH < -PI / 4)
1682 		{
1683 			result = -PI / 4;
1684 			HUDWEAPON_PITCH = result;
1685 		}
1686 		HUDWEAPON_ROLL += .25;
1687 		if ( HUDWEAPON_ROLL > 0 )
1688 		{
1689 			HUDWEAPON_ROLL = 0;
1690 		}
1691 		int targetY = -2;
1692 		if ( thrownWeapon )
1693 		{
1694 			targetY = -1;
1695 			HUDWEAPON_MOVEY -= .25;
1696 			HUDWEAPON_MOVEX -= .15;
1697 		}
1698 		else
1699 		{
1700 			HUDWEAPON_MOVEY -= .45;
1701 			HUDWEAPON_MOVEX -= .35;
1702 		}
1703 		if ( HUDWEAPON_MOVEX < -1 )
1704 		{
1705 			HUDWEAPON_MOVEX = -1;
1706 		}
1707 		if ( HUDWEAPON_MOVEY < targetY )
1708 		{
1709 			HUDWEAPON_MOVEY = targetY;
1710 		}
1711 		int targetZ = -6;
1712 		if ( whip )
1713 		{
1714 			targetZ = -6;
1715 			HUDWEAPON_MOVEZ -= .32;
1716 			if ( HUDWEAPON_MOVEY > 2 )
1717 			{
1718 				HUDWEAPON_MOVEY -= .45; // returning from side swing, y offset is larger than normal so assist here.
1719 			}
1720 		}
1721 		else if ( thrownWeapon )
1722 		{
1723 			targetZ = -3;
1724 			HUDWEAPON_MOVEZ -= .35;
1725 		}
1726 		else
1727 		{
1728 			HUDWEAPON_MOVEZ -= .65;
1729 		}
1730 		if ( HUDWEAPON_MOVEZ < targetZ )
1731 		{
1732 			HUDWEAPON_MOVEZ = targetZ;
1733 			if ( HUDWEAPON_PITCH == result && HUDWEAPON_ROLL == 0 && HUDWEAPON_YAW == 0 && HUDWEAPON_MOVEX == -1 && HUDWEAPON_MOVEY == targetY )
1734 			{
1735 				if ( !swingweapon )
1736 				{
1737 					HUDWEAPON_CHOP++;
1738 					players[clientnum]->entity->attack(1, HUDWEAPON_CHARGE, nullptr);
1739 					if ( stats[clientnum]->weapon
1740 						&& (stats[clientnum]->weapon->type == CROSSBOW || stats[clientnum]->weapon->type == HEAVY_CROSSBOW) )
1741 					{
1742 						throwGimpTimer = 40; // fix for swapping weapon to crossbow while charging.
1743 					}
1744 					else if ( (stats[clientnum]->weapon
1745 						&& stats[clientnum]->weapon->type == TOOL_PICKAXE) || whip )
1746 					{
1747 						if ( pickaxeGimpTimer < 20 )
1748 						{
1749 							pickaxeGimpTimer = 20; // fix for swapping weapon from pickaxe causing issues.
1750 						}
1751 					}
1752 
1753 
1754 					if ( thrownWeapon && multiplayer == CLIENT )
1755 					{
1756 						Item* item = stats[clientnum]->weapon;
1757 						if ( item )
1758 						{
1759 							item->count--;
1760 							if ( item->count <= 0 )
1761 							{
1762 								if ( item->node )
1763 								{
1764 									list_RemoveNode(item->node);
1765 								}
1766 								else
1767 								{
1768 									free(item);
1769 								}
1770 								stats[clientnum]->weapon = NULL;
1771 							}
1772 						}
1773 					}
1774 
1775 					HUDWEAPON_CHARGE = 0;
1776 					HUDWEAPON_OVERCHARGE = 0;
1777 					if (players[clientnum]->entity->skill[3] == 0)   // debug cam OFF
1778 					{
1779 						camera_shakey += 6;
1780 					}
1781 				}
1782 				else
1783 				{
1784 					HUDWEAPON_CHARGE = std::min<real_t>(HUDWEAPON_CHARGE + 1, MAXCHARGE);
1785 				}
1786 			}
1787 		}
1788 	}
1789 	else if ( HUDWEAPON_CHOP == 2 )     // first swing
1790 	{
1791 		if ( whip )
1792 		{
1793 			real_t animationMult = 0.8;
1794 			HUDWEAPON_MOVEX += 1 * animationMult;
1795 			if ( HUDWEAPON_MOVEX > 4 )
1796 			{
1797 				HUDWEAPON_MOVEX = 4;
1798 			}
1799 			HUDWEAPON_MOVEY += .45 * animationMult;
1800 			if ( HUDWEAPON_MOVEY > 0 )
1801 			{
1802 				HUDWEAPON_MOVEY = 0;
1803 			}
1804 			HUDWEAPON_PITCH += .5 * animationMult;
1805 			if ( HUDWEAPON_PITCH >= 3 * PI / 4 )
1806 			{
1807 				HUDWEAPON_PITCH = 3 * PI / 4;
1808 			}
1809 			HUDWEAPON_MOVEZ += 1 * animationMult;
1810 			if ( HUDWEAPON_MOVEZ > 4 )
1811 			{
1812 				HUDWEAPON_MOVEZ = 4;
1813 			}
1814 			if ( HUDWEAPON_PITCH >= PI / 8 )
1815 			{
1816 				my->sprite = items[TOOL_WHIP].fpindex + 1;
1817 			}
1818 			if ( HUDWEAPON_YAW > -.1 )
1819 			{
1820 				HUDWEAPON_YAW = std::max<real_t>(HUDWEAPON_YAW - .1, -.1);
1821 			}
1822 			else if ( HUDWEAPON_YAW < -.1 )
1823 			{
1824 				HUDWEAPON_YAW = std::min<real_t>(HUDWEAPON_YAW + .1, -.1);
1825 			}
1826 			if ( HUDWEAPON_MOVEZ == 4 && HUDWEAPON_PITCH == 3 * PI / 4 )
1827 			{
1828 				HUDWEAPON_CHOP++;
1829 			}
1830 		}
1831 		else
1832 		{
1833 			HUDWEAPON_PITCH += .75;
1834 			if ( HUDWEAPON_PITCH >= (PI * 3) / 4 )
1835 			{
1836 				HUDWEAPON_PITCH = (PI * 3) / 4;
1837 			}
1838 			HUDWEAPON_MOVEX += 1;
1839 			if ( HUDWEAPON_MOVEX > 4 )
1840 			{
1841 				HUDWEAPON_MOVEX = 4;
1842 			}
1843 			HUDWEAPON_MOVEZ += .8;
1844 			if ( HUDWEAPON_MOVEZ > 0 )
1845 			{
1846 				HUDWEAPON_MOVEZ = 0;
1847 				HUDWEAPON_CHOP++;
1848 			}
1849 		}
1850 	}
1851 	else if ( HUDWEAPON_CHOP == 3 )     // return from first swing
1852 	{
1853 		if ( swingweapon )
1854 		{
1855 			// another swing...
1856 			Item* item = stats[clientnum]->weapon;
1857 			if ( item && !hideWeapon )
1858 			{
1859 				if ( !rangedweapon
1860 					&& item->type != TOOL_SKELETONKEY
1861 					&& item->type != TOOL_LOCKPICK
1862 					&& itemCategory(item) != POTION
1863 					&& itemCategory(item) != GEM
1864 					&& item->type != FOOD_CREAMPIE
1865 					&& !(item->type >= ARTIFACT_ORB_BLUE && item->type <= ARTIFACT_ORB_GREEN)
1866 					&& !(itemIsThrowableTinkerTool(item))
1867 					&& item->type != TOOL_WHIP )
1868 				{
1869 					if ( stats[clientnum]->weapon->type != TOOL_PICKAXE && itemCategory(item) != THROWN )
1870 					{
1871 						HUDWEAPON_CHOP = 4;
1872 					}
1873 					else
1874 					{
1875 						if ( itemCategory(item) == THROWN )
1876 						{
1877 							throwGimpTimer = 20;
1878 							HUDWEAPON_CHOP = 0;
1879 						}
1880 						else if ( pickaxeGimpTimer <= 0 )
1881 						{
1882 							HUDWEAPON_CHOP = 1; // allow another swing of pickaxe
1883 						}
1884 						else
1885 						{
1886 							HUDWEAPON_CHOP = 0;
1887 						}
1888 					}
1889 				}
1890 			}
1891 		}
1892 		else
1893 		{
1894 			if (stats[clientnum]->weapon && !hideWeapon )
1895 			{
1896 				if ( stats[clientnum]->weapon->type == SLING
1897 					|| stats[clientnum]->weapon->type == SHORTBOW
1898 					|| stats[clientnum]->weapon->type == ARTIFACT_BOW
1899 					|| stats[clientnum]->weapon->type == LONGBOW
1900 					|| stats[clientnum]->weapon->type == COMPOUND_BOW )
1901 				{
1902 					if (bowFire)
1903 					{
1904 						players[clientnum]->entity->attack(0, 0, nullptr);
1905 						HUDWEAPON_MOVEX = -2;
1906 					}
1907 				}
1908 			}
1909 		}
1910 
1911 		bool crossbow = stats[clientnum]->weapon && (stats[clientnum]->weapon->type == CROSSBOW || stats[clientnum]->weapon->type == HEAVY_CROSSBOW);
1912 
1913 		if ( stats[clientnum]->weapon && !hideWeapon )
1914 		{
1915 			if ( rangedweapon )
1916 			{
1917 				if ( HUDWEAPON_MOVEX > 0 )
1918 				{
1919 					HUDWEAPON_MOVEX = std::max<real_t>(HUDWEAPON_MOVEX - 1, 0.0);
1920 				}
1921 				else if ( HUDWEAPON_MOVEX < 0 )
1922 				{
1923 					HUDWEAPON_MOVEX = std::min<real_t>(HUDWEAPON_MOVEX + .1, 0.0);
1924 				}
1925 				if ( HUDWEAPON_MOVEY > 0 )
1926 				{
1927 					HUDWEAPON_MOVEY = std::max<real_t>(HUDWEAPON_MOVEY - 1, 0.0);
1928 				}
1929 				else if ( HUDWEAPON_MOVEY < 0 )
1930 				{
1931 					HUDWEAPON_MOVEY = std::min<real_t>(HUDWEAPON_MOVEY + 1, 0.0);
1932 				}
1933 				if ( HUDWEAPON_MOVEZ > 0 )
1934 				{
1935 					HUDWEAPON_MOVEZ = std::max<real_t>(HUDWEAPON_MOVEZ - 1, 0.0);
1936 				}
1937 				else if ( HUDWEAPON_MOVEZ < 0 )
1938 				{
1939 					HUDWEAPON_MOVEZ = std::min<real_t>(HUDWEAPON_MOVEZ + 1, 0.0);
1940 				}
1941 				if ( HUDWEAPON_YAW > -.1 )
1942 				{
1943 					HUDWEAPON_YAW = std::max<real_t>(HUDWEAPON_YAW - .1, -.1);
1944 				}
1945 				else if ( HUDWEAPON_YAW < -.1 )
1946 				{
1947 					HUDWEAPON_YAW = std::min<real_t>(HUDWEAPON_YAW + .1, -.1);
1948 				}
1949 				if ( HUDWEAPON_PITCH > 0 )
1950 				{
1951 					HUDWEAPON_PITCH = std::max<real_t>(HUDWEAPON_PITCH - .1, 0.0);
1952 				}
1953 				else if ( HUDWEAPON_PITCH < 0 )
1954 				{
1955 					HUDWEAPON_PITCH = std::min<real_t>(HUDWEAPON_PITCH + .1, 0.0);
1956 				}
1957 				if ( HUDWEAPON_ROLL > 0 )
1958 				{
1959 					HUDWEAPON_ROLL = std::max<real_t>(HUDWEAPON_ROLL - .1, 0.0);
1960 				}
1961 				else if ( HUDWEAPON_ROLL < 0 )
1962 				{
1963 					HUDWEAPON_ROLL = std::min<real_t>(HUDWEAPON_ROLL + .1, 0.0);
1964 				}
1965 			}
1966 			else
1967 			{
1968 				HUDWEAPON_MOVEX -= .25;
1969 				if ( HUDWEAPON_MOVEX < 0 )
1970 				{
1971 					HUDWEAPON_MOVEX = 0;
1972 				}
1973 			}
1974 		}
1975 		else
1976 		{
1977 			HUDWEAPON_MOVEX -= .25;
1978 			if ( HUDWEAPON_MOVEX < 0 )
1979 			{
1980 				HUDWEAPON_MOVEX = 0;
1981 			}
1982 		}
1983 		HUDWEAPON_PITCH -= .15;
1984 		if ( HUDWEAPON_PITCH < 0 )
1985 		{
1986 			HUDWEAPON_PITCH = 0;
1987 		}
1988 		HUDWEAPON_MOVEY += .45;
1989 		if ( HUDWEAPON_MOVEY > 0 )
1990 		{
1991 			HUDWEAPON_MOVEY = 0;
1992 		}
1993 		HUDWEAPON_MOVEZ -= .35;
1994 		if ( HUDWEAPON_MOVEZ < 0 )
1995 		{
1996 			HUDWEAPON_MOVEZ = 0;
1997 			if ( HUDWEAPON_PITCH == 0 && HUDWEAPON_MOVEY == 0 && HUDWEAPON_MOVEX == 0 )
1998 			{
1999 				HUDWEAPON_CHOP = 0;
2000 			}
2001 		}
2002 	}
2003 	else if ( HUDWEAPON_CHOP == 4 )     // prepare for second swing
2004 	{
2005 		int targetZ = -4;
2006 		real_t targetRoll = -PI / 2;
2007 		real_t rateY = .75;
2008 		real_t rateRoll = .25;
2009 		int targetY = -6;
2010 		real_t targetPitch = 0.f;
2011 		if ( whip )
2012 		{
2013 			HUDWEAPON_PITCH += .25;
2014 			targetPitch = PI / 8;
2015 			if ( HUDWEAPON_PITCH > targetPitch )
2016 			{
2017 				HUDWEAPON_PITCH = targetPitch;
2018 			}
2019 			HUDWEAPON_WHIP_ANGLE = 0;
2020 			HUDWEAPON_YAW -= .35;
2021 			if ( HUDWEAPON_YAW < -PI / 4 )
2022 			{
2023 				HUDWEAPON_YAW = -PI / 4;
2024 			}
2025 			rateY = .55;
2026 			rateRoll = .35;
2027 		}
2028 		else
2029 		{
2030 			HUDWEAPON_YAW = 0;
2031 			HUDWEAPON_PITCH -= .25;
2032 			if ( HUDWEAPON_PITCH < targetPitch )
2033 			{
2034 				HUDWEAPON_PITCH = targetPitch;
2035 			}
2036 		}
2037 		HUDWEAPON_MOVEX -= .35;
2038 		if ( HUDWEAPON_MOVEX < 0 )
2039 		{
2040 			HUDWEAPON_MOVEX = 0;
2041 		}
2042 		HUDWEAPON_MOVEZ -= .75;
2043 		if ( HUDWEAPON_MOVEZ < targetZ )
2044 		{
2045 			HUDWEAPON_MOVEZ = targetZ;
2046 		}
2047 		HUDWEAPON_MOVEY -= rateY;
2048 		if ( HUDWEAPON_MOVEY < targetY )
2049 		{
2050 			HUDWEAPON_MOVEY = targetY;
2051 		}
2052 		HUDWEAPON_ROLL -= rateRoll;
2053 
2054 		if (HUDWEAPON_ROLL < targetRoll )
2055 		{
2056 			HUDWEAPON_ROLL = targetRoll;
2057 			if (HUDWEAPON_PITCH == targetPitch && HUDWEAPON_MOVEX == 0 && HUDWEAPON_MOVEY == targetY && HUDWEAPON_MOVEZ == targetZ)
2058 			{
2059 				if (!swingweapon)
2060 				{
2061 					HUDWEAPON_CHOP++;
2062 					players[clientnum]->entity->attack(2, HUDWEAPON_CHARGE, nullptr);
2063 					if ( stats[clientnum]->weapon
2064 						&& (stats[clientnum]->weapon->type == CROSSBOW || stats[clientnum]->weapon->type == HEAVY_CROSSBOW) )
2065 					{
2066 						throwGimpTimer = 40; // fix for swapping weapon to crossbow while charging.
2067 					}
2068 					HUDWEAPON_CHARGE = 0;
2069 					HUDWEAPON_OVERCHARGE = 0;
2070 					if (players[clientnum]->entity->skill[3] == 0)   // debug cam OFF
2071 					{
2072 						camera_shakex += .07;
2073 					}
2074 					if ( whip && pickaxeGimpTimer < 20 )
2075 					{
2076 						pickaxeGimpTimer = 20; // fix for swapping weapon from whip causing issues.
2077 					}
2078 				}
2079 				else
2080 				{
2081 					HUDWEAPON_CHARGE = std::min<real_t>(HUDWEAPON_CHARGE + 1, MAXCHARGE);
2082 				}
2083 			}
2084 		}
2085 	}
2086 	else if (HUDWEAPON_CHOP == 5)     // second swing
2087 	{
2088 		if ( whip )
2089 		{
2090 			if ( HUDWEAPON_WHIP_ANGLE == 0 && my->sprite == items[TOOL_WHIP].fpindex )
2091 			{
2092 				HUDWEAPON_WHIP_ANGLE = 1;
2093 				HUDWEAPON_PITCH = 3 * PI / 8;	// convert from whip.vox to whip_attack.vox
2094 				HUDWEAPON_YAW -= PI / 4;		// convert from whip.vox to whip_attack.vox
2095 			}
2096 
2097 			if ( HUDWEAPON_WHIP_ANGLE >= 1 )
2098 			{
2099 				my->sprite = items[TOOL_WHIP].fpindex + 1;
2100 			}
2101 
2102 			real_t animationMul = 0.8;
2103 
2104 			HUDWEAPON_MOVEX = sin(HUDWEAPON_YAW + PI / 4) * -4;
2105 			HUDWEAPON_MOVEY = -2 + cos(std::min(HUDWEAPON_YAW + PI / 4, 3 * PI / 4)) * -4;
2106 			HUDWEAPON_YAW += .35 * animationMul;
2107 			if ( HUDWEAPON_YAW > PI / 4 )
2108 			{
2109 				my->sprite = items[TOOL_WHIP].fpindex;
2110 				HUDWEAPON_PITCH = PI / 8;	// convert from whip_attack.vox to whip.vox
2111 				HUDWEAPON_YAW = PI / 2;		// convert from whip_attack.vox to whip.vox
2112 				HUDWEAPON_CHOP++;
2113 				HUDWEAPON_WHIP_ANGLE = 0;
2114 				HUDWEAPON_MOVEX += 2; // trial and error got these numbers for MOVEX and MOVEY :)
2115 				HUDWEAPON_MOVEY += 10;
2116 			}
2117 		}
2118 		else
2119 		{
2120 			HUDWEAPON_MOVEX = sin(HUDWEAPON_YAW) * 1;
2121 			HUDWEAPON_MOVEY = cos(HUDWEAPON_YAW) * -6;
2122 			HUDWEAPON_YAW += .35;
2123 			if ( HUDWEAPON_YAW > (3 * PI) / 4 )
2124 			{
2125 				HUDWEAPON_YAW = (3 * PI) / 4;
2126 				HUDWEAPON_CHOP++;
2127 			}
2128 		}
2129 	}
2130 	else if (HUDWEAPON_CHOP == 6)     // return from second swing
2131 	{
2132 		if ( swingweapon )
2133 		{
2134 			// one more swing...
2135 			if ( stats[clientnum]->weapon && !hideWeapon )
2136 			{
2137 				int weaponSkill = getWeaponSkill(stats[clientnum]->weapon);
2138 				if ( weaponSkill == PRO_SWORD || stats[clientnum]->weapon->type == STEEL_HALBERD )
2139 				{
2140 					HUDWEAPON_CHOP = 7;  // swords + halberds can stab
2141 				}
2142 				else
2143 				{
2144 					HUDWEAPON_CHOP = 1;  // everything else can't
2145 				}
2146 			}
2147 		}
2148 
2149 		if ( whip )
2150 		{
2151 			real_t animationMultiplier = 0.8;
2152 			if ( HUDWEAPON_MOVEX > 0.f )
2153 			{
2154 				HUDWEAPON_MOVEX = std::max<real_t>(HUDWEAPON_MOVEX - .2 * animationMultiplier, 0.f);
2155 			}
2156 			else if ( HUDWEAPON_MOVEX < 0.f )
2157 			{
2158 				HUDWEAPON_MOVEX = std::min<real_t>(HUDWEAPON_MOVEX + .2 * animationMultiplier, 0.f);
2159 			}
2160 			HUDWEAPON_MOVEY -= 0.9 * animationMultiplier;
2161 			if ( HUDWEAPON_MOVEY < 0 )
2162 			{
2163 				HUDWEAPON_MOVEY = 0;
2164 			}
2165 			if ( HUDWEAPON_ROLL > -PI / 8 )
2166 			{
2167 				HUDWEAPON_PITCH -= .2 * animationMultiplier;
2168 				if ( HUDWEAPON_PITCH < 0.f )
2169 				{
2170 					HUDWEAPON_PITCH = 0.f;
2171 				}
2172 			}
2173 			HUDWEAPON_ROLL += .2 * animationMultiplier;
2174 		}
2175 		else
2176 		{
2177 			HUDWEAPON_MOVEX -= .25;
2178 			if ( HUDWEAPON_MOVEX < 0 )
2179 			{
2180 				HUDWEAPON_MOVEX = 0;
2181 			}
2182 			HUDWEAPON_MOVEY -= .25;
2183 			if ( HUDWEAPON_MOVEY < 0 )
2184 			{
2185 				HUDWEAPON_MOVEY = 0;
2186 			}
2187 			HUDWEAPON_ROLL += .25;
2188 		}
2189 		HUDWEAPON_YAW -= .25;
2190 		if ( HUDWEAPON_YAW < -.1 )
2191 		{
2192 			HUDWEAPON_YAW = -.1;
2193 		}
2194 		HUDWEAPON_MOVEZ += .35;
2195 		if ( HUDWEAPON_MOVEZ > 0 )
2196 		{
2197 			HUDWEAPON_MOVEZ = 0;
2198 		}
2199 		if ( HUDWEAPON_ROLL > 0 )
2200 		{
2201 			HUDWEAPON_ROLL = 0;
2202 			if ( HUDWEAPON_YAW == -.1 && HUDWEAPON_MOVEZ == 0 && HUDWEAPON_MOVEY == 0 && HUDWEAPON_MOVEX == 0 )
2203 			{
2204 				HUDWEAPON_CHOP = 0;
2205 			}
2206 		}
2207 	}
2208 	else if ( HUDWEAPON_CHOP == 7 )     // prepare for third swing
2209 	{
2210 		HUDWEAPON_MOVEX -= .35;
2211 		if ( HUDWEAPON_MOVEX < 0 )
2212 		{
2213 			HUDWEAPON_MOVEX = 0;
2214 		}
2215 		HUDWEAPON_MOVEY -= .45;
2216 		if ( HUDWEAPON_MOVEY < -1 )
2217 		{
2218 			HUDWEAPON_MOVEY = -1;
2219 		}
2220 		HUDWEAPON_MOVEZ -= .25;
2221 		if ( HUDWEAPON_MOVEZ < -2 )
2222 		{
2223 			HUDWEAPON_MOVEZ = -2;
2224 		}
2225 		HUDWEAPON_YAW -= .15;
2226 		if ( HUDWEAPON_YAW < 2 * PI / 5 )
2227 		{
2228 			result = 2 * PI / 5;
2229 			HUDWEAPON_YAW = result;
2230 		}
2231 		real_t pitchLimit = .2;
2232 		if ( playerRace == SPIDER )
2233 		{
2234 			pitchLimit = -PI / 2;
2235 			HUDWEAPON_PITCH -= .2;
2236 		}
2237 		else
2238 		{
2239 			HUDWEAPON_PITCH -= .05;
2240 		}
2241 		if ( HUDWEAPON_PITCH < pitchLimit )
2242 		{
2243 			HUDWEAPON_PITCH = pitchLimit;
2244 		}
2245 		HUDWEAPON_ROLL -= .15;
2246 		if (HUDWEAPON_ROLL < -2 * PI / 5)
2247 		{
2248 			HUDWEAPON_ROLL = -2 * PI / 5;
2249 			if (HUDWEAPON_PITCH == pitchLimit && HUDWEAPON_YAW == result
2250 				&& HUDWEAPON_MOVEX == 0 && HUDWEAPON_MOVEY == -1 && (HUDWEAPON_MOVEZ == -2))
2251 			{
2252 				if (!swingweapon)
2253 				{
2254 					HUDWEAPON_CHOP++;
2255 					if ( stats[clientnum]->weapon && hideWeapon )
2256 					{
2257 						players[clientnum]->entity->attack(1, HUDWEAPON_CHARGE, nullptr);
2258 					}
2259 					else
2260 					{
2261 						players[clientnum]->entity->attack(3, HUDWEAPON_CHARGE, nullptr);
2262 					}
2263 					if ( stats[clientnum]->weapon
2264 						&& (stats[clientnum]->weapon->type == CROSSBOW || stats[clientnum]->weapon->type == HEAVY_CROSSBOW) )
2265 					{
2266 						throwGimpTimer = 40; // fix for swapping weapon to crossbow while charging.
2267 					}
2268 					HUDWEAPON_CHARGE = 0;
2269 					HUDWEAPON_OVERCHARGE = 0;
2270 					if (players[clientnum]->entity->skill[3] == 0)   // debug cam OFF
2271 					{
2272 						camera_shakex += .03;
2273 						camera_shakey += 4;
2274 					}
2275 				}
2276 				else
2277 				{
2278 					HUDWEAPON_CHARGE = std::min<real_t>(HUDWEAPON_CHARGE + 1, MAXCHARGE);
2279 				}
2280 			}
2281 		}
2282 	}
2283 	else if ( HUDWEAPON_CHOP == 8 )     // third swing
2284 	{
2285 		if ( playerRace == SPIDER )
2286 		{
2287 			HUDWEAPON_MOVEX += 1;
2288 			if ( HUDWEAPON_MOVEX > 2 )
2289 			{
2290 				HUDWEAPON_MOVEX = 2;
2291 				HUDWEAPON_CHOP++;
2292 			}
2293 			HUDWEAPON_PITCH += .2;
2294 			if ( HUDWEAPON_PITCH > 0 )
2295 			{
2296 				HUDWEAPON_PITCH = 0;
2297 			}
2298 		}
2299 		else
2300 		{
2301 			HUDWEAPON_MOVEX += 2;
2302 			if ( HUDWEAPON_MOVEX > 4 )
2303 			{
2304 				HUDWEAPON_MOVEX = 4;
2305 				HUDWEAPON_CHOP++;
2306 			}
2307 		}
2308 	}
2309 	else if ( HUDWEAPON_CHOP == 9 )     // return from third swing
2310 	{
2311 		if ( playerRace == SPIDER )
2312 		{
2313 			HUDWEAPON_MOVEX -= .25;
2314 		}
2315 		else
2316 		{
2317 			HUDWEAPON_MOVEX -= .5;
2318 		}
2319 		if ( HUDWEAPON_MOVEX < 0 )
2320 		{
2321 			HUDWEAPON_MOVEX = 0;
2322 		}
2323 		HUDWEAPON_MOVEY += .25;
2324 		if ( HUDWEAPON_MOVEY > 0 )
2325 		{
2326 			HUDWEAPON_MOVEY = 0;
2327 		}
2328 		HUDWEAPON_MOVEZ += .35;
2329 		if ( HUDWEAPON_MOVEZ > 0 )
2330 		{
2331 			HUDWEAPON_MOVEZ = 0;
2332 		}
2333 		if ( HUDWEAPON_MOVEX == 0 )
2334 		{
2335 			if ( swingweapon )
2336 			{
2337 				// restart the combo...
2338 				if ( stats[clientnum]->weapon == NULL || hideWeapon )
2339 				{
2340 					HUDWEAPON_CHOP = 7;
2341 				}
2342 				else
2343 				{
2344 					if ( itemCategory(stats[clientnum]->weapon) != MAGICSTAFF && stats[clientnum]->weapon->type != CRYSTAL_SPEAR && stats[clientnum]->weapon->type != IRON_SPEAR && stats[clientnum]->weapon->type != ARTIFACT_SPEAR )
2345 					{
2346 						HUDWEAPON_CHOP = 1;
2347 					}
2348 					else
2349 					{
2350 						HUDWEAPON_CHOP = 7;
2351 					}
2352 				}
2353 			}
2354 			HUDWEAPON_YAW -= .25;
2355 			if ( HUDWEAPON_YAW < -.1 )
2356 			{
2357 				HUDWEAPON_YAW = -.1;
2358 			}
2359 			if ( playerRace == SPIDER )
2360 			{
2361 				HUDWEAPON_PITCH += .12;
2362 			}
2363 			else
2364 			{
2365 				HUDWEAPON_PITCH += .05;
2366 			}
2367 			if ( HUDWEAPON_PITCH > 0)
2368 			{
2369 				HUDWEAPON_PITCH = 0;
2370 			}
2371 			HUDWEAPON_ROLL += .25;
2372 			if ( HUDWEAPON_ROLL > 0 )
2373 			{
2374 				HUDWEAPON_ROLL = 0;
2375 				if ( HUDWEAPON_YAW == -.1 && HUDWEAPON_PITCH == 0 && HUDWEAPON_MOVEZ == 0 && HUDWEAPON_MOVEY == 0 && HUDWEAPON_MOVEX == 0 )
2376 				{
2377 					HUDWEAPON_CHOP = 0;
2378 				}
2379 			}
2380 		}
2381 	}
2382 	else if ( HUDWEAPON_CHOP == 10 ) // special punch
2383 	{
2384 		HUDWEAPON_MOVEX = std::max(static_cast<real_t>(0.0), HUDWEAPON_MOVEX - .15); // forward/back
2385 		HUDWEAPON_MOVEY = std::min(static_cast<real_t>(1.0), HUDWEAPON_MOVEY + .25); // left/right
2386 		HUDWEAPON_MOVEZ = std::max(static_cast<real_t>(-2.0), HUDWEAPON_MOVEZ - .05); // up/down
2387 
2388 		HUDWEAPON_YAW -= .15;
2389 		if ( HUDWEAPON_YAW < 2 * PI / 5 )
2390 		{
2391 			result = 2 * PI / 5;
2392 			HUDWEAPON_YAW = result;
2393 		}
2394 		real_t pitchLimit = .2;
2395 		HUDWEAPON_PITCH -= .05;
2396 		if ( HUDWEAPON_PITCH < pitchLimit )
2397 		{
2398 			HUDWEAPON_PITCH = pitchLimit;
2399 		}
2400 		HUDWEAPON_ROLL -= .15;
2401 		if ( HUDWEAPON_ROLL < -2 * PI / 5 )
2402 		{
2403 			HUDWEAPON_ROLL = -2 * PI / 5;
2404 			if ( HUDWEAPON_CHARGE < 40 )
2405 			{
2406 				HUDWEAPON_CHARGE += 1;
2407 			}
2408 			else
2409 			{
2410 				HUDWEAPON_CHOP = 11;
2411 				HUDWEAPON_CHARGE = 0;
2412 				HUDWEAPON_OVERCHARGE = 0;
2413 				if ( players[clientnum]->entity->skill[3] == 0 )   // debug cam OFF
2414 				{
2415 					camera_shakex += .06;
2416 					camera_shakey += 6;
2417 				}
2418 				players[clientnum]->entity->attack(PLAYER_POSE_GOLEM_SMASH, MAXCHARGE, nullptr);
2419 			}
2420 		}
2421 	}
2422 	else if ( HUDWEAPON_CHOP == 11 )     // third swing
2423 	{
2424 		HUDWEAPON_MOVEX += 1;
2425 		if ( HUDWEAPON_MOVEX > 4 )
2426 		{
2427 			HUDWEAPON_MOVEX = 4;
2428 			HUDWEAPON_CHOP = 12;
2429 		}
2430 	}
2431 	else if ( HUDWEAPON_CHOP == 12 )     // return from third swing
2432 	{
2433 		HUDWEAPON_MOVEX -= .2;
2434 		if ( HUDWEAPON_MOVEX < 0 )
2435 		{
2436 			HUDWEAPON_MOVEX = 0;
2437 		}
2438 		HUDWEAPON_MOVEY += .15;
2439 		if ( HUDWEAPON_MOVEY > 0 )
2440 		{
2441 			HUDWEAPON_MOVEY = 0;
2442 		}
2443 		HUDWEAPON_MOVEZ += .25;
2444 		if ( HUDWEAPON_MOVEZ > 0 )
2445 		{
2446 			HUDWEAPON_MOVEZ = 0;
2447 		}
2448 		if ( HUDWEAPON_MOVEX == 0 )
2449 		{
2450 			HUDWEAPON_YAW -= .25;
2451 			if ( HUDWEAPON_YAW < -.1 )
2452 			{
2453 				HUDWEAPON_YAW = -.1;
2454 			}
2455 			HUDWEAPON_PITCH += .05;
2456 			if ( HUDWEAPON_PITCH > 0 )
2457 			{
2458 				HUDWEAPON_PITCH = 0;
2459 			}
2460 			HUDWEAPON_ROLL += .25;
2461 			if ( HUDWEAPON_ROLL > 0 )
2462 			{
2463 				HUDWEAPON_ROLL = 0;
2464 				if ( HUDWEAPON_YAW == -.1 && HUDWEAPON_PITCH == 0 && HUDWEAPON_MOVEZ == 0 && HUDWEAPON_MOVEY == 0 && HUDWEAPON_MOVEX == 0 )
2465 				{
2466 					HUDWEAPON_CHOP = 0;
2467 				}
2468 			}
2469 		}
2470 	}
2471 	else if ( HUDWEAPON_CHOP == 13 ) // tool placing
2472 	{
2473 		int targetZ = -4;
2474 		real_t targetRoll = -PI / 2;
2475 		real_t rateY = .1;
2476 		real_t rateRoll = .25;
2477 		int targetY = 1;
2478 		if ( !swingweapon )
2479 		{
2480 			//targetY = 0;
2481 		}
2482 		real_t targetPitch = 0.f;
2483 
2484 		HUDWEAPON_YAW = 0;
2485 		HUDWEAPON_PITCH -= .25;
2486 		if ( HUDWEAPON_PITCH < targetPitch )
2487 		{
2488 			HUDWEAPON_PITCH = targetPitch;
2489 		}
2490 		HUDWEAPON_MOVEX -= .35;
2491 		if ( HUDWEAPON_MOVEX < 0 )
2492 		{
2493 			HUDWEAPON_MOVEX = 0;
2494 		}
2495 		HUDWEAPON_MOVEZ -= .75;
2496 		if ( HUDWEAPON_MOVEZ < targetZ )
2497 		{
2498 			HUDWEAPON_MOVEZ = targetZ;
2499 		}
2500 		HUDWEAPON_MOVEY += rateY;
2501 		if ( HUDWEAPON_MOVEY > targetY )
2502 		{
2503 			HUDWEAPON_MOVEY = targetY;
2504 		}
2505 		HUDWEAPON_ROLL -= rateRoll;
2506 
2507 		if ( HUDWEAPON_ROLL < targetRoll )
2508 		{
2509 			HUDWEAPON_ROLL = targetRoll;
2510 			if ( HUDWEAPON_PITCH == targetPitch && HUDWEAPON_MOVEX == 0 && HUDWEAPON_MOVEY == targetY && HUDWEAPON_MOVEZ == targetZ )
2511 			{
2512 				if ( !swingweapon )
2513 				{
2514 					HUDWEAPON_CHOP = 14;
2515 					if ( players[clientnum]->entity->skill[3] == 0 )   // debug cam OFF
2516 					{
2517 						camera_shakex += .07;
2518 					}
2519 					Entity* player = players[clientnum]->entity;
2520 					if ( stats[clientnum]->weapon && (stats[clientnum]->weapon->isTinkeringItemWithThrownLimit())
2521 						&& !playerCanSpawnMoreTinkeringBots(stats[clientnum]) )
2522 					{
2523 						throwGimpTimer = TICKS_PER_SECOND / 2; // limits how often you can throw objects
2524 						if ( stats[clientnum]->PROFICIENCIES[PRO_LOCKPICKING] >= SKILL_LEVEL_LEGENDARY )
2525 						{
2526 							messagePlayer(clientnum, language[3884]);
2527 						}
2528 						else
2529 						{
2530 							messagePlayer(clientnum, language[3883]);
2531 						}
2532 					}
2533 					else if ( stats[clientnum]->weapon && player )
2534 					{
2535 						//lineTrace(player, player->x, player->y, player->yaw, STRIKERANGE, 0, false);
2536 						players[clientnum]->entity->attack(2, HUDWEAPON_CHARGE, nullptr);
2537 						throwGimpTimer = TICKS_PER_SECOND / 2; // limits how often you can throw objects
2538 						Item* item = stats[clientnum]->weapon;
2539 						if ( multiplayer == CLIENT )
2540 						{
2541 							item->count--;
2542 							if ( item->count <= 0 )
2543 							{
2544 								if ( item->node )
2545 								{
2546 									list_RemoveNode(item->node);
2547 								}
2548 								else
2549 								{
2550 									free(item);
2551 								}
2552 								stats[clientnum]->weapon = NULL;
2553 							}
2554 						}
2555 						if ( !stats[clientnum]->weapon )
2556 						{
2557 							HUDWEAPON_ROLL = 0;
2558 							HUDWEAPON_MOVEZ = 3;
2559 						}
2560 					}
2561 					HUDWEAPON_CHARGE = 0;
2562 					HUDWEAPON_OVERCHARGE = 0;
2563 				}
2564 				else
2565 				{
2566 					HUDWEAPON_CHARGE = std::min<real_t>(HUDWEAPON_CHARGE + 1, MAXCHARGE);
2567 				}
2568 			}
2569 		}
2570 	}
2571 	else if ( HUDWEAPON_CHOP == 14 )     // second swing
2572 	{
2573 		HUDWEAPON_MOVEX = sin(HUDWEAPON_YAW) * 2;
2574 		HUDWEAPON_MOVEY = cos(HUDWEAPON_YAW) * 1;
2575 		HUDWEAPON_YAW += .3;
2576 		if ( HUDWEAPON_YAW > (2 * PI) / 4 )
2577 		{
2578 			HUDWEAPON_YAW = (2 * PI) / 4;
2579 			HUDWEAPON_CHOP++;
2580 		}
2581 	}
2582 	else if ( HUDWEAPON_CHOP == 15 )     // return from second swing
2583 	{
2584 		HUDWEAPON_MOVEX -= .25;
2585 		if ( HUDWEAPON_MOVEX < 0 )
2586 		{
2587 			HUDWEAPON_MOVEX = 0;
2588 		}
2589 		HUDWEAPON_MOVEY -= .25;
2590 		if ( HUDWEAPON_MOVEY < 0 )
2591 		{
2592 			HUDWEAPON_MOVEY = 0;
2593 		}
2594 		HUDWEAPON_ROLL += .05;
2595 
2596 		HUDWEAPON_YAW -= .05;
2597 		if ( HUDWEAPON_YAW < -.1 )
2598 		{
2599 			HUDWEAPON_YAW = -.1;
2600 		}
2601 		HUDWEAPON_MOVEZ += .35;
2602 		if ( HUDWEAPON_MOVEZ > 0 )
2603 		{
2604 			HUDWEAPON_MOVEZ = 0;
2605 		}
2606 		if ( HUDWEAPON_ROLL > 0 )
2607 		{
2608 			HUDWEAPON_ROLL = 0;
2609 			if ( HUDWEAPON_YAW == -.1 && HUDWEAPON_MOVEZ == 0 && HUDWEAPON_MOVEY == 0 && HUDWEAPON_MOVEX == 0 )
2610 			{
2611 				HUDWEAPON_CHOP = 0;
2612 			}
2613 		}
2614 	}
2615 	else if ( HUDWEAPON_CHOP == CROSSBOW_CHOP_RELOAD_START )     // crossbow reload
2616 	{
2617 		if ( HUDWEAPON_MOVEX > 0 )
2618 		{
2619 			HUDWEAPON_MOVEX = std::max<real_t>(HUDWEAPON_MOVEX - 1, 0.0);
2620 		}
2621 		else if ( HUDWEAPON_MOVEX < 0 )
2622 		{
2623 			HUDWEAPON_MOVEX = std::min<real_t>(HUDWEAPON_MOVEX + .15, 0.0);
2624 			if ( HUDWEAPON_MOVEX > -1 )
2625 			{
2626 				if ( HUDWEAPON_CROSSBOW_RELOAD_ANIMATION == CROSSBOW_ANIM_SHOOT
2627 					&& stats[clientnum]->weapon && stats[clientnum]->weapon->type == HEAVY_CROSSBOW )
2628 				{
2629 #ifdef SOUND
2630 					bowDrawingSoundChannel = playSound(410, 64);
2631 #endif
2632 				}
2633 
2634 				HUDWEAPON_CROSSBOW_RELOAD_ANIMATION = CROSSBOW_ANIM_RELOAD_START;
2635 
2636 				HUDWEAPON_MOVEZ += .15;
2637 				real_t targetZ = 1;
2638 				if ( !rangedWeaponUseQuiverOnAttack(stats[clientnum]) )
2639 				{
2640 					targetZ = 0.5;
2641 				}
2642 				if ( HUDWEAPON_MOVEZ > targetZ )
2643 				{
2644 					if ( stats[clientnum]->weapon && stats[clientnum]->weapon->type == HEAVY_CROSSBOW )
2645 					{
2646 						HUDWEAPON_CROSSBOW_RELOAD_ANIMATION = CROSSBOW_ANIM_HEAVY_RELOAD_MIDPOINT;
2647 					}
2648 					else
2649 					{
2650 						HUDWEAPON_CROSSBOW_RELOAD_ANIMATION = CROSSBOW_ANIM_RELOAD_END;
2651 					}
2652 					HUDWEAPON_MOVEZ = targetZ;
2653 				}
2654 			}
2655 		}
2656 		if ( fabs(HUDWEAPON_MOVEX) < 0.01 )
2657 		{
2658 			HUDWEAPON_CHOP = CROSSBOW_CHOP_RELOAD_ENDING;
2659 		}
2660 
2661 		if ( HUDWEAPON_MOVEY > 0 )
2662 		{
2663 			HUDWEAPON_MOVEY = std::max<real_t>(HUDWEAPON_MOVEY - 1, 0.0);
2664 		}
2665 		else if ( HUDWEAPON_MOVEY < 0 )
2666 		{
2667 			HUDWEAPON_MOVEY = std::min<real_t>(HUDWEAPON_MOVEY + 1, 0.0);
2668 		}
2669 		if ( HUDWEAPON_YAW > -.1 )
2670 		{
2671 			HUDWEAPON_YAW = std::max<real_t>(HUDWEAPON_YAW - .1, -.1);
2672 		}
2673 		else if ( HUDWEAPON_YAW < -.1 )
2674 		{
2675 			HUDWEAPON_YAW = std::min<real_t>(HUDWEAPON_YAW + .1, -.1);
2676 		}
2677 		if ( HUDWEAPON_ROLL > 0 )
2678 		{
2679 			HUDWEAPON_ROLL = std::max<real_t>(HUDWEAPON_ROLL - .1, 0.0);
2680 		}
2681 		else if ( HUDWEAPON_ROLL < 0 )
2682 		{
2683 			HUDWEAPON_ROLL = std::min<real_t>(HUDWEAPON_ROLL + .1, 0.0);
2684 		}
2685 		if ( HUDWEAPON_PITCH > 0 )
2686 		{
2687 			HUDWEAPON_PITCH = std::max<real_t>(HUDWEAPON_PITCH - .1, 0.0);
2688 		}
2689 		else if ( HUDWEAPON_PITCH < 0 )
2690 		{
2691 			HUDWEAPON_PITCH = std::min<real_t>(HUDWEAPON_PITCH + .1, 0.0);
2692 		}
2693 	}
2694 	else if ( HUDWEAPON_CHOP == CROSSBOW_CHOP_RELOAD_ENDING )     // crossbow reload
2695 	{
2696 		if ( HUDWEAPON_MOVEZ > 1 )
2697 		{
2698 			HUDWEAPON_MOVEZ = std::max<real_t>(HUDWEAPON_MOVEZ - 0.2, 1);
2699 		}
2700 		if ( stats[clientnum]->weapon && stats[clientnum]->weapon->type == HEAVY_CROSSBOW )
2701 		{
2702 			if ( HUDWEAPON_MOVEZ > 1 )
2703 			{
2704 				HUDWEAPON_MOVEZ -= .1; // just in case we're overshooting from another animation or something move faster.
2705 			}
2706 			else
2707 			{
2708 				if ( rangedWeaponUseQuiverOnAttack(stats[clientnum]) )
2709 				{
2710 				// we fired a quiver shot, the crossbow will be lower here so move faster.
2711 					HUDWEAPON_MOVEZ -= .02;
2712 					if ( HUDWEAPON_MOVEZ < 0.5 )
2713 					{
2714 						HUDWEAPON_CROSSBOW_RELOAD_ANIMATION = CROSSBOW_ANIM_RELOAD_END;
2715 					}
2716 					else if ( HUDWEAPON_MOVEZ < 0.8 )
2717 					{
2718 						shakeRangedWeapon = true;
2719 					}
2720 				}
2721 				else
2722 				{
2723 					HUDWEAPON_MOVEZ -= .01;
2724 					if ( HUDWEAPON_MOVEZ < 0.25 )
2725 					{
2726 						HUDWEAPON_CROSSBOW_RELOAD_ANIMATION = CROSSBOW_ANIM_RELOAD_END;
2727 					}
2728 					else if ( HUDWEAPON_MOVEZ < 0.4 )
2729 					{
2730 						shakeRangedWeapon = true;
2731 					}
2732 				}
2733 			}
2734 		}
2735 		else
2736 		{
2737 			HUDWEAPON_MOVEZ -= .1;
2738 		}
2739 		if ( HUDWEAPON_MOVEZ < 0 )
2740 		{
2741 			HUDWEAPON_MOVEZ = 0;
2742 			HUDWEAPON_CHOP = 0;
2743 		}
2744 
2745 		if ( HUDWEAPON_MOVEY > 0 )
2746 		{
2747 			HUDWEAPON_MOVEY = std::max<real_t>(HUDWEAPON_MOVEY - 1, 0.0);
2748 		}
2749 		else if ( HUDWEAPON_MOVEY < 0 )
2750 		{
2751 			HUDWEAPON_MOVEY = std::min<real_t>(HUDWEAPON_MOVEY + 1, 0.0);
2752 		}
2753 		if ( HUDWEAPON_YAW > -.1 )
2754 		{
2755 			HUDWEAPON_YAW = std::max<real_t>(HUDWEAPON_YAW - .1, -.1);
2756 		}
2757 		else if ( HUDWEAPON_YAW < -.1 )
2758 		{
2759 			HUDWEAPON_YAW = std::min<real_t>(HUDWEAPON_YAW + .1, -.1);
2760 		}
2761 		if ( HUDWEAPON_ROLL > 0 )
2762 		{
2763 			HUDWEAPON_ROLL = std::max<real_t>(HUDWEAPON_ROLL - .1, 0.0);
2764 		}
2765 		else if ( HUDWEAPON_ROLL < 0 )
2766 		{
2767 			HUDWEAPON_ROLL = std::min<real_t>(HUDWEAPON_ROLL + .1, 0.0);
2768 		}
2769 		if ( HUDWEAPON_PITCH > 0 )
2770 		{
2771 			HUDWEAPON_PITCH = std::max<real_t>(HUDWEAPON_PITCH - .1, 0.0);
2772 		}
2773 		else if ( HUDWEAPON_PITCH < 0 )
2774 		{
2775 			HUDWEAPON_PITCH = std::min<real_t>(HUDWEAPON_PITCH + .1, 0.0);
2776 		}
2777 	}
2778 
2779 	if ( HUDWEAPON_CHARGE == MAXCHARGE || castStrikeAnimation
2780 		|| players[clientnum]->entity->skill[9] == MONSTER_POSE_SPECIAL_WINDUP2
2781 		|| shakeRangedWeapon )
2782 	{
2783 		if ( ticks % 5 == 0 && players[clientnum]->entity->skill[9] == MONSTER_POSE_SPECIAL_WINDUP2 )
2784 		{
2785 			camera_shakey += 6;
2786 		}
2787 		if ( ticks % 2 == 0 )
2788 		{
2789 			if ( shakeRangedWeapon )
2790 			{
2791 				HUDWEAPON_MOVEX -= HUDWEAPON_OLDVIBRATEX;
2792 				HUDWEAPON_MOVEY -= HUDWEAPON_OLDVIBRATEY;
2793 				HUDWEAPON_OLDVIBRATEX = (rand() % 30 - 10) / 150.f;
2794 				HUDWEAPON_OLDVIBRATEY = (rand() % 30 - 10) / 150.f;
2795 				HUDWEAPON_MOVEX += HUDWEAPON_OLDVIBRATEX;
2796 				HUDWEAPON_MOVEY += HUDWEAPON_OLDVIBRATEY;
2797 			}
2798 			else
2799 			{
2800 				// charge vibration
2801 				HUDWEAPON_MOVEX -= HUDWEAPON_OLDVIBRATEX;
2802 				HUDWEAPON_MOVEY -= HUDWEAPON_OLDVIBRATEY;
2803 				HUDWEAPON_MOVEZ -= HUDWEAPON_OLDVIBRATEZ;
2804 				HUDWEAPON_OLDVIBRATEX = (rand() % 30 - 10) / 80.f;
2805 				HUDWEAPON_OLDVIBRATEY = (rand() % 30 - 10) / 80.f;
2806 				HUDWEAPON_OLDVIBRATEZ = (rand() % 30 - 10) / 80.f;
2807 				HUDWEAPON_MOVEX += HUDWEAPON_OLDVIBRATEX;
2808 				HUDWEAPON_MOVEY += HUDWEAPON_OLDVIBRATEY;
2809 				HUDWEAPON_MOVEZ += HUDWEAPON_OLDVIBRATEZ;
2810 			}
2811 		}
2812 		if ( (castStrikeAnimation || players[clientnum]->entity->skill[9] == MONSTER_POSE_SPECIAL_WINDUP2)
2813 			|| shakeRangedWeapon )
2814 		{
2815 			// don't overcharge here.
2816 		}
2817 		else
2818 		{
2819 			HUDWEAPON_OVERCHARGE++;
2820 		}
2821 	}
2822 	if ( castStrikeAnimation ) // magic sprite particles around the fist
2823 	{
2824 		if ( ticks % 5 == 0 )
2825 		{
2826 			Entity* entity = spawnGib(my);
2827 			entity->flags[INVISIBLE] = false;
2828 			entity->flags[SPRITE] = true;
2829 			entity->flags[NOUPDATE] = true;
2830 			entity->flags[UPDATENEEDED] = false;
2831 			entity->flags[OVERDRAW] = true;
2832 			entity->flags[BRIGHT] = true;
2833 			entity->scalex = 0.25f; //MAKE 'EM SMALL PLEASE!
2834 			entity->scaley = 0.25f;
2835 			entity->scalez = 0.25f;
2836 			entity->z -= 3.5;
2837 			entity->sprite = 16; //TODO: Originally. 22. 16 -- spark sprite instead?
2838 			entity->yaw = ((rand() % 6) * 60) * PI / 180.0;
2839 			entity->pitch = (rand() % 360) * PI / 180.0;
2840 			entity->roll = (rand() % 360) * PI / 180.0;
2841 			entity->vel_x = cos(entity->yaw) * .1;
2842 			entity->vel_y = sin(entity->yaw) * .1;
2843 			entity->vel_z = -.15;
2844 			entity->fskill[3] = 0.01;
2845 		}
2846 	}
2847 
2848 	// move the weapon
2849 	if (players[clientnum] == nullptr || players[clientnum]->entity == nullptr)
2850 	{
2851 		return;
2852 	}
2853 	double defaultpitch = PI / 8.f;
2854 	if (stats[clientnum]->weapon == nullptr || hideWeapon)
2855 	{
2856 		if ( playerRace == RAT )
2857 		{
2858 			my->x = 6 + HUDWEAPON_MOVEX / 3;
2859 			my->y = 3;// +HUDWEAPON_MOVEY;
2860 			my->z = (cameras[HUDWEAPON_PLAYERNUM].z * .1 - players[clientnum]->entity->z) + 7 + HUDWEAPON_MOVEZ / 10;
2861 			my->yaw = 0.f - camera_shakex2;
2862 			my->pitch = defaultpitch + HUDWEAPON_PITCH - camera_shakey2 / 200.f;
2863 			my->roll = HUDWEAPON_ROLL;
2864 
2865 			if ( isLevitating(stats[clientnum]) )
2866 			{
2867 				my->z -= 2 * .4;
2868 			}
2869 		}
2870 		else if ( playerRace == SPIDER )
2871 		{
2872 			my->x = 6 + HUDWEAPON_MOVEX;
2873 			my->y = 3;// +HUDWEAPON_MOVEY;
2874 			my->z = (cameras[HUDWEAPON_PLAYERNUM].z * .5 - players[clientnum]->entity->z) + 7 + HUDWEAPON_MOVEZ;
2875 			my->yaw = 0.f - camera_shakex2;
2876 			my->pitch = defaultpitch + HUDWEAPON_PITCH - camera_shakey2 / 200.f;
2877 			my->roll = HUDWEAPON_ROLL;
2878 		}
2879 		else
2880 		{
2881 			my->x = 6 + HUDWEAPON_MOVEX;
2882 			my->y = 3 + HUDWEAPON_MOVEY;
2883 			my->z = (cameras[HUDWEAPON_PLAYERNUM].z * .5 - players[clientnum]->entity->z) + 7 + HUDWEAPON_MOVEZ;
2884 			my->yaw = HUDWEAPON_YAW - camera_shakex2;
2885 			my->pitch = defaultpitch + HUDWEAPON_PITCH - camera_shakey2 / 200.f;
2886 			my->roll = HUDWEAPON_ROLL;
2887 		}
2888 
2889 		// dirty hack because we altered the camera height in actPlayer(). adjusts HUD to match new height.
2890 		if ( playerRace == CREATURE_IMP && players[clientnum]->entity->z == -4.5 )
2891 		{
2892 			my->z -= .5;
2893 		}
2894 		else if ( playerRace == TROLL && players[clientnum]->entity->z <= -1.5 )
2895 		{
2896 			my->z -= -2 * .5;
2897 		}
2898 	}
2899 	else
2900 	{
2901 		Item* item = stats[clientnum]->weapon;
2902 		if (item)
2903 		{
2904 			if (item->type == TOOL_SKELETONKEY || item->type == TOOL_LOCKPICK
2905 				|| (item->type >= ARTIFACT_ORB_BLUE && item->type <= ARTIFACT_ORB_GREEN))
2906 			{
2907 				defaultpitch = -PI / 8.f;
2908 			}
2909 			else if ( item->type == TOOL_WHIP )
2910 			{
2911 				defaultpitch = -PI / 8.f;
2912 			}
2913 			if ( item->type == CROSSBOW || item->type == HEAVY_CROSSBOW )
2914 			{
2915 				my->x = 6 + HUDWEAPON_MOVEX;
2916 				my->y = 1.5 + HUDWEAPON_MOVEY;
2917 				my->z = (cameras[HUDWEAPON_PLAYERNUM].z * .5 - players[clientnum]->entity->z) + 8 + HUDWEAPON_MOVEZ;
2918 				my->yaw = -.05 - camera_shakex2;
2919 				my->pitch = HUDWEAPON_PITCH - camera_shakey2 / 200.f;
2920 				my->roll = HUDWEAPON_ROLL;
2921 			}
2922 			else if ( item->type == SLING
2923 				|| item->type == SHORTBOW
2924 				|| item->type == ARTIFACT_BOW
2925 				|| item->type == LONGBOW
2926 				|| item->type == COMPOUND_BOW )
2927 			{
2928 				my->x = 6 + HUDWEAPON_MOVEX;
2929 				my->y = 3 + HUDWEAPON_MOVEY;
2930 				my->z = (cameras[HUDWEAPON_PLAYERNUM].z * .5 - players[clientnum]->entity->z) + 7 + HUDWEAPON_MOVEZ;
2931 				my->yaw = HUDWEAPON_YAW - camera_shakex2;
2932 				my->pitch = HUDWEAPON_PITCH - camera_shakey2 / 200.f;
2933 				my->roll = HUDWEAPON_ROLL;
2934 			}
2935 			else if ( item->type == TOOL_WHIP )
2936 			{
2937 				my->x = 6 + HUDWEAPON_MOVEX + 5;
2938 				my->y = 3 + HUDWEAPON_MOVEY - 0.5 + 1;
2939 				//my->flags[OVERDRAW] = false;
2940 				my->z = (cameras[HUDWEAPON_PLAYERNUM].z * .5 - players[clientnum]->entity->z) + 7 + HUDWEAPON_MOVEZ;
2941 				my->yaw = HUDWEAPON_YAW - camera_shakex2;
2942 				my->pitch = defaultpitch + HUDWEAPON_PITCH - camera_shakey2 / 200.f;
2943 				if ( my->sprite == items[TOOL_WHIP].fpindex + 1 )
2944 				{
2945 					my->pitch -= PI / 4;
2946 					my->focalx = 10 + (HUDWEAPON_CHOP == 5 ? 4 : 0);
2947 					my->focaly = 0;
2948 					my->focalz = -4;
2949 					my->x += (HUDWEAPON_CHOP == 5 ? -3 : 0);
2950 					my->y += (HUDWEAPON_CHOP == 5 ? 6 : 0);
2951 				}
2952 				else
2953 				{
2954 					my->focalx = 0;
2955 					my->focaly = 0;
2956 					my->focalz = -4;
2957 				}
2958 				my->roll = HUDWEAPON_ROLL;
2959 			}
2960 			else
2961 			{
2962 				my->x = 6 + HUDWEAPON_MOVEX + 3 * (itemCategory(item) == POTION);
2963 				my->y = 3 + HUDWEAPON_MOVEY - 3 * (itemCategory(item) == POTION);
2964 				my->z = (cameras[HUDWEAPON_PLAYERNUM].z * .5 - players[clientnum]->entity->z) + 7 + HUDWEAPON_MOVEZ - 3 * (itemCategory(item) == POTION);
2965 				my->yaw = HUDWEAPON_YAW - camera_shakex2;
2966 				my->pitch = defaultpitch + HUDWEAPON_PITCH - camera_shakey2 / 200.f;
2967 				my->roll = HUDWEAPON_ROLL + (PI / 2) * (itemCategory(item) == POTION);
2968 				my->focalx = 0;
2969 			}
2970 
2971 			if ( item->type >= TOOL_BOMB && item->type <= TOOL_TELEPORT_BOMB )
2972 			{
2973 				my->z += .5;
2974 			}
2975 		}
2976 
2977 		// dirty hack because we altered the camera height in actPlayer(). adjusts HUD to match new height.
2978 		if ( playerRace == CREATURE_IMP && players[clientnum]->entity->z == -4.5 )
2979 		{
2980 			my->z -= .5;
2981 		}
2982 		else if ( playerRace == TROLL && players[clientnum]->entity->z <= -1.5 )
2983 		{
2984 			my->z -= -2 * .5;
2985 		}
2986 	}
2987 	if ( !my->flags[OVERDRAW] )
2988 	{
2989 		my->x += 32;
2990 		my->y += 32;
2991 		my->z -= 3.5;
2992 	}
2993 }
2994 
2995 #define HUDSHIELD_DEFEND my->skill[0]
2996 #define HUDSHIELD_SNEAKING my->skill[1]
2997 #define HUDSHIELD_PLAYERNUM my->skill[2]
2998 #define HUDSHIELD_MOVEX my->fskill[0]
2999 #define HUDSHIELD_MOVEY my->fskill[1]
3000 #define HUDSHIELD_MOVEZ my->fskill[2]
3001 #define HUDSHIELD_YAW my->fskill[3]
3002 #define HUDSHIELD_PITCH my->fskill[4]
3003 #define HUDSHIELD_ROLL my->fskill[5]
3004 
actHudShield(Entity * my)3005 void actHudShield(Entity* my)
3006 {
3007 	my->flags[UNCLICKABLE] = true;
3008 
3009 	auto& camera_shakex = cameravars[HUDSHIELD_PLAYERNUM].shakex;
3010 	auto& camera_shakey = cameravars[HUDSHIELD_PLAYERNUM].shakey;
3011 	auto& camera_shakex2 = cameravars[HUDSHIELD_PLAYERNUM].shakex2;
3012 	auto& camera_shakey2 = cameravars[HUDSHIELD_PLAYERNUM].shakey2;
3013 
3014 	// isn't active during intro/menu sequence
3015 	if (intro == true)
3016 	{
3017 		my->flags[INVISIBLE] = true;
3018 		return;
3019 	}
3020 
3021 	if (multiplayer == CLIENT)
3022 	{
3023 		if (stats[clientnum]->HP <= 0)
3024 		{
3025 			my->flags[INVISIBLE] = true;
3026 			return;
3027 		}
3028 	}
3029 
3030 	// this entity only exists so long as the player exists
3031 	if (players[clientnum] == nullptr || players[clientnum]->entity == nullptr || !hudweapon)
3032 	{
3033 		list_RemoveNode(my->mynode);
3034 		return;
3035 	}
3036 
3037 	// check levitating value
3038 	bool levitating = isLevitating(stats[clientnum]);
3039 
3040 	// select model
3041 	bool wearingring = false;
3042 	if ( stats[clientnum]->ring != nullptr )
3043 	{
3044 		if ( stats[clientnum]->ring->type == RING_INVISIBILITY )
3045 		{
3046 			wearingring = true;
3047 		}
3048 	}
3049 	if ( stats[clientnum]->cloak != nullptr )
3050 	{
3051 		if ( stats[clientnum]->cloak->type == CLOAK_INVISIBILITY )
3052 		{
3053 			wearingring = true;
3054 		}
3055 	}
3056 
3057 	Monster playerRace = players[clientnum]->entity->getMonsterFromPlayerRace(stats[clientnum]->playerRace);
3058 	if ( players[clientnum]->entity->effectShapeshift != NOTHING )
3059 	{
3060 		playerRace = static_cast<Monster>(players[clientnum]->entity->effectShapeshift);
3061 		if ( playerRace == RAT || playerRace == SPIDER )
3062 		{
3063 			HUD_SHAPESHIFT_HIDE = 1;
3064 		}
3065 	}
3066 	else if ( players[clientnum]->entity->effectPolymorph != NOTHING )
3067 	{
3068 		if ( players[clientnum]->entity->effectPolymorph > NUMMONSTERS )
3069 		{
3070 			playerRace = HUMAN;
3071 		}
3072 		else
3073 		{
3074 			playerRace = static_cast<Monster>(players[clientnum]->entity->effectPolymorph);
3075 		}
3076 	}
3077 
3078 	bool hideShield = false;
3079 	if ( playerRace == RAT
3080 		|| playerRace == CREATURE_IMP
3081 		|| playerRace == TROLL )
3082 	{
3083 		hideShield = true;
3084 	}
3085 
3086 	bool spellbook = false;
3087 	bool quiver = false;
3088 	if ( stats[clientnum]->shield && itemCategory(stats[clientnum]->shield) == SPELLBOOK )
3089 	{
3090 		spellbook = true;
3091 		if ( playerRace == CREATURE_IMP )
3092 		{
3093 			hideShield = false;
3094 		}
3095 	}
3096 	else if ( stats[clientnum]->shield && itemTypeIsQuiver(stats[clientnum]->shield->type) )
3097 	{
3098 		quiver = true;
3099 	}
3100 
3101 	// when reverting form, render shield as invisible for 2 ticks as it's position needs to settle.
3102 	if ( HUD_LASTSHAPESHIFT_FORM != playerRace )
3103 	{
3104 		if ( HUD_SHAPESHIFT_HIDE > 0 )
3105 		{
3106 			hideShield = true;
3107 			--HUD_SHAPESHIFT_HIDE;
3108 		}
3109 	}
3110 	HUD_LASTSHAPESHIFT_FORM = playerRace;
3111 
3112 	if ( players[clientnum]->entity->skill[3] == 1 || players[clientnum]->entity->isInvisible() )   // debug cam or player invisible
3113 	{
3114 		my->flags[INVISIBLE] = true;
3115 	}
3116 	else
3117 	{
3118 		if (stats[clientnum]->shield == nullptr && playerRace != SPIDER )
3119 		{
3120 			my->flags[INVISIBLE] = true;
3121 		}
3122 		else
3123 		{
3124 			if (stats[clientnum]->shield)
3125 			{
3126 				if (itemModelFirstperson(stats[clientnum]->shield) != itemModel(stats[clientnum]->shield))
3127 				{
3128 					if ( spellbook )
3129 					{
3130 						my->scalex = 0.35;
3131 						my->scaley = 0.35;
3132 						my->scalez = 0.35;
3133 					}
3134 					else if ( quiver )
3135 					{
3136 						my->scalex = 0.5f;
3137 						my->scaley = 0.5f;
3138 						my->scalez = 0.5f;
3139 					}
3140 					else
3141 					{
3142 						my->scalex = 0.5f;
3143 						my->scaley = 0.5f;
3144 						my->scalez = 0.5f;
3145 					}
3146 				}
3147 				else
3148 				{
3149 					my->scalex = 1.f;
3150 					my->scaley = 1.f;
3151 					my->scalez = 1.f;
3152 				}
3153 			}
3154 			my->sprite = itemModelFirstperson(stats[clientnum]->shield);
3155 			my->flags[INVISIBLE] = false;
3156 		}
3157 	}
3158 
3159 	// swimming
3160 	bool swimming = false;
3161 	if (players[clientnum] && players[clientnum]->entity)
3162 	{
3163 		if ( isPlayerSwimming(players[clientnum]->entity) || players[clientnum]->entity->skill[13] != 0 ) //skill[13] PLAYER_INWATER
3164 		{
3165 			my->flags[INVISIBLE] = true;
3166 			Entity* parent = uidToEntity(my->parent);
3167 			if ( parent )
3168 			{
3169 				parent->flags[INVISIBLE] = true;
3170 			}
3171 			swimming = true;
3172 		}
3173 	}
3174 
3175 	if ( hideShield )
3176 	{
3177 		my->flags[INVISIBLE] = true;
3178 	}
3179 	else if ( cast_animation.active )
3180 	{
3181 		my->flags[INVISIBLE] = true;
3182 	}
3183 	else if ( cast_animation.active_spellbook && !spellbook )
3184 	{
3185 		my->flags[INVISIBLE] = true;
3186 	}
3187 
3188 	bool defending = false;
3189 	bool sneaking = false;
3190 	if (!command && !swimming)
3191 	{
3192 		if ( players[clientnum] && players[clientnum]->entity
3193 			&& (*inputPressed(impulses[IN_DEFEND]) || (shootmode && *inputPressed(joyimpulses[INJOY_GAME_DEFEND])))
3194 			&& players[clientnum]->entity->isMobile()
3195 			&& !gamePaused
3196 			&& !cast_animation.active
3197 			&& !cast_animation.active_spellbook
3198 			&& (!spellbook || (spellbook && hideShield)) )
3199 		{
3200 			if ( stats[clientnum]->shield && (hudweapon->skill[0] % 3 == 0) )
3201 			{
3202 				defending = true;
3203 			}
3204 			sneaking = true;
3205 		}
3206 	}
3207 
3208 	if ( stats[clientnum]->shield && itemTypeIsQuiver(stats[clientnum]->shield->type) )
3209 	{
3210 		// can't defend with quivers.
3211 		defending = false;
3212 	}
3213 	if ( playerRace == RAT
3214 		|| playerRace == CREATURE_IMP
3215 		|| playerRace == TROLL
3216 		|| playerRace == SPIDER )
3217 	{
3218 		defending = false;
3219 	}
3220 
3221 	if (defending)
3222 	{
3223 		stats[clientnum]->defending = true;
3224 	}
3225 	else
3226 	{
3227 		stats[clientnum]->defending = false;
3228 	}
3229 	if ( sneaking )
3230 	{
3231 		stats[clientnum]->sneaking = true;
3232 	}
3233 	else
3234 	{
3235 		stats[clientnum]->sneaking = false;
3236 	}
3237 
3238 	if (multiplayer == CLIENT)
3239 	{
3240 		if (HUDSHIELD_DEFEND != defending || ticks % 120 == 0)
3241 		{
3242 			strcpy((char*)net_packet->data, "SHLD");
3243 			net_packet->data[4] = clientnum;
3244 			net_packet->data[5] = defending;
3245 			net_packet->address.host = net_server.host;
3246 			net_packet->address.port = net_server.port;
3247 			net_packet->len = 6;
3248 			sendPacketSafe(net_sock, -1, net_packet, 0);
3249 		}
3250 		if ( HUDSHIELD_SNEAKING != sneaking || ticks % 120 == 0 )
3251 		{
3252 			strcpy((char*)net_packet->data, "SNEK");
3253 			net_packet->data[4] = clientnum;
3254 			net_packet->data[5] = sneaking;
3255 			net_packet->address.host = net_server.host;
3256 			net_packet->address.port = net_server.port;
3257 			net_packet->len = 6;
3258 			sendPacketSafe(net_sock, -1, net_packet, 0);
3259 		}
3260 	}
3261 	HUDSHIELD_DEFEND = defending;
3262 	HUDSHIELD_SNEAKING = sneaking;
3263 
3264 	bool crossbow = (stats[clientnum]->weapon && (stats[clientnum]->weapon->type == CROSSBOW || stats[clientnum]->weapon->type == HEAVY_CROSSBOW) );
3265 	bool doCrossbowReloadAnimation = false;
3266 	bool doBowReload = false;
3267 
3268 	// shield switching animation
3269 	if ( shieldSwitch )
3270 	{
3271 		if ( hudweapon )
3272 		{
3273 			if ( crossbow )
3274 			{
3275 				if ( rangedWeaponUseQuiverOnAttack(stats[clientnum]) )
3276 				{
3277 					doCrossbowReloadAnimation = true;
3278 					if ( stats[clientnum]->weapon->type == HEAVY_CROSSBOW )
3279 					{
3280 						playSound(410, 64);
3281 					}
3282 				}
3283 			}
3284 			else if ( stats[clientnum]->weapon && isRangedWeapon(*stats[clientnum]->weapon) )
3285 			{
3286 				if ( rangedWeaponUseQuiverOnAttack(stats[clientnum]) )
3287 				{
3288 					hudweapon->skill[10] = 1; // HUDWEAPON_BOW_FORCE_RELOAD
3289 					hudweapon->skill[7] = RANGED_ANIM_IDLE;
3290 					doBowReload = true;
3291 				}
3292 			}
3293 		}
3294 
3295 		if ( !spellbook )
3296 		{
3297 			shieldSwitch = false;
3298 		}
3299 		if ( !(defending || (spellbook && cast_animation.active_spellbook) || doBowReload) )
3300 		{
3301 			HUDSHIELD_MOVEY = -6;
3302 			HUDSHIELD_MOVEZ = 2;
3303 			HUDSHIELD_MOVEX = -2;
3304 		}
3305 	}
3306 
3307 	bool crossbowReloadAnimation = true;
3308 	if ( hudweapon && crossbow
3309 		&& hudweapon->skill[8] == CROSSBOW_ANIM_SWAPPED_WEAPON && rangedWeaponUseQuiverOnAttack(stats[clientnum]) )
3310 	{
3311 		// CROSSBOW_ANIM_SWAPPED_WEAPON requires the weapon to not be in the swapping animation to finish.
3312 		if ( fabs(hudweapon->fskill[5]) < (3 * PI / 8) )
3313 		{
3314 			doCrossbowReloadAnimation = true;
3315 		}
3316 		else
3317 		{
3318 			crossbowReloadAnimation = false;
3319 		}
3320 	}
3321 
3322 	// main animation
3323 	if ( defending || cast_animation.active_spellbook )
3324 	{
3325 		if ( !spellbook )
3326 		{
3327 			if ( HUDSHIELD_MOVEY < 3 )
3328 			{
3329 				HUDSHIELD_MOVEY += .5;
3330 				if ( HUDSHIELD_MOVEY > 3 )
3331 				{
3332 					HUDSHIELD_MOVEY = 3;
3333 				}
3334 			}
3335 			if ( HUDSHIELD_MOVEZ > -1 )
3336 			{
3337 				HUDSHIELD_MOVEZ -= .2;
3338 				if ( HUDSHIELD_MOVEZ < -1 )
3339 				{
3340 					HUDSHIELD_MOVEZ = -1;
3341 				}
3342 			}
3343 			if ( HUDSHIELD_YAW < PI / 3 )
3344 			{
3345 				HUDSHIELD_YAW += .15;
3346 				if ( HUDSHIELD_YAW > PI / 3 )
3347 				{
3348 					HUDSHIELD_YAW = PI / 3;
3349 				}
3350 			}
3351 			if ( stats[clientnum]->shield )
3352 			{
3353 				if ( stats[clientnum]->shield->type == TOOL_TORCH || stats[clientnum]->shield->type == TOOL_CRYSTALSHARD )
3354 				{
3355 					if ( HUDSHIELD_MOVEX < 1.5 )
3356 					{
3357 						HUDSHIELD_MOVEX += .5;
3358 						if ( HUDSHIELD_MOVEX > 1.5 )
3359 						{
3360 							HUDSHIELD_MOVEX = 1.5;
3361 						}
3362 					}
3363 					if ( HUDSHIELD_ROLL < PI / 5 )
3364 					{
3365 						HUDSHIELD_ROLL += .15;
3366 						if ( HUDSHIELD_ROLL > PI / 5 )
3367 						{
3368 							HUDSHIELD_ROLL = PI / 5;
3369 						}
3370 					}
3371 				}
3372 			}
3373 		}
3374 		else
3375 		{
3376 			if ( cast_animation.active_spellbook )
3377 			{
3378 				HUDSHIELD_ROLL = std::min<real_t>(HUDSHIELD_ROLL + .15, PI / 2);
3379 				if ( HUDSHIELD_MOVEZ > -1 )
3380 				{
3381 					HUDSHIELD_MOVEZ -= .2;
3382 					if ( HUDSHIELD_MOVEZ < -1 )
3383 					{
3384 						HUDSHIELD_MOVEZ = -1;
3385 					}
3386 				}
3387 			}
3388 		}
3389 	}
3390 	else if ( !hideShield && quiver && hudweapon && rangedWeaponUseQuiverOnAttack(stats[clientnum])
3391 		&& hudweapon->skill[7] != RANGED_ANIM_IDLE
3392 		&& (!crossbow || (crossbow && crossbowReloadAnimation && hudweapon->skill[8] != CROSSBOW_ANIM_RELOAD_START)) )
3393 	{
3394 		// skill[7] == 1 is hudweapon bow drawing, skill[8] is the crossbow reload animation state.
3395 		if ( hudweapon->skill[7] == RANGED_ANIM_FIRED && (!crossbow || (crossbow && hudweapon->skill[8] == CROSSBOW_ANIM_SHOOT)) )
3396 		{
3397 			my->flags[INVISIBLE] = true;
3398 			HUDSHIELD_MOVEY = 0;
3399 			HUDSHIELD_PITCH = 0;
3400 			HUDSHIELD_YAW = 0;
3401 			HUDSHIELD_MOVEZ = 0;
3402 			HUDSHIELD_MOVEX = 0;
3403 
3404 			if ( crossbow && hudweapon->skill[8] == CROSSBOW_ANIM_SHOOT )
3405 			{
3406 				// after shooting, lower the Z to create illusion of drawing the next arrow out of your hud.
3407 				HUDSHIELD_MOVEZ = 2;
3408 			}
3409 		}
3410 
3411 		real_t targetY = 5.05;// +limbs[HUMAN][11][0];
3412 		real_t targetPitch = PI / 2;// +limbs[HUMAN][11][1];
3413 		real_t targetYaw = PI / 3 - 0.1;// +limbs[HUMAN][11][2];
3414 		real_t targetZ = -3.5;// +limbs[HUMAN][12][0];
3415 		real_t targetX = -1.75;// +limbs[HUMAN][12][1];
3416 		if ( stats[clientnum]->shield->type == QUIVER_LIGHTWEIGHT )
3417 		{
3418 			targetZ -= 0.25; // offset a bit higher.
3419 		}
3420 
3421 		if ( crossbow )
3422 		{
3423 			targetY = 4.8 + 0.01;
3424 			targetPitch = PI / 2;
3425 			targetYaw = PI / 3 - 0.05;
3426 			targetZ = -2.75;
3427 			targetX = 2.75;
3428 
3429 			if ( hudweapon && stats[clientnum]->weapon->type == HEAVY_CROSSBOW )
3430 			{
3431 				if ( hudweapon->sprite == items[HEAVY_CROSSBOW].fpindex - 1 )
3432 				{
3433 					targetX += 1;
3434 				}
3435 				else if ( hudweapon->sprite == items[HEAVY_CROSSBOW].fpindex )
3436 				{
3437 					targetX += -1.5;
3438 					if ( HUDSHIELD_MOVEX < targetX )
3439 					{
3440 						HUDSHIELD_MOVEX += 2.5;
3441 						if ( HUDSHIELD_MOVEX > targetX )
3442 						{
3443 							HUDSHIELD_MOVEX = targetX;
3444 						}
3445 					}
3446 					else if ( HUDSHIELD_MOVEX > targetX )
3447 					{
3448 						HUDSHIELD_MOVEX -= 2.5;
3449 						if ( HUDSHIELD_MOVEX < targetX )
3450 						{
3451 							HUDSHIELD_MOVEX = targetX;
3452 						}
3453 					}
3454 				}
3455 			}
3456 
3457 			if ( stats[clientnum]->shield->type == QUIVER_LIGHTWEIGHT )
3458 			{
3459 				targetZ -= 0.25; // offset a bit higher.
3460 			}
3461 
3462 			if ( doCrossbowReloadAnimation )
3463 			{
3464 				hudweapon->skill[8] = CROSSBOW_ANIM_RELOAD_START;
3465 				hudweapon->skill[0] = CROSSBOW_CHOP_RELOAD_START;
3466 				hudweapon->fskill[0] = -1;
3467 				throwGimpTimer = std::max(throwGimpTimer, 20);
3468 
3469 				if ( fabs(hudweapon->fskill[5]) < 0.01 )
3470 				{
3471 					throwGimpTimer = std::max(throwGimpTimer, 20);
3472 					my->flags[INVISIBLE] = true;
3473 					HUDSHIELD_MOVEY = 0;
3474 					HUDSHIELD_PITCH = 0;
3475 					HUDSHIELD_YAW = 0;
3476 					HUDSHIELD_MOVEZ = 2;
3477 					HUDSHIELD_MOVEX = 0;
3478 				}
3479 			}
3480 		}
3481 
3482 		bool doMovement = true;
3483 		if ( doCrossbowReloadAnimation || doBowReload )
3484 		{
3485 			doMovement = false;
3486 		}
3487 		if ( doMovement )
3488 		{
3489 			if ( HUDSHIELD_MOVEY < targetY )
3490 			{
3491 				HUDSHIELD_MOVEY += 0.5;
3492 				if ( HUDSHIELD_MOVEY > targetY )
3493 				{
3494 					HUDSHIELD_MOVEY = targetY;
3495 				}
3496 			}
3497 			if ( targetX < 0 )
3498 			{
3499 				if ( HUDSHIELD_MOVEX > targetX )
3500 				{
3501 					HUDSHIELD_MOVEX -= 0.4;
3502 					if ( HUDSHIELD_MOVEX < targetX )
3503 					{
3504 						HUDSHIELD_MOVEX = targetX;
3505 					}
3506 				}
3507 			}
3508 			else if ( targetX >= 0 )
3509 			{
3510 				if ( HUDSHIELD_MOVEX < targetX )
3511 				{
3512 					HUDSHIELD_MOVEX += 0.4;
3513 					if ( HUDSHIELD_MOVEX > targetX )
3514 					{
3515 						HUDSHIELD_MOVEX = targetX;
3516 					}
3517 				}
3518 			}
3519 
3520 			if ( HUDSHIELD_PITCH < targetPitch )
3521 			{
3522 				HUDSHIELD_PITCH += .2;
3523 				if ( HUDSHIELD_PITCH > targetPitch )
3524 				{
3525 					HUDSHIELD_PITCH = targetPitch;
3526 				}
3527 			}
3528 			if ( HUDSHIELD_YAW < targetYaw )
3529 			{
3530 				HUDSHIELD_YAW += .3;
3531 				if ( HUDSHIELD_YAW > targetYaw )
3532 				{
3533 					HUDSHIELD_YAW = targetYaw;
3534 				}
3535 			}
3536 			if ( HUDSHIELD_MOVEZ > targetZ )
3537 			{
3538 				HUDSHIELD_MOVEZ -= 0.4;
3539 				if ( HUDSHIELD_MOVEZ < targetZ )
3540 				{
3541 					HUDSHIELD_MOVEZ = targetZ;
3542 				}
3543 			}
3544 		}
3545 	}
3546 	else
3547 	{
3548 		if ( HUDSHIELD_MOVEX > 0 )
3549 		{
3550 			HUDSHIELD_MOVEX = std::max<real_t>(HUDSHIELD_MOVEX - .5, 0.0);
3551 		}
3552 		else if ( HUDSHIELD_MOVEX < 0 )
3553 		{
3554 			HUDSHIELD_MOVEX = std::min<real_t>(HUDSHIELD_MOVEX + .5, 0.0);
3555 		}
3556 		if ( HUDSHIELD_MOVEY > 0 )
3557 		{
3558 			HUDSHIELD_MOVEY = std::max<real_t>(HUDSHIELD_MOVEY - .5, 0.0);
3559 		}
3560 		else if ( HUDSHIELD_MOVEY < 0 )
3561 		{
3562 			HUDSHIELD_MOVEY = std::min<real_t>(HUDSHIELD_MOVEY + .5, 0.0);
3563 		}
3564 		if ( HUDSHIELD_MOVEZ > 0 )
3565 		{
3566 			HUDSHIELD_MOVEZ = std::max<real_t>(HUDSHIELD_MOVEZ - .2, 0.0);
3567 		}
3568 		else if ( HUDSHIELD_MOVEZ < 0 )
3569 		{
3570 			HUDSHIELD_MOVEZ = std::min<real_t>(HUDSHIELD_MOVEZ + .2, 0.0);
3571 		}
3572 		if ( HUDSHIELD_YAW > 0 )
3573 		{
3574 			HUDSHIELD_YAW = std::max<real_t>(HUDSHIELD_YAW - .15, 0.0);
3575 		}
3576 		else if ( HUDSHIELD_YAW < 0 )
3577 		{
3578 			HUDSHIELD_YAW = std::min<real_t>(HUDSHIELD_YAW + .15, 0.0);
3579 		}
3580 		if ( HUDSHIELD_PITCH > 0 )
3581 		{
3582 			HUDSHIELD_PITCH = std::max<real_t>(HUDSHIELD_PITCH - .15, 0.0);
3583 		}
3584 		else if ( HUDSHIELD_PITCH < 0 )
3585 		{
3586 			HUDSHIELD_PITCH = std::min<real_t>(HUDSHIELD_PITCH + .15, 0.0);
3587 		}
3588 		if ( HUDSHIELD_ROLL > 0 )
3589 		{
3590 			HUDSHIELD_ROLL = std::max<real_t>(HUDSHIELD_ROLL - .15, 0);
3591 		}
3592 		else if ( HUDSHIELD_ROLL < 0 )
3593 		{
3594 			HUDSHIELD_ROLL = std::min<real_t>(HUDSHIELD_ROLL + .15, 0);
3595 		}
3596 	}
3597 
3598 	// set entity position
3599 	my->x = 7 + HUDSHIELD_MOVEX;
3600 	my->y = -3.5 + HUDSHIELD_MOVEY;
3601 	my->z = 6 + HUDSHIELD_MOVEZ + (cameras[HUDSHIELD_PLAYERNUM].z * .5 - players[clientnum]->entity->z);
3602 	if ( !my->flags[OVERDRAW] )
3603 	{
3604 		my->x += 32;
3605 		my->y += 32;
3606 		my->z -= 3.5;
3607 	}
3608 	my->yaw = HUDSHIELD_YAW - camera_shakex2 - PI / 3;
3609 	my->pitch = HUDSHIELD_PITCH - camera_shakey2 / 200.f;
3610 	my->roll = HUDSHIELD_ROLL;
3611 	if ( spellbook )
3612 	{
3613 		my->x += 0.87;
3614 		my->y += -0.23;
3615 		my->z += -1;
3616 
3617 		my->pitch += PI / 2 + PI / 5;
3618 		my->yaw -= PI / 3 - 2 * PI / 5;
3619 		my->roll -= PI / 2;
3620 
3621 		my->focalx = 0;
3622 		my->focaly = -1.2;
3623 		my->focalz = -0.1;
3624 	}
3625 	else if ( quiver && hudweapon && crossbow )
3626 	{
3627 		if ( hudweapon->skill[8] != CROSSBOW_ANIM_SHOOT
3628 			&& hudweapon->skill[8] != CROSSBOW_ANIM_RELOAD_START
3629 			&& hudweapon->skill[8] != CROSSBOW_ANIM_SWAPPED_WEAPON )
3630 		{
3631 			// only bob the arrow if idle animation or DRAW_END animation
3632 			my->x += hudweapon->fskill[0]; // HUDWEAPON_MOVEX
3633 			my->y += hudweapon->fskill[1]; // HUDWEAPON_MOVEY
3634 			my->z += hudweapon->fskill[2]; // HUDWEAPON_MOVEZ
3635 		}
3636 		my->focalx = 0;
3637 		my->focaly = 0;
3638 		my->focalz = 0;
3639 	}
3640 	else
3641 	{
3642 		my->focalx = 0;
3643 		my->focaly = 0;
3644 		my->focalz = 0;
3645 	}
3646 
3647 	if ( my->sprite == items[TOOL_TINKERING_KIT].fpindex && !hideShield )
3648 	{
3649 		my->yaw += PI / 2 - HUDSHIELD_YAW / 4;
3650 		my->focalz -= 0.5;
3651 	}
3652 
3653 	if ( playerRace == SPIDER && hudarm && players[clientnum]->entity->bodyparts.at(0) )
3654 	{
3655 		my->sprite = 854;
3656 		my->x = hudarm->x;
3657 		my->y = -hudarm->y;
3658 		my->z = hudarm->z;
3659 		my->pitch = hudarm->pitch - camera_shakey2 / 200.f;
3660 		my->roll = -hudarm->roll;
3661 		my->yaw = -players[clientnum]->entity->bodyparts.at(0)->yaw + players[clientnum]->entity->fskill[10] - camera_shakex2;
3662 		my->scalex = hudarm->scalex;
3663 		my->scaley = hudarm->scaley;
3664 		my->scalez = hudarm->scalez;
3665 		my->focalz = hudarm->focalz;
3666 	}
3667 
3668 	// dirty hack because we altered the camera height in actPlayer(). adjusts HUD to match new height.
3669 	if ( playerRace == CREATURE_IMP && players[clientnum]->entity->z == -4.5 )
3670 	{
3671 		my->z -= .5;
3672 	}
3673 	else if ( playerRace == TROLL && players[clientnum]->entity->z <= -1.5 )
3674 	{
3675 		my->z -= -2 * .5;
3676 	}
3677 
3678 	// torch/lantern flames
3679 	my->flags[BRIGHT] = false;
3680 	if ( playerRace == TROLL || playerRace == SPIDER || playerRace == CREATURE_IMP || playerRace == RAT )
3681 	{
3682 		// don't process flames as these don't hold torches.
3683 		return;
3684 	}
3685 	if (stats[clientnum]->shield && !swimming && players[clientnum]->entity->skill[3] == 0 && !cast_animation.active && !cast_animation.active_spellbook && !shieldSwitch)
3686 	{
3687 		if (itemCategory(stats[clientnum]->shield) == TOOL)
3688 		{
3689 			if (stats[clientnum]->shield->type == TOOL_TORCH)
3690 			{
3691 				Entity* entity = spawnFlame(my, SPRITE_FLAME);
3692 				entity->flags[OVERDRAW] = true;
3693 				entity->z -= 2.5 * cos(HUDSHIELD_ROLL);
3694 				entity->y += 2.5 * sin(HUDSHIELD_ROLL);
3695 				my->flags[BRIGHT] = true;
3696 			}
3697 			if ( stats[clientnum]->shield->type == TOOL_CRYSTALSHARD )
3698 			{
3699 				Entity* entity = spawnFlame(my, SPRITE_CRYSTALFLAME);
3700 				entity->flags[OVERDRAW] = true;
3701 				entity->z -= 2.5 * cos(HUDSHIELD_ROLL);
3702 				entity->y += 2.5 * sin(HUDSHIELD_ROLL);
3703 				my->flags[BRIGHT] = true;
3704 			}
3705 			else if (stats[clientnum]->shield->type == TOOL_LANTERN)
3706 			{
3707 				Entity* entity = spawnFlame(my, SPRITE_FLAME);
3708 				entity->flags[OVERDRAW] = true;
3709 				entity->z += 1;
3710 				my->flags[BRIGHT] = true;
3711 			}
3712 		}
3713 	}
3714 }
3715 
actHudAdditional(Entity * my)3716 void actHudAdditional(Entity* my)
3717 {
3718 	bool spellbook = false;
3719 	if ( stats[clientnum]->shield && itemCategory(stats[clientnum]->shield) == SPELLBOOK )
3720 	{
3721 		spellbook = true;
3722 	}
3723 
3724 	my->flags[UNCLICKABLE] = true;
3725 
3726 	auto& camera_shakex = cameravars[HUDSHIELD_PLAYERNUM].shakex;
3727 	auto& camera_shakey = cameravars[HUDSHIELD_PLAYERNUM].shakey;
3728 	auto& camera_shakex2 = cameravars[HUDSHIELD_PLAYERNUM].shakex2;
3729 	auto& camera_shakey2 = cameravars[HUDSHIELD_PLAYERNUM].shakey2;
3730 
3731 	// isn't active during intro/menu sequence
3732 	if ( intro == true )
3733 	{
3734 		my->flags[INVISIBLE] = true;
3735 		return;
3736 	}
3737 
3738 	if ( multiplayer == CLIENT )
3739 	{
3740 		if ( stats[clientnum]->HP <= 0 )
3741 		{
3742 			my->flags[INVISIBLE] = true;
3743 			return;
3744 		}
3745 	}
3746 
3747 	// this entity only exists so long as the player exists
3748 	if ( players[clientnum] == nullptr || players[clientnum]->entity == nullptr || !hudweapon )
3749 	{
3750 		list_RemoveNode(my->mynode);
3751 		return;
3752 	}
3753 
3754 	if ( !spellbook )
3755 	{
3756 		my->flags[INVISIBLE] = true;
3757 		return;
3758 	}
3759 
3760 	if ( !players[clientnum]->entity->bodyparts.at(2)
3761 		|| players[clientnum]->entity->bodyparts.at(2)->flags[INVISIBLE]
3762 		|| players[clientnum]->entity->bodyparts.at(2)->sprite == 854 )
3763 	{
3764 		// if shield invisible or spider arm we're invis.
3765 		my->flags[INVISIBLE] = true;
3766 		return;
3767 	}
3768 
3769 	if ( stats[clientnum]->shield == nullptr )
3770 	{
3771 		my->flags[INVISIBLE] = true;
3772 	}
3773 	else
3774 	{
3775 		if ( itemModelFirstperson(stats[clientnum]->shield) != itemModel(stats[clientnum]->shield) )
3776 		{
3777 			if ( spellbook )
3778 			{
3779 				my->scalex = 0.35;
3780 				my->scaley = 0.35;
3781 				my->scalez = 0.35;
3782 			}
3783 			else
3784 			{
3785 				my->scalex = 0.5f;
3786 				my->scaley = 0.5f;
3787 				my->scalez = 0.5f;
3788 			}
3789 		}
3790 		else
3791 		{
3792 			my->scalex = 1.f;
3793 			my->scaley = 1.f;
3794 			my->scalez = 1.f;
3795 		}
3796 		my->sprite = itemModelFirstperson(stats[clientnum]->shield);
3797 		my->flags[INVISIBLE] = false;
3798 	}
3799 
3800 	if ( cast_animation.active )
3801 	{
3802 		my->flags[INVISIBLE] = true;
3803 	}
3804 	else if ( cast_animation.active_spellbook && !spellbook )
3805 	{
3806 		my->flags[INVISIBLE] = true;
3807 	}
3808 
3809 	bool defending = false;
3810 	bool sneaking = false;
3811 	/*if ( !command )
3812 	{
3813 		if ( players[clientnum] && players[clientnum]->entity
3814 			&& (*inputPressed(impulses[IN_DEFEND]) || (shootmode && *inputPressed(joyimpulses[INJOY_GAME_DEFEND])))
3815 			&& players[clientnum]->entity->isMobile()
3816 			&& !gamePaused
3817 			&& !cast_animation.active )
3818 		{
3819 			if ( stats[clientnum]->shield && (hudweapon->skill[0] % 3 == 0) )
3820 			{
3821 				defending = true;
3822 			}
3823 			sneaking = true;
3824 		}
3825 	}*/
3826 
3827 	// shield switching animation
3828 	if ( shieldSwitch )
3829 	{
3830 		if ( spellbook )
3831 		{
3832 			shieldSwitch = false;
3833 		}
3834 		if ( !(defending || (spellbook && cast_animation.active_spellbook)) )
3835 		{
3836 			HUDSHIELD_MOVEY = -6;
3837 			HUDSHIELD_MOVEZ = 2;
3838 			HUDSHIELD_MOVEX = -2;
3839 		}
3840 	}
3841 
3842 	// main animation
3843 	if ( cast_animation.active_spellbook && spellbook )
3844 	{
3845 		HUDSHIELD_ROLL = std::max<real_t>(HUDSHIELD_ROLL - .1, -1 * PI / 3);
3846 		if ( HUDSHIELD_MOVEZ > -1 )
3847 		{
3848 			HUDSHIELD_MOVEZ -= .2;
3849 			if ( HUDSHIELD_MOVEZ < -1 )
3850 			{
3851 				HUDSHIELD_MOVEZ = -1;
3852 			}
3853 		}
3854 	}
3855 	else
3856 	{
3857 		if ( HUDSHIELD_MOVEX > 0 )
3858 		{
3859 			HUDSHIELD_MOVEX = std::max<real_t>(HUDSHIELD_MOVEX - .5, 0.0);
3860 		}
3861 		else if ( HUDSHIELD_MOVEX < 0 )
3862 		{
3863 			HUDSHIELD_MOVEX = std::min<real_t>(HUDSHIELD_MOVEX + .5, 0.0);
3864 		}
3865 		if ( HUDSHIELD_MOVEY > 0 )
3866 		{
3867 			HUDSHIELD_MOVEY = std::max<real_t>(HUDSHIELD_MOVEY - .5, 0.0);
3868 		}
3869 		else if ( HUDSHIELD_MOVEY < 0 )
3870 		{
3871 			HUDSHIELD_MOVEY = std::min<real_t>(HUDSHIELD_MOVEY + .5, 0.0);
3872 		}
3873 		if ( HUDSHIELD_MOVEZ > 0 )
3874 		{
3875 			HUDSHIELD_MOVEZ = std::max<real_t>(HUDSHIELD_MOVEZ - .2, 0.0);
3876 		}
3877 		else if ( HUDSHIELD_MOVEZ < 0 )
3878 		{
3879 			HUDSHIELD_MOVEZ = std::min<real_t>(HUDSHIELD_MOVEZ + .2, 0.0);
3880 		}
3881 		if ( HUDSHIELD_YAW > 0 )
3882 		{
3883 			HUDSHIELD_YAW = std::max<real_t>(HUDSHIELD_YAW - .15, 0.0);
3884 		}
3885 		else if ( HUDSHIELD_YAW < 0 )
3886 		{
3887 			HUDSHIELD_YAW = std::min<real_t>(HUDSHIELD_YAW + .15, 0.0);
3888 		}
3889 		if ( HUDSHIELD_PITCH > 0 )
3890 		{
3891 			HUDSHIELD_PITCH = std::max<real_t>(HUDSHIELD_PITCH - .15, 0.0);
3892 		}
3893 		else if ( HUDSHIELD_PITCH < 0 )
3894 		{
3895 			HUDSHIELD_PITCH = std::min<real_t>(HUDSHIELD_PITCH + .15, 0.0);
3896 		}
3897 		if ( HUDSHIELD_ROLL > 0 )
3898 		{
3899 			HUDSHIELD_ROLL = std::max<real_t>(HUDSHIELD_ROLL - .15, 0);
3900 		}
3901 		else if ( HUDSHIELD_ROLL < 0 )
3902 		{
3903 			if ( spellbook )
3904 			{
3905 				HUDSHIELD_ROLL = std::min<real_t>(HUDSHIELD_ROLL + .10, 0);
3906 			}
3907 			else
3908 			{
3909 				HUDSHIELD_ROLL = std::min<real_t>(HUDSHIELD_ROLL + .15, 0);
3910 			}
3911 		}
3912 	}
3913 
3914 	// set entity position
3915 	my->x = 7 + HUDSHIELD_MOVEX;
3916 	my->y = -3.5 + HUDSHIELD_MOVEY;
3917 	my->z = 6 + HUDSHIELD_MOVEZ + (cameras[HUDSHIELD_PLAYERNUM].z * .5 - players[clientnum]->entity->z);
3918 	my->yaw = HUDSHIELD_YAW - camera_shakex2 - PI / 3;
3919 	my->pitch = HUDSHIELD_PITCH - camera_shakey2 / 200.f;
3920 	my->roll = HUDSHIELD_ROLL;
3921 	if ( spellbook )
3922 	{
3923 		my->sprite += items[(stats[clientnum]->shield->type)].variations;
3924 		my->pitch += PI / 2 + PI / 5;
3925 		my->yaw -= PI / 3 - 2 * PI / 5;
3926 		my->roll -= PI / 2;
3927 
3928 		my->x += 1;
3929 		my->y += -0.2;
3930 		my->z -= 0.95;
3931 
3932 		my->focalx = 0;
3933 		my->focaly = -1.1;
3934 		my->focalz = 0.25;
3935 	}
3936 	else
3937 	{
3938 		my->focalx = 0;
3939 		my->focaly = 0;
3940 		my->focalz = 0;
3941 	}
3942 
3943 	// dirty hack because we altered the camera height in actPlayer(). adjusts HUD to match new height.
3944 	if ( stats[clientnum]->type == CREATURE_IMP && players[clientnum]->entity->z == -4.5 )
3945 	{
3946 		my->z -= .5;
3947 	}
3948 	else if ( stats[clientnum]->type == TROLL && players[clientnum]->entity->z <= -1.5 )
3949 	{
3950 		my->z -= -2 * .5;
3951 	}
3952 }
3953 
actHudArrowModel(Entity * my)3954 void actHudArrowModel(Entity* my)
3955 {
3956 	bool bow = false;
3957 	bool crossbow = false;
3958 	if ( stats[clientnum]->weapon
3959 		&& (stats[clientnum]->weapon->type == SHORTBOW
3960 			|| stats[clientnum]->weapon->type == LONGBOW
3961 			|| stats[clientnum]->weapon->type == ARTIFACT_BOW
3962 			|| stats[clientnum]->weapon->type == COMPOUND_BOW )
3963 		)
3964 	{
3965 		bow = true;
3966 	}
3967 	else if ( stats[clientnum]->weapon
3968 		&& (stats[clientnum]->weapon->type == CROSSBOW || stats[clientnum]->weapon->type == HEAVY_CROSSBOW) )
3969 	{
3970 		crossbow = true;
3971 	}
3972 
3973 	my->flags[UNCLICKABLE] = true;
3974 
3975 	// isn't active during intro/menu sequence
3976 	if ( intro == true )
3977 	{
3978 		my->flags[INVISIBLE] = true;
3979 		return;
3980 	}
3981 
3982 	if ( multiplayer == CLIENT )
3983 	{
3984 		if ( stats[clientnum]->HP <= 0 )
3985 		{
3986 			my->flags[INVISIBLE] = true;
3987 			return;
3988 		}
3989 	}
3990 
3991 	// this entity only exists so long as the player exists
3992 	if ( players[clientnum] == nullptr || players[clientnum]->entity == nullptr || !hudweapon )
3993 	{
3994 		list_RemoveNode(my->mynode);
3995 		return;
3996 	}
3997 
3998 	if ( (!crossbow && !bow) || cast_animation.active || cast_animation.active_spellbook )
3999 	{
4000 		my->flags[INVISIBLE] = true;
4001 		return;
4002 	}
4003 
4004 	if ( crossbow )
4005 	{
4006 		if ( hudweapon->flags[INVISIBLE] || hudweapon->skill[6] != 0 ) // skill[6] is hideWeapon
4007 		{
4008 			my->flags[INVISIBLE] = true;
4009 			return;
4010 		}
4011 		if ( stats[clientnum]->shield && itemTypeIsQuiver(stats[clientnum]->shield->type) )
4012 		{
4013 			my->flags[INVISIBLE] = true;
4014 			return;
4015 		}
4016 		if ( stats[clientnum]->weapon->type == CROSSBOW )
4017 		{
4018 			if ( hudweapon->sprite != items[CROSSBOW].fpindex )
4019 			{
4020 				my->flags[INVISIBLE] = true;
4021 				return;
4022 			}
4023 		}
4024 		if ( stats[clientnum]->weapon->type == HEAVY_CROSSBOW )
4025 		{
4026 			if ( hudweapon->sprite == items[HEAVY_CROSSBOW].fpindex + 1 )
4027 			{
4028 				my->flags[INVISIBLE] = true;
4029 				return;
4030 			}
4031 		}
4032 	}
4033 	else if ( hudweapon->flags[INVISIBLE]
4034 		|| hudweapon->skill[6] != 0
4035 		|| hudweapon->skill[7] != RANGED_ANIM_FIRED ) // skill[6] is hiding weapon, skill[7] is shooting something
4036 	{
4037 		my->flags[INVISIBLE] = true;
4038 		return;
4039 	}
4040 
4041 	my->scalex = 1.f;
4042 	my->scaley = 1.f;
4043 	my->scalez = 1.f;
4044 
4045 	my->flags[INVISIBLE] = false;
4046 	my->sprite = 934;
4047 
4048 	if ( crossbow )
4049 	{
4050 		my->sprite = 976;
4051 	}
4052 	else if ( stats[clientnum]->shield && itemTypeIsQuiver(stats[clientnum]->shield->type) )
4053 	{
4054 		switch ( stats[clientnum]->shield->type )
4055 		{
4056 			case QUIVER_SILVER:
4057 				my->sprite = 935;
4058 				break;
4059 			case QUIVER_PIERCE:
4060 				my->sprite = 936;
4061 				break;
4062 			case QUIVER_LIGHTWEIGHT:
4063 				my->sprite = 937;
4064 				break;
4065 			case QUIVER_FIRE:
4066 				my->sprite = 938;
4067 				break;
4068 			case QUIVER_KNOCKBACK:
4069 				my->sprite = 939;
4070 				break;
4071 			case QUIVER_CRYSTAL:
4072 				my->sprite = 940;
4073 				break;
4074 			case QUIVER_HUNTING:
4075 				my->sprite = 941;
4076 				break;
4077 			default:
4078 				break;
4079 		}
4080 	}
4081 
4082 	// set entity position
4083 	my->x = hudweapon->x;
4084 	my->y = hudweapon->y;
4085 	my->z = hudweapon->z;
4086 
4087 	my->yaw = hudweapon->yaw;
4088 	my->pitch = hudweapon->pitch;
4089 	my->roll = hudweapon->roll;
4090 
4091 	my->focalx = hudweapon->focalx - 0.125;
4092 	if ( hudweapon->sprite == items[COMPOUND_BOW].fpindex + 1 )
4093 	{
4094 		my->focalx += 0.125; // shorter bowstring on compound bow, push arrow forward.
4095 	}
4096 	my->focaly = hudweapon->focaly - 0.25;
4097 	my->focalz = hudweapon->focalz - 0.25;
4098 
4099 	if ( crossbow )
4100 	{
4101 		if ( hudweapon->sprite == items[CROSSBOW].fpindex )
4102 		{
4103 			my->focalx += 3.5;
4104 			my->focaly += 0.25;
4105 			my->focalz += -0.25;
4106 		}
4107 		else if ( hudweapon->sprite == items[HEAVY_CROSSBOW].fpindex || hudweapon->sprite == items[HEAVY_CROSSBOW].fpindex - 1 )
4108 		{
4109 			my->focalx += 4.5;
4110 			my->focaly += 0.25;
4111 			my->focalz += -0.25;
4112 
4113 			if ( hudweapon->sprite == items[HEAVY_CROSSBOW].fpindex )
4114 			{
4115 				my->focalx -= 2;
4116 			}
4117 		}
4118 	}
4119 
4120 	my->scalex = hudweapon->scalex;
4121 	my->scaley = hudweapon->scaley;
4122 	my->scalez = hudweapon->scalez;
4123 }