1 /*-------------------------------------------------------------------------------
2 
3 	BARONY
4 	File: actplayer.cpp
5 	Desc: behavior function(s) for player
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 "messages.hpp"
16 #include "entity.hpp"
17 #include "interface/interface.hpp"
18 #include "sound.hpp"
19 #include "items.hpp"
20 #include "magic/magic.hpp"
21 #include "menu.hpp"
22 #include "scores.hpp"
23 #include "monster.hpp"
24 #include "net.hpp"
25 #include "collision.hpp"
26 #include "player.hpp"
27 #include "colors.hpp"
28 #include "draw.hpp"
29 #include "mod_tools.hpp"
30 
31 bool smoothmouse = false;
32 bool settings_smoothmouse = false;
33 bool usecamerasmoothing = false;
34 bool disablemouserotationlimit = false;
35 bool settings_disablemouserotationlimit = false;
36 bool swimDebuffMessageHasPlayed = false;
37 int monsterEmoteGimpTimer = 0;
38 int selectedEntityGimpTimer = 0;
39 bool insectoidLevitating[MAXPLAYERS] = { false, false, false, false };
40 
41 /*-------------------------------------------------------------------------------
42 
43 	act*
44 
45 	The following functions describe various entity behaviors. All functions
46 	take a pointer to the entities that use them as an argument.
47 
48 -------------------------------------------------------------------------------*/
49 
50 #define DEATHCAM_TIME my->skill[0]
51 #define DEATHCAM_PLAYERTARGET my->skill[1]
52 #define DEATHCAM_PLAYERNUM my->skill[2]
53 #define DEATHCAM_ROTX my->fskill[0]
54 #define DEATHCAM_ROTY my->fskill[1]
55 
actDeathCam(Entity * my)56 void actDeathCam(Entity* my)
57 {
58 	/*if ( keystatus[SDL_SCANCODE_F4] )
59 	{
60 		buttonStartSingleplayer(nullptr);
61 		keystatus[SDL_SCANCODE_F4] = 0;
62 	}*/
63 	DEATHCAM_TIME++;
64 
65 	Uint32 deathcamGameoverPromptTicks = TICKS_PER_SECOND * 6;
66 	if ( gameModeManager.getMode() == GameModeManager_t::GAME_MODE_TUTORIAL )
67 	{
68 		deathcamGameoverPromptTicks = TICKS_PER_SECOND * 3;
69 	}
70 
71 	if ( DEATHCAM_TIME == 1 )
72 	{
73 		DEATHCAM_PLAYERTARGET = -1;
74 	}
75 	else if ( DEATHCAM_TIME == deathcamGameoverPromptTicks )
76 	{
77 		if ( gameModeManager.getMode() == GameModeManager_t::GAME_MODE_TUTORIAL )
78 		{
79 			gameModeManager.Tutorial.openGameoverWindow();
80 		}
81 		else
82 		{
83 			openGameoverWindow();
84 		}
85 	}
86 	if ( shootmode && !gamePaused )
87 	{
88 		if ( smoothmouse )
89 		{
90 			DEATHCAM_ROTX += mousexrel * .006 * (mousespeed / 128.f);
91 			DEATHCAM_ROTX = fmin(fmax(-0.35, DEATHCAM_ROTX), 0.35);
92 		}
93 		else
94 		{
95 			DEATHCAM_ROTX = std::min<float>(std::max<float>(-0.35f, mousexrel * .01f * (mousespeed / 128.f)), 0.35f);
96 		}
97 		my->yaw += DEATHCAM_ROTX;
98 		if ( my->yaw >= PI * 2 )
99 		{
100 			my->yaw -= PI * 2;
101 		}
102 		else if ( my->yaw < 0 )
103 		{
104 			my->yaw += PI * 2;
105 		}
106 
107 		if ( smoothmouse )
108 		{
109 			DEATHCAM_ROTY += mouseyrel * .006 * (mousespeed / 128.f) * (reversemouse * 2 - 1);
110 			DEATHCAM_ROTY = fmin(fmax(-0.35, DEATHCAM_ROTY), 0.35);
111 		}
112 		else
113 		{
114 			DEATHCAM_ROTY = std::min<float>(std::max<float>(-0.35f, mouseyrel * .01f * (mousespeed / 128.f) * (reversemouse * 2 - 1)), 0.35f);
115 		}
116 		my->pitch -= DEATHCAM_ROTY;
117 		if ( my->pitch > PI / 2 )
118 		{
119 			my->pitch = PI / 2;
120 		}
121 		else if ( my->pitch < -PI / 2 )
122 		{
123 			my->pitch = -PI / 2;
124 		}
125 	}
126 	if ( smoothmouse )
127 	{
128 		DEATHCAM_ROTX *= .5;
129 		DEATHCAM_ROTY *= .5;
130 	}
131 	else
132 	{
133 		DEATHCAM_ROTX = 0;
134 		DEATHCAM_ROTY = 0;
135 	}
136 
137 	if ( players[DEATHCAM_PLAYERNUM] && players[DEATHCAM_PLAYERNUM]->entity )
138 	{
139 		// do nothing if still alive
140 	}
141 	else if ((*inputPressed(impulses[IN_ATTACK]) || (shootmode && *inputPressed(joyimpulses[INJOY_GAME_ATTACK]))) && shootmode)
142 	{
143 		*inputPressed(impulses[IN_ATTACK]) = 0;
144 		if ( shootmode )
145 		{
146 			*inputPressed(joyimpulses[INJOY_GAME_ATTACK]) = 0;
147 		}
148 		DEATHCAM_PLAYERTARGET++;
149 		if (DEATHCAM_PLAYERTARGET >= MAXPLAYERS)
150 		{
151 			DEATHCAM_PLAYERTARGET = 0;
152 		}
153 		int c = 0;
154 		while (!players[DEATHCAM_PLAYERTARGET] || !players[DEATHCAM_PLAYERTARGET]->entity)   //TODO: PLAYERSWAP VERIFY. I'm not sure if the loop's condition should look like this. I think it should be fine...
155 		{
156 			if (c > MAXPLAYERS)
157 			{
158 				break;
159 			}
160 			DEATHCAM_PLAYERTARGET++;
161 			if (DEATHCAM_PLAYERTARGET >= MAXPLAYERS)
162 			{
163 				DEATHCAM_PLAYERTARGET = 0;
164 			}
165 			c++;
166 		}
167 	}
168 
169 	if (DEATHCAM_PLAYERTARGET >= 0)
170 	{
171 		if (players[DEATHCAM_PLAYERTARGET] && players[DEATHCAM_PLAYERTARGET]->entity)
172 		{
173 			my->x = players[DEATHCAM_PLAYERTARGET]->entity->x;
174 			my->y = players[DEATHCAM_PLAYERTARGET]->entity->y;
175 		}
176 	}
177 
178 	my->removeLightField();
179 	my->light = lightSphereShadow(my->x / 16, my->y / 16, 3, 128);
180 
181 	cameras[DEATHCAM_PLAYERNUM].x = my->x / 16.f;
182 	cameras[DEATHCAM_PLAYERNUM].y = my->y / 16.f;
183 	cameras[DEATHCAM_PLAYERNUM].z = my->z * 2.f;
184 	cameras[DEATHCAM_PLAYERNUM].ang = my->yaw;
185 	cameras[DEATHCAM_PLAYERNUM].vang = my->pitch;
186 
187 	cameras[DEATHCAM_PLAYERNUM].x -= cos(my->yaw) * cos(my->pitch) * 1.5;
188 	cameras[DEATHCAM_PLAYERNUM].y -= sin(my->yaw) * cos(my->pitch) * 1.5;
189 	cameras[DEATHCAM_PLAYERNUM].z -= sin(my->pitch) * 16;
190 }
191 
192 #define PLAYER_INIT my->skill[0]
193 #define PLAYER_TORCH my->skill[1]
194 #define PLAYER_NUM my->skill[2]
195 #define PLAYER_DEBUGCAM my->skill[3]
196 #define PLAYER_BOBMODE my->skill[4]
197 #define PLAYER_ATTACK my->skill[9]
198 #define PLAYER_ATTACKTIME my->skill[10]
199 #define PLAYER_ARMBENDED my->skill[11]
200 #define PLAYER_ALIVETIME my->skill[12]
201 #define PLAYER_INWATER my->skill[13]
202 #define PLAYER_CLICKED my->skill[14]
203 #define PLAYER_DEATH_AUTOMATON my->skill[15]
204 #define PLAYER_VELX my->vel_x
205 #define PLAYER_VELY my->vel_y
206 #define PLAYER_VELZ my->vel_z
207 #define PLAYER_BOB my->fskill[0]
208 #define PLAYER_BOBMOVE my->fskill[1]
209 #define PLAYER_WEAPONYAW my->fskill[2]
210 #define PLAYER_DX my->fskill[3]
211 #define PLAYER_DY my->fskill[4]
212 #define PLAYER_DYAW my->fskill[5]
213 #define PLAYER_ROTX my->fskill[6]
214 #define PLAYER_ROTY my->fskill[7]
215 #define PLAYER_SHIELDYAW my->fskill[8]
216 #define PLAYER_SIDEBOB my->fskill[10]
217 #define PLAYER_CAMERAZ_ACCEL my->fskill[14]
218 #define PLAYERWALKSPEED .12
219 
isPlayerSwimming(Entity * my)220 bool isPlayerSwimming(Entity* my)
221 {
222 	// swimming
223 	bool waterwalkingboots = false;
224 	if ( stats[PLAYER_NUM]->shoes != NULL )
225 	{
226 		if ( stats[PLAYER_NUM]->shoes->type == IRON_BOOTS_WATERWALKING )
227 		{
228 			waterwalkingboots = true;
229 		}
230 	}
231 	bool swimming = false;
232 	bool levitating = isLevitating(stats[PLAYER_NUM]);
233 	if ( !levitating && !waterwalkingboots && !noclip && !skillCapstoneUnlocked(PLAYER_NUM, PRO_SWIMMING) )
234 	{
235 		int x = std::min(std::max<unsigned int>(0, floor(my->x / 16)), map.width - 1);
236 		int y = std::min(std::max<unsigned int>(0, floor(my->y / 16)), map.height - 1);
237 		if ( swimmingtiles[map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height]]
238 			|| lavatiles[map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height]] )
239 		{
240 			// can swim in lavatiles or swimmingtiles only.
241 			swimming = true;
242 		}
243 	}
244 	return swimming;
245 }
246 
handlePlayerCameraUpdate(Entity * my,int playernum,bool useRefreshRateDelta)247 void handlePlayerCameraUpdate(Entity* my, int playernum, bool useRefreshRateDelta)
248 {
249 	if ( !my )
250 	{
251 		return;
252 	}
253 
254 	double refreshRateDelta = 1.0;
255 	if ( useRefreshRateDelta && fps > 0.0 )
256 	{
257 		refreshRateDelta *= TICKS_PER_SECOND / fps;
258 	}
259 
260 	// rotate
261 	if ( !command && my->isMobile() )
262 	{
263 		if ( !stats[PLAYER_NUM]->EFFECTS[EFF_CONFUSED] )
264 		{
265 			if ( noclip )
266 			{
267 				my->z -= (*inputPressed(impulses[IN_TURNR]) - *inputPressed(impulses[IN_TURNL])) * .25 * refreshRateDelta;
268 			}
269 			else
270 			{
271 				my->yaw += (*inputPressed(impulses[IN_TURNR]) - *inputPressed(impulses[IN_TURNL])) * .05 * refreshRateDelta;
272 			}
273 		}
274 		else
275 		{
276 			my->yaw += (*inputPressed(impulses[IN_TURNL]) - *inputPressed(impulses[IN_TURNR])) * .05 * refreshRateDelta;
277 		}
278 	}
279 	if ( shootmode && !gamePaused )
280 	{
281 		if ( !stats[PLAYER_NUM]->EFFECTS[EFF_CONFUSED] )
282 		{
283 			if ( smoothmouse )
284 			{
285 				if ( my->isMobile() )
286 				{
287 					PLAYER_ROTX += mousexrel * .006 * (mousespeed / 128.f);
288 				}
289 				if ( !disablemouserotationlimit )
290 				{
291 					PLAYER_ROTX = fmin(fmax(-0.35, PLAYER_ROTX), 0.35);
292 				}
293 				PLAYER_ROTX *= pow(0.5, refreshRateDelta);
294 			}
295 			else
296 			{
297 				if ( my->isMobile() )
298 				{
299 					if ( disablemouserotationlimit )
300 					{
301 						PLAYER_ROTX = mousexrel * .01f * (mousespeed / 128.f);
302 					}
303 					else
304 					{
305 						PLAYER_ROTX = std::min<float>(std::max<float>(-0.35f, mousexrel * .01f * (mousespeed / 128.f)), 0.35f);
306 					}
307 				}
308 				else
309 				{
310 					PLAYER_ROTX = 0;
311 				}
312 			}
313 		}
314 		else
315 		{
316 			if ( smoothmouse )
317 			{
318 				if ( my->isMobile() )
319 				{
320 					PLAYER_ROTX -= mousexrel * .006f * (mousespeed / 128.f);
321 				}
322 				if ( !disablemouserotationlimit )
323 				{
324 					PLAYER_ROTX = fmin(fmax(-0.35f, PLAYER_ROTX), 0.35f);
325 				}
326 				PLAYER_ROTX *= pow(0.5, refreshRateDelta);
327 			}
328 			else
329 			{
330 				if ( my->isMobile() )
331 				{
332 					if ( disablemouserotationlimit )
333 					{
334 						PLAYER_ROTX = -mousexrel * .01f * (mousespeed / 128.f);
335 					}
336 					else
337 					{
338 						PLAYER_ROTX = -std::min<float>(std::max<float>(-0.35f, mousexrel * .01f * (mousespeed / 128.f)), 0.35f);
339 					}
340 				}
341 				else
342 				{
343 					PLAYER_ROTX = 0;
344 				}
345 			}
346 		}
347 	}
348 	my->yaw += PLAYER_ROTX * refreshRateDelta;
349 	while ( my->yaw >= PI * 2 )
350 	{
351 		my->yaw -= PI * 2;
352 	}
353 	while ( my->yaw < 0 )
354 	{
355 		my->yaw += PI * 2;
356 	}
357 	if ( smoothmouse )
358 	{
359 		PLAYER_ROTX *= pow(0.5, refreshRateDelta);
360 	}
361 	else
362 	{
363 		PLAYER_ROTX = 0;
364 	}
365 
366 	// look up and down
367 	if ( !command && my->isMobile() )
368 	{
369 		if ( !stats[PLAYER_NUM]->EFFECTS[EFF_CONFUSED] )
370 		{
371 			my->pitch += (*inputPressed(impulses[IN_DOWN]) - *inputPressed(impulses[IN_UP])) * .05 * refreshRateDelta;
372 		}
373 		else
374 		{
375 			my->pitch += (*inputPressed(impulses[IN_UP]) - *inputPressed(impulses[IN_DOWN])) * .05 * refreshRateDelta;
376 		}
377 	}
378 	if ( shootmode && !gamePaused )
379 	{
380 		if ( !stats[PLAYER_NUM]->EFFECTS[EFF_CONFUSED] )
381 		{
382 			if ( smoothmouse )
383 			{
384 				if ( my->isMobile() )
385 				{
386 					PLAYER_ROTY += mouseyrel * .006 * (mousespeed / 128.f) * (reversemouse * 2 - 1);
387 				}
388 				PLAYER_ROTY = fmin(fmax(-0.35, PLAYER_ROTY), 0.35);
389 				PLAYER_ROTY *= pow(0.5, refreshRateDelta);
390 			}
391 			else
392 			{
393 				if ( my->isMobile() )
394 				{
395 					PLAYER_ROTY = std::min<float>(std::max<float>(-0.35f,
396 						mouseyrel * .01f * (mousespeed / 128.f) * (reversemouse * 2 - 1)), 0.35f);
397 				}
398 				else
399 				{
400 					PLAYER_ROTY = 0;
401 				}
402 			}
403 		}
404 		else
405 		{
406 			if ( smoothmouse )
407 			{
408 				if ( my->isMobile() )
409 				{
410 					PLAYER_ROTY -= mouseyrel * .006f * (mousespeed / 128.f) * (reversemouse * 2 - 1);
411 				}
412 				PLAYER_ROTY = fmin(fmax(-0.35f, PLAYER_ROTY), 0.35f);
413 				PLAYER_ROTY *= pow(0.5, refreshRateDelta);
414 			}
415 			else
416 			{
417 				if ( my->isMobile() )
418 				{
419 					PLAYER_ROTY = std::min<float>(std::max<float>(-0.35f,
420 						mouseyrel * .01f * (mousespeed / 128.f) * (reversemouse * 2 - 1)), 0.35f);
421 				}
422 				else
423 				{
424 					PLAYER_ROTY = 0;
425 				}
426 			}
427 		}
428 	}
429 	my->pitch -= PLAYER_ROTY * refreshRateDelta;
430 
431 	if ( softwaremode )
432 	{
433 		if ( my->pitch > PI / 6 )
434 		{
435 			my->pitch = PI / 6;
436 		}
437 		if ( my->pitch < -PI / 6 )
438 		{
439 			my->pitch = -PI / 6;
440 		}
441 	}
442 	else
443 	{
444 		if ( my->pitch > PI / 3 )
445 		{
446 			my->pitch = PI / 3;
447 		}
448 		if ( my->pitch < -PI / 3 )
449 		{
450 			my->pitch = -PI / 3;
451 		}
452 	}
453 	if ( !smoothmouse )
454 	{
455 		PLAYER_ROTY = 0;
456 	}
457 	else if ( !shootmode )
458 	{
459 		PLAYER_ROTY *= .5;
460 	}
461 }
462 
handlePlayerCameraBobbing(Entity * my,int playernum,bool useRefreshRateDelta)463 void handlePlayerCameraBobbing(Entity* my, int playernum, bool useRefreshRateDelta)
464 {
465 	if ( !my )
466 	{
467 		return;
468 	}
469 	bool swimming = isPlayerSwimming(my);
470 
471 	double refreshRateDelta = 1.0;
472 	if ( useRefreshRateDelta && fps > 0.0 )
473 	{
474 		refreshRateDelta *= TICKS_PER_SECOND / fps;
475 	}
476 
477 	// camera bobbing
478 	if ( bobbing )
479 	{
480 		if ( swimming )
481 		{
482 			if ( PLAYER_BOBMODE )
483 			{
484 				PLAYER_BOBMOVE += .03 * refreshRateDelta;
485 			}
486 			else
487 			{
488 				PLAYER_BOBMOVE -= .03 * refreshRateDelta;
489 			}
490 		}
491 		else if ( ((*inputPressed(impulses[IN_FORWARD])
492 				|| *inputPressed(impulses[IN_BACK]))
493 				|| (*inputPressed(impulses[IN_RIGHT]) - *inputPressed(impulses[IN_LEFT]))
494 				|| (game_controller && (game_controller->getLeftXPercent() || game_controller->getLeftYPercent())))
495 			&& !command && !swimming )
496 		{
497 			if ( !(stats[PLAYER_NUM]->defending || stats[PLAYER_NUM]->sneaking == 0) )
498 			{
499 				if ( PLAYER_BOBMODE )
500 				{
501 					PLAYER_BOBMOVE += .0125 * refreshRateDelta;
502 				}
503 				else
504 				{
505 					PLAYER_BOBMOVE -= .0125 * refreshRateDelta;
506 				}
507 			}
508 			else
509 			{
510 				if ( PLAYER_BOBMODE )
511 				{
512 					PLAYER_BOBMOVE += .025 * refreshRateDelta;
513 				}
514 				else
515 				{
516 					PLAYER_BOBMOVE -= .025 * refreshRateDelta;
517 				}
518 			}
519 		}
520 		else if ( !swimming )
521 		{
522 			PLAYER_BOBMOVE = 0;
523 			PLAYER_BOB = 0;
524 			PLAYER_BOBMODE = 0;
525 		}
526 
527 		if ( !command && !swimming && (*inputPressed(impulses[IN_RIGHT]) - *inputPressed(impulses[IN_LEFT])) )
528 		{
529 			if ( (*inputPressed(impulses[IN_RIGHT]) && !(*inputPressed(impulses[IN_BACK])))
530 				|| (*inputPressed(impulses[IN_LEFT]) && (*inputPressed(impulses[IN_BACK]))) )
531 			{
532 				PLAYER_SIDEBOB += 0.01 * refreshRateDelta;
533 				real_t angle = PI / 32;
534 				if ( *inputPressed(impulses[IN_BACK]) )
535 				{
536 					angle = PI / 64;
537 				}
538 				if ( PLAYER_SIDEBOB > angle )
539 				{
540 					PLAYER_SIDEBOB = angle;
541 				}
542 			}
543 			else if ( (*inputPressed(impulses[IN_LEFT]) && !(*inputPressed(impulses[IN_BACK])))
544 				|| (*inputPressed(impulses[IN_RIGHT]) && (*inputPressed(impulses[IN_BACK]))) )
545 			{
546 				PLAYER_SIDEBOB -= 0.01 * refreshRateDelta;
547 				real_t angle = -PI / 32;
548 				if ( *inputPressed(impulses[IN_BACK]) )
549 				{
550 					angle = -PI / 64;
551 				}
552 				if ( PLAYER_SIDEBOB < angle )
553 				{
554 					PLAYER_SIDEBOB = angle;
555 				}
556 			}
557 		}
558 		else
559 		{
560 			if ( PLAYER_SIDEBOB > 0.001 )
561 			{
562 				PLAYER_SIDEBOB -= 0.02 * refreshRateDelta;
563 				if ( PLAYER_SIDEBOB < 0.f )
564 				{
565 					PLAYER_SIDEBOB = 0.f;
566 				}
567 			}
568 			else
569 			{
570 				PLAYER_SIDEBOB += 0.02 * refreshRateDelta;
571 				if ( PLAYER_SIDEBOB > 0.f )
572 				{
573 					PLAYER_SIDEBOB = 0.f;
574 				}
575 			}
576 		}
577 
578 		if ( !swimming && !(stats[PLAYER_NUM]->defending || stats[PLAYER_NUM]->sneaking == 0) )
579 		{
580 			if ( PLAYER_BOBMOVE > .1 )
581 			{
582 				PLAYER_BOBMOVE = .1;
583 				PLAYER_BOBMODE = 0;
584 			}
585 			else if ( PLAYER_BOBMOVE < -.1 )
586 			{
587 				PLAYER_BOBMOVE = -.1;
588 				PLAYER_BOBMODE = 1;
589 			}
590 		}
591 		else if ( swimming )
592 		{
593 			if ( PLAYER_BOBMOVE > .3 )
594 			{
595 				PLAYER_BOBMOVE = .3;
596 				PLAYER_BOBMODE = 0;
597 			}
598 			else if ( PLAYER_BOBMOVE < -.3 )
599 			{
600 				PLAYER_BOBMOVE = -.3;
601 				PLAYER_BOBMODE = 1;
602 			}
603 		}
604 		else
605 		{
606 			if ( PLAYER_BOBMOVE > .1 )
607 			{
608 				PLAYER_BOBMOVE = .1;
609 				PLAYER_BOBMODE = 0;
610 			}
611 			else if ( PLAYER_BOBMOVE < -.1 )
612 			{
613 				PLAYER_BOBMOVE = -.1;
614 				PLAYER_BOBMODE = 1;
615 			}
616 		}
617 		PLAYER_BOB += PLAYER_BOBMOVE * refreshRateDelta;
618 		if ( static_cast<Monster>(my->effectShapeshift) == SPIDER || static_cast<Monster>(my->effectShapeshift) == RAT )
619 		{
620 			PLAYER_BOB = std::min(static_cast<real_t>(1), PLAYER_BOB);
621 		}
622 	}
623 	else
624 	{
625 		PLAYER_BOBMOVE = 0;
626 		PLAYER_BOB = 0;
627 		PLAYER_BOBMODE = 0;
628 	}
629 }
630 
handlePlayerMovement(Entity * my,int playernum,bool useRefreshRateDelta)631 void handlePlayerMovement(Entity* my, int playernum, bool useRefreshRateDelta)
632 {
633 	if ( !my )
634 	{
635 		return;
636 	}
637 
638 	double refreshRateDelta = 1.0;
639 	if ( useRefreshRateDelta && fps > 0.0 )
640 	{
641 		refreshRateDelta *= TICKS_PER_SECOND / fps;
642 	}
643 
644 	// calculate weight
645 	double weightratio = 0.0;
646 	int weight = 0;
647 	for ( node_t* node = stats[PLAYER_NUM]->inventory.first; node != NULL; node = node->next )
648 	{
649 		Item* item = (Item*)node->element;
650 		if ( item != NULL )
651 		{
652 			if ( item->type >= 0 && item->type < NUMITEMS )
653 			{
654 				if ( itemTypeIsQuiver(item->type) )
655 				{
656 					weight += std::max(1, items[item->type].weight * item->count / 5);
657 				}
658 				else
659 				{
660 					weight += items[item->type].weight * item->count;
661 				}
662 			}
663 		}
664 	}
665 	weight += stats[PLAYER_NUM]->GOLD / 100;
666 	if ( gameplayCustomManager.inUse() )
667 	{
668 		weight = weight * (gameplayCustomManager.playerWeightPercent / 100.f);
669 	}
670 	if ( stats[PLAYER_NUM]->EFFECTS[EFF_FAST] && !stats[PLAYER_NUM]->EFFECTS[EFF_SLOW] )
671 	{
672 		weight = weight * 0.5;
673 	}
674 	weightratio = (1000 + my->getSTR() * 100 - weight) / (double)(1000 + my->getSTR() * 100);
675 	weightratio = fmin(fmax(0, weightratio), 1);
676 
677 	// calculate movement forces
678 
679 	bool allowMovement = my->isMobile();
680 	bool pacified = stats[PLAYER_NUM]->EFFECTS[EFF_PACIFY];
681 	if ( !allowMovement && pacified )
682 	{
683 		if ( !stats[PLAYER_NUM]->EFFECTS[EFF_PARALYZED] && !stats[PLAYER_NUM]->EFFECTS[EFF_STUNNED]
684 			&& !stats[PLAYER_NUM]->EFFECTS[EFF_ASLEEP] )
685 		{
686 			allowMovement = true;
687 		}
688 	}
689 
690 	if ( (!command || pacified) && allowMovement )
691 	{
692 		//x_force and y_force represent the amount of percentage pushed on that respective axis. Given a keyboard, it's binary; either you're pushing "move left" or you aren't. On an analog stick, it can range from whatever value to whatever.
693 		float x_force = 0;
694 		float y_force = 0;
695 
696 		if ( pacified )
697 		{
698 			x_force = 0.f;
699 			y_force = -0.1;
700 			if ( stats[PLAYER_NUM]->EFFECTS[EFF_CONFUSED] )
701 			{
702 				y_force *= -1;
703 			}
704 		}
705 		else
706 		{
707 			double backpedalMultiplier = 0.25;
708 			if ( stats[PLAYER_NUM]->EFFECTS[EFF_DASH] )
709 			{
710 				backpedalMultiplier = 1.25;
711 			}
712 
713 			if ( !stats[PLAYER_NUM]->EFFECTS[EFF_CONFUSED] )
714 			{
715 				//Normal controls.
716 				x_force = (*inputPressed(impulses[IN_RIGHT]) - *inputPressed(impulses[IN_LEFT]));
717 				y_force = (*inputPressed(impulses[IN_FORWARD]) - (double)* inputPressed(impulses[IN_BACK]) * backpedalMultiplier);
718 				if ( noclip )
719 				{
720 					if ( keystatus[SDL_SCANCODE_LSHIFT] )
721 					{
722 						x_force = x_force * 0.5;
723 						y_force = y_force * 0.5;
724 					}
725 				}
726 			}
727 			else
728 			{
729 				//Confused controls.
730 				x_force = (*inputPressed(impulses[IN_LEFT]) - *inputPressed(impulses[IN_RIGHT]));
731 				y_force = (*inputPressed(impulses[IN_BACK]) - (double)* inputPressed(impulses[IN_FORWARD]) * backpedalMultiplier);
732 			}
733 
734 			if ( game_controller && !*inputPressed(impulses[IN_LEFT]) && !*inputPressed(impulses[IN_RIGHT]) )
735 			{
736 				x_force = game_controller->getLeftXPercent();
737 
738 				if ( stats[PLAYER_NUM]->EFFECTS[EFF_CONFUSED] )
739 				{
740 					x_force *= -1;
741 				}
742 			}
743 			if ( game_controller && !*inputPressed(impulses[IN_FORWARD]) && !*inputPressed(impulses[IN_BACK]) )
744 			{
745 				y_force = game_controller->getLeftYPercent();
746 
747 				if ( stats[PLAYER_NUM]->EFFECTS[EFF_CONFUSED] )
748 				{
749 					y_force *= -1;
750 				}
751 
752 				if ( y_force < 0 )
753 				{
754 					y_force *= backpedalMultiplier;    //Move backwards more slowly.
755 				}
756 			}
757 		}
758 
759 		int DEX = my->getDEX();
760 		real_t slowSpeedPenalty = 0.0;
761 		if ( !stats[PLAYER_NUM]->EFFECTS[EFF_FAST] && stats[PLAYER_NUM]->EFFECTS[EFF_SLOW] )
762 		{
763 			DEX = std::min(DEX - 3, -2);
764 			slowSpeedPenalty = 2.0;
765 		}
766 
767 		double maxSpeed = 18.0;
768 		if ( gameplayCustomManager.inUse() )
769 		{
770 			maxSpeed = gameplayCustomManager.playerSpeedMax;
771 		}
772 
773 		real_t speedFactor = std::min((DEX * 0.1 + 15.5 - slowSpeedPenalty) * weightratio, maxSpeed);
774 		if ( DEX <= 5 )
775 		{
776 			speedFactor = std::min((DEX + 10) * weightratio, maxSpeed);
777 		}
778 		else if ( DEX <= 15 )
779 		{
780 			speedFactor = std::min((DEX * 0.2 + 14 - slowSpeedPenalty) * weightratio, maxSpeed);
781 		}
782 		/*if ( ticks % 50 == 0 )
783 		{
784 		messagePlayer(0, "%f", speedFactor);
785 		}*/
786 		if ( stats[PLAYER_NUM]->EFFECTS[EFF_DASH] )
787 		{
788 			PLAYER_VELX += my->monsterKnockbackVelocity * cos(my->monsterKnockbackTangentDir) * refreshRateDelta;
789 			PLAYER_VELY += my->monsterKnockbackVelocity * sin(my->monsterKnockbackTangentDir) * refreshRateDelta;
790 			my->monsterKnockbackVelocity *= pow(0.95, refreshRateDelta);
791 		}
792 		else if ( stats[PLAYER_NUM]->EFFECTS[EFF_KNOCKBACK] )
793 		{
794 			speedFactor = std::min(speedFactor, 5.0);
795 			PLAYER_VELX += my->monsterKnockbackVelocity * cos(my->monsterKnockbackTangentDir) * refreshRateDelta;
796 			PLAYER_VELY += my->monsterKnockbackVelocity * sin(my->monsterKnockbackTangentDir) * refreshRateDelta;
797 			my->monsterKnockbackVelocity *= pow(0.95, refreshRateDelta);
798 		}
799 		else
800 		{
801 			my->monsterKnockbackVelocity = 0.f;
802 			my->monsterKnockbackTangentDir = 0.f;
803 		}
804 
805 		if ( fabs(my->playerStrafeVelocity) > 0.1 )
806 		{
807 			//speedFactor = std::min(speedFactor, 5.0);
808 			PLAYER_VELX += my->playerStrafeVelocity * cos(my->playerStrafeDir) * refreshRateDelta;
809 			PLAYER_VELY += my->playerStrafeVelocity * sin(my->playerStrafeDir) * refreshRateDelta;
810 			my->playerStrafeVelocity *= pow(0.95, refreshRateDelta);
811 		}
812 		else
813 		{
814 			my->playerStrafeDir = 0.0f;
815 			my->playerStrafeVelocity = 0.0f;
816 		}
817 
818 		speedFactor *= refreshRateDelta;
819 		PLAYER_VELX += y_force * cos(my->yaw) * .045 * speedFactor / (1 + (stats[PLAYER_NUM]->defending || stats[PLAYER_NUM]->sneaking == 1));
820 		PLAYER_VELY += y_force * sin(my->yaw) * .045 * speedFactor / (1 + (stats[PLAYER_NUM]->defending || stats[PLAYER_NUM]->sneaking == 1));
821 		PLAYER_VELX += x_force * cos(my->yaw + PI / 2) * .0225 * speedFactor / (1 + (stats[PLAYER_NUM]->defending || stats[PLAYER_NUM]->sneaking == 1));
822 		PLAYER_VELY += x_force * sin(my->yaw + PI / 2) * .0225 * speedFactor / (1 + (stats[PLAYER_NUM]->defending || stats[PLAYER_NUM]->sneaking == 1));
823 
824 	}
825 	PLAYER_VELX *= pow(0.75, refreshRateDelta);
826 	PLAYER_VELY *= pow(0.75, refreshRateDelta);
827 
828 	/*if ( keystatus[SDL_SCANCODE_G] )
829 	{
830 		messagePlayer(0, "X: %5.5f, Y: %5.5f", PLAYER_VELX, PLAYER_VELY);
831 	}*/
832 
833 	for ( node_t* node = map.creatures->first; node != nullptr; node = node->next ) //Since looking for players only, don't search full entity list. Best idea would be to directly example players[] though.
834 	{
835 		Entity* entity = (Entity*)node->element;
836 		if ( entity == my )
837 		{
838 			continue;
839 		}
840 		if ( entity->behavior == &actPlayer )
841 		{
842 			if ( entityInsideEntity(my, entity) )
843 			{
844 				double tangent = atan2(my->y - entity->y, my->x - entity->x);
845 				PLAYER_VELX += cos(tangent) * 0.075 * refreshRateDelta;
846 				PLAYER_VELY += sin(tangent) * 0.075 * refreshRateDelta;
847 			}
848 		}
849 	}
850 
851 	// swimming slows you down
852 	bool amuletwaterbreathing = false;
853 	if ( stats[PLAYER_NUM]->amulet != NULL )
854 	{
855 		if ( stats[PLAYER_NUM]->amulet->type == AMULET_WATERBREATHING )
856 		{
857 			amuletwaterbreathing = true;
858 		}
859 	}
860 	bool swimming = isPlayerSwimming(my);
861 	if ( swimming && !amuletwaterbreathing )
862 	{
863 		PLAYER_VELX *= (((stats[PLAYER_NUM]->PROFICIENCIES[PRO_SWIMMING] / 100.f) * 50.f) + 50) / 100.f;
864 		PLAYER_VELY *= (((stats[PLAYER_NUM]->PROFICIENCIES[PRO_SWIMMING] / 100.f) * 50.f) + 50) / 100.f;
865 
866 		if ( stats[PLAYER_NUM]->type == SKELETON )
867 		{
868 			if ( !swimDebuffMessageHasPlayed )
869 			{
870 				messagePlayer(PLAYER_NUM, language[3182]);
871 				swimDebuffMessageHasPlayed = true;
872 			}
873 			// no swim good
874 			PLAYER_VELX *= 0.5;
875 			PLAYER_VELY *= 0.5;
876 		}
877 	}
878 }
879 
handlePlayerCameraPosition(Entity * my,int playernum,bool useRefreshRateDelta)880 void handlePlayerCameraPosition(Entity* my, int playernum, bool useRefreshRateDelta)
881 {
882 	if ( !my )
883 	{
884 		return;
885 	}
886 	int playerRace = my->getMonsterTypeFromSprite();
887 	bool swimming = isPlayerSwimming(my);
888 
889 	double refreshRateDelta = 1.0;
890 	if ( useRefreshRateDelta && fps > 0.0 )
891 	{
892 		refreshRateDelta *= TICKS_PER_SECOND / fps;
893 	}
894 
895 	// camera
896 	if ( !PLAYER_DEBUGCAM && stats[PLAYER_NUM] && stats[PLAYER_NUM]->HP > 0 )
897 	{
898 		cameras[PLAYER_NUM].x = my->x / 16.0;
899 		cameras[PLAYER_NUM].y = my->y / 16.0;
900 		real_t cameraSetpointZ = (my->z * 2) - 2.5 + (swimming ? 1 : 0);
901 		if ( swimming && (playerRace == RAT || playerRace == SPIDER) )
902 		{
903 			cameraSetpointZ -= 0.5; // float a little higher.
904 		}
905 
906 		if ( playerRace == CREATURE_IMP && my->z == -4.5 )
907 		{
908 			cameraSetpointZ += 1;
909 		}
910 		else if ( playerRace == TROLL && my->z <= -1.5 )
911 		{
912 			cameraSetpointZ -= 2;
913 		}
914 
915 		real_t diff = abs(PLAYER_CAMERAZ_ACCEL - cameraSetpointZ);
916 		if ( diff > 0.01 )
917 		{
918 			real_t rateChange = std::min(2.0, std::max(0.3, diff * 0.5)) * refreshRateDelta;
919 
920 			if ( cameraSetpointZ >= 0.f )
921 			{
922 				PLAYER_CAMERAZ_ACCEL += rateChange;
923 				PLAYER_CAMERAZ_ACCEL = std::min(cameraSetpointZ, PLAYER_CAMERAZ_ACCEL);
924 			}
925 			else if ( cameraSetpointZ < 0.f )
926 			{
927 				PLAYER_CAMERAZ_ACCEL += -rateChange;
928 				PLAYER_CAMERAZ_ACCEL = std::max(cameraSetpointZ, PLAYER_CAMERAZ_ACCEL);
929 			}
930 			cameras[PLAYER_NUM].z = PLAYER_CAMERAZ_ACCEL;
931 
932 			// check updated value.
933 			if ( abs(PLAYER_CAMERAZ_ACCEL - cameraSetpointZ) <= 0.01 )
934 			{
935 				PLAYER_BOBMOVE = 0;
936 				PLAYER_BOB = 0;
937 				PLAYER_BOBMODE = 0;
938 			}
939 		}
940 		else
941 		{
942 			PLAYER_CAMERAZ_ACCEL = cameraSetpointZ;
943 			cameras[PLAYER_NUM].z = PLAYER_CAMERAZ_ACCEL + PLAYER_BOB;
944 		}
945 
946 		//messagePlayer(0, "Z: %.2f | %.2f | %.2f", my->z, PLAYER_CAMERAZ_ACCEL, cameraSetpointZ);
947 
948 		cameras[PLAYER_NUM].ang = my->yaw;
949 		if ( softwaremode )
950 		{
951 			cameras[PLAYER_NUM].vang = (my->pitch / (PI / 4)) * cameras[PLAYER_NUM].winh;
952 		}
953 		else
954 		{
955 			cameras[PLAYER_NUM].vang = my->pitch;
956 		}
957 	}
958 }
959 
actPlayer(Entity * my)960 void actPlayer(Entity* my)
961 {
962 	if (!my)
963 	{
964 		return;
965 	}
966 	if ( logCheckObstacle )
967 	{
968 		if ( ticks % 50 == 0 )
969 		{
970 			messagePlayer(0, "checkObstacle() calls/sec: %d", logCheckObstacleCount);
971 			logCheckObstacleCount = 0;
972 		}
973 	}
974 	if ( spamming && my->ticks % 2 == 0 )
975 	{
976 		for (int i = 0; i < 1; ++i)
977 		{
978 			char s[64] = "";
979 			char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
980 
981 			for ( int j = 0; j < 63; ++j ) {
982 				s[j] = alphanum[rand() % (sizeof(alphanum) - 1)];
983 			}
984 			Uint32 totalSize = 0;
985 			for ( size_t c = 0; c < HASH_SIZE; ++c ) {
986 				totalSize += list_Size(&ttfTextHash[c]);
987 			}
988 			messagePlayer(0, "IMGREF: %d, total size: %d", imgref, totalSize);
989 			s[63] = '\0';
990 			messagePlayer(0, "%s", s);
991 			//messagePlayer(0, "Lorem ipsum dolor sit amet, dico accusam reprehendunt ne mea, ea est illum tincidunt voluptatibus. Ne labore voluptua eos, nostro fierent mnesarchum an mei, cu mea dolor verear epicuri. Est id iriure principes, unum cotidieque qui te. An sit tractatos complectitur.");
992 		}
993 	}
994 	if ( autoLimbReload && ticks % 20 == 0 && (PLAYER_NUM == clientnum || splitscreen) )
995 	{
996 		consoleCommand("/reloadlimbs");
997 	}
998 
999 	Entity* entity;
1000 	Entity* entity2 = nullptr;
1001 	Entity* rightbody = nullptr;
1002 	Entity* weaponarm = nullptr;
1003 	Entity* shieldarm = nullptr;
1004 	Entity* additionalLimb = nullptr;
1005 	Entity* torso = nullptr;
1006 	node_t* node;
1007 	Item* item;
1008 	int i, bodypart;
1009 	double dist = 0;
1010 	bool wearingring = false;
1011 	bool levitating = false;
1012 	bool isHumanoid = true;
1013 	bool showEquipment = true;
1014 	if ( PLAYER_NUM < 0 || PLAYER_NUM >= MAXPLAYERS )
1015 	{
1016 		return;
1017 	}
1018 
1019 	Monster playerRace = HUMAN;
1020 	int spriteTorso = 106 + 12 * stats[PLAYER_NUM]->sex;
1021 	int spriteLegRight = 107 + 12 * stats[PLAYER_NUM]->sex;
1022 	int spriteLegLeft = 108 + 12 * stats[PLAYER_NUM]->sex;
1023 	int spriteArmRight = 109 + 12 * stats[PLAYER_NUM]->sex;
1024 	int spriteArmLeft = 110 + 12 * stats[PLAYER_NUM]->sex;
1025 	int playerAppearance = stats[PLAYER_NUM]->appearance;
1026 
1027 	if ( my->effectShapeshift != NOTHING )
1028 	{
1029 		playerRace = static_cast<Monster>(my->effectShapeshift);
1030 		stats[PLAYER_NUM]->type = playerRace;
1031 	}
1032 	else if ( stats[PLAYER_NUM]->playerRace > 0 || stats[PLAYER_NUM]->EFFECTS[EFF_POLYMORPH] || my->effectPolymorph != NOTHING )
1033 	{
1034 		playerRace = my->getMonsterFromPlayerRace(stats[PLAYER_NUM]->playerRace);
1035 		if ( my->effectPolymorph != NOTHING )
1036 		{
1037 			if ( my->effectPolymorph > NUMMONSTERS )
1038 			{
1039 				playerRace = HUMAN;
1040 				playerAppearance = my->effectPolymorph - 100;
1041 			}
1042 			else
1043 			{
1044 				playerRace = static_cast<Monster>(my->effectPolymorph);
1045 			}
1046 		}
1047 		if ( stats[PLAYER_NUM]->appearance == 0 || my->effectPolymorph != NOTHING )
1048 		{
1049 			stats[PLAYER_NUM]->type = playerRace;
1050 		}
1051 		else
1052 		{
1053 			stats[PLAYER_NUM]->type = HUMAN; // appearance of 1 is aesthetic only
1054 		}
1055 	}
1056 	else
1057 	{
1058 		stats[PLAYER_NUM]->type = HUMAN;
1059 	}
1060 
1061 	if ( stats[PLAYER_NUM]->type == RAT || stats[PLAYER_NUM]->type == SPIDER )
1062 	{
1063 		isHumanoid = false;
1064 	}
1065 	else if ( stats[PLAYER_NUM]->type == TROLL || stats[PLAYER_NUM]->type == CREATURE_IMP )
1066 	{
1067 		showEquipment = false;
1068 	}
1069 
1070 	if ( multiplayer != CLIENT )
1071 	{
1072 		if ( stats[PLAYER_NUM]->EFFECTS[EFF_SHAPESHIFT] )
1073 		{
1074 			stats[PLAYER_NUM]->playerShapeshiftStorage = my->effectShapeshift; // keep track of player shapeshift effects
1075 		}
1076 		else
1077 		{
1078 			if ( my->effectShapeshift != NOTHING ) // just in case this was cleared other than normal progression ticking down
1079 			{
1080 				my->effectShapeshift = NOTHING;
1081 				serverUpdateEntitySkill(my, 53);
1082 			}
1083 		}
1084 
1085 		if ( stats[PLAYER_NUM]->EFFECTS[EFF_POLYMORPH] )
1086 		{
1087 			stats[PLAYER_NUM]->playerPolymorphStorage = my->effectPolymorph; // keep track of player polymorph effects
1088 		}
1089 		else
1090 		{
1091 			if ( my->effectPolymorph != NOTHING ) // just in case this was cleared other than normal progression ticking down
1092 			{
1093 				my->effectPolymorph = NOTHING;
1094 				serverUpdateEntitySkill(my, 50);
1095 			}
1096 		}
1097 	}
1098 
1099 	if ( PLAYER_NUM == clientnum || splitscreen )
1100 	{
1101 		if ( stats[PLAYER_NUM]->type != HUMAN && stats[PLAYER_NUM]->EFFECTS[EFF_SHAPESHIFT] )
1102 		{
1103 			if ( swapHotbarOnShapeshift == 0 )
1104 			{
1105 				initShapeshiftHotbar();
1106 			}
1107 			else if ( swapHotbarOnShapeshift != stats[PLAYER_NUM]->type )
1108 			{
1109 				// we likely transformed while still shapeshifted, fully init the hotbar code again.
1110 				deinitShapeshiftHotbar();
1111 				initShapeshiftHotbar();
1112 			}
1113 		}
1114 		else if ( !stats[PLAYER_NUM]->EFFECTS[EFF_SHAPESHIFT] && swapHotbarOnShapeshift > 0 )
1115 		{
1116 			deinitShapeshiftHotbar();
1117 		}
1118 	}
1119 
1120 	my->focalx = limbs[playerRace][0][0];
1121 	my->focaly = limbs[playerRace][0][1];
1122 	my->focalz = limbs[playerRace][0][2];
1123 
1124 	if ( playerRace == GOATMAN && my->sprite == 768 )
1125 	{
1126 		my->focalz = limbs[playerRace][0][2] - 0.25; // minor head position fix to match male variant.
1127 	}
1128 
1129 	if ( playerRace == TROLL )
1130 	{
1131 		my->focalz += 1.25;
1132 		my->scalex = 1.01;
1133 		my->scaley = 1.01;
1134 		my->scalez = 1.01;
1135 	}
1136 	else
1137 	{
1138 		my->scalex = 1.f;
1139 		my->scaley = 1.f;
1140 		my->scalez = 1.f;
1141 	}
1142 
1143 	if ( multiplayer == CLIENT )
1144 	{
1145 		if ( PLAYER_NUM != clientnum )
1146 		{
1147 			my->flags[UPDATENEEDED] = true;
1148 		}
1149 
1150 		my->handleEffectsClient();
1151 
1152 		// request entity update (check if I've been deleted)
1153 		if ( ticks % (TICKS_PER_SECOND * 5) == my->getUID() % (TICKS_PER_SECOND * 5) )
1154 		{
1155 			strcpy((char*)net_packet->data, "ENTE");
1156 			net_packet->data[4] = clientnum;
1157 			SDLNet_Write32(my->getUID(), &net_packet->data[5]);
1158 			net_packet->address.host = net_server.host;
1159 			net_packet->address.port = net_server.port;
1160 			net_packet->len = 9;
1161 			sendPacketSafe(net_sock, -1, net_packet, 0);
1162 		}
1163 	}
1164 
1165 	if ( !PLAYER_INIT )
1166 	{
1167 		PLAYER_INIT = 1;
1168 		my->flags[BURNABLE] = true;
1169 
1170 		Entity* nametag = newEntity(-1, 1, map.entities, nullptr);
1171 		nametag->x = my->x;
1172 		nametag->y = my->y;
1173 		nametag->z = my->z - 6;
1174 		nametag->sizex = 1;
1175 		nametag->sizey = 1;
1176 		nametag->flags[NOUPDATE] = true;
1177 		nametag->flags[PASSABLE] = true;
1178 		nametag->flags[SPRITE] = true;
1179 		nametag->flags[BRIGHT] = true;
1180 		nametag->flags[UNCLICKABLE] = true;
1181 		nametag->behavior = &actSpriteNametag;
1182 		nametag->parent = my->getUID();
1183 		nametag->scalex = 0.2;
1184 		nametag->scaley = 0.2;
1185 		nametag->scalez = 0.2;
1186 		if ( multiplayer != CLIENT )
1187 		{
1188 			entity_uids--;
1189 		}
1190 		nametag->setUID(-3);
1191 
1192 		// hud weapon
1193 		if ( PLAYER_NUM == clientnum || splitscreen )
1194 		{
1195 			if ( multiplayer == CLIENT )
1196 			{
1197 				my->flags[UPDATENEEDED] = false;
1198 			}
1199 
1200 			entity = newEntity(-1, 1, map.entities, nullptr); //HUD entity.
1201 			entity->flags[PASSABLE] = true;
1202 			entity->flags[OVERDRAW] = true;
1203 			entity->flags[NOUPDATE] = true;
1204 			entity->flags[INVISIBLE] = true;
1205 			entity->skill[11] = PLAYER_NUM;
1206 			entity->behavior = &actHudWeapon;
1207 			entity->focalz = -4;
1208 			node = list_AddNodeLast(&my->children);
1209 			node->element = entity;
1210 			node->deconstructor = &emptyDeconstructor;
1211 			node->size = sizeof(Entity*);
1212 			my->bodyparts.push_back(entity);
1213 
1214 			// magic hands
1215 
1216 			//Left hand.
1217 			entity = newEntity(-1, 1, map.entities, nullptr); //HUD entity.
1218 			entity->flags[PASSABLE] = true;
1219 			entity->flags[OVERDRAW] = true;
1220 			entity->flags[NOUPDATE] = true;
1221 			entity->flags[INVISIBLE] = true;
1222 			entity->skill[2] = PLAYER_NUM;
1223 			entity->behavior = &actLeftHandMagic;
1224 			entity->focalz = -4;
1225 			magicLeftHand = entity;
1226 			//Right hand.
1227 			entity = newEntity(-1, 1, map.entities, nullptr); //HUD entity.
1228 			entity->flags[PASSABLE] = true;
1229 			entity->flags[OVERDRAW] = true;
1230 			entity->flags[NOUPDATE] = true;
1231 			entity->flags[INVISIBLE] = true;
1232 			entity->skill[2] = PLAYER_NUM;
1233 			entity->behavior = &actRightHandMagic;
1234 			entity->focalz = -4;
1235 			magicRightHand = entity;
1236 			my->bodyparts.push_back(entity);
1237 
1238 			// hud shield
1239 			entity = newEntity(-1, 1, map.entities, nullptr); //HUD entity.
1240 			entity->flags[PASSABLE] = true;
1241 			entity->flags[OVERDRAW] = true;
1242 			entity->flags[NOUPDATE] = true;
1243 			entity->flags[INVISIBLE] = true;
1244 			entity->skill[2] = PLAYER_NUM;
1245 			entity->behavior = &actHudShield;
1246 			my->bodyparts.push_back(entity);
1247 
1248 			// hud additional limb
1249 			entity = newEntity(-1, 1, map.entities, nullptr); //HUD entity.
1250 			entity->flags[PASSABLE] = true;
1251 			entity->flags[OVERDRAW] = true;
1252 			entity->flags[NOUPDATE] = true;
1253 			entity->flags[INVISIBLE] = true;
1254 			entity->skill[2] = PLAYER_NUM;
1255 			entity->behavior = &actHudAdditional;
1256 			my->bodyparts.push_back(entity);
1257 
1258 			// hud additional limb 2
1259 			entity = newEntity(-1, 1, map.entities, nullptr); //HUD entity.
1260 			entity->flags[PASSABLE] = true;
1261 			entity->flags[OVERDRAW] = true;
1262 			entity->flags[NOUPDATE] = true;
1263 			entity->flags[INVISIBLE] = true;
1264 			entity->skill[2] = PLAYER_NUM;
1265 			entity->behavior = &actHudArrowModel;
1266 			my->bodyparts.push_back(entity);
1267 		}
1268 		else
1269 		{
1270 			node = list_AddNodeLast(&my->children);
1271 			node->element = NULL;
1272 			node->deconstructor = &emptyDeconstructor;
1273 			node->size = 0;
1274 			if ( multiplayer == CLIENT )
1275 			{
1276 				PLAYER_TORCH = 0;
1277 			}
1278 		}
1279 
1280 		// torso
1281 		entity = newEntity(spriteTorso, 1, map.entities, nullptr); //Limb entity.
1282 		entity->sizex = 4;
1283 		entity->sizey = 4;
1284 		entity->skill[2] = PLAYER_NUM;
1285 		entity->flags[PASSABLE] = true;
1286 		entity->flags[NOUPDATE] = true;
1287 		entity->flags[GENIUS] = true;
1288 		entity->focalx = limbs[playerRace][1][0];
1289 		entity->focaly = limbs[playerRace][1][1];
1290 		entity->focalz = limbs[playerRace][1][2];
1291 		entity->behavior = &actPlayerLimb;
1292 		entity->parent = my->getUID();
1293 		node = list_AddNodeLast(&my->children);
1294 		node->element = entity;
1295 		node->deconstructor = &emptyDeconstructor;
1296 		node->size = sizeof(Entity*);
1297 		my->bodyparts.push_back(entity);
1298 		entity->setDefaultPlayerModel(PLAYER_NUM, playerRace, LIMB_HUMANOID_TORSO);
1299 
1300 		// right leg
1301 		entity = newEntity(spriteLegRight, 1, map.entities, nullptr); //Limb entity.
1302 		entity->sizex = 4;
1303 		entity->sizey = 4;
1304 		entity->skill[2] = PLAYER_NUM;
1305 		entity->flags[PASSABLE] = true;
1306 		entity->flags[NOUPDATE] = true;
1307 		entity->flags[GENIUS] = true;
1308 		entity->focalx = limbs[playerRace][2][0];
1309 		entity->focaly = limbs[playerRace][2][1];
1310 		entity->focalz = limbs[playerRace][2][2];
1311 		entity->behavior = &actPlayerLimb;
1312 		entity->parent = my->getUID();
1313 		node = list_AddNodeLast(&my->children);
1314 		node->element = entity;
1315 		node->deconstructor = &emptyDeconstructor;
1316 		node->size = sizeof(Entity*);
1317 		my->bodyparts.push_back(entity);
1318 		entity->setDefaultPlayerModel(PLAYER_NUM, playerRace, LIMB_HUMANOID_RIGHTLEG);
1319 
1320 		// left leg
1321 		entity = newEntity(spriteLegLeft, 1, map.entities, nullptr); //Limb entity.
1322 		entity->sizex = 4;
1323 		entity->sizey = 4;
1324 		entity->skill[2] = PLAYER_NUM;
1325 		entity->flags[PASSABLE] = true;
1326 		entity->flags[NOUPDATE] = true;
1327 		entity->flags[GENIUS] = true;
1328 		entity->focalx = limbs[playerRace][3][0];
1329 		entity->focaly = limbs[playerRace][3][1];
1330 		entity->focalz = limbs[playerRace][3][2];
1331 		entity->behavior = &actPlayerLimb;
1332 		entity->parent = my->getUID();
1333 		node = list_AddNodeLast(&my->children);
1334 		node->element = entity;
1335 		node->deconstructor = &emptyDeconstructor;
1336 		node->size = sizeof(Entity*);
1337 		my->bodyparts.push_back(entity);
1338 		entity->setDefaultPlayerModel(PLAYER_NUM, playerRace, LIMB_HUMANOID_LEFTLEG);
1339 
1340 		// right arm
1341 		entity = newEntity(spriteArmRight, 1, map.entities, nullptr); //Limb entity.
1342 		entity->sizex = 4;
1343 		entity->sizey = 4;
1344 		entity->skill[2] = PLAYER_NUM;
1345 		entity->flags[PASSABLE] = true;
1346 		entity->flags[NOUPDATE] = true;
1347 		entity->flags[GENIUS] = true;
1348 		entity->focalx = limbs[playerRace][4][0];
1349 		entity->focaly = limbs[playerRace][4][1];
1350 		entity->focalz = limbs[playerRace][4][2];
1351 		entity->behavior = &actPlayerLimb;
1352 		entity->parent = my->getUID();
1353 		node = list_AddNodeLast(&my->children);
1354 		node->element = entity;
1355 		node->deconstructor = &emptyDeconstructor;
1356 		node->size = sizeof(Entity*);
1357 		my->bodyparts.push_back(entity);
1358 		entity->setDefaultPlayerModel(PLAYER_NUM, playerRace, LIMB_HUMANOID_RIGHTARM);
1359 
1360 		// left arm
1361 		entity = newEntity(spriteArmLeft, 1, map.entities, nullptr); //Limb entity.
1362 		entity->sizex = 4;
1363 		entity->sizey = 4;
1364 		entity->skill[2] = PLAYER_NUM;
1365 		entity->flags[PASSABLE] = true;
1366 		entity->flags[NOUPDATE] = true;
1367 		entity->flags[GENIUS] = true;
1368 		entity->focalx = limbs[playerRace][5][0];
1369 		entity->focaly = limbs[playerRace][5][1];
1370 		entity->focalz = limbs[playerRace][5][2];
1371 		entity->behavior = &actPlayerLimb;
1372 		entity->parent = my->getUID();
1373 		node = list_AddNodeLast(&my->children);
1374 		node->element = entity;
1375 		node->deconstructor = &emptyDeconstructor;
1376 		node->size = sizeof(Entity*);
1377 		my->bodyparts.push_back(entity);
1378 		entity->setDefaultPlayerModel(PLAYER_NUM, playerRace, LIMB_HUMANOID_LEFTARM);
1379 
1380 		// world weapon
1381 		entity = newEntity(-1, 1, map.entities, nullptr); //Limb entity.
1382 		entity->sizex = 4;
1383 		entity->sizey = 4;
1384 		entity->skill[2] = PLAYER_NUM;
1385 		entity->flags[PASSABLE] = true;
1386 		entity->flags[NOUPDATE] = true;
1387 		entity->flags[GENIUS] = true;
1388 		entity->flags[INVISIBLE] = true;
1389 		entity->focalx = limbs[playerRace][6][0];
1390 		entity->focaly = limbs[playerRace][6][1];
1391 		entity->focalz = limbs[playerRace][6][2];
1392 		entity->behavior = &actPlayerLimb;
1393 		entity->parent = my->getUID();
1394 		node = list_AddNodeLast(&my->children);
1395 		node->element = entity;
1396 		node->deconstructor = &emptyDeconstructor;
1397 		node->size = sizeof(Entity*);
1398 		my->bodyparts.push_back(entity);
1399 
1400 		// shield
1401 		entity = newEntity(-1, 1, map.entities, nullptr); //Limb entity.
1402 		entity->sizex = 4;
1403 		entity->sizey = 4;
1404 		entity->skill[2] = PLAYER_NUM;
1405 		entity->flags[PASSABLE] = true;
1406 		entity->flags[NOUPDATE] = true;
1407 		entity->flags[GENIUS] = true;
1408 		entity->flags[INVISIBLE] = true;
1409 		entity->focalx = limbs[playerRace][7][0];
1410 		entity->focaly = limbs[playerRace][7][1];
1411 		entity->focalz = limbs[playerRace][7][2];
1412 		entity->behavior = &actPlayerLimb;
1413 		entity->parent = my->getUID();
1414 		entity->focalx = 2;
1415 		node = list_AddNodeLast(&my->children);
1416 		node->element = entity;
1417 		node->deconstructor = &emptyDeconstructor;
1418 		node->size = sizeof(Entity*);
1419 		my->bodyparts.push_back(entity);
1420 
1421 		// cloak
1422 		entity = newEntity(-1, 1, map.entities, nullptr); //Limb entity.
1423 		entity->sizex = 4;
1424 		entity->sizey = 4;
1425 		entity->scalex = 1.01;
1426 		entity->scaley = 1.01;
1427 		entity->scalez = 1.01;
1428 		entity->skill[2] = PLAYER_NUM;
1429 		entity->flags[PASSABLE] = true;
1430 		entity->flags[NOUPDATE] = true;
1431 		entity->flags[GENIUS] = true;
1432 		entity->flags[INVISIBLE] = true;
1433 		entity->focalx = limbs[playerRace][8][0];
1434 		entity->focaly = limbs[playerRace][8][1];
1435 		entity->focalz = limbs[playerRace][8][2];
1436 		entity->behavior = &actPlayerLimb;
1437 		entity->parent = my->getUID();
1438 		node = list_AddNodeLast(&my->children);
1439 		node->element = entity;
1440 		node->deconstructor = &emptyDeconstructor;
1441 		node->size = sizeof(Entity*);
1442 		my->bodyparts.push_back(entity);
1443 
1444 		// helmet
1445 		entity = newEntity(-1, 1, map.entities, nullptr); //Limb entity.
1446 		entity->sizex = 4;
1447 		entity->sizey = 4;
1448 		entity->scalex = 1.01;
1449 		entity->scaley = 1.01;
1450 		entity->scalez = 1.01;
1451 		entity->skill[2] = PLAYER_NUM;
1452 		entity->flags[PASSABLE] = true;
1453 		entity->flags[NOUPDATE] = true;
1454 		entity->flags[GENIUS] = true;
1455 		entity->flags[INVISIBLE] = true;
1456 		entity->focalx = limbs[playerRace][9][0];
1457 		entity->focaly = limbs[playerRace][9][1];
1458 		entity->focalz = limbs[playerRace][9][2];
1459 		entity->behavior = &actPlayerLimb;
1460 		entity->parent = my->getUID();
1461 		node = list_AddNodeLast(&my->children);
1462 		node->element = entity;
1463 		node->deconstructor = &emptyDeconstructor;
1464 		node->size = sizeof(Entity*);
1465 		my->bodyparts.push_back(entity);
1466 
1467 		// mask
1468 		entity = newEntity(-1, 1, map.entities, nullptr); //Limb entity.
1469 		entity->sizex = 4;
1470 		entity->sizey = 4;
1471 		entity->scalex = .99;
1472 		entity->scaley = .99;
1473 		entity->scalez = .99;
1474 		entity->skill[2] = PLAYER_NUM;
1475 		entity->flags[PASSABLE] = true;
1476 		entity->flags[NOUPDATE] = true;
1477 		entity->flags[GENIUS] = true;
1478 		entity->flags[INVISIBLE] = true;
1479 		entity->focalx = limbs[playerRace][10][0];
1480 		entity->focaly = limbs[playerRace][10][1];
1481 		entity->focalz = limbs[playerRace][10][2];
1482 		entity->behavior = &actPlayerLimb;
1483 		entity->parent = my->getUID();
1484 		node = list_AddNodeLast(&my->children);
1485 		node->element = entity;
1486 		node->deconstructor = &emptyDeconstructor;
1487 		node->size = sizeof(Entity*);
1488 		my->bodyparts.push_back(entity);
1489 
1490 		// additional limb 1
1491 		entity = newEntity(-1, 1, map.entities, nullptr); //Limb entity.
1492 		entity->sizex = 4;
1493 		entity->sizey = 4;
1494 		entity->skill[2] = PLAYER_NUM;
1495 		entity->flags[PASSABLE] = true;
1496 		entity->flags[NOUPDATE] = true;
1497 		entity->flags[GENIUS] = true;
1498 		entity->flags[INVISIBLE] = true;
1499 		entity->focalx = limbs[playerRace][11][0];
1500 		entity->focaly = limbs[playerRace][11][1];
1501 		entity->focalz = limbs[playerRace][11][2];
1502 		entity->behavior = &actPlayerLimb;
1503 		entity->parent = my->getUID();
1504 		node = list_AddNodeLast(&my->children);
1505 		node->element = entity;
1506 		node->deconstructor = &emptyDeconstructor;
1507 		node->size = sizeof(Entity*);
1508 		my->bodyparts.push_back(entity);
1509 
1510 		// additional limb 2
1511 		entity = newEntity(-1, 1, map.entities, nullptr); //Limb entity.
1512 		entity->sizex = 4;
1513 		entity->sizey = 4;
1514 		entity->skill[2] = PLAYER_NUM;
1515 		entity->flags[PASSABLE] = true;
1516 		entity->flags[NOUPDATE] = true;
1517 		entity->flags[GENIUS] = true;
1518 		entity->flags[INVISIBLE] = true;
1519 		entity->focalx = limbs[playerRace][12][0];
1520 		entity->focaly = limbs[playerRace][12][1];
1521 		entity->focalz = limbs[playerRace][12][2];
1522 		entity->behavior = &actPlayerLimb;
1523 		entity->parent = my->getUID();
1524 		node = list_AddNodeLast(&my->children);
1525 		node->element = entity;
1526 		node->deconstructor = &emptyDeconstructor;
1527 		node->size = sizeof(Entity*);
1528 		my->bodyparts.push_back(entity);
1529 
1530 		// additional limb 3 - 18.
1531 		for ( int c = 0; c < 8; ++c )
1532 		{
1533 			entity = newEntity(-1, 1, map.entities, nullptr); //Limb entity.
1534 			entity->sizex = 1;
1535 			entity->sizey = 1;
1536 			entity->skill[2] = PLAYER_NUM;
1537 			entity->fskill[10] = (c / 8.f);
1538 			entity->flags[PASSABLE] = true;
1539 			entity->flags[NOUPDATE] = true;
1540 			entity->flags[GENIUS] = true;
1541 			entity->flags[INVISIBLE] = true;
1542 			entity->focalx = limbs[playerRace][11][0];
1543 			entity->focaly = limbs[playerRace][11][1];
1544 			entity->focalz = limbs[playerRace][11][2];
1545 			entity->behavior = &actPlayerLimb;
1546 			entity->parent = my->getUID();
1547 			node = list_AddNodeLast(&my->children);
1548 			node->element = entity;
1549 			node->deconstructor = &emptyDeconstructor;
1550 			node->size = sizeof(Entity*);
1551 			my->bodyparts.push_back(entity);
1552 
1553 			entity = newEntity(-1, 1, map.entities, nullptr); //Limb entity.
1554 			entity->sizex = 1;
1555 			entity->sizey = 1;
1556 			entity->skill[2] = PLAYER_NUM;
1557 			entity->flags[PASSABLE] = true;
1558 			entity->flags[NOUPDATE] = true;
1559 			entity->flags[GENIUS] = true;
1560 			entity->flags[INVISIBLE] = true;
1561 			entity->focalx = limbs[playerRace][12][0];
1562 			entity->focaly = limbs[playerRace][12][1];
1563 			entity->focalz = limbs[playerRace][12][2];
1564 			entity->behavior = &actPlayerLimb;
1565 			entity->parent = my->getUID();
1566 			node = list_AddNodeLast(&my->children);
1567 			node->element = entity;
1568 			node->deconstructor = &emptyDeconstructor;
1569 			node->size = sizeof(Entity*);
1570 			my->bodyparts.push_back(entity);
1571 		}
1572 	}
1573 	Uint32 color = SDL_MapRGB(mainsurface->format, 255, 0, 255);
1574 	int blueSpeechVolume = 100;
1575 	int orangeSpeechVolume = 128;
1576 
1577 	if ( !intro )
1578 	{
1579 		PLAYER_ALIVETIME++;
1580 		if ( PLAYER_NUM == clientnum || splitscreen )
1581 		{
1582 			clientplayer = my->getUID();
1583 			if ( !strcmp(map.name, "Boss") && !my->skill[29] )
1584 			{
1585 				bool foundherx = false;
1586 				for ( node = map.creatures->first; node != nullptr; node = node->next ) //Herx is in the creature list, so only search that.
1587 				{
1588 					Entity* entity = (Entity*)node->element;
1589 					if ( entity->sprite == 274 )
1590 					{
1591 						foundherx = true;
1592 						break;
1593 					}
1594 				}
1595 				if ( !foundherx )
1596 				{
1597 					// ding, dong, the witch is dead
1598 					my->skill[29] = PLAYER_ALIVETIME;
1599 				}
1600 				else
1601 				{
1602 					if ( PLAYER_ALIVETIME == 300 )
1603 					{
1604 						playSound(185, 128);
1605 						messagePlayerColor(clientnum, color, language[537]);
1606 						messagePlayerColor(clientnum, color, language[89]);
1607 					}
1608 				}
1609 			}
1610 			else
1611 			{
1612 				if ( PLAYER_ALIVETIME == 300 && !MFLAG_DISABLEMESSAGES )
1613 				{
1614 					// five seconds in, herx chimes in (maybe)
1615 					my->playerLevelEntrySpeech = 0;
1616 					if ( currentlevel == 0 && !secretlevel )
1617 					{
1618 						int speech = rand() % 3;
1619 						playSound(126 + speech, 128);
1620 						messagePlayerColor(clientnum, color, language[537]);
1621 						messagePlayerColor(clientnum, color, language[77 + speech]);
1622 					}
1623 					else if ( currentlevel == 1 && !secretlevel )
1624 					{
1625 						int speech = rand() % 3;
1626 						playSound(117 + speech, 128);
1627 						messagePlayerColor(clientnum, color, language[537]);
1628 						messagePlayerColor(clientnum, color, language[70 + speech]);
1629 					}
1630 					else if ( currentlevel == 5 && !secretlevel )
1631 					{
1632 						int speech = rand() % 2;
1633 						playSound(156 + speech, 128);
1634 						messagePlayerColor(clientnum, color, language[537]);
1635 						messagePlayerColor(clientnum, color, language[83 + speech]);
1636 					}
1637 					else if ( currentlevel == 10 && !secretlevel )
1638 					{
1639 						int speech = rand() % 2;
1640 						playSound(158 + speech, 128);
1641 						messagePlayerColor(clientnum, color, language[537]);
1642 						messagePlayerColor(clientnum, color, language[85 + speech]);
1643 					}
1644 					else if ( currentlevel == 15 && !secretlevel )
1645 					{
1646 						int speech = rand() % 2;
1647 						playSound(160 + speech, 128);
1648 						messagePlayerColor(clientnum, color, language[537]);
1649 						messagePlayerColor(clientnum, color, language[87 + speech]);
1650 					}
1651 					else if ( currentlevel == 26 && !secretlevel )
1652 					{
1653 						int speech = 1 + rand() % 3;
1654 						switch ( speech )
1655 						{
1656 							case 1:
1657 								playSound(341, blueSpeechVolume);
1658 								messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[537]);
1659 								messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2615]);
1660 								break;
1661 							case 2:
1662 								playSound(343, orangeSpeechVolume);
1663 								messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[537]);
1664 								messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2617]);
1665 								break;
1666 							case 3:
1667 								playSound(346, orangeSpeechVolume);
1668 								messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[537]);
1669 								messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2620]);
1670 								break;
1671 						}
1672 						my->playerLevelEntrySpeech = speech;
1673 					}
1674 					else if ( currentlevel == 28 && !secretlevel )
1675 					{
1676 						int speech = 1 + rand() % 3;
1677 						switch ( speech )
1678 						{
1679 							case 1:
1680 								playSound(349, blueSpeechVolume);
1681 								messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[537]);
1682 								messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2629]);
1683 								break;
1684 							case 2:
1685 								playSound(352, orangeSpeechVolume);
1686 								messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[537]);
1687 								messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2632]);
1688 								break;
1689 							case 3:
1690 								playSound(354, blueSpeechVolume);
1691 								messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[537]);
1692 								messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2634]);
1693 								break;
1694 						}
1695 						my->playerLevelEntrySpeech = speech;
1696 					}
1697 					else if ( currentlevel == 30 && !secretlevel )
1698 					{
1699 						int speech = 1;
1700 						switch ( speech )
1701 						{
1702 							case 1:
1703 								playSound(356, blueSpeechVolume - 16);
1704 								messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[537]);
1705 								messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2636]);
1706 								break;
1707 						}
1708 						my->playerLevelEntrySpeech = speech;
1709 					}
1710 					else if ( currentlevel == 31 && !secretlevel )
1711 					{
1712 						int speech = 1;
1713 						switch ( speech )
1714 						{
1715 							case 1:
1716 								playSound(358, blueSpeechVolume);
1717 								messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[537]);
1718 								messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2638]);
1719 								break;
1720 						}
1721 						my->playerLevelEntrySpeech = speech;
1722 					}
1723 					else if ( currentlevel == 33 && !secretlevel )
1724 					{
1725 						int speech = 1 + rand() % 2;
1726 						switch ( speech )
1727 						{
1728 							case 1:
1729 								playSound(360, orangeSpeechVolume);
1730 								messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[537]);
1731 								messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2640]);
1732 								break;
1733 							case 2:
1734 								playSound(362, blueSpeechVolume);
1735 								messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[537]);
1736 								messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2642]);
1737 								break;
1738 						}
1739 						my->playerLevelEntrySpeech = speech;
1740 					}
1741 					else if ( currentlevel == 35 && !secretlevel )
1742 					{
1743 						int speech = 1;
1744 						switch ( speech )
1745 						{
1746 							case 1:
1747 								playSound(364, orangeSpeechVolume);
1748 								messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[537]);
1749 								messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2644]);
1750 								break;
1751 						}
1752 						my->playerLevelEntrySpeech = speech;
1753 					}
1754 					else if ( minotaurlevel )
1755 					{
1756 						if ( currentlevel < 25 )
1757 						{
1758 							int speech = rand() % 3;
1759 							playSound(123 + speech, 128);
1760 							messagePlayerColor(clientnum, color, language[537]);
1761 							messagePlayerColor(clientnum, color, language[74 + speech]);
1762 						}
1763 						else
1764 						{
1765 							int speech = 1 + rand() % 3;
1766 							switch ( speech )
1767 							{
1768 								case 1:
1769 									playSound(366, blueSpeechVolume);
1770 									messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[537]);
1771 									messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2623]);
1772 									break;
1773 								case 2:
1774 									playSound(368, orangeSpeechVolume);
1775 									messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[537]);
1776 									messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2625]);
1777 									break;
1778 								case 3:
1779 									playSound(370, blueSpeechVolume);
1780 									messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[537]);
1781 									messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2627]);
1782 									break;
1783 							}
1784 							my->playerLevelEntrySpeech = speech;
1785 						}
1786 					}
1787 				}
1788 				else if ( PLAYER_ALIVETIME == 480 && !MFLAG_DISABLEMESSAGES )
1789 				{
1790 					// 8 seconds in, herx chimes in again (maybe)
1791 					if ( currentlevel == 1 && !secretlevel )
1792 					{
1793 						playSound(120 + rand() % 3, 128);
1794 						messagePlayerColor(clientnum, color, language[73]);
1795 					}
1796 					else if ( minotaurlevel && currentlevel < 25 )
1797 					{
1798 						int speech = rand() % 3;
1799 						playSound(129 + speech, 128);
1800 						messagePlayerColor(clientnum, color, language[80 + speech]);
1801 					}
1802 				}
1803 				else if ( my->playerLevelEntrySpeech > 0 )
1804 				{
1805 					my->playerLevelEntrySpeechSecond();
1806 				}
1807 			}
1808 
1809 			// shurar the talking mace
1810 			if ( stats[PLAYER_NUM]->weapon )
1811 			{
1812 				if ( stats[PLAYER_NUM]->weapon->type == ARTIFACT_MACE )
1813 				{
1814 					if ( PLAYER_ALIVETIME % 420 == 0 )
1815 					{
1816 						messagePlayerColor(clientnum, color, language[538 + rand() % 32]);
1817 					}
1818 				}
1819 			}
1820 
1821 			if ( monsterEmoteGimpTimer > 0 )
1822 			{
1823 				--monsterEmoteGimpTimer;
1824 			}
1825 		}
1826 		if ( multiplayer == SERVER )
1827 		{
1828 			if ( my->getUID() % (TICKS_PER_SECOND * 3) == ticks % (TICKS_PER_SECOND * 3) )
1829 			{
1830 				serverUpdateBodypartIDs(my);
1831 
1832 				int i;
1833 				for ( i = 1; i < 11; i++ )
1834 				{
1835 					serverUpdateEntityBodypart(my, i);
1836 				}
1837 			}
1838 		}
1839 		if ( multiplayer != CLIENT )
1840 		{
1841 			if ( PLAYER_ALIVETIME == 50 && currentlevel == 0 )
1842 			{
1843 				int monsterSquad = 0;
1844 				for ( int c = 0; c < MAXPLAYERS; ++c )
1845 				{
1846 					if ( players[c] && players[c]->entity && stats[c]->playerRace > 0 )
1847 					{
1848 						++monsterSquad;
1849 					}
1850 				}
1851 				if ( monsterSquad >= 3 )
1852 				{
1853 					for ( int c = 0; c < MAXPLAYERS; ++c )
1854 					{
1855 						steamAchievementClient(c, "BARONY_ACH_MONSTER_SQUAD");
1856 					}
1857 				}
1858 				if ( client_classes[PLAYER_NUM] == CLASS_ACCURSED )
1859 				{
1860 					my->setEffect(EFF_VAMPIRICAURA, true, -2, true);
1861 					my->playerVampireCurse = 1;
1862 					serverUpdateEntitySkill(my, 51);
1863 					Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
1864 					messagePlayerColor(PLAYER_NUM, color, language[2477]);
1865 					color = SDL_MapRGB(mainsurface->format, 255, 255, 0);
1866 					messagePlayerColor(PLAYER_NUM, color, language[3202]);
1867 
1868 					playSoundEntity(my, 167, 128);
1869 					playSoundEntity(my, 403, 128);
1870 					createParticleDropRising(my, 600, 0.7);
1871 					serverSpawnMiscParticles(my, PARTICLE_EFFECT_VAMPIRIC_AURA, 600);
1872 				}
1873 			}
1874 			if ( currentlevel == 0 && stats[PLAYER_NUM]->playerRace == RACE_GOATMAN && stats[PLAYER_NUM]->appearance == 0 )
1875 			{
1876 				if ( PLAYER_ALIVETIME == 1 )
1877 				{
1878 					my->setEffect(EFF_WITHDRAWAL, true, -2, true);
1879 				}
1880 				if ( PLAYER_ALIVETIME == 330 )
1881 				{
1882 					my->setEffect(EFF_ASLEEP, false, 0, true);
1883 					if ( svFlags & SV_FLAG_HUNGER )
1884 					{
1885 						if ( stats[PLAYER_NUM]->HUNGER <= 1000 ) // just in case you ate before scripted sequence
1886 						{
1887 							playSoundPlayer(PLAYER_NUM, 32, 128);
1888 							stats[PLAYER_NUM]->HUNGER = 150;
1889 							serverUpdateHunger(PLAYER_NUM);
1890 						}
1891 						else
1892 						{
1893 							stats[PLAYER_NUM]->HUNGER -= 850;
1894 							serverUpdateHunger(PLAYER_NUM);
1895 						}
1896 					}
1897 				}
1898 				if ( stats[PLAYER_NUM]->EFFECTS[EFF_WITHDRAWAL] )
1899 				{
1900 					if ( PLAYER_ALIVETIME == 500 )
1901 					{
1902 						color = SDL_MapRGB(mainsurface->format, 255, 255, 255);
1903 						messagePlayerColor(PLAYER_NUM, color, language[3221]);
1904 					}
1905 					else if ( PLAYER_ALIVETIME == 700 )
1906 					{
1907 						color = SDL_MapRGB(mainsurface->format, 255, 255, 255);
1908 						messagePlayerColor(PLAYER_NUM, color, language[3222]);
1909 					}
1910 				}
1911 			}
1912 		}
1913 		if ( multiplayer == CLIENT && client_classes[PLAYER_NUM] == CLASS_ACCURSED )
1914 		{
1915 			if ( PLAYER_NUM == clientnum && my->playerVampireCurse == 1 )
1916 			{
1917 				stats[PLAYER_NUM]->EFFECTS_TIMERS[EFF_VAMPIRICAURA] = -2;
1918 			}
1919 			else
1920 			{
1921 				stats[PLAYER_NUM]->EFFECTS_TIMERS[EFF_VAMPIRICAURA] = 0;
1922 			}
1923 		}
1924 	}
1925 
1926 	//if ( keystatus[SDL_SCANCODE_F1] )
1927 	//{
1928 	//	//gameloopFreezeEntities = !gameloopFreezeEntities;
1929 	//	cpp_SteamMatchmaking_RequestAppTicket();
1930 	//	keystatus[SDL_SCANCODE_F1] = 0;
1931 	//}
1932 	/*if ( my->ticks % 50 == 0 )
1933 	{
1934 		messagePlayer(clientnum, "%d", stats[clientnum]->HUNGER);
1935 	}*/
1936 	/*
1937 	if ( keystatus[SDL_SCANCODE_F2] )
1938 	{
1939 		if ( players[clientnum] != nullptr && players[clientnum]->entity != nullptr )
1940 		{
1941 			lightSphereShadow(players[clientnum]->entity->x / 16, players[clientnum]->entity->y / 16, 8, 150);
1942 		}
1943 		keystatus[SDL_SCANCODE_F2] = 0;
1944 	}
1945 	if ( keystatus[SDL_SCANCODE_F3] )
1946 	{
1947 		if ( players[clientnum] != nullptr && players[clientnum]->entity != nullptr )
1948 		{
1949 			players[clientnum]->entity->skill[3] = (players[clientnum]->entity->skill[3] == 0);
1950 		}
1951 		keystatus[SDL_SCANCODE_F3] = 0;
1952 	}
1953 	if ( keystatus[SDL_SCANCODE_F4] )
1954 	{
1955 		buttonStartSingleplayer(nullptr);
1956 		keystatus[SDL_SCANCODE_F4] = 0;
1957 	}
1958 	if ( keystatus[SDL_SCANCODE_F4] )
1959 	{
1960 		keystatus[SDL_SCANCODE_F4] = 0;
1961 
1962 		SteamUserStats()->SetAchievement("BARONY_ACH_BONY_BARON");
1963 		SteamUserStats()->SetAchievement("BARONY_ACH_BUCKTOOTH_BARON");
1964 		SteamUserStats()->SetAchievement("BARONY_ACH_BOMBSHELL_BARON");
1965 		SteamUserStats()->SetAchievement("BARONY_ACH_BLEATING_BARON");
1966 		SteamUserStats()->SetAchievement("BARONY_ACH_BOILERPLATE_BARON");
1967 		SteamUserStats()->SetAchievement("BARONY_ACH_BAD_BOY_BARON");
1968 		SteamUserStats()->SetAchievement("BARONY_ACH_BAYOU_BARON");
1969 		SteamUserStats()->SetAchievement("BARONY_ACH_BUGGAR_BARON");
1970 		SteamUserStats()->StoreStats();
1971 	}
1972 	if ( keystatus[SDL_SCANCODE_F5] )
1973 	{
1974 		keystatus[SDL_SCANCODE_F5] = 0;
1975 		SteamUserStats()->ClearAchievement("BARONY_ACH_BONY_BARON");
1976 		SteamUserStats()->ClearAchievement("BARONY_ACH_BUCKTOOTH_BARON");
1977 		SteamUserStats()->ClearAchievement("BARONY_ACH_BOMBSHELL_BARON");
1978 		SteamUserStats()->ClearAchievement("BARONY_ACH_BLEATING_BARON");
1979 		SteamUserStats()->ClearAchievement("BARONY_ACH_BOILERPLATE_BARON");
1980 		SteamUserStats()->ClearAchievement("BARONY_ACH_BAD_BOY_BARON");
1981 		SteamUserStats()->ClearAchievement("BARONY_ACH_BAYOU_BARON");
1982 		SteamUserStats()->ClearAchievement("BARONY_ACH_BUGGAR_BARON");
1983 		SteamUserStats()->StoreStats();
1984 	}
1985 	if ( keystatus[SDL_SCANCODE_KP_1] )
1986 	{
1987 		keystatus[SDL_SCANCODE_KP_1] = 0;
1988 		SteamUserStats()->SetAchievement("BARONY_ACH_BONY_BARON");
1989 		SteamUserStats()->StoreStats();
1990 	}
1991 	if ( keystatus[SDL_SCANCODE_KP_2] )
1992 	{
1993 		keystatus[SDL_SCANCODE_KP_2] = 0;
1994 		SteamUserStats()->SetAchievement("BARONY_ACH_BUCKTOOTH_BARON");
1995 		SteamUserStats()->StoreStats();
1996 	}
1997 	if ( keystatus[SDL_SCANCODE_KP_3] )
1998 	{
1999 		keystatus[SDL_SCANCODE_KP_3] = 0;
2000 		SteamUserStats()->SetAchievement("BARONY_ACH_BOMBSHELL_BARON");
2001 		SteamUserStats()->StoreStats();
2002 	}
2003 	if ( keystatus[SDL_SCANCODE_KP_4] )
2004 	{
2005 		keystatus[SDL_SCANCODE_KP_4] = 0;
2006 		SteamUserStats()->SetAchievement("BARONY_ACH_BLEATING_BARON");
2007 		SteamUserStats()->StoreStats();
2008 	}
2009 	if ( keystatus[SDL_SCANCODE_KP_5] )
2010 	{
2011 		keystatus[SDL_SCANCODE_KP_5] = 0;
2012 		SteamUserStats()->SetAchievement("BARONY_ACH_BOILERPLATE_BARON");
2013 		SteamUserStats()->StoreStats();
2014 	}
2015 	if ( keystatus[SDL_SCANCODE_KP_6] )
2016 	{
2017 		keystatus[SDL_SCANCODE_KP_6] = 0;
2018 		SteamUserStats()->SetAchievement("BARONY_ACH_BAD_BOY_BARON");
2019 		SteamUserStats()->StoreStats();
2020 	}
2021 	if ( keystatus[SDL_SCANCODE_KP_7] )
2022 	{
2023 		keystatus[SDL_SCANCODE_KP_7] = 0;
2024 		SteamUserStats()->SetAchievement("BARONY_ACH_BAYOU_BARON");
2025 		SteamUserStats()->StoreStats();
2026 	}
2027 	if ( keystatus[SDL_SCANCODE_KP_8] )
2028 	{
2029 		keystatus[SDL_SCANCODE_KP_8] = 0;
2030 		SteamUserStats()->SetAchievement("BARONY_ACH_BUGGAR_BARON");
2031 		SteamUserStats()->StoreStats();
2032 	}*/
2033 
2034 	// SPLITSCREEN TODO
2035 	if (PLAYER_NUM == clientnum && appraisal_timer > 0)
2036 	{
2037 		Item* tempItem = uidToItem(appraisal_item);
2038 		if ( tempItem )
2039 		{
2040 			if ( tempItem->identified )
2041 			{
2042 				appraisal_timer = 0;
2043 				appraisal_item = 0;
2044 			}
2045 			else if ( tempItem->type == GEM_ROCK )
2046 			{
2047 				//Auto-succeed on rocks.
2048 				tempItem->identified = true;
2049 				messagePlayer(clientnum, language[570], tempItem->description());
2050 				appraisal_item = 0;
2051 				appraisal_timer = 0;
2052 
2053 				// update inventory by trying to stack the newly identified item.
2054 				std::unordered_set<Uint32> appearancesOfSimilarItems;
2055 				for ( node = stats[PLAYER_NUM]->inventory.first; node != NULL; node = node->next )
2056 				{
2057 					Item* item2 = (Item*)node->element;
2058 					if ( item2 == tempItem )
2059 					{
2060 						continue;
2061 					}
2062 					if ( !item2 )
2063 					{
2064 						continue;
2065 					}
2066 					if ( !itemCompare(tempItem, item2, false) )
2067 					{
2068 						// if items are the same, check to see if they should stack
2069 						if ( item2->shouldItemStack(PLAYER_NUM) )
2070 						{
2071 							item2->count += tempItem->count;
2072 							if ( multiplayer == CLIENT && itemIsEquipped(item2, clientnum) )
2073 							{
2074 								// if incrementing qty and holding item, then send "equip" for server to update their count of your held item.
2075 								clientSendEquipUpdateToServer(EQUIP_ITEM_SLOT_WEAPON, EQUIP_ITEM_SUCCESS_UPDATE_QTY, PLAYER_NUM,
2076 									item2->type, item2->status, item2->beatitude, item2->count, item2->appearance, item2->identified);
2077 							}
2078 							if ( tempItem->node )
2079 							{
2080 								list_RemoveNode(tempItem->node);
2081 								tempItem = nullptr;
2082 							}
2083 							else
2084 							{
2085 								free(tempItem);
2086 								tempItem = nullptr;
2087 							}
2088 							break;
2089 						}
2090 						else if ( !itemCompare(tempItem, item2, true) )
2091 						{
2092 							// items are the same (incl. appearance!)
2093 							// if they shouldn't stack, we need to change appearance of the new item.
2094 							appearancesOfSimilarItems.insert(item2->appearance);
2095 						}
2096 					}
2097 				}
2098 				if ( tempItem && !appearancesOfSimilarItems.empty() )
2099 				{
2100 					int tries = 100;
2101 					// we need to find a unique appearance within the list.
2102 					tempItem->appearance = rand();
2103 					auto it = appearancesOfSimilarItems.find(tempItem->appearance);
2104 					while ( it != appearancesOfSimilarItems.end() && tries > 0 )
2105 					{
2106 						tempItem->appearance = rand();
2107 						it = appearancesOfSimilarItems.find(tempItem->appearance);
2108 						--tries;
2109 					}
2110 				}
2111 			}
2112 			else
2113 			{
2114 				appraisal_timer -= 1; //De-increment appraisal timer.
2115 				if (appraisal_timer <= 0)
2116 				{
2117 					appraisal_timer = 0;
2118 
2119 					//Cool. Time to identify the item.
2120 					bool success = false;
2121 					if ( stats[PLAYER_NUM]->PROFICIENCIES[PRO_APPRAISAL] < 100 )
2122 					{
2123 						if ( tempItem->type != GEM_GLASS )
2124 						{
2125 							success = (stats[PLAYER_NUM]->PROFICIENCIES[PRO_APPRAISAL] + my->getPER() * 5 >= items[tempItem->type].value / 10);
2126 						}
2127 						else
2128 						{
2129 							success = (stats[PLAYER_NUM]->PROFICIENCIES[PRO_APPRAISAL] + my->getPER() * 5 >= 100);
2130 						}
2131 					}
2132 					else
2133 					{
2134 						success = true; // always succeed when appraisal is maxed out
2135 					}
2136 					if ( success )
2137 					{
2138 						tempItem->identified = true;
2139 						messagePlayer(clientnum, language[570], tempItem->description());
2140 						if ( tempItem->type == GEM_GLASS )
2141 						{
2142 							steamStatisticUpdate(STEAM_STAT_RHINESTONE_COWBOY, STEAM_STAT_INT, 1);
2143 						}
2144 					}
2145 					else
2146 					{
2147 						if ( itemCategory(tempItem) == GEM )
2148 						{
2149 							messagePlayer(clientnum, language[3240], tempItem->description());
2150 						}
2151 					}
2152 
2153 					//Attempt a level up.
2154 					if ( tempItem && items[tempItem->type].value > 0 && stats[PLAYER_NUM] )
2155 					{
2156 						if ( tempItem->identified )
2157 						{
2158 							int appraisalEaseOfDifficulty = 0;
2159 							if ( items[tempItem->type].value < 100 )
2160 							{
2161 								// easy junk items
2162 								appraisalEaseOfDifficulty = 2;
2163 							}
2164 							else if ( items[tempItem->type].value < 200 )
2165 							{
2166 								// medium
2167 								appraisalEaseOfDifficulty = 1;
2168 							}
2169 							else if ( items[tempItem->type].value < 300 )
2170 							{
2171 								// medium
2172 								appraisalEaseOfDifficulty = 0;
2173 							}
2174 							else if ( items[tempItem->type].value < 400 )
2175 							{
2176 								// hardest
2177 								appraisalEaseOfDifficulty = -1;
2178 							}
2179 							else
2180 							{
2181 								// hardest
2182 								appraisalEaseOfDifficulty = -1;
2183 							}
2184 							appraisalEaseOfDifficulty += stats[PLAYER_NUM]->PROFICIENCIES[PRO_APPRAISAL] / 20;
2185 							// difficulty ranges from 1-in-1 to 1-in-6
2186 							appraisalEaseOfDifficulty = std::max(appraisalEaseOfDifficulty, 1);
2187 							//messagePlayer(0, "Appraisal level up chance: 1 in %d", appraisalEaseOfDifficulty);
2188 							if ( rand() % appraisalEaseOfDifficulty == 0 )
2189 							{
2190 								my->increaseSkill(PRO_APPRAISAL);
2191 							}
2192 						}
2193 						else if ( rand() % 7 == 0 )
2194 						{
2195 							my->increaseSkill(PRO_APPRAISAL);
2196 						}
2197 					}
2198 
2199 					if ( success )
2200 					{
2201 						// update inventory by trying to stack the newly identified item.
2202 						std::unordered_set<Uint32> appearancesOfSimilarItems;
2203 						for ( node = stats[PLAYER_NUM]->inventory.first; node != NULL; node = node->next )
2204 						{
2205 							Item* item2 = (Item*)node->element;
2206 							if ( item2 && item2 != tempItem && !itemCompare(tempItem, item2, false) )
2207 							{
2208 								if ( itemTypeIsQuiver(item2->type) && (tempItem->count + item2->count) >= QUIVER_MAX_AMMO_QTY )
2209 								{
2210 									int maxStack = QUIVER_MAX_AMMO_QTY;
2211 									// too many, split off into a new stack with reduced qty.
2212 									if ( tempItem->count >= (maxStack - 1) )
2213 									{
2214 										// identified item is at max count so don't stack, abort.
2215 										break;
2216 									}
2217 									if ( item2->count >= (maxStack - 1) )
2218 									{
2219 										// if we're at max count then skip this check.
2220 
2221 										if ( tempItem->appearance == item2->appearance )
2222 										{
2223 											// items are the same (incl. appearance!)
2224 											// if they shouldn't stack, we need to change appearance of the new item.
2225 											appearancesOfSimilarItems.insert(item2->appearance);
2226 										}
2227 										continue;
2228 									}
2229 									int total = tempItem->count + item2->count;
2230 									item2->count = maxStack - 1;
2231 									tempItem->count = total - item2->count;
2232 									if ( multiplayer == CLIENT && itemIsEquipped(item2, clientnum) )
2233 									{
2234 										// if incrementing qty and holding item, then send "equip" for server to update their count of your held item.
2235 										strcpy((char*)net_packet->data, "EQUS");
2236 										SDLNet_Write32((Uint32)item2->type, &net_packet->data[4]);
2237 										SDLNet_Write32((Uint32)item2->status, &net_packet->data[8]);
2238 										SDLNet_Write32((Uint32)item2->beatitude, &net_packet->data[12]);
2239 										SDLNet_Write32((Uint32)item2->count, &net_packet->data[16]);
2240 										SDLNet_Write32((Uint32)item2->appearance, &net_packet->data[20]);
2241 										net_packet->data[24] = item2->identified;
2242 										net_packet->data[25] = clientnum;
2243 										net_packet->address.host = net_server.host;
2244 										net_packet->address.port = net_server.port;
2245 										net_packet->len = 27;
2246 										sendPacketSafe(net_sock, -1, net_packet, 0);
2247 									}
2248 									if ( tempItem->count <= 0 )
2249 									{
2250 										if ( tempItem->node )
2251 										{
2252 											list_RemoveNode(tempItem->node);
2253 											tempItem = nullptr;
2254 										}
2255 										else
2256 										{
2257 											free(tempItem);
2258 											tempItem = nullptr;
2259 										}
2260 										break;
2261 									}
2262 									else
2263 									{
2264 										// we have to search other items to stack with, otherwise this search ends after 1 full stack.
2265 										if ( tempItem->appearance == item2->appearance )
2266 										{
2267 											// items are the same (incl. appearance!)
2268 											// if they shouldn't stack, we need to change appearance of the new item.
2269 											appearancesOfSimilarItems.insert(item2->appearance);
2270 										}
2271 										continue;
2272 									}
2273 								}
2274 								// if items are the same, check to see if they should stack
2275 								else if ( item2->shouldItemStack(PLAYER_NUM) )
2276 								{
2277 									item2->count += tempItem->count;
2278 									if ( multiplayer == CLIENT && itemIsEquipped(item2, clientnum) )
2279 									{
2280 										// if incrementing qty and holding item, then send "equip" for server to update their count of your held item.
2281 										Item** slot = itemSlot(stats[PLAYER_NUM], item2);
2282 										if ( slot )
2283 										{
2284 											if ( slot == &stats[clientnum]->weapon )
2285 											{
2286 												clientSendEquipUpdateToServer(EQUIP_ITEM_SLOT_WEAPON, EQUIP_ITEM_SUCCESS_UPDATE_QTY, PLAYER_NUM,
2287 													item2->type, item2->status, item2->beatitude, item2->count, item2->appearance, item2->identified);
2288 											}
2289 											else if ( slot == &stats[clientnum]->shield )
2290 											{
2291 												clientSendEquipUpdateToServer(EQUIP_ITEM_SLOT_SHIELD, EQUIP_ITEM_SUCCESS_UPDATE_QTY, PLAYER_NUM,
2292 													item2->type, item2->status, item2->beatitude, item2->count, item2->appearance, item2->identified);
2293 											}
2294 										}
2295 									}
2296 									if ( tempItem->node )
2297 									{
2298 										list_RemoveNode(tempItem->node);
2299 										tempItem = nullptr;
2300 									}
2301 									else
2302 									{
2303 										free(tempItem);
2304 										tempItem = nullptr;
2305 									}
2306 									break;
2307 								}
2308 								else if ( !itemCompare(tempItem, item2, true) )
2309 								{
2310 									// items are the same (incl. appearance!)
2311 									// if they shouldn't stack, we need to change appearance of the new item.
2312 									appearancesOfSimilarItems.insert(item2->appearance);
2313 								}
2314 							}
2315 						}
2316 						if ( tempItem )
2317 						{
2318 							if ( !appearancesOfSimilarItems.empty() )
2319 							{
2320 								int tries = 100;
2321 								bool robot = false;
2322 								// we need to find a unique appearance within the list.
2323 								if ( tempItem->type == TOOL_SENTRYBOT || tempItem->type == TOOL_SPELLBOT || tempItem->type == TOOL_GYROBOT
2324 									|| tempItem->type == TOOL_DUMMYBOT )
2325 								{
2326 									robot = true;
2327 									tempItem->appearance += (rand() % 100000) * 10;
2328 								}
2329 								else
2330 								{
2331 									tempItem->appearance = rand();
2332 								}
2333 								auto it = appearancesOfSimilarItems.find(tempItem->appearance);
2334 								while ( it != appearancesOfSimilarItems.end() && tries > 0 )
2335 								{
2336 									if ( robot )
2337 									{
2338 										tempItem->appearance += (rand() % 100000) * 10;
2339 									}
2340 									else
2341 									{
2342 										tempItem->appearance = rand();
2343 									}
2344 									it = appearancesOfSimilarItems.find(tempItem->appearance);
2345 									--tries;
2346 								}
2347 							}
2348 						}
2349 					}
2350 
2351 					appraisal_item = 0;
2352 				}
2353 			}
2354 		}
2355 		else
2356 		{
2357 			appraisal_timer = 0;
2358 			appraisal_item = 0;
2359 		}
2360 	}
2361 
2362 	// remove broken equipment
2363 	if ( stats[PLAYER_NUM]->helmet != NULL )
2364 		if ( stats[PLAYER_NUM]->helmet->status == BROKEN )
2365 		{
2366 			stats[PLAYER_NUM]->helmet = NULL;
2367 		}
2368 	if ( stats[PLAYER_NUM]->breastplate != NULL )
2369 		if ( stats[PLAYER_NUM]->breastplate->status == BROKEN )
2370 		{
2371 			stats[PLAYER_NUM]->breastplate = NULL;
2372 		}
2373 	if ( stats[PLAYER_NUM]->gloves != NULL )
2374 		if ( stats[PLAYER_NUM]->gloves->status == BROKEN )
2375 		{
2376 			stats[PLAYER_NUM]->gloves = NULL;
2377 		}
2378 	if ( stats[PLAYER_NUM]->shoes != NULL )
2379 		if ( stats[PLAYER_NUM]->shoes->status == BROKEN )
2380 		{
2381 			stats[PLAYER_NUM]->shoes = NULL;
2382 		}
2383 	if ( stats[PLAYER_NUM]->shield != NULL )
2384 		if ( stats[PLAYER_NUM]->shield->status == BROKEN )
2385 		{
2386 			stats[PLAYER_NUM]->shield = NULL;
2387 		}
2388 	if ( stats[PLAYER_NUM]->weapon != NULL )
2389 		if ( stats[PLAYER_NUM]->weapon->status == BROKEN )
2390 		{
2391 			stats[PLAYER_NUM]->weapon = NULL;
2392 		}
2393 	if ( stats[PLAYER_NUM]->cloak != NULL )
2394 		if ( stats[PLAYER_NUM]->cloak->status == BROKEN )
2395 		{
2396 			stats[PLAYER_NUM]->cloak = NULL;
2397 		}
2398 	if ( stats[PLAYER_NUM]->amulet != NULL )
2399 		if ( stats[PLAYER_NUM]->amulet->status == BROKEN )
2400 		{
2401 			stats[PLAYER_NUM]->amulet = NULL;
2402 		}
2403 	if ( stats[PLAYER_NUM]->ring != NULL )
2404 		if ( stats[PLAYER_NUM]->ring->status == BROKEN )
2405 		{
2406 			stats[PLAYER_NUM]->ring = NULL;
2407 		}
2408 	if ( stats[PLAYER_NUM]->mask != NULL )
2409 		if ( stats[PLAYER_NUM]->mask->status == BROKEN )
2410 		{
2411 			stats[PLAYER_NUM]->mask = NULL;
2412 		}
2413 
2414 	if ( multiplayer != CLIENT )
2415 	{
2416 		my->effectTimes();
2417 	}
2418 
2419 	// invisibility
2420 	if ( !intro )
2421 	{
2422 		if ( PLAYER_NUM == clientnum || multiplayer == SERVER || splitscreen )
2423 		{
2424 			if ( stats[PLAYER_NUM]->ring != NULL )
2425 				if ( stats[PLAYER_NUM]->ring->type == RING_INVISIBILITY )
2426 				{
2427 					wearingring = true;
2428 				}
2429 			if ( stats[PLAYER_NUM]->cloak != NULL )
2430 				if ( stats[PLAYER_NUM]->cloak->type == CLOAK_INVISIBILITY )
2431 				{
2432 					wearingring = true;
2433 				}
2434 			//if ( stats[PLAYER_NUM]->EFFECTS[EFF_INVISIBLE] == true || wearingring == true )
2435 			if ( my->isInvisible() )
2436 			{
2437 				if ( !my->flags[INVISIBLE] )
2438 				{
2439 					my->flags[INVISIBLE] = true;
2440 					serverUpdateEntityFlag(my, INVISIBLE);
2441 				}
2442 				my->flags[BLOCKSIGHT] = false;
2443 				if ( multiplayer != CLIENT )
2444 				{
2445 					for ( i = 0, node = my->children.first; node != NULL; node = node->next, ++i )
2446 					{
2447 						if ( i == 0 )
2448 						{
2449 							continue;
2450 						}
2451 						if ( i >= 6 )
2452 						{
2453 							break;
2454 						}
2455 						entity = (Entity*)node->element;
2456 						if ( !entity->flags[INVISIBLE] )
2457 						{
2458 							entity->flags[INVISIBLE] = true;
2459 							serverUpdateEntityBodypart(my, i);
2460 						}
2461 					}
2462 				}
2463 			}
2464 			else
2465 			{
2466 				if ( my->flags[INVISIBLE] )
2467 				{
2468 					my->flags[INVISIBLE] = false;
2469 					serverUpdateEntityFlag(my, INVISIBLE);
2470 				}
2471 				my->flags[BLOCKSIGHT] = true;
2472 				if ( multiplayer != CLIENT )
2473 				{
2474 					for (i = 0, node = my->children.first; node != NULL; node = node->next, i++)
2475 					{
2476 						if ( i == 0 )
2477 						{
2478 							continue;
2479 						}
2480 						if ( i >= 6 )
2481 						{
2482 							break;
2483 						}
2484 						entity = (Entity*)node->element;
2485 						if ( entity->flags[INVISIBLE] )
2486 						{
2487 							if ( stats[PLAYER_NUM]->type == RAT )
2488 							{
2489 								if ( i == 1 )
2490 								{
2491 									// only unhide the body.
2492 									if ( entity->flags[INVISIBLE] )
2493 									{
2494 										entity->flags[INVISIBLE] = false;
2495 										serverUpdateEntityBodypart(my, i);
2496 									}
2497 								}
2498 							}
2499 							else if ( stats[PLAYER_NUM]->type == SPIDER )
2500 							{
2501 								// do nothing, these limbs are invisible for the spider so don't unhide.
2502 							}
2503 							else
2504 							{
2505 								if ( entity->flags[INVISIBLE] )
2506 								{
2507 									entity->flags[INVISIBLE] = false;
2508 									serverUpdateEntityBodypart(my, i);
2509 								}
2510 							}
2511 						}
2512 					}
2513 				}
2514 			}
2515 		}
2516 	}
2517 
2518 	real_t zOffset = 0;
2519 	bool oldInsectoidLevitate = insectoidLevitating[PLAYER_NUM];
2520 	insectoidLevitating[PLAYER_NUM] = false;
2521 
2522 	if ( PLAYER_NUM == clientnum || multiplayer == SERVER || splitscreen )
2523 	{
2524 		switch ( stats[PLAYER_NUM]->type )
2525 		{
2526 			case RAT:
2527 				zOffset = 6;
2528 				break;
2529 			case TROLL:
2530 				zOffset = -1.5;
2531 				break;
2532 			case SPIDER:
2533 				zOffset = 4.5;
2534 				break;
2535 			case CREATURE_IMP:
2536 				zOffset = -3.5;
2537 				break;
2538 			default:
2539 				break;
2540 		}
2541 		bool prevlevitating = false;
2542 		if ( multiplayer != CLIENT )
2543 		{
2544 			if ( abs(zOffset) <= 0.05 )
2545 			{
2546 				if ( (my->z >= -2.05 && my->z <= -1.95 ) || (my->z >= -1.55 && my->z <= -1.45) )
2547 				{
2548 					prevlevitating = true;
2549 				}
2550 			}
2551 			else
2552 			{
2553 				if( (my->z >= (zOffset - 1.05)) && (my->z <= (zOffset - 0.95))
2554 					|| (my->z >= (zOffset - .55)) && (my->z <= (zOffset - .45)) )
2555 				{
2556 					prevlevitating = true;
2557 				}
2558 			}
2559 		}
2560 
2561 		// sleeping
2562 		if ( stats[PLAYER_NUM]->EFFECTS[EFF_ASLEEP] )
2563 		{
2564 			switch ( playerRace )
2565 			{
2566 				case GOBLIN:
2567 				case GOATMAN:
2568 				case INSECTOID:
2569 					my->z = 2.5;
2570 					break;
2571 				case SKELETON:
2572 				case AUTOMATON:
2573 					my->z = 2.f;
2574 					break;
2575 				case HUMAN:
2576 				case VAMPIRE:
2577 				case INCUBUS:
2578 				case SUCCUBUS:
2579 				case TROLL:
2580 					my->z = 1.5;
2581 					break;
2582 				default:
2583 					my->z = 1.5;
2584 					break;
2585 			}
2586 			my->pitch = PI / 4;
2587 		}
2588 		else if ( !noclip || (noclip && intro) )
2589 		{
2590 			my->z = -1;
2591 			if ( abs(zOffset) >= 0.05 )
2592 			{
2593 				my->z = zOffset;
2594 			}
2595 			if ( intro )
2596 			{
2597 				my->pitch = 0;
2598 			}
2599 		}
2600 
2601 		// levitation
2602 		levitating = isLevitating(stats[PLAYER_NUM]);
2603 
2604 		if ( levitating )
2605 		{
2606 			my->z -= 1; // floating
2607 			insectoidLevitating[PLAYER_NUM] = (playerRace == INSECTOID && stats[PLAYER_NUM]->EFFECTS[EFF_FLUTTER]);
2608 		}
2609 
2610 		if ( !levitating && prevlevitating )
2611 		{
2612 			int x, y, u, v;
2613 			x = std::min(std::max<unsigned int>(1, my->x / 16), map.width - 2);
2614 			y = std::min(std::max<unsigned int>(1, my->y / 16), map.height - 2);
2615 			std::vector<std::pair<std::pair<int, int>, real_t>> safeTiles; // pair of coordinates, with a distance to player.
2616 			std::vector<std::pair<int, int>> deathTiles;
2617 			bool checkSafeTiles = true;
2618 			for ( u = x - 1; u <= x + 1; u++ )
2619 			{
2620 				for ( v = y - 1; v <= y + 1; v++ )
2621 				{
2622 					if ( entityInsideTile(my, u, v, 0, !checkSafeTiles) )
2623 					{
2624 						// intersecting with no floor, we might die.
2625 						deathTiles.push_back(std::make_pair(u, v));
2626 					}
2627 					else if ( entityInsideTile(my, u, v, 0, checkSafeTiles) )
2628 					{
2629 						// intersecting with a safe floor, we might live.
2630 						if ( barony_clear(u * 16 + 8, v * 16 + 8, my) )
2631 						{
2632 							// tile is clear from obstacles.
2633 							real_t dx = my->x - u * 16 + 8;
2634 							real_t dy = my->y - v * 16 + 8;
2635 							real_t dist = sqrt(dx * dx + dy * dy);
2636 							safeTiles.push_back(std::make_pair(std::make_pair(u, v), dist));
2637 						}
2638 					}
2639 				}
2640 			}
2641 
2642 			if ( !deathTiles.empty() )
2643 			{
2644 				if ( !safeTiles.empty() )
2645 				{
2646 					// we might be able to warp ourselves to a safe spot.
2647 					real_t lowestDist = 1000.0;
2648 					int lowestIndex = -1;
2649 					for ( auto it = safeTiles.begin(); it != safeTiles.end(); ++it )
2650 					{
2651 						if ( (*it).second < lowestDist )
2652 						{
2653 							lowestIndex = it - safeTiles.begin();
2654 						}
2655 					}
2656 					if ( lowestIndex >= 0 )
2657 					{
2658 						int newx = safeTiles.at(lowestIndex).first.first;
2659 						int newy = safeTiles.at(lowestIndex).first.second;
2660 						real_t velx = newx * 16 + 8 - my->x;
2661 						real_t vely = newy * 16 + 8 - my->y;
2662 						// try moving in one direction only.
2663 						if ( newy == y ) // keep y the same
2664 						{
2665 							if ( newx != x )
2666 							{
2667 								if ( barony_clear(newx * 16 + 8, y, my) )
2668 								{
2669 									vely = 0.0;
2670 								}
2671 							}
2672 						}
2673 						else if ( newx == x ) // keep x the same
2674 						{
2675 							if ( newy != y )
2676 							{
2677 								if ( barony_clear(x, newy * 16 + 8, my) )
2678 								{
2679 									velx = 0.0;
2680 								}
2681 							}
2682 						}
2683 						clipMove(&my->x, &my->y, velx, vely, my);
2684 						messagePlayer(PLAYER_NUM, language[3869]);
2685 						if ( PLAYER_NUM == clientnum || splitscreen )
2686 						{
2687 							cameravars[PLAYER_NUM].shakex += .1;
2688 							cameravars[PLAYER_NUM].shakey += 10;
2689 						}
2690 						else if ( PLAYER_NUM != clientnum && multiplayer == SERVER )
2691 						{
2692 							if ( PLAYER_NUM > 0 )
2693 							{
2694 								strcpy((char*)net_packet->data, "SHAK");
2695 								net_packet->data[4] = 10; // turns into .1
2696 								net_packet->data[5] = 10;
2697 								net_packet->address.host = net_clients[PLAYER_NUM - 1].host;
2698 								net_packet->address.port = net_clients[PLAYER_NUM - 1].port;
2699 								net_packet->len = 6;
2700 								sendPacketSafe(net_sock, -1, net_packet, PLAYER_NUM - 1);
2701 							}
2702 						}
2703 					}
2704 					else
2705 					{
2706 						my->setObituary(language[3010]); // fell to their death.
2707 						stats[PLAYER_NUM]->HP = 0; // kill me instantly
2708 						if (stats[PLAYER_NUM]->type == AUTOMATON)
2709 						{
2710 							my->playerAutomatonDeathCounter = TICKS_PER_SECOND * 5; // set the death timer to immediately pop for players.
2711 						}
2712 					}
2713 				}
2714 				else if ( safeTiles.empty() )
2715 				{
2716 					my->setObituary(language[3010]); // fell to their death.
2717 					stats[PLAYER_NUM]->HP = 0; // kill me instantly
2718 					if (stats[PLAYER_NUM]->type == AUTOMATON)
2719 					{
2720 						my->playerAutomatonDeathCounter = TICKS_PER_SECOND * 5; // set the death timer to immediately pop for players.
2721 					}
2722 				}
2723 			}
2724 
2725 		}
2726 	}
2727 	else
2728 	{
2729 		if ( playerRace == INSECTOID && stats[PLAYER_NUM]->EFFECTS[EFF_FLUTTER] && (my->z >= -2.05 && my->z <= -1.95) )
2730 		{
2731 			insectoidLevitating[PLAYER_NUM] = true;
2732 		}
2733 	}
2734 
2735 	// swimming
2736 	bool waterwalkingboots = false;
2737 	if ( stats[PLAYER_NUM]->shoes != NULL )
2738 		if ( stats[PLAYER_NUM]->shoes->type == IRON_BOOTS_WATERWALKING )
2739 		{
2740 			waterwalkingboots = true;
2741 		}
2742 	bool swimming = isPlayerSwimming(my);
2743 	if ( PLAYER_NUM == clientnum || multiplayer == SERVER || splitscreen )
2744 	{
2745 		if ( swimming )
2746 		{
2747 			int x = std::min(std::max<unsigned int>(0, floor(my->x / 16)), map.width - 1);
2748 			int y = std::min(std::max<unsigned int>(0, floor(my->y / 16)), map.height - 1);
2749 			if ( rand() % 400 == 0 && multiplayer != CLIENT )
2750 			{
2751 				my->increaseSkill(PRO_SWIMMING);
2752 			}
2753 			my->z = 7;
2754 			if ( playerRace == SPIDER || playerRace == RAT )
2755 			{
2756 				my->z += 1;
2757 			}
2758 			if ( !PLAYER_INWATER && (PLAYER_NUM == clientnum || splitscreen) )
2759 			{
2760 				PLAYER_INWATER = 1;
2761 				if ( lavatiles[map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height]] )
2762 				{
2763 					messagePlayer(PLAYER_NUM, language[573]);
2764 					if ( stats[PLAYER_NUM]->type == AUTOMATON )
2765 					{
2766 						messagePlayer(PLAYER_NUM, language[3703]);
2767 					}
2768 					cameravars[PLAYER_NUM].shakex += .1;
2769 					cameravars[PLAYER_NUM].shakey += 10;
2770 				}
2771 				else if ( swimmingtiles[map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height]] && stats[PLAYER_NUM]->type == VAMPIRE )
2772 				{
2773 					messagePlayerColor(PLAYER_NUM, SDL_MapRGB(mainsurface->format, 255, 0, 0), language[3183]);
2774 					playSoundPlayer(PLAYER_NUM, 28, 128);
2775 					playSoundPlayer(PLAYER_NUM, 249, 128);
2776 					cameravars[PLAYER_NUM].shakex += .1;
2777 					cameravars[PLAYER_NUM].shakey += 10;
2778 				}
2779 				else if ( swimmingtiles[map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height]] && stats[PLAYER_NUM]->type == AUTOMATON )
2780 				{
2781 					messagePlayer(PLAYER_NUM, language[3702]);
2782 					playSound(136, 128);
2783 				}
2784 				else if ( swimmingtiles[map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height]] )
2785 				{
2786 					playSound(136, 128);
2787 				}
2788 			}
2789 			if ( multiplayer != CLIENT )
2790 			{
2791 				// Check if the Player is in Water or Lava
2792 				if ( swimmingtiles[map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height]] )
2793 				{
2794 					if ( my->flags[BURNING] )
2795 					{
2796 						my->flags[BURNING] = false;
2797 						messagePlayer(PLAYER_NUM, language[574]); // "The water extinguishes the flames!"
2798 						serverUpdateEntityFlag(my, BURNING);
2799 					}
2800 					if ( stats[PLAYER_NUM]->EFFECTS[EFF_POLYMORPH] )
2801 					{
2802 						if ( stats[PLAYER_NUM]->EFFECTS[EFF_POLYMORPH] )
2803 						{
2804 							my->setEffect(EFF_POLYMORPH, false, 0, true);
2805 							my->effectPolymorph = 0;
2806 							serverUpdateEntitySkill(my, 50);
2807 
2808 							messagePlayer(PLAYER_NUM, language[3192]);
2809 							messagePlayer(PLAYER_NUM, language[3185]);
2810 						}
2811 						/*if ( stats[PLAYER_NUM]->EFFECTS[EFF_SHAPESHIFT] )
2812 						{
2813 							my->setEffect(EFF_SHAPESHIFT, false, 0, true);
2814 							my->effectShapeshift = 0;
2815 							serverUpdateEntitySkill(my, 53);
2816 
2817 							messagePlayer(PLAYER_NUM, language[3418]);
2818 							messagePlayer(PLAYER_NUM, language[3417]);
2819 						}*/
2820 						playSoundEntity(my, 400, 92);
2821 						createParticleDropRising(my, 593, 1.f);
2822 						serverSpawnMiscParticles(my, PARTICLE_EFFECT_RISING_DROP, 593);
2823 					}
2824 					if ( stats[PLAYER_NUM]->type == VAMPIRE )
2825 					{
2826 						if ( ticks % 10 == 0 ) // Water deals damage every 10 ticks
2827 						{
2828 							my->modHP(-2 - rand() % 2);
2829 							if ( ticks % 20 == 0 )
2830 							{
2831 								playSoundPlayer(PLAYER_NUM, 28, 92);
2832 							}
2833 							my->setObituary(language[3254]); // "goes for a swim in some water."
2834 							steamAchievementClient(PLAYER_NUM, "BARONY_ACH_BLOOD_BOIL");
2835 						}
2836 					}
2837 					else if ( stats[PLAYER_NUM]->type == AUTOMATON )
2838 					{
2839 						if ( ticks % 10 == 0 ) // Water deals heat damage every 10 ticks
2840 						{
2841 							my->safeConsumeMP(2);
2842 						}
2843 						if ( ticks % 50 == 0 )
2844 						{
2845 							messagePlayer(PLAYER_NUM, language[3702]);
2846 							stats[PLAYER_NUM]->HUNGER -= 25;
2847 							serverUpdateHunger(PLAYER_NUM);
2848 						}
2849 					}
2850 				}
2851 				else if ( ticks % 10 == 0 ) // Lava deals damage every 10 ticks
2852 				{
2853 					my->modHP(-2 - rand() % 2);
2854 					if ( stats[PLAYER_NUM]->type == AUTOMATON )
2855 					{
2856 						my->modMP(2);
2857 						if ( ticks % 50 == 0 )
2858 						{
2859 							messagePlayer(PLAYER_NUM, language[3703]);
2860 							stats[PLAYER_NUM]->HUNGER += 50;
2861 							serverUpdateHunger(PLAYER_NUM);
2862 						}
2863 					}
2864 					my->setObituary(language[1506]); // "goes for a swim in some lava."
2865 					if ( !my->flags[BURNING] )
2866 					{
2867 						// Attempt to set the Entity on fire
2868 						my->SetEntityOnFire();
2869 					}
2870 					if ( stats[PLAYER_NUM]->type == AUTOMATON || stats[PLAYER_NUM]->type == SKELETON )
2871 					{
2872 						if ( ticks % 20 == 0 )
2873 						{
2874 							playSoundPlayer(PLAYER_NUM, 28, 92);
2875 						}
2876 					}
2877 				}
2878 			}
2879 		}
2880 	}
2881 
2882 	if ( !swimming )
2883 	{
2884 		if ( PLAYER_INWATER != 0 )
2885 		{
2886 			PLAYER_INWATER = 0;
2887 			PLAYER_BOBMOVE = 0;
2888 			PLAYER_BOB = 0;
2889 			PLAYER_BOBMODE = 0;
2890 		}
2891 	}
2892 
2893 	if (PLAYER_NUM == clientnum || splitscreen)
2894 	{
2895 		players[PLAYER_NUM]->entity = my;
2896 
2897 		if ( !usecamerasmoothing )
2898 		{
2899 			handlePlayerCameraBobbing(my, PLAYER_NUM, false);
2900 		}
2901 
2902 		// object interaction
2903 		if ( intro == false )
2904 		{
2905 			clickDescription(PLAYER_NUM, NULL); // inspecting objects
2906 
2907 			if ( FollowerMenu.optionSelected == ALLY_CMD_ATTACK_SELECT )
2908 			{
2909 				Entity* underMouse = nullptr;
2910 				if ( FollowerMenu.optionSelected == ALLY_CMD_ATTACK_SELECT && ticks % 10 == 0 )
2911 				{
2912 					if ( !shootmode )
2913 					{
2914 						Uint32 uidnum = GO_GetPixelU32(omousex, yres - omousey, cameras[PLAYER_NUM]);
2915 						if ( uidnum > 0 )
2916 						{
2917 							underMouse = uidToEntity(uidnum);
2918 						}
2919 					}
2920 					else
2921 					{
2922 						Uint32 uidnum = GO_GetPixelU32(xres / 2, yres / 2, cameras[PLAYER_NUM]);
2923 						if ( uidnum > 0 )
2924 						{
2925 							underMouse = uidToEntity(uidnum);
2926 						}
2927 					}
2928 
2929 					if ( underMouse && FollowerMenu.followerToCommand )
2930 					{
2931 						Entity* parent = uidToEntity(underMouse->skill[2]);
2932 						if ( underMouse->behavior == &actMonster || (parent && parent->behavior == &actMonster) )
2933 						{
2934 							// see if we selected a limb
2935 							if ( parent )
2936 							{
2937 								underMouse = parent;
2938 							}
2939 						}
2940 						FollowerMenu.allowedInteractEntity(*underMouse);
2941 					}
2942 					else
2943 					{
2944 						strcpy(FollowerMenu.interactText, "");
2945 					}
2946 				}
2947 			}
2948 
2949 			if ( FollowerMenu.followerToCommand == nullptr && FollowerMenu.selectMoveTo == false )
2950 			{
2951 				bool clickedOnGUI = false;
2952 				selectedEntity = entityClicked(&clickedOnGUI, false, PLAYER_NUM); // using objects
2953 				if ( !selectedEntity && !clickedOnGUI )
2954 				{
2955 					// otherwise if we hold right click we'll keep trying this function, FPS will drop.
2956 					++selectedEntityGimpTimer;
2957 				}
2958 			}
2959 			else
2960 			{
2961 				selectedEntity = NULL;
2962 
2963 				if ( !command && (*inputPressed(impulses[IN_USE]) || *inputPressed(joyimpulses[INJOY_GAME_USE])) )
2964 				{
2965 					if ( !FollowerMenu.menuToggleClick && FollowerMenu.selectMoveTo )
2966 					{
2967 						if ( FollowerMenu.optionSelected == ALLY_CMD_MOVETO_SELECT )
2968 						{
2969 							// we're selecting a point for the ally to move to.
2970 							*inputPressed(impulses[IN_USE]) = 0;
2971 							*inputPressed(joyimpulses[INJOY_GAME_USE]) = 0;
2972 
2973 							int minimapTotalScale = minimapScaleQuickToggle + minimapScale;
2974 							if ( map.height > 64 || map.width > 64 )
2975 							{
2976 								int maxDimension = std::max(map.height, map.width);
2977 								maxDimension -= 64;
2978 								int numMinimapSizesToReduce = 0;
2979 								while ( maxDimension > 0 )
2980 								{
2981 									maxDimension -= 32;
2982 									++numMinimapSizesToReduce;
2983 								}
2984 								minimapTotalScale = std::max(1, minimapScale - numMinimapSizesToReduce) + minimapScaleQuickToggle;
2985 							}
2986 							if ( !shootmode && mouseInBounds(xres - map.width * minimapTotalScale, xres, yres - map.height * minimapTotalScale, yres) ) // mouse within minimap pixels (each map tile is 4 pixels)
2987 							{
2988 								MinimapPing newPing(ticks, -1, (omousex - (xres - map.width * minimapTotalScale)) / minimapTotalScale, (omousey - (yres - map.height * minimapTotalScale)) / minimapTotalScale);
2989 								minimapPingAdd(newPing);
2990 								createParticleFollowerCommand(newPing.x, newPing.y, 0, 174);
2991 								FollowerMenu.optionSelected = ALLY_CMD_MOVETO_CONFIRM;
2992 								FollowerMenu.selectMoveTo = false;
2993 								FollowerMenu.moveToX = static_cast<int>(newPing.x);
2994 								FollowerMenu.moveToY = static_cast<int>(newPing.y);
2995 							}
2996 							else if ( players[PLAYER_NUM] && players[PLAYER_NUM]->entity )
2997 							{
2998 								real_t startx = players[PLAYER_NUM]->entity->x;
2999 								real_t starty = players[PLAYER_NUM]->entity->y;
3000 								real_t startz = -4;
3001 								real_t pitch = players[PLAYER_NUM]->entity->pitch;
3002 								if ( pitch < 0 )
3003 								{
3004 									pitch = 0;
3005 								}
3006 								// draw line from the players height and direction until we hit the ground.
3007 								real_t previousx = startx;
3008 								real_t previousy = starty;
3009 								int index = 0;
3010 								for ( ; startz < 0.f; startz += abs(0.05 * tan(pitch)) )
3011 								{
3012 									startx += 0.1 * cos(players[PLAYER_NUM]->entity->yaw);
3013 									starty += 0.1 * sin(players[PLAYER_NUM]->entity->yaw);
3014 									index = (static_cast<int>(starty + 16 * sin(players[PLAYER_NUM]->entity->yaw)) >> 4) * MAPLAYERS + (static_cast<int>(startx + 16 * cos(players[PLAYER_NUM]->entity->yaw)) >> 4) * MAPLAYERS * map.height;
3015 									if ( map.tiles[index] && !map.tiles[OBSTACLELAYER + index] )
3016 									{
3017 										// store the last known good coordinate
3018 										previousx = startx;
3019 										previousy = starty;
3020 									}
3021 									if ( map.tiles[OBSTACLELAYER + index] )
3022 									{
3023 										break;
3024 									}
3025 								}
3026 
3027 								createParticleFollowerCommand(previousx, previousy, 0, 174);
3028 								FollowerMenu.optionSelected = ALLY_CMD_MOVETO_CONFIRM;
3029 								FollowerMenu.selectMoveTo = false;
3030 								FollowerMenu.moveToX = static_cast<int>(previousx) / 16;
3031 								FollowerMenu.moveToY = static_cast<int>(previousy) / 16;
3032 								//messagePlayer(PLAYER_NUM, "%d, %d, pitch: %f", followerMoveToX, followerMoveToY, players[PLAYER_NUM]->entity->pitch);
3033 							}
3034 						}
3035 						else if ( FollowerMenu.optionSelected == ALLY_CMD_ATTACK_SELECT )
3036 						{
3037 							// we're selecting a target for the ally.
3038 							Entity* target = entityClicked(nullptr, false, PLAYER_NUM);
3039 							*inputPressed(impulses[IN_USE]) = 0;
3040 							*inputPressed(joyimpulses[INJOY_GAME_USE]) = 0;
3041 							if ( target )
3042 							{
3043 								Entity* parent = uidToEntity(target->skill[2]);
3044 								if ( target->behavior == &actMonster || (parent && parent->behavior == &actMonster) )
3045 								{
3046 									// see if we selected a limb
3047 									if ( parent )
3048 									{
3049 										target = parent;
3050 									}
3051 								}
3052 								else if ( target->sprite == 184 ) // switch base.
3053 								{
3054 									parent = uidToEntity(target->parent);
3055 									if ( parent )
3056 									{
3057 										target = parent;
3058 									}
3059 								}
3060 								if ( FollowerMenu.allowedInteractEntity(*target) )
3061 								{
3062 									createParticleFollowerCommand(target->x, target->y, 0, 174);
3063 									FollowerMenu.optionSelected = ALLY_CMD_ATTACK_CONFIRM;
3064 									FollowerMenu.followerToCommand->monsterAllyInteractTarget = target->getUID();
3065 								}
3066 								else
3067 								{
3068 									messagePlayer(clientnum, language[3094]);
3069 									FollowerMenu.optionSelected = ALLY_CMD_CANCEL;
3070 									FollowerMenu.optionPrevious = ALLY_CMD_ATTACK_CONFIRM;
3071 									FollowerMenu.followerToCommand->monsterAllyInteractTarget = 0;
3072 								}
3073 							}
3074 							else
3075 							{
3076 								FollowerMenu.optionSelected = ALLY_CMD_CANCEL;
3077 								FollowerMenu.optionPrevious = ALLY_CMD_ATTACK_CONFIRM;
3078 								FollowerMenu.followerToCommand->monsterAllyInteractTarget = 0;
3079 							}
3080 							FollowerMenu.selectMoveTo = false;
3081 							strcpy(FollowerMenu.interactText, "");
3082 						}
3083 					}
3084 				}
3085 			}
3086 
3087 			if ( !command && !FollowerMenu.followerToCommand && FollowerMenu.recentEntity )
3088 			{
3089 				if ( *inputPressed(impulses[IN_FOLLOWERMENU]) || *inputPressed(joyimpulses[INJOY_GAME_FOLLOWERMENU]) )
3090 				{
3091 					if ( players[PLAYER_NUM] && players[PLAYER_NUM]->entity
3092 						&& FollowerMenu.recentEntity->monsterTarget == players[PLAYER_NUM]->entity->getUID() )
3093 					{
3094 						// your ally is angry at you!
3095 					}
3096 					else
3097 					{
3098 						selectedEntity = FollowerMenu.recentEntity;
3099 						FollowerMenu.holdWheel = true;
3100 					}
3101 				}
3102 				else if ( *inputPressed(impulses[IN_FOLLOWERMENU_LASTCMD]) || *inputPressed(joyimpulses[INJOY_GAME_FOLLOWERMENU_LASTCMD]) )
3103 				{
3104 					if ( players[PLAYER_NUM] && players[PLAYER_NUM]->entity
3105 						&& FollowerMenu.recentEntity->monsterTarget == players[PLAYER_NUM]->entity->getUID() )
3106 					{
3107 						// your ally is angry at you!
3108 						*inputPressed(impulses[IN_FOLLOWERMENU_LASTCMD]) = 0;
3109 						*inputPressed(joyimpulses[INJOY_GAME_FOLLOWERMENU_LASTCMD]) = 0;
3110 					}
3111 					else if ( FollowerMenu.optionPrevious != -1 )
3112 					{
3113 						FollowerMenu.followerToCommand = FollowerMenu.recentEntity;
3114 					}
3115 					else
3116 					{
3117 						*inputPressed(impulses[IN_FOLLOWERMENU_LASTCMD]) = 0;
3118 						*inputPressed(joyimpulses[INJOY_GAME_FOLLOWERMENU_LASTCMD]) = 0;
3119 					}
3120 				}
3121 			}
3122 			if ( selectedEntity != NULL )
3123 			{
3124 				FollowerMenu.followerToCommand = nullptr;
3125 				Entity* parent = uidToEntity(selectedEntity->skill[2]);
3126 				if ( selectedEntity->behavior == &actMonster || (parent && parent->behavior == &actMonster) )
3127 				{
3128 					// see if we selected a follower to process right click menu.
3129 					if ( parent && parent->monsterAllyIndex == PLAYER_NUM )
3130 					{
3131 						FollowerMenu.followerToCommand = parent;
3132 						//messagePlayer(0, "limb");
3133 					}
3134 					else if ( selectedEntity->monsterAllyIndex == PLAYER_NUM )
3135 					{
3136 						FollowerMenu.followerToCommand = selectedEntity;
3137 						//messagePlayer(0, "head");
3138 					}
3139 
3140 					if ( FollowerMenu.followerToCommand )
3141 					{
3142 						if ( players[PLAYER_NUM] && players[PLAYER_NUM]->entity
3143 							&& FollowerMenu.followerToCommand->monsterTarget == players[PLAYER_NUM]->entity->getUID() )
3144 						{
3145 							// your ally is angry at you!
3146 							FollowerMenu.followerToCommand = nullptr;
3147 							FollowerMenu.optionPrevious = -1;
3148 						}
3149 						else
3150 						{
3151 							FollowerMenu.recentEntity = FollowerMenu.followerToCommand;
3152 							FollowerMenu.initFollowerMenuGUICursor(true);
3153 							FollowerMenu.updateScrollPartySheet();
3154 							selectedEntity = NULL;
3155 						}
3156 					}
3157 				}
3158 				if ( selectedEntity )
3159 				{
3160 					*inputPressed(impulses[IN_USE]) = 0;
3161 					*inputPressed(joyimpulses[INJOY_GAME_USE]) = 0;
3162 					bool foundTinkeringKit = false;
3163 					if ( entityDist(my, selectedEntity) <= TOUCHRANGE )
3164 					{
3165 						inrange[PLAYER_NUM] = true;
3166 
3167 						if ( (selectedEntity->behavior == &actItem
3168 							|| selectedEntity->behavior == &actTorch
3169 							|| selectedEntity->behavior == &actCrystalShard)
3170 							&& stats[clientnum] && stats[clientnum]->shield && stats[clientnum]->defending
3171 							&& stats[clientnum]->shield->type == TOOL_TINKERING_KIT )
3172 						{
3173 							foundTinkeringKit = true;
3174 						}
3175 						if ( foundTinkeringKit && (clientnum == 0 || splitscreen) )
3176 						{
3177 							selectedEntity->itemAutoSalvageByPlayer = static_cast<Sint32>(players[PLAYER_NUM]->entity->getUID());
3178 						}
3179 					}
3180 					else
3181 					{
3182 						inrange[PLAYER_NUM] = false;
3183 					}
3184 					if ( multiplayer == CLIENT )
3185 					{
3186 						if ( inrange[PLAYER_NUM] )
3187 						{
3188 							if ( foundTinkeringKit )
3189 							{
3190 								strcpy((char*)net_packet->data, "SALV");
3191 							}
3192 							else
3193 							{
3194 								strcpy((char*)net_packet->data, "CKIR");
3195 								if ( stats[PLAYER_NUM]->type == RAT
3196 									&& selectedEntity->behavior == &actItem
3197 									&& selectedEntity->itemShowOnMap == 1 )
3198 								{
3199 									strcpy((char*)net_packet->data, "RATF");
3200 								}
3201 							}
3202 						}
3203 						else
3204 						{
3205 							strcpy((char*)net_packet->data, "CKOR");
3206 						}
3207 						net_packet->data[4] = PLAYER_NUM;
3208 						if (selectedEntity->behavior == &actPlayerLimb)
3209 						{
3210 							SDLNet_Write32((Uint32)players[selectedEntity->skill[2]]->entity->getUID(), &net_packet->data[5]);
3211 						}
3212 						else
3213 						{
3214 							Entity* tempEntity = uidToEntity(selectedEntity->skill[2]);
3215 							if (tempEntity)
3216 							{
3217 								if (tempEntity->behavior == &actMonster)
3218 								{
3219 									SDLNet_Write32((Uint32)tempEntity->getUID(), &net_packet->data[5]);
3220 								}
3221 								else
3222 								{
3223 									SDLNet_Write32((Uint32)selectedEntity->getUID(), &net_packet->data[5]);
3224 								}
3225 							}
3226 							else
3227 							{
3228 								SDLNet_Write32((Uint32)selectedEntity->getUID(), &net_packet->data[5]);
3229 							}
3230 						}
3231 						net_packet->address.host = net_server.host;
3232 						net_packet->address.port = net_server.port;
3233 						net_packet->len = 9;
3234 						sendPacketSafe(net_sock, -1, net_packet, 0);
3235 					}
3236 				}
3237 			}
3238 		}
3239 	}
3240 
3241 	if (multiplayer != CLIENT)
3242 	{
3243 		for (i = 0; i < MAXPLAYERS; i++)
3244 		{
3245 			if ((i == 0 && selectedEntity == my) || (client_selected[i] == my) || i == PLAYER_CLICKED - 1)
3246 			{
3247 				PLAYER_CLICKED = 0;
3248 				if (inrange[i] && i != PLAYER_NUM)
3249 				{
3250 					messagePlayer(i, language[575], stats[PLAYER_NUM]->name, stats[PLAYER_NUM]->HP, stats[PLAYER_NUM]->MAXHP, stats[PLAYER_NUM]->MP, stats[PLAYER_NUM]->MAXMP);
3251 					messagePlayer(PLAYER_NUM, language[576], stats[i]->name);
3252 					if (PLAYER_NUM == clientnum && players[i] && players[i]->entity)
3253 					{
3254 						double tangent = atan2(my->y - players[i]->entity->y, my->x - players[i]->entity->x);
3255 						PLAYER_VELX += cos(tangent);
3256 						PLAYER_VELY += sin(tangent);
3257 					}
3258 				}
3259 			}
3260 		}
3261 	}
3262 
3263 	// torch light
3264 	if ( !intro )
3265 	{
3266 		if ( multiplayer == SERVER || PLAYER_NUM == clientnum || splitscreen )
3267 		{
3268 			if ( stats[PLAYER_NUM]->shield != NULL && (showEquipment && isHumanoid) && !itemTypeIsQuiver(stats[PLAYER_NUM]->shield->type) )
3269 			{
3270 				if ( PLAYER_NUM == clientnum || splitscreen)
3271 				{
3272 					if ( stats[PLAYER_NUM]->shield->type == TOOL_TORCH )
3273 					{
3274 						PLAYER_TORCH = 7 + my->getPER() / 3 + (stats[PLAYER_NUM]->defending) * 1;
3275 					}
3276 					else if ( stats[PLAYER_NUM]->shield->type == TOOL_LANTERN )
3277 					{
3278 						PLAYER_TORCH = 10 + my->getPER() / 3 + (stats[PLAYER_NUM]->defending) * 1;
3279 					}
3280 					else if ( stats[PLAYER_NUM]->shield->type == TOOL_CRYSTALSHARD )
3281 					{
3282 						PLAYER_TORCH = 5 + my->getPER() / 3 + (stats[PLAYER_NUM]->defending) * 2;
3283 					}
3284 					else if ( !PLAYER_DEBUGCAM )
3285 					{
3286 						PLAYER_TORCH = 3 + my->getPER() / 3;
3287 					}
3288 					else
3289 					{
3290 						PLAYER_TORCH = 0;
3291 					}
3292 				}
3293 				else
3294 				{
3295 					if ( stats[PLAYER_NUM]->shield->type == TOOL_TORCH )
3296 					{
3297 						PLAYER_TORCH = 7;
3298 					}
3299 					else if ( stats[PLAYER_NUM]->shield->type == TOOL_LANTERN )
3300 					{
3301 						PLAYER_TORCH = 10;
3302 					}
3303 					else if ( stats[PLAYER_NUM]->shield->type == TOOL_CRYSTALSHARD )
3304 					{
3305 						PLAYER_TORCH = 5;
3306 					}
3307 					else
3308 					{
3309 						PLAYER_TORCH = 0;
3310 					}
3311 				}
3312 			}
3313 			else
3314 			{
3315 				if ( (PLAYER_NUM == clientnum || splitscreen) && !PLAYER_DEBUGCAM )
3316 				{
3317 					PLAYER_TORCH = 3 + (my->getPER() / 3);
3318 					if ( playerRace == RAT )
3319 					{
3320 						PLAYER_TORCH += 3;
3321 					}
3322 					else if ( playerRace == SPIDER )
3323 					{
3324 						PLAYER_TORCH += 2;
3325 					}
3326 					// more visible world if defending/sneaking with no shield
3327 					PLAYER_TORCH += ((stats[PLAYER_NUM]->sneaking == 1) * (2 + (stats[PLAYER_NUM]->PROFICIENCIES[PRO_STEALTH] / 40)));
3328 				}
3329 				else
3330 				{
3331 					PLAYER_TORCH = 0;
3332 				}
3333 			}
3334 		}
3335 	}
3336 	else
3337 	{
3338 		PLAYER_TORCH = 0;
3339 	}
3340 
3341 	my->removeLightField();
3342 
3343 	if ( PLAYER_TORCH && my->light == NULL )
3344 	{
3345 		my->light = lightSphereShadow(my->x / 16, my->y / 16, PLAYER_TORCH, 50 + 15 * PLAYER_TORCH);
3346 	}
3347 
3348 	// server controls players primarily
3349 	if ( PLAYER_NUM == clientnum || multiplayer == SERVER || splitscreen )
3350 	{
3351 		// set head model
3352 		if ( playerRace != HUMAN )
3353 		{
3354 			if ( playerRace == SKELETON )
3355 			{
3356 				my->sprite = 686;
3357 			}
3358 			else if ( playerRace == RAT )
3359 			{
3360 				my->sprite = 814;
3361 			}
3362 			else if ( playerRace == TROLL )
3363 			{
3364 				my->sprite = 817;
3365 			}
3366 			else if ( playerRace == SPIDER )
3367 			{
3368 				my->sprite = 823;
3369 			}
3370 			else if ( playerRace == CREATURE_IMP )
3371 			{
3372 				my->sprite = 827;
3373 			}
3374 			else if ( playerRace == GOBLIN )
3375 			{
3376 				if ( stats[PLAYER_NUM]->sex == FEMALE )
3377 				{
3378 					my->sprite = 752;
3379 				}
3380 				else
3381 				{
3382 					my->sprite = 694;
3383 				}
3384 			}
3385 			else if ( playerRace == INCUBUS )
3386 			{
3387 				my->sprite = 702;
3388 			}
3389 			else if ( playerRace == SUCCUBUS )
3390 			{
3391 				my->sprite = 710;
3392 			}
3393 			else if ( playerRace == VAMPIRE )
3394 			{
3395 				if ( stats[PLAYER_NUM]->sex == FEMALE )
3396 				{
3397 					my->sprite = 756;
3398 				}
3399 				else
3400 				{
3401 					my->sprite = 718;
3402 				}
3403 			}
3404 			else if ( playerRace == INSECTOID )
3405 			{
3406 				if ( stats[PLAYER_NUM]->sex == FEMALE )
3407 				{
3408 					my->sprite = 760;
3409 				}
3410 				else
3411 				{
3412 					my->sprite = 726;
3413 				}
3414 			}
3415 			else if ( playerRace == GOATMAN )
3416 			{
3417 				if ( stats[PLAYER_NUM]->sex == FEMALE )
3418 				{
3419 					my->sprite = 768;
3420 				}
3421 				else
3422 				{
3423 					my->sprite = 734;
3424 				}
3425 			}
3426 			else if ( playerRace == AUTOMATON )
3427 			{
3428 				if ( stats[PLAYER_NUM]->sex == FEMALE )
3429 				{
3430 					my->sprite = 770;
3431 				}
3432 				else
3433 				{
3434 					my->sprite = 742;
3435 				}
3436 			}
3437 		}
3438 		else if ( playerAppearance < 5 )
3439 		{
3440 			my->sprite = 113 + 12 * stats[PLAYER_NUM]->sex + playerAppearance;
3441 		}
3442 		else if ( playerAppearance == 5 )
3443 		{
3444 			my->sprite = 332 + stats[PLAYER_NUM]->sex;
3445 		}
3446 		else if ( playerAppearance >= 6 && playerAppearance < 12 )
3447 		{
3448 			my->sprite = 341 + stats[PLAYER_NUM]->sex * 13 + playerAppearance - 6;
3449 		}
3450 		else if ( playerAppearance >= 12 )
3451 		{
3452 			my->sprite = 367 + stats[PLAYER_NUM]->sex * 13 + playerAppearance - 12;
3453 		}
3454 		else
3455 		{
3456 			my->sprite = 113; // default
3457 		}
3458 	}
3459 	if ( multiplayer != CLIENT )
3460 	{
3461 		// remove client entities that should no longer exist
3462 		if ( !intro )
3463 		{
3464 			my->handleEffects(stats[PLAYER_NUM]); // hunger, regaining hp/mp, poison, etc.
3465 
3466 			if ( client_disconnected[PLAYER_NUM] || stats[PLAYER_NUM]->HP <= 0 )
3467 			{
3468 				bool doDeathProcedure = true;
3469 				if ( client_disconnected[PLAYER_NUM] )
3470 				{
3471 					doDeathProcedure = true;
3472 				}
3473 				else if ( stats[PLAYER_NUM]->type == AUTOMATON && !client_disconnected[PLAYER_NUM] && stats[PLAYER_NUM]->HP <= 0 )
3474 				{
3475 					// delay death. (not via disconnection).
3476 					if ( PLAYER_DEATH_AUTOMATON == 0 )
3477 					{
3478 						my->flags[PASSABLE] = true;
3479 						serverUpdateEntityFlag(my, PASSABLE);
3480 						if ( clientnum == PLAYER_NUM || splitscreen )
3481 						{
3482 							// deathcam
3483 							entity = newEntity(-1, 1, map.entities, nullptr); //Deathcam entity.
3484 							entity->x = my->x;
3485 							entity->y = my->y;
3486 							entity->z = -2;
3487 							entity->flags[NOUPDATE] = true;
3488 							entity->flags[PASSABLE] = true;
3489 							entity->flags[INVISIBLE] = true;
3490 							entity->behavior = &actDeathCam;
3491 							entity->skill[2] = PLAYER_NUM;
3492 							entity->yaw = my->yaw;
3493 							entity->pitch = PI / 8;
3494 							my->playerCreatedDeathCam = 1;
3495 						}
3496 						createParticleExplosionCharge(my, 174, 100, 0.25);
3497 						serverSpawnMiscParticles(my, PARTICLE_EFFECT_PLAYER_AUTOMATON_DEATH, 174);
3498 						playSoundEntity(my, 263, 128);
3499 						playSoundEntity(my, 321, 128);
3500 					}
3501 					++PLAYER_DEATH_AUTOMATON;
3502 					if ( PLAYER_DEATH_AUTOMATON >= TICKS_PER_SECOND * 2 )
3503 					{
3504 						doDeathProcedure = true;
3505 						spawnExplosion(my->x, my->y, my->z);
3506 						playSoundEntity(my, 260 + rand() % 2, 128);
3507 						my->attack(MONSTER_POSE_AUTOMATON_MALFUNCTION, 0, my);
3508 					}
3509 					else
3510 					{
3511 						doDeathProcedure = false;
3512 					}
3513 				}
3514 				if ( doDeathProcedure )
3515 				{
3516 					// remove body parts
3517 					node_t* nextnode;
3518 					for ( node = my->children.first, i = 0; node != NULL; node = nextnode, i++ )
3519 					{
3520 						nextnode = node->next;
3521 						if ( i == 0 )
3522 						{
3523 							continue;
3524 						}
3525 						if ( node->element )
3526 						{
3527 							Entity* tempEntity = (Entity*)node->element;
3528 							if ( tempEntity )
3529 							{
3530 								list_RemoveNode(tempEntity->mynode);
3531 							}
3532 							if ( i > 28 )
3533 							{
3534 								break;
3535 							}
3536 						}
3537 					}
3538 					if ( stats[PLAYER_NUM]->HP <= 0 )
3539 					{
3540 						// die //TODO: Refactor.
3541 						playSoundEntity(my, 28, 128);
3542 						for ( i = 0; i < 5; i++ )
3543 						{
3544 							Entity* gib = spawnGib(my);
3545 							serverSpawnGibForClient(gib);
3546 						}
3547 						if ( spawn_blood )
3548 						{
3549 							if ( !checkObstacle(my->x, my->y, my, NULL) )
3550 							{
3551 								int x, y;
3552 								x = std::min(std::max<unsigned int>(0, my->x / 16), map.width - 1);
3553 								y = std::min(std::max<unsigned int>(0, my->y / 16), map.height - 1);
3554 								if ( map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height] )
3555 								{
3556 									entity = newEntity(160, 1, map.entities, nullptr); //Limb entity.
3557 									entity->x = my->x;
3558 									entity->y = my->y;
3559 									entity->z = 8.0 + (rand() % 20) / 100.0;
3560 									entity->parent = my->getUID();
3561 									entity->sizex = 2;
3562 									entity->sizey = 2;
3563 									entity->yaw = (rand() % 360) * PI / 180.0;
3564 									entity->flags[UPDATENEEDED] = true;
3565 									entity->flags[PASSABLE] = true;
3566 								}
3567 							}
3568 						}
3569 						node_t* spellnode;
3570 						spellnode = stats[PLAYER_NUM]->magic_effects.first;
3571 						while ( spellnode )
3572 						{
3573 							node_t* oldnode = spellnode;
3574 							spellnode = spellnode->next;
3575 							spell_t* spell = (spell_t*)oldnode->element;
3576 							spell->magic_effects_node = NULL;
3577 							list_RemoveNode(oldnode);
3578 						}
3579 						int c;
3580 						for ( c = 0; c < MAXPLAYERS; c++ )
3581 						{
3582 							if ( client_disconnected[c] )
3583 							{
3584 								continue;
3585 							}
3586 							char whatever[256];
3587 							snprintf(whatever, 255, "%s %s", stats[PLAYER_NUM]->name, stats[PLAYER_NUM]->obituary); //Potential snprintf of 256 bytes into 255 byte destination
3588 							messagePlayer(c, whatever);
3589 						}
3590 						Uint32 color = SDL_MapRGB(mainsurface->format, 255, 0, 0);
3591 						messagePlayerColor(PLAYER_NUM, color, language[577]);
3592 
3593 						for ( node_t* node = stats[PLAYER_NUM]->FOLLOWERS.first; node != nullptr; node = nextnode )
3594 						{
3595 							nextnode = node->next;
3596 							Uint32* c = (Uint32*)node->element;
3597 							Entity* myFollower = nullptr;
3598 							if ( c )
3599 							{
3600 								myFollower = uidToEntity(*c);
3601 							}
3602 							if ( myFollower )
3603 							{
3604 								if ( myFollower->monsterAllySummonRank != 0 )
3605 								{
3606 									myFollower->setMP(0);
3607 									myFollower->setHP(0); // rip
3608 								}
3609 								else if ( myFollower->flags[USERFLAG2] )
3610 								{
3611 									// our leader died, let's undo the color change since we're now rabid.
3612 									myFollower->flags[USERFLAG2] = false;
3613 									serverUpdateEntityFlag(myFollower, USERFLAG2);
3614 
3615 									int bodypart = 0;
3616 									for ( node_t* node = myFollower->children.first; node != nullptr; node = node->next )
3617 									{
3618 										if ( bodypart >= LIMB_HUMANOID_TORSO )
3619 										{
3620 											Entity* tmp = (Entity*)node->element;
3621 											if ( tmp )
3622 											{
3623 												tmp->flags[USERFLAG2] = false;
3624 											}
3625 										}
3626 										++bodypart;
3627 									}
3628 
3629 									Stat* followerStats = myFollower->getStats();
3630 									if ( followerStats )
3631 									{
3632 										followerStats->leader_uid = 0;
3633 									}
3634 									list_RemoveNode(node);
3635 									if ( PLAYER_NUM != clientnum && !splitscreen )
3636 									{
3637 										serverRemoveClientFollower(PLAYER_NUM, myFollower->getUID());
3638 									}
3639 								}
3640 							}
3641 						}
3642 
3643 						/* //TODO: Eventually.
3644 						{
3645 							strcpy((char *)net_packet->data,"UDIE");
3646 							net_packet->address.host = net_clients[player-1].host;
3647 							net_packet->address.port = net_clients[player-1].port;
3648 							net_packet->len = 4;
3649 							sendPacketSafe(net_sock, -1, net_packet, player-1);
3650 						}
3651 						*/
3652 						if ( clientnum == PLAYER_NUM || splitscreen )
3653 						{
3654 							if ( (stats[PLAYER_NUM]->type != AUTOMATON)
3655 								|| (stats[PLAYER_NUM]->type == AUTOMATON && my->playerCreatedDeathCam == 0) )
3656 							{
3657 								// deathcam
3658 								entity = newEntity(-1, 1, map.entities, nullptr); //Deathcam entity.
3659 								entity->x = my->x;
3660 								entity->y = my->y;
3661 								entity->z = -2;
3662 								entity->flags[NOUPDATE] = true;
3663 								entity->flags[PASSABLE] = true;
3664 								entity->flags[INVISIBLE] = true;
3665 								entity->behavior = &actDeathCam;
3666 								entity->skill[2] = PLAYER_NUM;
3667 								entity->yaw = my->yaw;
3668 								entity->pitch = PI / 8;
3669 							}
3670 							node_t* nextnode;
3671 
3672 							if ( gameModeManager.getMode() == GameModeManager_t::GAME_MODE_DEFAULT )
3673 							{
3674 								if ( multiplayer == SINGLE )
3675 								{
3676 									deleteSaveGame(multiplayer); // stops save scumming c:
3677 								}
3678 								else
3679 								{
3680 									deleteMultiplayerSaveGames(); //Will only delete save games if was last player alive.
3681 								}
3682 							}
3683 
3684 							closeBookGUI();
3685 
3686 #ifdef SOUND
3687 							levelmusicplaying = true;
3688 							combatmusicplaying = false;
3689 							fadein_increment = default_fadein_increment * 4;
3690 							fadeout_increment = default_fadeout_increment * 4;
3691 							if ( gameModeManager.getMode() == GameModeManager_t::GAME_MODE_TUTORIAL )
3692 							{
3693 								playmusic(tutorialmusic, true, true, true);
3694 							}
3695 							playmusic(sounds[209], false, true, false);
3696 #endif
3697 							combat = false;
3698 
3699 							if ( PLAYER_NUM == clientnum
3700 								&& gameModeManager.getMode() == GameModeManager_t::GAME_MODE_TUTORIAL )
3701 							{
3702 								if ( !strncmp(map.name, "Tutorial Hub", 12) )
3703 								{
3704 									steamAchievement("BARONY_ACH_EXPELLED");
3705 								}
3706 								else
3707 								{
3708 									steamAchievement("BARONY_ACH_TEACHABLE_MOMENT");
3709 								}
3710 							}
3711 
3712 							if ( multiplayer == SINGLE || !(svFlags & SV_FLAG_KEEPINVENTORY) )
3713 							{
3714 								for ( node = stats[PLAYER_NUM]->inventory.first; node != nullptr; node = nextnode )
3715 								{
3716 									nextnode = node->next;
3717 									Item* item = (Item*)node->element;
3718 									if ( itemCategory(item) == SPELL_CAT )
3719 									{
3720 										continue;    // don't drop spells on death, stupid!
3721 									}
3722 									if ( item->type >= ARTIFACT_SWORD && item->type <= ARTIFACT_GLOVES )
3723 									{
3724 										if ( itemIsEquipped(item, clientnum) )
3725 										{
3726 											steamAchievement("BARONY_ACH_CHOSEN_ONE");
3727 										}
3728 									}
3729 									int c = item->count;
3730 									for ( c = item->count; c > 0; c-- )
3731 									{
3732 										entity = newEntity(-1, 1, map.entities, nullptr); //Item entity.
3733 										entity->flags[INVISIBLE] = true;
3734 										entity->flags[UPDATENEEDED] = true;
3735 										entity->x = my->x;
3736 										entity->y = my->y;
3737 										entity->sizex = 4;
3738 										entity->sizey = 4;
3739 										entity->yaw = (rand() % 360) * (PI / 180.f);
3740 										entity->vel_x = (rand() % 20 - 10) / 10.0;
3741 										entity->vel_y = (rand() % 20 - 10) / 10.0;
3742 										entity->vel_z = -.5;
3743 										entity->flags[PASSABLE] = true;
3744 										entity->flags[USERFLAG1] = true;
3745 										entity->behavior = &actItem;
3746 										entity->skill[10] = item->type;
3747 										entity->skill[11] = item->status;
3748 										entity->skill[12] = item->beatitude;
3749 										int qtyToDrop = 1;
3750 										if ( c >= 10 && (item->type == TOOL_METAL_SCRAP || item->type == TOOL_MAGIC_SCRAP) )
3751 										{
3752 											qtyToDrop = 10;
3753 											c -= 9;
3754 										}
3755 										else if ( itemTypeIsQuiver(item->type) )
3756 										{
3757 											qtyToDrop = item->count;
3758 											c -= item->count;
3759 										}
3760 										entity->skill[13] = qtyToDrop;
3761 										entity->skill[14] = item->appearance;
3762 										entity->skill[15] = item->identified;
3763 									}
3764 								}
3765 								if ( multiplayer != SINGLE )
3766 								{
3767 									for ( node = stats[PLAYER_NUM]->inventory.first; node != nullptr; node = nextnode )
3768 									{
3769 										nextnode = node->next;
3770 										Item* item = (Item*)node->element;
3771 										if ( itemCategory(item) == SPELL_CAT )
3772 										{
3773 											continue;    // don't drop spells on death, stupid!
3774 										}
3775 										list_RemoveNode(node);
3776 									}
3777 									stats[0]->helmet = NULL;
3778 									stats[0]->breastplate = NULL;
3779 									stats[0]->gloves = NULL;
3780 									stats[0]->shoes = NULL;
3781 									stats[0]->shield = NULL;
3782 									stats[0]->weapon = NULL;
3783 									stats[0]->cloak = NULL;
3784 									stats[0]->amulet = NULL;
3785 									stats[0]->ring = NULL;
3786 									stats[0]->mask = NULL;
3787 								}
3788 							}
3789 							else
3790 							{
3791 								// to not soft lock at Herx
3792 								for ( node = stats[PLAYER_NUM]->inventory.first; node != nullptr; node = nextnode )
3793 								{
3794 									nextnode = node->next;
3795 									Item* item = (Item*)node->element;
3796 									if ( item->type == ARTIFACT_ORB_PURPLE )
3797 									{
3798 										int c = item->count;
3799 										for ( c = item->count; c > 0; c-- )
3800 										{
3801 											entity = newEntity(-1, 1, map.entities, nullptr); //Item entity.
3802 											entity->flags[INVISIBLE] = true;
3803 											entity->flags[UPDATENEEDED] = true;
3804 											entity->x = my->x;
3805 											entity->y = my->y;
3806 											entity->sizex = 4;
3807 											entity->sizey = 4;
3808 											entity->yaw = (rand() % 360) * (PI / 180.f);
3809 											entity->vel_x = (rand() % 20 - 10) / 10.0;
3810 											entity->vel_y = (rand() % 20 - 10) / 10.0;
3811 											entity->vel_z = -.5;
3812 											entity->flags[PASSABLE] = true;
3813 											entity->flags[USERFLAG1] = true;
3814 											entity->behavior = &actItem;
3815 											entity->skill[10] = item->type;
3816 											entity->skill[11] = item->status;
3817 											entity->skill[12] = item->beatitude;
3818 											entity->skill[13] = 1;
3819 											entity->skill[14] = item->appearance;
3820 											entity->skill[15] = item->identified;
3821 										}
3822 										break;
3823 									}
3824 								}
3825 							}
3826 							for ( node_t* mapNode = map.creatures->first; mapNode != nullptr; mapNode = mapNode->next )
3827 							{
3828 								Entity* mapCreature = (Entity*)mapNode->element;
3829 								if ( mapCreature )
3830 								{
3831 									mapCreature->monsterEntityRenderAsTelepath = 0; // do a final pass to undo any telepath rendering.
3832 								}
3833 							}
3834 						}
3835 						else
3836 						{
3837 							if ( !(svFlags & SV_FLAG_KEEPINVENTORY) )
3838 							{
3839 								my->x = ((int)(my->x / 16)) * 16 + 8;
3840 								my->y = ((int)(my->y / 16)) * 16 + 8;
3841 								item = stats[PLAYER_NUM]->helmet;
3842 								if ( item )
3843 								{
3844 									int c = item->count;
3845 									for ( c = item->count; c > 0; c-- )
3846 									{
3847 										dropItemMonster(item, my, stats[PLAYER_NUM]);
3848 									}
3849 								}
3850 								item = stats[PLAYER_NUM]->breastplate;
3851 								if ( item )
3852 								{
3853 									int c = item->count;
3854 									for ( c = item->count; c > 0; c-- )
3855 									{
3856 										dropItemMonster(item, my, stats[PLAYER_NUM]);
3857 									}
3858 								}
3859 								item = stats[PLAYER_NUM]->gloves;
3860 								if ( item )
3861 								{
3862 									int c = item->count;
3863 									for ( c = item->count; c > 0; c-- )
3864 									{
3865 										dropItemMonster(item, my, stats[PLAYER_NUM]);
3866 									}
3867 								}
3868 								item = stats[PLAYER_NUM]->shoes;
3869 								if ( item )
3870 								{
3871 									int c = item->count;
3872 									for ( c = item->count; c > 0; c-- )
3873 									{
3874 										dropItemMonster(item, my, stats[PLAYER_NUM]);
3875 									}
3876 								}
3877 								item = stats[PLAYER_NUM]->shield;
3878 								if ( item )
3879 								{
3880 									if ( itemTypeIsQuiver(item->type) )
3881 									{
3882 										dropItemMonster(item, my, stats[PLAYER_NUM], item->count);
3883 									}
3884 									else
3885 									{
3886 										int c = item->count;
3887 										for ( c = item->count; c > 0; c-- )
3888 										{
3889 											dropItemMonster(item, my, stats[PLAYER_NUM]);
3890 										}
3891 									}
3892 								}
3893 								item = stats[PLAYER_NUM]->weapon;
3894 								if ( item )
3895 								{
3896 									int c = item->count;
3897 									for ( c = item->count; c > 0; c-- )
3898 									{
3899 										dropItemMonster(item, my, stats[PLAYER_NUM]);
3900 									}
3901 								}
3902 								item = stats[PLAYER_NUM]->cloak;
3903 								if ( item )
3904 								{
3905 									int c = item->count;
3906 									for ( c = item->count; c > 0; c-- )
3907 									{
3908 										dropItemMonster(item, my, stats[PLAYER_NUM]);
3909 									}
3910 								}
3911 								item = stats[PLAYER_NUM]->amulet;
3912 								if ( item )
3913 								{
3914 									int c = item->count;
3915 									for ( c = item->count; c > 0; c-- )
3916 									{
3917 										dropItemMonster(item, my, stats[PLAYER_NUM]);
3918 									}
3919 								}
3920 								item = stats[PLAYER_NUM]->ring;
3921 								if ( item )
3922 								{
3923 									int c = item->count;
3924 									for ( c = item->count; c > 0; c-- )
3925 									{
3926 										dropItemMonster(item, my, stats[PLAYER_NUM]);
3927 									}
3928 								}
3929 								item = stats[PLAYER_NUM]->mask;
3930 								if ( item )
3931 								{
3932 									int c = item->count;
3933 									for ( c = item->count; c > 0; c-- )
3934 									{
3935 										dropItemMonster(item, my, stats[PLAYER_NUM]);
3936 									}
3937 								}
3938 								list_FreeAll(&stats[PLAYER_NUM]->inventory);
3939 							}
3940 
3941 							deleteMultiplayerSaveGames(); //Will only delete save games if was last player alive.
3942 						}
3943 
3944 						assailant[PLAYER_NUM] = false;
3945 						assailantTimer[PLAYER_NUM] = 0;
3946 
3947 						if ( multiplayer != SINGLE )
3948 						{
3949 							messagePlayer(PLAYER_NUM, language[578]);
3950 						}
3951 					}
3952 					my->removeLightField();
3953 					list_RemoveNode(my->mynode);
3954 					return;
3955 				}
3956 			}
3957 			else
3958 			{
3959 				my->playerCreatedDeathCam = 0;
3960 				PLAYER_DEATH_AUTOMATON = 0;
3961 			}
3962 		}
3963 	}
3964 
3965 	if ( (PLAYER_NUM == clientnum || splitscreen) && intro == false )
3966 	{
3967 		// effects of drunkenness
3968 		if ( (stats[PLAYER_NUM]->EFFECTS[EFF_DRUNK] && (stats[PLAYER_NUM]->type != GOATMAN))
3969 			|| stats[PLAYER_NUM]->EFFECTS[EFF_WITHDRAWAL] )
3970 		{
3971 			CHAR_DRUNK++;
3972 			int drunkInterval = 180;
3973 			if ( stats[PLAYER_NUM]->EFFECTS[EFF_WITHDRAWAL] )
3974 			{
3975 				if ( PLAYER_ALIVETIME < 800 )
3976 				{
3977 					drunkInterval = 300;
3978 				}
3979 				else
3980 				{
3981 					drunkInterval = TICKS_PER_SECOND * 30;
3982 				}
3983 			}
3984 
3985 			if ( CHAR_DRUNK >= drunkInterval )
3986 			{
3987 				CHAR_DRUNK = 0;
3988 				messagePlayer(PLAYER_NUM, language[579]);
3989 				cameravars[PLAYER_NUM].shakex -= .04;
3990 				cameravars[PLAYER_NUM].shakey -= 5;
3991 			}
3992 		}
3993 
3994 		if ( !my->isMobile() )
3995 		{
3996 			if ( (clientnum == PLAYER_NUM || splitscreen) && openedChest[PLAYER_NUM] )
3997 			{
3998 				openedChest[PLAYER_NUM]->closeChest();
3999 			}
4000 		}
4001 
4002 		if ( PLAYER_DEATH_AUTOMATON > 0 )
4003 		{
4004 			if ( my->pitch < PI / 3 || my->pitch > 5 * PI / 3 )
4005 			{
4006 				limbAnimateToLimit(my, ANIMATE_PITCH, 0.01, PI / 3, true, 0.005);
4007 			}
4008 		}
4009 
4010 		if ( !usecamerasmoothing )
4011 		{
4012 			handlePlayerMovement(my, PLAYER_NUM, false);
4013 			handlePlayerCameraUpdate(my, PLAYER_NUM, false);
4014 		}
4015 
4016 		// send movement updates to server
4017 		if ( multiplayer == CLIENT )
4018 		{
4019 			strcpy((char*)net_packet->data, "PMOV");
4020 			net_packet->data[4] = clientnum;
4021 			net_packet->data[5] = currentlevel;
4022 			SDLNet_Write16((Sint16)(my->x * 32), &net_packet->data[6]);
4023 			SDLNet_Write16((Sint16)(my->y * 32), &net_packet->data[8]);
4024 			SDLNet_Write16((Sint16)(PLAYER_VELX * 128), &net_packet->data[10]);
4025 			SDLNet_Write16((Sint16)(PLAYER_VELY * 128), &net_packet->data[12]);
4026 			SDLNet_Write16((Sint16)(my->yaw * 128), &net_packet->data[14]);
4027 			SDLNet_Write16((Sint16)(my->pitch * 128), &net_packet->data[16]);
4028 			net_packet->data[18] = secretlevel;
4029 			net_packet->address.host = net_server.host;
4030 			net_packet->address.port = net_server.port;
4031 			net_packet->len = 19;
4032 			sendPacket(net_sock, -1, net_packet, 0);
4033 		}
4034 
4035 		// move
4036 		if ( noclip == false )
4037 		{
4038 			// perform collision detection
4039 			dist = clipMove(&my->x, &my->y, PLAYER_VELX, PLAYER_VELY, my);
4040 
4041 			// bumping into monsters disturbs them
4042 			if ( hit.entity && !everybodyfriendly && multiplayer != CLIENT )
4043 			{
4044 				if ( hit.entity->behavior == &actMonster )
4045 				{
4046 					bool enemy = my->checkEnemy(hit.entity);
4047 					if ( enemy )
4048 					{
4049 						if ( hit.entity->monsterState == MONSTER_STATE_WAIT || (hit.entity->monsterState == MONSTER_STATE_HUNT && hit.entity->monsterTarget == 0) )
4050 						{
4051 							double tangent = atan2( my->y - hit.entity->y, my->x - hit.entity->x );
4052 							hit.entity->skill[4] = 1;
4053 							hit.entity->skill[6] = rand() % 10 + 1;
4054 							hit.entity->fskill[4] = tangent;
4055 						}
4056 					}
4057 				}
4058 				else if ( stats[PLAYER_NUM]->EFFECTS[EFF_DASH] && hit.entity->behavior == &actDoor )
4059 				{
4060 					hit.entity->doorHealth = 0;
4061 				}
4062 			}
4063 		}
4064 		else
4065 		{
4066 			// no collision detection
4067 			my->x += PLAYER_VELX;
4068 			my->y += PLAYER_VELY;
4069 			dist = sqrt(PLAYER_VELX * PLAYER_VELX + PLAYER_VELY * PLAYER_VELY);
4070 		}
4071 	}
4072 
4073 	if ( PLAYER_NUM != clientnum && multiplayer == SERVER )
4074 	{
4075 		// PLAYER_VEL* skills updated by messages sent to server from client
4076 
4077 		// move (dead reckoning)
4078 		if ( noclip == false )
4079 		{
4080 			// from PMOV in serverHandlePacket - new_x and new_y are accumulated positions
4081 			if ( my->new_x > 0.001 )
4082 			{
4083 				my->x = my->new_x;
4084 			}
4085 			if ( my->new_y > 0.001 )
4086 			{
4087 				my->y = my->new_y;
4088 			}
4089 
4090 			dist = clipMove(&my->x, &my->y, PLAYER_VELX, PLAYER_VELY, my);
4091 
4092 			// bumping into monsters disturbs them
4093 			if ( hit.entity )
4094 			{
4095 				if ( hit.entity->behavior == &actMonster )
4096 				{
4097 					bool enemy = my->checkEnemy(hit.entity);
4098 					if ( enemy )
4099 					{
4100 						if ( hit.entity->monsterState == MONSTER_STATE_WAIT || (hit.entity->monsterState == MONSTER_STATE_HUNT && hit.entity->monsterTarget == 0) )
4101 						{
4102 							double tangent = atan2( my->y - hit.entity->y, my->x - hit.entity->x );
4103 							hit.entity->skill[4] = 1;
4104 							hit.entity->skill[6] = rand() % 10 + 1;
4105 							hit.entity->fskill[4] = tangent;
4106 						}
4107 					}
4108 				}
4109 				else if ( stats[PLAYER_NUM]->EFFECTS[EFF_DASH] && hit.entity->behavior == &actDoor )
4110 				{
4111 					hit.entity->doorHealth = 0;
4112 				}
4113 			}
4114 		}
4115 		else
4116 		{
4117 			my->x += PLAYER_VELX;
4118 			my->y += PLAYER_VELY;
4119 			dist = sqrt(PLAYER_VELX * PLAYER_VELX + PLAYER_VELY * PLAYER_VELY);
4120 		}
4121 	}
4122 
4123 	if ( PLAYER_NUM != clientnum && multiplayer == CLIENT )
4124 	{
4125 		dist = sqrt(PLAYER_VELX * PLAYER_VELX + PLAYER_VELY * PLAYER_VELY);
4126 	}
4127 
4128 	if ( (PLAYER_NUM == clientnum || splitscreen) && ticks % 65 == 0 )
4129 	{
4130 		for ( node_t* mapNode = map.creatures->first; mapNode != nullptr; mapNode = mapNode->next )
4131 		{
4132 			Entity* mapCreature = (Entity*)mapNode->element;
4133 			if ( mapCreature )
4134 			{
4135 				if ( stats[PLAYER_NUM]->EFFECTS[EFF_TELEPATH] )
4136 				{
4137 					// periodically set the telepath rendering flag.
4138 					mapCreature->monsterEntityRenderAsTelepath = 1;
4139 				}
4140 				else
4141 				{
4142 					mapCreature->monsterEntityRenderAsTelepath = 0;
4143 				}
4144 			}
4145 		}
4146 	}
4147 
4148 	Entity* helmet = nullptr;
4149 
4150 	// move bodyparts
4151 	if ( isHumanoid )
4152 	{
4153 		for ( bodypart = 0, node = my->children.first; node != NULL; node = node->next, bodypart++ )
4154 		{
4155 			if ( bodypart == 0 )
4156 			{
4157 				// hudweapon case
4158 				continue;
4159 			}
4160 			entity = (Entity*)node->element;
4161 			entity->x = my->x;
4162 			entity->y = my->y;
4163 			entity->z = my->z;
4164 
4165 			if ( bodypart < 9 ) // don't shift helm/mask.
4166 			{
4167 				// these monsters are shorter than humans so extend the limbs down to floor, gives longer neck.
4168 				if ( playerRace == GOBLIN || playerRace == INSECTOID || playerRace == GOATMAN )
4169 				{
4170 					entity->z += 0.5;
4171 				}
4172 				else if ( playerRace == SKELETON || playerRace == AUTOMATON )
4173 				{
4174 					entity->z += 0.25;
4175 				}
4176 			}
4177 
4178 			if ( bodypart > 12 )
4179 			{
4180 				entity->flags[INVISIBLE] = true;
4181 				continue;
4182 			}
4183 
4184 			entity->yaw = my->yaw;
4185 			if ( bodypart == 2 || bodypart == 5 ) // right leg, left arm
4186 			{
4187 				if ( bodypart == 2 )
4188 				{
4189 					rightbody = (Entity*)node->next->element;
4190 				}
4191 				if ( bodypart == 5 )
4192 				{
4193 					shieldarm = entity;
4194 				}
4195 				double limbSpeed = dist;
4196 				double pitchLimit = PI / 4.f;
4197 				if ( playerRace == CREATURE_IMP )
4198 				{
4199 					limbSpeed = 1 / 12.f;
4200 					pitchLimit = PI / 8.f;
4201 				}
4202 				if ( stats[PLAYER_NUM]->EFFECTS[EFF_DASH] )
4203 				{
4204 					limbSpeed = 1 / 12.f;
4205 				}
4206 				node_t* shieldNode = list_Node(&my->children, 7);
4207 				if ( shieldNode )
4208 				{
4209 					Entity* shield = (Entity*)shieldNode->element;
4210 					bool bendArm = true;
4211 					if ( shield->flags[INVISIBLE] )
4212 					{
4213 						bendArm = false;
4214 					}
4215 					else if ( shield->sprite >= items[SPELLBOOK_LIGHT].index
4216 						&& shield->sprite < (items[SPELLBOOK_LIGHT].index + items[SPELLBOOK_LIGHT].variations) )
4217 					{
4218 						bendArm = false;
4219 					}
4220 
4221 					if ( insectoidLevitating[PLAYER_NUM] )
4222 					{
4223 						// hands stationary, legs pitched back and little swing.
4224 						limbSpeed = 0.03;
4225 						if ( bodypart == 5 ) // left arm
4226 						{
4227 							if ( entity->pitch < 0 )
4228 							{
4229 								entity->pitch += 1 / fmax(limbSpeed * .1, 10.0);
4230 								if ( entity->pitch > 0 )
4231 								{
4232 									entity->pitch = 0;
4233 								}
4234 							}
4235 							else if ( entity->pitch > 0 )
4236 							{
4237 								entity->pitch -= 1 / fmax(limbSpeed * .1, 10.0);
4238 								if ( entity->pitch < 0 )
4239 								{
4240 									entity->pitch = 0;
4241 								}
4242 							}
4243 						}
4244 						else if ( bodypart == 2 )
4245 						{
4246 							if ( entity->pitch < 0 )
4247 							{
4248 								entity->pitch += 5 * limbSpeed * PLAYERWALKSPEED; // speed up to reach target.
4249 							}
4250 							if ( !rightbody->skill[3] )
4251 							{
4252 								entity->pitch -= limbSpeed * PLAYERWALKSPEED;
4253 								if ( entity->pitch < PI / 6.f )
4254 								{
4255 									entity->pitch = PI / 6.f;
4256 								}
4257 							}
4258 							else
4259 							{
4260 								entity->pitch += limbSpeed * PLAYERWALKSPEED;
4261 								if ( entity->pitch > PI / 3.f )
4262 								{
4263 									entity->pitch = PI / 3.f;
4264 								}
4265 							}
4266 						}
4267 					}
4268 					else if ( (fabs(PLAYER_VELX) > 0.1 || fabs(PLAYER_VELY) > 0.1) && (bodypart != 5 || !bendArm)
4269 						|| playerRace == CREATURE_IMP )
4270 					{
4271 						if ( oldInsectoidLevitate )
4272 						{
4273 							entity->pitch = 0;
4274 						}
4275 
4276 						if ( !rightbody->skill[0] )
4277 						{
4278 							entity->pitch -= limbSpeed * PLAYERWALKSPEED;
4279 							if ( entity->pitch < -pitchLimit )
4280 							{
4281 								entity->pitch = -pitchLimit;
4282 								if ( bodypart == 2 && dist > .4 && !levitating && !swimming )
4283 								{
4284 									node_t* tempNode = list_Node(&my->children, 2);
4285 									if ( tempNode )
4286 									{
4287 										Entity* foot = (Entity*)tempNode->element;
4288 										if ( playerRace == TROLL )
4289 										{
4290 											playSoundEntityLocal(my, my->getMonsterFootstepSound(MONSTER_FOOTSTEP_STOMP, foot->sprite), 32);
4291 										}
4292 										else if ( playerRace == SPIDER || playerRace == RAT || playerRace == CREATURE_IMP )
4293 										{
4294 											// no sound.
4295 										}
4296 										else
4297 										{
4298 											playSoundEntityLocal(my, my->getMonsterFootstepSound(MONSTER_FOOTSTEP_USE_BOOTS, foot->sprite), 32);
4299 										}
4300 									}
4301 								}
4302 							}
4303 						}
4304 						else
4305 						{
4306 							entity->pitch += limbSpeed * PLAYERWALKSPEED;
4307 							if ( entity->pitch > pitchLimit )
4308 							{
4309 								entity->pitch = pitchLimit;
4310 								if ( bodypart == 2 && dist > .4 && !levitating && !swimming )
4311 								{
4312 									node_t* tempNode = list_Node(&my->children, 2);
4313 									if ( tempNode )
4314 									{
4315 										Entity* foot = (Entity*)tempNode->element;
4316 										if ( playerRace == TROLL )
4317 										{
4318 											playSoundEntityLocal(my, my->getMonsterFootstepSound(MONSTER_FOOTSTEP_STOMP, foot->sprite), 32);
4319 										}
4320 										else if ( playerRace == SPIDER || playerRace == RAT || playerRace == CREATURE_IMP )
4321 										{
4322 											// no sound.
4323 										}
4324 										else
4325 										{
4326 											playSoundEntityLocal(my, my->getMonsterFootstepSound(MONSTER_FOOTSTEP_USE_BOOTS, foot->sprite), 32);
4327 										}
4328 									}
4329 								}
4330 							}
4331 						}
4332 					}
4333 					else
4334 					{
4335 						if ( entity->pitch < 0 )
4336 						{
4337 							entity->pitch += 1 / fmax(limbSpeed * .1, 10.0);
4338 							if ( entity->pitch > 0 )
4339 							{
4340 								entity->pitch = 0;
4341 							}
4342 						}
4343 						else if ( entity->pitch > 0 )
4344 						{
4345 							entity->pitch -= 1 / fmax(limbSpeed * .1, 10.0);
4346 							if ( entity->pitch < 0 )
4347 							{
4348 								entity->pitch = 0;
4349 							}
4350 						}
4351 					}
4352 				}
4353 			}
4354 			else if ( bodypart == 3 || bodypart == 4 || bodypart == 8 ) // left leg, right arm, cloak
4355 			{
4356 				if ( bodypart == 4 )
4357 				{
4358 					weaponarm = entity;
4359 					if ( PLAYER_ATTACK == 1 || PLAYER_ATTACK == PLAYER_POSE_GOLEM_SMASH )
4360 					{
4361 						// vertical chop
4362 						if ( PLAYER_ATTACKTIME == 0 )
4363 						{
4364 							PLAYER_ARMBENDED = 0;
4365 							PLAYER_WEAPONYAW = 0;
4366 							entity->pitch = 0;
4367 							entity->roll = 0;
4368 							entity->skill[1] = 0;
4369 						}
4370 						else
4371 						{
4372 							if ( entity->skill[1] == 0 )
4373 							{
4374 								// upswing
4375 								if ( limbAnimateToLimit(entity, ANIMATE_PITCH, -0.5, 5 * PI / 4, false, 0.0) )
4376 								{
4377 									entity->skill[1] = 1;
4378 								}
4379 							}
4380 							else
4381 							{
4382 								if ( entity->pitch >= 3 * PI / 2 )
4383 								{
4384 									PLAYER_ARMBENDED = 1;
4385 								}
4386 								if ( limbAnimateToLimit(entity, ANIMATE_PITCH, 0.3, PI / 4, false, 0.0) )
4387 								{
4388 									entity->skill[0] = rightbody->skill[0];
4389 									entity->skill[1] = 0;
4390 									PLAYER_WEAPONYAW = 0;
4391 									entity->pitch = rightbody->pitch;
4392 									entity->roll = 0;
4393 									PLAYER_ARMBENDED = 0;
4394 									PLAYER_ATTACK = 0;
4395 								}
4396 							}
4397 						}
4398 
4399 						if ( PLAYER_ATTACK == PLAYER_POSE_GOLEM_SMASH && (PLAYER_NUM == clientnum || splitscreen) )
4400 						{
4401 							if ( my->pitch < PI / 32 )
4402 							{
4403 								// rotate head upwards
4404 								if ( limbAngleWithinRange(my->pitch, 0.1, PI / 32) )
4405 								{
4406 									my->pitch = PI / 32;
4407 								}
4408 								else
4409 								{
4410 									my->pitch += 0.1;
4411 								}
4412 							}
4413 							else
4414 							{
4415 								// rotate head downwards
4416 								if ( limbAngleWithinRange(my->pitch, -0.1, PI / 32) )
4417 								{
4418 									my->pitch = PI / 32;
4419 								}
4420 								else
4421 								{
4422 									my->pitch -= 0.1;
4423 								}
4424 							}
4425 						}
4426 					}
4427 					else if ( PLAYER_ATTACK == 2 )
4428 					{
4429 						// horizontal chop
4430 						if ( PLAYER_ATTACKTIME == 0 )
4431 						{
4432 							PLAYER_ARMBENDED = 1;
4433 							PLAYER_WEAPONYAW = -3 * PI / 4;
4434 							entity->pitch = 0;
4435 							entity->roll = -PI / 2;
4436 						}
4437 						else
4438 						{
4439 							if ( PLAYER_WEAPONYAW >= PI / 8 )
4440 							{
4441 								entity->skill[0] = rightbody->skill[0];
4442 								PLAYER_WEAPONYAW = 0;
4443 								entity->pitch = rightbody->pitch;
4444 								entity->roll = 0;
4445 								PLAYER_ARMBENDED = 0;
4446 								PLAYER_ATTACK = 0;
4447 							}
4448 							else
4449 							{
4450 								PLAYER_WEAPONYAW += .25;
4451 							}
4452 						}
4453 					}
4454 					else if ( PLAYER_ATTACK == 3 )
4455 					{
4456 						// stab
4457 						if ( PLAYER_ATTACKTIME == 0 )
4458 						{
4459 							PLAYER_ARMBENDED = 0;
4460 							PLAYER_WEAPONYAW = 0;
4461 							entity->pitch = 0;
4462 							entity->roll = 0;
4463 						}
4464 						else
4465 						{
4466 							if ( PLAYER_ATTACKTIME >= 5 )
4467 							{
4468 								if ( playerRace != CREATURE_IMP )
4469 								{
4470 									PLAYER_ARMBENDED = 1;
4471 								}
4472 								limbAnimateToLimit(entity, ANIMATE_PITCH, -0.5, 11 * PI / 6, false, 0.0);
4473 							}
4474 							else
4475 							{
4476 								limbAnimateToLimit(entity, ANIMATE_PITCH, 0.4, 2 * PI / 3, false, 0.0);
4477 							}
4478 							if ( PLAYER_ATTACKTIME >= 10 )
4479 							{
4480 								entity->skill[0] = rightbody->skill[0];
4481 								PLAYER_WEAPONYAW = 0;
4482 								entity->pitch = rightbody->pitch;
4483 								entity->roll = 0;
4484 								PLAYER_ARMBENDED = 0;
4485 								PLAYER_ATTACK = 0;
4486 							}
4487 						}
4488 					}
4489 					// special double vertical chop
4490 					else if ( PLAYER_ATTACK == MONSTER_POSE_SPECIAL_WINDUP1
4491 						|| PLAYER_ATTACK == MONSTER_POSE_SPECIAL_WINDUP2 )
4492 					{
4493 						if ( PLAYER_ATTACKTIME == 0 )
4494 						{
4495 							// init rotations
4496 							PLAYER_ARMBENDED = 0;
4497 							PLAYER_WEAPONYAW = 0;
4498 							entity->pitch = 0;
4499 							entity->roll = 0;
4500 							entity->skill[1] = 0;
4501 							if ( PLAYER_ATTACK == MONSTER_POSE_SPECIAL_WINDUP1 )
4502 							{
4503 								createParticleDot(my);
4504 							}
4505 						}
4506 						else
4507 						{
4508 							// move the head.
4509 							//limbAnimateToLimit(my, ANIMATE_PITCH, -0.1, 11 * PI / 6, true, 0.1);
4510 							if ( (PLAYER_NUM == clientnum || splitscreen) && PLAYER_ATTACK == MONSTER_POSE_SPECIAL_WINDUP1 )
4511 							{
4512 								if ( my->pitch > -PI / 12 )
4513 								{
4514 									// rotate head upwards
4515 									if ( limbAngleWithinRange(my->pitch, -0.03, -PI / 12) )
4516 									{
4517 										my->pitch = -PI / 12;
4518 									}
4519 									else
4520 									{
4521 										my->pitch += -0.02;
4522 									}
4523 								}
4524 								else
4525 								{
4526 									// slowly rotate head downwards
4527 									if ( limbAngleWithinRange(my->pitch, 0.03, -PI / 12) )
4528 									{
4529 										my->pitch = -PI / 12;
4530 									}
4531 									else
4532 									{
4533 										my->pitch -= -0.01;
4534 									}
4535 								}
4536 							}
4537 
4538 							if ( PLAYER_ATTACK == MONSTER_POSE_SPECIAL_WINDUP2 )
4539 							{
4540 								// lower right arm.
4541 								if ( entity->skill[1] == 0 )
4542 								{
4543 									// upswing
4544 									if ( limbAnimateToLimit(entity, ANIMATE_PITCH, -0.5, 5 * PI / 4, false, 0.0) )
4545 									{
4546 										entity->skill[1] = 1;
4547 									}
4548 								}
4549 								else
4550 								{
4551 									if ( entity->pitch >= 3 * PI / 2 )
4552 									{
4553 										PLAYER_ARMBENDED = 1;
4554 									}
4555 									if ( limbAnimateToLimit(entity, ANIMATE_PITCH, 0.3, PI / 4, false, 0.1) )
4556 									{
4557 										entity->skill[0] = rightbody->skill[0];
4558 										entity->skill[1] = 0;
4559 										PLAYER_WEAPONYAW = 0;
4560 										entity->pitch = rightbody->pitch;
4561 										entity->roll = 0;
4562 										PLAYER_ARMBENDED = 0;
4563 										PLAYER_ATTACK = 0;
4564 									}
4565 								}
4566 							}
4567 							else
4568 							{
4569 								// raise right arm and tilt.
4570 								limbAnimateToLimit(entity, ANIMATE_PITCH, -0.1, 9 * PI / 8, true, 0.1);
4571 								limbAnimateToLimit(entity, ANIMATE_ROLL, -0.2, PI / 32, false, 0);
4572 								if ( PLAYER_ATTACKTIME == 5 )
4573 								{
4574 									if ( playerRace == TROLL && rand() % 4 == 0 )
4575 									{
4576 										playSoundEntityLocal(players[PLAYER_NUM]->entity, 79, 128);
4577 									}
4578 								}
4579 								else if ( PLAYER_ATTACKTIME == 35 )
4580 								{
4581 									playSoundEntityLocal(players[PLAYER_NUM]->entity, 164, 128);
4582 								}
4583 							}
4584 						}
4585 					}
4586 					else if ( PLAYER_ATTACK == MONSTER_POSE_RANGED_SHOOT1 || PLAYER_ATTACK == MONSTER_POSE_RANGED_SHOOT2 )
4587 					{
4588 						// init rotations
4589 						PLAYER_ARMBENDED = 0;
4590 						PLAYER_WEAPONYAW = 0;
4591 						weaponarm->roll = 0;
4592 						weaponarm->skill[1] = 0;
4593 						weaponarm->pitch = 0;
4594 						PLAYER_ATTACK = MONSTER_POSE_RANGED_SHOOT3;
4595 					}
4596 					else if ( PLAYER_ATTACK == MONSTER_POSE_RANGED_SHOOT3 )
4597 					{
4598 						// recoil upwards
4599 						if ( weaponarm->skill[1] == 0 )
4600 						{
4601 							real_t targetPitch = 14 * PI / 8;
4602 							if ( weaponarm->sprite == items[CROSSBOW].index || weaponarm->sprite == items[HEAVY_CROSSBOW].index )
4603 							{
4604 								targetPitch = 15 * PI / 8;
4605 							}
4606 							if ( limbAnimateToLimit(weaponarm, ANIMATE_PITCH, -0.2, 14 * PI / 8, false, 0.0) )
4607 							{
4608 								weaponarm->skill[1] = 1;
4609 							}
4610 						}
4611 						// recoil downwards
4612 						else if ( weaponarm->skill[1] == 1 )
4613 						{
4614 							if ( limbAnimateToLimit(weaponarm, ANIMATE_PITCH, 0.1, 1 * PI / 3, false, 0.0) )
4615 							{
4616 								weaponarm->skill[1] = 2;
4617 							}
4618 						}
4619 						else if ( weaponarm->skill[1] >= 2 )
4620 						{
4621 							// limbAngleWithinRange cuts off animation early so it doesn't snap too far back to position.
4622 							real_t targetPitch = rightbody->pitch;
4623 							while ( targetPitch < 0 )
4624 							{
4625 								targetPitch += 2 * PI;
4626 							}
4627 							while ( targetPitch >= 2 * PI )
4628 							{
4629 								targetPitch -= 2 * PI;
4630 							}
4631 							if ( limbAnimateToLimit(weaponarm, ANIMATE_PITCH, -0.2, targetPitch, false, 0.0)
4632 								|| limbAngleWithinRange(weaponarm->pitch, -0.4, targetPitch)
4633 								|| weaponarm->pitch < -PI / 8)
4634 							{
4635 								weaponarm->skill[0] = rightbody->skill[0];
4636 								PLAYER_WEAPONYAW = 0;
4637 								weaponarm->pitch = rightbody->pitch;
4638 								weaponarm->roll = 0;
4639 								PLAYER_ARMBENDED = 0;
4640 								PLAYER_ATTACK = 0;
4641 							}
4642 						}
4643 					}
4644 				}
4645 				else if ( bodypart == 8 )
4646 				{
4647 					entity->pitch = entity->fskill[0];
4648 				}
4649 
4650 				if ( insectoidLevitating[PLAYER_NUM] )
4651 				{
4652 					// hands stationary, legs pitched back and little swing.
4653 					double limbSpeed = 0.03;
4654 					if ( bodypart == 4 && (PLAYER_ATTACK == 0 && PLAYER_ATTACKTIME == 0) ) // right arm relaxed, not attacking.
4655 					{
4656 						entity->skill[0] = rightbody->skill[0];
4657 						if ( entity->pitch < 0 )
4658 						{
4659 							entity->pitch += 1 / fmax(limbSpeed * .1, 10.0);
4660 							if ( entity->pitch > 0 )
4661 							{
4662 								entity->pitch = 0;
4663 							}
4664 						}
4665 						else if ( entity->pitch > 0 )
4666 						{
4667 							entity->pitch -= 1 / fmax(limbSpeed * .1, 10.0);
4668 							if ( entity->pitch < 0 )
4669 							{
4670 								entity->pitch = 0;
4671 							}
4672 						}
4673 					}
4674 					else if ( bodypart == 3 ) // leftleg
4675 					{
4676 						if ( entity->pitch < 0 )
4677 						{
4678 							entity->pitch += 5 * limbSpeed * PLAYERWALKSPEED; // speed up to reach target.
4679 						}
4680 						entity->skill[0] = 1;
4681 						if ( entity->skill[3] == 1 ) // throwaway skill.
4682 						{
4683 							entity->pitch -= limbSpeed * PLAYERWALKSPEED;
4684 							if ( entity->pitch < PI / 6.f )
4685 							{
4686 								entity->skill[3] = 0;
4687 								entity->pitch = PI / 6.f;
4688 							}
4689 						}
4690 						else
4691 						{
4692 							entity->pitch += limbSpeed * PLAYERWALKSPEED;
4693 							if ( entity->pitch > PI / 3.f )
4694 							{
4695 								entity->skill[3] = 1;
4696 								entity->pitch = PI / 3.f;
4697 							}
4698 						}
4699 					}
4700 				}
4701 				else if ( bodypart != 4 || (PLAYER_ATTACK == 0 && PLAYER_ATTACKTIME == 0) )
4702 				{
4703 					if ( bodypart != 8 )
4704 					{
4705 						if ( oldInsectoidLevitate )
4706 						{
4707 							entity->pitch = 0;
4708 						}
4709 					}
4710 
4711 					double limbSpeed = dist;
4712 					double pitchLimit = PI / 4.f;
4713 					if ( playerRace == CREATURE_IMP )
4714 					{
4715 						limbSpeed = 1 / 12.f;
4716 						pitchLimit = PI / 8.f;
4717 					}
4718 					if ( stats[PLAYER_NUM]->EFFECTS[EFF_DASH] )
4719 					{
4720 						limbSpeed = 1 / 12.f;
4721 					}
4722 					if ( (fabs(PLAYER_VELX) > 0.1 || fabs(PLAYER_VELY) > 0.1 || playerRace == CREATURE_IMP) )
4723 					{
4724 						if ( entity->skill[0] )
4725 						{
4726 							entity->pitch -= limbSpeed * PLAYERWALKSPEED;
4727 							if ( entity->pitch < -pitchLimit )
4728 							{
4729 								entity->skill[0] = 0;
4730 								entity->pitch = -pitchLimit;
4731 							}
4732 						}
4733 						else
4734 						{
4735 							entity->pitch += limbSpeed * PLAYERWALKSPEED;
4736 							if ( entity->pitch > pitchLimit )
4737 							{
4738 								entity->skill[0] = 1;
4739 								entity->pitch = pitchLimit;
4740 							}
4741 						}
4742 					}
4743 					else
4744 					{
4745 						if ( entity->pitch < 0 )
4746 						{
4747 							entity->pitch += 1 / fmax(limbSpeed * .1, 10.0);
4748 							if ( entity->pitch > 0 )
4749 							{
4750 								entity->pitch = 0;
4751 							}
4752 						}
4753 						else if ( entity->pitch > 0 )
4754 						{
4755 							entity->pitch -= 1 / fmax(limbSpeed * .1, 10.0);
4756 							if ( entity->pitch < 0 )
4757 							{
4758 								entity->pitch = 0;
4759 							}
4760 						}
4761 					}
4762 				}
4763 				if ( bodypart == 8 )
4764 				{
4765 					entity->fskill[0] = entity->pitch;
4766 					entity->roll = my->roll - fabs(entity->pitch) / 2;
4767 					entity->pitch = 0;
4768 				}
4769 			}
4770 
4771 			switch ( bodypart )
4772 			{
4773 				// torso
4774 				case 1:
4775 					torso = entity;
4776 					entity->focalx = limbs[playerRace][1][0];
4777 					entity->focaly = limbs[playerRace][1][1];
4778 					entity->focalz = limbs[playerRace][1][2];
4779 					if ( multiplayer != CLIENT )
4780 					{
4781 						if ( stats[PLAYER_NUM]->breastplate == NULL || !showEquipment )
4782 						{
4783 							entity->setDefaultPlayerModel(PLAYER_NUM, playerRace, LIMB_HUMANOID_TORSO);
4784 						}
4785 						else
4786 						{
4787 							entity->sprite = itemModel(stats[PLAYER_NUM]->breastplate);
4788 						}
4789 						if ( multiplayer == SERVER )
4790 						{
4791 							// update sprites for clients
4792 							if ( entity->skill[10] != entity->sprite )
4793 							{
4794 								entity->skill[10] = entity->sprite;
4795 								serverUpdateEntityBodypart(my, bodypart);
4796 							}
4797 							if ( PLAYER_ALIVETIME == TICKS_PER_SECOND + bodypart )
4798 							{
4799 								serverUpdateEntityBodypart(my, bodypart);
4800 							}
4801 						}
4802 					}
4803 					my->setHumanoidLimbOffset(entity, playerRace, LIMB_HUMANOID_TORSO);
4804 					break;
4805 					// right leg
4806 				case 2:
4807 					entity->focalx = limbs[playerRace][2][0];
4808 					entity->focaly = limbs[playerRace][2][1];
4809 					entity->focalz = limbs[playerRace][2][2];
4810 					if ( multiplayer != CLIENT )
4811 					{
4812 						if ( stats[PLAYER_NUM]->shoes == NULL || !showEquipment )
4813 						{
4814 							entity->setDefaultPlayerModel(PLAYER_NUM, playerRace, LIMB_HUMANOID_RIGHTLEG);
4815 						}
4816 						else
4817 						{
4818 							my->setBootSprite(entity, SPRITE_BOOT_RIGHT_OFFSET);
4819 						}
4820 						if ( multiplayer == SERVER )
4821 						{
4822 							// update sprites for clients
4823 							if ( entity->skill[10] != entity->sprite )
4824 							{
4825 								entity->skill[10] = entity->sprite;
4826 								serverUpdateEntityBodypart(my, bodypart);
4827 							}
4828 							if ( PLAYER_ALIVETIME == TICKS_PER_SECOND + bodypart )
4829 							{
4830 								serverUpdateEntityBodypart(my, bodypart);
4831 							}
4832 						}
4833 					}
4834 					my->setHumanoidLimbOffset(entity, playerRace, LIMB_HUMANOID_RIGHTLEG);
4835 					break;
4836 					// left leg
4837 				case 3:
4838 					entity->focalx = limbs[playerRace][3][0];
4839 					entity->focaly = limbs[playerRace][3][1];
4840 					entity->focalz = limbs[playerRace][3][2];
4841 					if ( multiplayer != CLIENT )
4842 					{
4843 						if ( stats[PLAYER_NUM]->shoes == NULL || !showEquipment )
4844 						{
4845 							entity->setDefaultPlayerModel(PLAYER_NUM, playerRace, LIMB_HUMANOID_LEFTLEG);
4846 						}
4847 						else
4848 						{
4849 							my->setBootSprite(entity, SPRITE_BOOT_LEFT_OFFSET);
4850 						}
4851 						if ( multiplayer == SERVER )
4852 						{
4853 							// update sprites for clients
4854 							if ( entity->skill[10] != entity->sprite )
4855 							{
4856 								entity->skill[10] = entity->sprite;
4857 								serverUpdateEntityBodypart(my, bodypart);
4858 							}
4859 							if ( PLAYER_ALIVETIME == TICKS_PER_SECOND + bodypart )
4860 							{
4861 								serverUpdateEntityBodypart(my, bodypart);
4862 							}
4863 						}
4864 					}
4865 					my->setHumanoidLimbOffset(entity, playerRace, LIMB_HUMANOID_LEFTLEG);
4866 					break;
4867 					// right arm
4868 				case 4:
4869 				{
4870 					if ( multiplayer != CLIENT )
4871 					{
4872 						if ( stats[PLAYER_NUM]->gloves == NULL || !showEquipment )
4873 						{
4874 							entity->setDefaultPlayerModel(PLAYER_NUM, playerRace, LIMB_HUMANOID_RIGHTARM);
4875 						}
4876 						else
4877 						{
4878 							if ( setGloveSprite(stats[PLAYER_NUM], entity, SPRITE_GLOVE_RIGHT_OFFSET) != 0 )
4879 							{
4880 								// successfully set sprite for the human model
4881 							}
4882 						}
4883 						if ( (!PLAYER_ARMBENDED && showEquipment) || (insectoidLevitating[PLAYER_NUM] && PLAYER_ATTACK == 0 && PLAYER_ATTACKTIME == 0) )
4884 						{
4885 							entity->sprite += 2 * (stats[PLAYER_NUM]->weapon != NULL);
4886 
4887 							if ( stats[PLAYER_NUM]->weapon == nullptr
4888 								&& insectoidLevitating[PLAYER_NUM] )
4889 							{
4890 								entity->sprite += 2;
4891 							}
4892 						}
4893 						if ( multiplayer == SERVER )
4894 						{
4895 							// update sprites for clients
4896 							if ( entity->skill[10] != entity->sprite )
4897 							{
4898 								entity->skill[10] = entity->sprite;
4899 								serverUpdateEntityBodypart(my, bodypart);
4900 							}
4901 							if ( PLAYER_ALIVETIME == TICKS_PER_SECOND + bodypart )
4902 							{
4903 								serverUpdateEntityBodypart(my, bodypart);
4904 							}
4905 						}
4906 					}
4907 					my->setHumanoidLimbOffset(entity, playerRace, LIMB_HUMANOID_RIGHTARM);
4908 					node_t* tempNode = list_Node(&my->children, 6);
4909 					if ( tempNode )
4910 					{
4911 						Entity* weapon = (Entity*)tempNode->element;
4912 						if ( weapon->flags[INVISIBLE] || PLAYER_ARMBENDED || playerRace == CREATURE_IMP )
4913 						{
4914 							if ( playerRace == INCUBUS || playerRace == SUCCUBUS )
4915 							{
4916 								entity->focalx = limbs[playerRace][4][0] - 0.25;
4917 								entity->focaly = limbs[playerRace][4][1] - 0.25;
4918 								entity->focalz = limbs[playerRace][4][2];
4919 							}
4920 							else
4921 							{
4922 								entity->focalx = limbs[playerRace][4][0]; // 0
4923 								entity->focaly = limbs[playerRace][4][1]; // 0
4924 								entity->focalz = limbs[playerRace][4][2]; // 1.5
4925 							}
4926 						}
4927 						else
4928 						{
4929 							if ( playerRace == INCUBUS || playerRace == SUCCUBUS )
4930 							{
4931 								entity->focalx = limbs[playerRace][4][0];
4932 								entity->focaly = limbs[playerRace][4][1];
4933 								entity->focalz = limbs[playerRace][4][2];
4934 							}
4935 							else if ( playerRace == AUTOMATON )
4936 							{
4937 								entity->focalx = limbs[playerRace][4][0] + 1.5; // 1
4938 								entity->focaly = limbs[playerRace][4][1] + 0.25; // 0
4939 								entity->focalz = limbs[playerRace][4][2] - 1; // 1
4940 							}
4941 							else
4942 							{
4943 								entity->focalx = limbs[playerRace][4][0] + 0.75;
4944 								entity->focaly = limbs[playerRace][4][1];
4945 								entity->focalz = limbs[playerRace][4][2] - 0.75;
4946 							}
4947 						}
4948 					}
4949 					entity->yaw += PLAYER_WEAPONYAW;
4950 					break;
4951 				}
4952 				// left arm
4953 				case 5:
4954 				{
4955 					if ( multiplayer != CLIENT )
4956 					{
4957 						if ( stats[PLAYER_NUM]->gloves == NULL || !showEquipment )
4958 						{
4959 							entity->setDefaultPlayerModel(PLAYER_NUM, playerRace, LIMB_HUMANOID_LEFTARM);
4960 						}
4961 						else
4962 						{
4963 							if ( setGloveSprite(stats[PLAYER_NUM], entity, SPRITE_GLOVE_LEFT_OFFSET) != 0 )
4964 							{
4965 								// successfully set sprite for the human model
4966 							}
4967 						}
4968 						if ( showEquipment )
4969 						{
4970 							bool bendArm = false;
4971 							if ( insectoidLevitating[PLAYER_NUM] )
4972 							{
4973 								bendArm = true;
4974 							}
4975 							if ( stats[PLAYER_NUM]->shield != NULL )
4976 							{
4977 								if ( itemCategory(stats[PLAYER_NUM]->shield) == SPELLBOOK )
4978 								{
4979 									bendArm = false;
4980 								}
4981 								else
4982 								{
4983 									bendArm = true;
4984 								}
4985 							}
4986 							entity->sprite += 2 * (bendArm);
4987 						}
4988 						if ( multiplayer == SERVER )
4989 						{
4990 							// update sprites for clients
4991 							if ( entity->skill[10] != entity->sprite )
4992 							{
4993 								entity->skill[10] = entity->sprite;
4994 								serverUpdateEntityBodypart(my, bodypart);
4995 							}
4996 							if ( PLAYER_ALIVETIME == TICKS_PER_SECOND + bodypart )
4997 							{
4998 								serverUpdateEntityBodypart(my, bodypart);
4999 							}
5000 						}
5001 					}
5002 					my->setHumanoidLimbOffset(entity, playerRace, LIMB_HUMANOID_LEFTARM);
5003 
5004 					if ( weaponarm && !showEquipment &&
5005 						(PLAYER_ATTACK == MONSTER_POSE_SPECIAL_WINDUP1
5006 							|| PLAYER_ATTACK == MONSTER_POSE_SPECIAL_WINDUP2
5007 							|| PLAYER_ATTACK == PLAYER_POSE_GOLEM_SMASH))
5008 					{
5009 						// special swing - copy the right arm movements.
5010 						entity->pitch = weaponarm->pitch;
5011 						entity->roll = -weaponarm->roll;
5012 					}
5013 					else
5014 					{
5015 						entity->roll = 0.f;
5016 					}
5017 
5018 					node_t* tempNode = list_Node(&my->children, 7);
5019 					if ( tempNode )
5020 					{
5021 						Entity* shield = (Entity*)tempNode->element;
5022 						bool bendArm = true;
5023 						if ( shield->flags[INVISIBLE] )
5024 						{
5025 							bendArm = false;
5026 							if ( insectoidLevitating[PLAYER_NUM] )
5027 							{
5028 								bendArm = true;
5029 							}
5030 						}
5031 						else if ( shield->sprite >= items[SPELLBOOK_LIGHT].index
5032 							&& shield->sprite < (items[SPELLBOOK_LIGHT].index + items[SPELLBOOK_LIGHT].variations) )
5033 						{
5034 							bendArm = false;
5035 						}
5036 						else if ( playerRace == CREATURE_IMP )
5037 						{
5038 							bendArm = false;
5039 						}
5040 
5041 						if ( !bendArm )
5042 						{
5043 							if ( playerRace == INCUBUS || playerRace == SUCCUBUS )
5044 							{
5045 								entity->focalx = limbs[playerRace][5][0] - 0.25;
5046 								entity->focaly = limbs[playerRace][5][1] + 0.25;
5047 								entity->focalz = limbs[playerRace][5][2];
5048 							}
5049 							else
5050 							{
5051 								entity->focalx = limbs[playerRace][5][0]; // 0
5052 								entity->focaly = limbs[playerRace][5][1]; // 0
5053 								entity->focalz = limbs[playerRace][5][2]; // 1.5
5054 							}
5055 						}
5056 						else
5057 						{
5058 							if ( playerRace == INCUBUS || playerRace == SUCCUBUS )
5059 							{
5060 								entity->focalx = limbs[playerRace][5][0];
5061 								entity->focaly = limbs[playerRace][5][1];
5062 								entity->focalz = limbs[playerRace][5][2];
5063 							}
5064 							else if ( playerRace == AUTOMATON )
5065 							{
5066 								entity->focalx = limbs[playerRace][5][0] + 1.5; // 1
5067 								entity->focaly = limbs[playerRace][5][1] - 0.25; // 0
5068 								entity->focalz = limbs[playerRace][5][2] - 1; // 1
5069 							}
5070 							else
5071 							{
5072 								entity->focalx = limbs[playerRace][5][0] + 0.75;
5073 								entity->focaly = limbs[playerRace][5][1];
5074 								entity->focalz = limbs[playerRace][5][2] - 0.75;
5075 							}
5076 						}
5077 					}
5078 					if ( multiplayer != CLIENT )
5079 					{
5080 						real_t prevYaw = PLAYER_SHIELDYAW;
5081 						if ( stats[PLAYER_NUM]->defending )
5082 						{
5083 							PLAYER_SHIELDYAW = PI / 5;
5084 						}
5085 						else
5086 						{
5087 							PLAYER_SHIELDYAW = 0;
5088 						}
5089 						if ( prevYaw != PLAYER_SHIELDYAW || ticks % 200 == 0 )
5090 						{
5091 							serverUpdateEntityFSkill(players[PLAYER_NUM]->entity, 8);
5092 						}
5093 					}
5094 					entity->yaw += PLAYER_SHIELDYAW;
5095 					break;
5096 				}
5097 				// weapon
5098 				case 6:
5099 					if ( multiplayer != CLIENT )
5100 					{
5101 						if ( swimming )
5102 						{
5103 							entity->flags[INVISIBLE] = true;
5104 						}
5105 						else
5106 						{
5107 							if ( stats[PLAYER_NUM]->weapon == NULL || my->isInvisible() )
5108 							{
5109 								entity->flags[INVISIBLE] = true;
5110 							}
5111 							else
5112 							{
5113 								entity->sprite = itemModel(stats[PLAYER_NUM]->weapon);
5114 								if ( itemCategory(stats[PLAYER_NUM]->weapon) == SPELLBOOK )
5115 								{
5116 									entity->flags[INVISIBLE] = true;
5117 								}
5118 								else
5119 								{
5120 									entity->flags[INVISIBLE] = false;
5121 								}
5122 							}
5123 						}
5124 						if ( multiplayer == SERVER )
5125 						{
5126 							// update sprites for clients
5127 							if ( entity->skill[10] != entity->sprite )
5128 							{
5129 								entity->skill[10] = entity->sprite;
5130 								serverUpdateEntityBodypart(my, bodypart);
5131 							}
5132 							if ( entity->skill[11] != entity->flags[INVISIBLE] )
5133 							{
5134 								entity->skill[11] = entity->flags[INVISIBLE];
5135 								serverUpdateEntityBodypart(my, bodypart);
5136 							}
5137 							if ( PLAYER_ALIVETIME == TICKS_PER_SECOND + bodypart )
5138 							{
5139 								serverUpdateEntityBodypart(my, bodypart);
5140 							}
5141 						}
5142 					}
5143 					else
5144 					{
5145 						if ( entity->sprite <= 0 )
5146 						{
5147 							entity->flags[INVISIBLE] = true;
5148 						}
5149 					}
5150 					my->handleHumanoidWeaponLimb(entity, weaponarm);
5151 					break;
5152 				// shield
5153 				case 7:
5154 					if ( multiplayer != CLIENT )
5155 					{
5156 						if ( swimming )
5157 						{
5158 							entity->flags[INVISIBLE] = true;
5159 						}
5160 						else
5161 						{
5162 							if ( stats[PLAYER_NUM]->shield == NULL )
5163 							{
5164 								entity->flags[INVISIBLE] = true;
5165 								entity->sprite = 0;
5166 							}
5167 							else
5168 							{
5169 								entity->flags[INVISIBLE] = false;
5170 								entity->sprite = itemModel(stats[PLAYER_NUM]->shield);
5171 								if ( itemTypeIsQuiver(stats[PLAYER_NUM]->shield->type) )
5172 								{
5173 									if ( itemTypeIsQuiver(stats[PLAYER_NUM]->shield->type) )
5174 									{
5175 										entity->handleQuiverThirdPersonModel(*stats[PLAYER_NUM]);
5176 									}
5177 								}
5178 							}
5179 							if ( my->isInvisible() )
5180 							{
5181 								entity->flags[INVISIBLE] = true;
5182 							}
5183 						}
5184 						if ( multiplayer == SERVER )
5185 						{
5186 							// update sprites for clients
5187 							if ( entity->skill[10] != entity->sprite )
5188 							{
5189 								entity->skill[10] = entity->sprite;
5190 								serverUpdateEntityBodypart(my, bodypart);
5191 							}
5192 							if ( entity->skill[11] != entity->flags[INVISIBLE] )
5193 							{
5194 								entity->skill[11] = entity->flags[INVISIBLE];
5195 								serverUpdateEntityBodypart(my, bodypart);
5196 							}
5197 							if ( PLAYER_ALIVETIME == TICKS_PER_SECOND + bodypart )
5198 							{
5199 								serverUpdateEntityBodypart(my, bodypart);
5200 							}
5201 						}
5202 					}
5203 					else
5204 					{
5205 						if ( entity->sprite <= 0 )
5206 						{
5207 							entity->flags[INVISIBLE] = true;
5208 						}
5209 					}
5210 					my->handleHumanoidShieldLimb(entity, shieldarm);
5211 					break;
5212 					// cloak
5213 				case 8:
5214 					entity->focalx = limbs[playerRace][8][0];
5215 					entity->focaly = limbs[playerRace][8][1];
5216 					entity->focalz = limbs[playerRace][8][2];
5217 					entity->scalex = 1.01;
5218 					entity->scaley = 1.01;
5219 					if ( multiplayer != CLIENT )
5220 					{
5221 						if ( stats[PLAYER_NUM]->cloak == NULL || my->isInvisible() )
5222 						{
5223 							entity->flags[INVISIBLE] = true;
5224 						}
5225 						else
5226 						{
5227 							entity->flags[INVISIBLE] = false;
5228 							entity->sprite = itemModel(stats[PLAYER_NUM]->cloak);
5229 						}
5230 						if ( multiplayer == SERVER )
5231 						{
5232 							// update sprites for clients
5233 							if ( entity->skill[10] != entity->sprite )
5234 							{
5235 								entity->skill[10] = entity->sprite;
5236 								serverUpdateEntityBodypart(my, bodypart);
5237 							}
5238 							if ( entity->skill[11] != entity->flags[INVISIBLE] )
5239 							{
5240 								entity->skill[11] = entity->flags[INVISIBLE];
5241 								serverUpdateEntityBodypart(my, bodypart);
5242 							}
5243 							if ( PLAYER_ALIVETIME == TICKS_PER_SECOND + bodypart )
5244 							{
5245 								serverUpdateEntityBodypart(my, bodypart);
5246 							}
5247 						}
5248 					}
5249 					else
5250 					{
5251 						if ( entity->sprite <= 0 )
5252 						{
5253 							entity->flags[INVISIBLE] = true;
5254 						}
5255 					}
5256 
5257 					if ( entity->sprite == items[CLOAK_BACKPACK].index )
5258 					{
5259 						// human
5260 						if ( playerRace == HUMAN || playerRace == VAMPIRE )
5261 						{
5262 							entity->focaly = limbs[playerRace][8][1] + 0.25;
5263 							entity->focalz = limbs[playerRace][8][2] - 0.3;
5264 						}
5265 						else if ( playerRace == SUCCUBUS || playerRace == INCUBUS )
5266 						{
5267 							// succubus/incubus
5268 							entity->focaly = limbs[playerRace][8][1] + 0.25;
5269 							entity->focalz = limbs[playerRace][8][2] - 0.7;
5270 						}
5271 						else if ( playerRace == SKELETON )
5272 						{
5273 							entity->focaly = limbs[playerRace][8][1] + 0.25;
5274 							entity->focalz = limbs[playerRace][8][2] - 0.5;
5275 						}
5276 						else if ( playerRace == AUTOMATON )
5277 						{
5278 							entity->focaly = limbs[playerRace][8][1] - 0.25;
5279 							entity->focalz = limbs[playerRace][8][2] - 0.5;
5280 						}
5281 						else if ( playerRace == GOATMAN || playerRace == INSECTOID || playerRace == GOBLIN )
5282 						{
5283 							entity->focaly = limbs[playerRace][8][1] - 0.25;
5284 							entity->focalz = limbs[playerRace][8][2] - 0.5;
5285 						}
5286 
5287 						entity->scalex = 0.99;
5288 						entity->scaley = 0.99;
5289 					}
5290 					entity->x -= cos(my->yaw);
5291 					entity->y -= sin(my->yaw);
5292 					entity->yaw += PI / 2;
5293 					break;
5294 					// helm
5295 				case 9:
5296 					helmet = entity;
5297 					entity->focalx = limbs[playerRace][9][0]; // 0
5298 					entity->focaly = limbs[playerRace][9][1]; // 0
5299 					entity->focalz = limbs[playerRace][9][2]; // -1.75
5300 					entity->pitch = my->pitch;
5301 					entity->roll = 0;
5302 					if ( multiplayer != CLIENT )
5303 					{
5304 						entity->sprite = itemModel(stats[PLAYER_NUM]->helmet);
5305 						if ( stats[PLAYER_NUM]->helmet == NULL || my->isInvisible() )
5306 						{
5307 							entity->flags[INVISIBLE] = true;
5308 						}
5309 						else
5310 						{
5311 							entity->flags[INVISIBLE] = false;
5312 						}
5313 						if ( multiplayer == SERVER )
5314 						{
5315 							// update sprites for clients
5316 							if ( entity->skill[10] != entity->sprite )
5317 							{
5318 								entity->skill[10] = entity->sprite;
5319 								serverUpdateEntityBodypart(my, bodypart);
5320 							}
5321 							if ( entity->skill[11] != entity->flags[INVISIBLE] )
5322 							{
5323 								entity->skill[11] = entity->flags[INVISIBLE];
5324 								serverUpdateEntityBodypart(my, bodypart);
5325 							}
5326 							if ( PLAYER_ALIVETIME == TICKS_PER_SECOND + bodypart )
5327 							{
5328 								serverUpdateEntityBodypart(my, bodypart);
5329 							}
5330 						}
5331 					}
5332 					else
5333 					{
5334 						if ( entity->sprite <= 0 )
5335 						{
5336 							entity->flags[INVISIBLE] = true;
5337 						}
5338 					}
5339 					my->setHelmetLimbOffset(entity);
5340 					break;
5341 					// mask
5342 				case 10:
5343 					entity->focalx = limbs[playerRace][10][0]; // 0
5344 					entity->focaly = limbs[playerRace][10][1]; // 0
5345 					entity->focalz = limbs[playerRace][10][2]; // .5
5346 					entity->pitch = my->pitch;
5347 					entity->roll = PI / 2;
5348 					if ( multiplayer != CLIENT )
5349 					{
5350 						bool hasSteelHelm = false;
5351 						if ( stats[PLAYER_NUM]->helmet )
5352 						{
5353 							if ( stats[PLAYER_NUM]->helmet->type == STEEL_HELM
5354 								|| stats[PLAYER_NUM]->helmet->type == CRYSTAL_HELM
5355 								|| stats[PLAYER_NUM]->helmet->type == ARTIFACT_HELM )
5356 							{
5357 								hasSteelHelm = true;
5358 							}
5359 						}
5360 						if ( stats[PLAYER_NUM]->mask == NULL || my->isInvisible() || hasSteelHelm )
5361 						{
5362 							entity->flags[INVISIBLE] = true;
5363 						}
5364 						else
5365 						{
5366 							entity->flags[INVISIBLE] = false;
5367 						}
5368 						if ( stats[PLAYER_NUM]->mask != NULL )
5369 						{
5370 							if ( stats[PLAYER_NUM]->mask->type == TOOL_GLASSES )
5371 							{
5372 								entity->sprite = 165; // GlassesWorn.vox
5373 							}
5374 							else
5375 							{
5376 								entity->sprite = itemModel(stats[PLAYER_NUM]->mask);
5377 							}
5378 						}
5379 						if ( multiplayer == SERVER )
5380 						{
5381 							// update sprites for clients
5382 							if ( entity->skill[10] != entity->sprite )
5383 							{
5384 								entity->skill[10] = entity->sprite;
5385 								serverUpdateEntityBodypart(my, bodypart);
5386 							}
5387 							if ( entity->skill[11] != entity->flags[INVISIBLE] )
5388 							{
5389 								entity->skill[11] = entity->flags[INVISIBLE];
5390 								serverUpdateEntityBodypart(my, bodypart);
5391 							}
5392 							if ( PLAYER_ALIVETIME == TICKS_PER_SECOND + bodypart )
5393 							{
5394 								serverUpdateEntityBodypart(my, bodypart);
5395 							}
5396 						}
5397 					}
5398 					else
5399 					{
5400 						if ( entity->sprite <= 0 )
5401 						{
5402 							entity->flags[INVISIBLE] = true;
5403 						}
5404 					}
5405 					entity->scalex = 0.99;
5406 					entity->scaley = 0.99;
5407 					entity->scalez = 0.99;
5408 					if ( entity->sprite == 165 )
5409 					{
5410 						entity->focalx = limbs[playerRace][10][0] + .25; // .25
5411 						entity->focaly = limbs[playerRace][10][1] - 2.25; // -2.25
5412 						entity->focalz = limbs[playerRace][10][2]; // .5
5413 						if ( helmet && !helmet->flags[INVISIBLE] && helmet->sprite == items[PUNISHER_HOOD].index )
5414 						{
5415 							switch ( playerRace )
5416 							{
5417 								case HUMAN:
5418 								case VAMPIRE:
5419 								case SHOPKEEPER:
5420 								case INSECTOID:
5421 									entity->focaly += 0.25; // lower glasses a bit.
5422 									break;
5423 								case INCUBUS:
5424 								case SUCCUBUS:
5425 								case AUTOMATON:
5426 								case GOBLIN:
5427 								case GOATMAN:
5428 								case SKELETON:
5429 									// no change.
5430 									break;
5431 								default:
5432 									break;
5433 							}
5434 						}
5435 					}
5436 					else if ( entity->sprite == items[MASK_SHAMAN].index )
5437 					{
5438 						entity->roll = 0;
5439 						my->setHelmetLimbOffset(entity);
5440 						my->setHelmetLimbOffsetWithMask(helmet, entity);
5441 					}
5442 					else
5443 					{
5444 						entity->focalx = limbs[playerRace][10][0] + .35; // .35
5445 						entity->focaly = limbs[playerRace][10][1] - 2; // -2
5446 						entity->focalz = limbs[playerRace][10][2]; // .5
5447 					}
5448 
5449 					break;
5450 				case 11:
5451 					additionalLimb = entity;
5452 					entity->focalx = limbs[playerRace][11][0];
5453 					entity->focaly = limbs[playerRace][11][1];
5454 					entity->focalz = limbs[playerRace][11][2];
5455 					entity->flags[INVISIBLE] = true;
5456 					if ( playerRace == INSECTOID || playerRace == CREATURE_IMP )
5457 					{
5458 						entity->flags[INVISIBLE] = my->flags[INVISIBLE];
5459 						if ( playerRace == INSECTOID )
5460 						{
5461 							if ( stats[PLAYER_NUM]->sex == FEMALE )
5462 							{
5463 								entity->sprite = 771;
5464 							}
5465 							else
5466 							{
5467 								entity->sprite = 750;
5468 							}
5469 							if ( torso && torso->sprite != 727 && torso->sprite != 761 && torso->sprite != 458 )
5470 							{
5471 								// wearing armor, offset more.
5472 								entity->x -= 2.25 * cos(my->yaw);
5473 								entity->y -= 2.25 * sin(my->yaw);
5474 							}
5475 							else
5476 							{
5477 								entity->x -= 1.5 * cos(my->yaw);
5478 								entity->y -= 1.5 * sin(my->yaw);
5479 							}
5480 						}
5481 						else if ( playerRace == CREATURE_IMP )
5482 						{
5483 							entity->sprite = 833;
5484 							entity->focalx = limbs[playerRace][7][0];
5485 							entity->focaly = limbs[playerRace][7][1];
5486 							entity->focalz = limbs[playerRace][7][2];
5487 							entity->x -= 1 * cos(my->yaw + PI / 2) + 2.5 * cos(my->yaw);
5488 							entity->y -= 1 * sin(my->yaw + PI / 2) + 2.5 * sin(my->yaw);
5489 							entity->z += 1;
5490 						}
5491 						bool moving = false;
5492 						if ( fabs(PLAYER_VELX) > 0.1 || fabs(PLAYER_VELY) > 0.1 || insectoidLevitating )
5493 						{
5494 							moving = true;
5495 						}
5496 
5497 						if ( entity->skill[0] == 0 )
5498 						{
5499 							if ( moving )
5500 							{
5501 								if ( insectoidLevitating[PLAYER_NUM] )
5502 								{
5503 									entity->fskill[0] += std::min(std::max(0.2, dist * PLAYERWALKSPEED), 2.f * PLAYERWALKSPEED); // move proportional to move speed
5504 								}
5505 								else
5506 								{
5507 									entity->fskill[0] += std::min(dist * PLAYERWALKSPEED, 2.f * PLAYERWALKSPEED); // move proportional to move speed
5508 								}
5509 							}
5510 							else if ( PLAYER_ATTACK != 0 )
5511 							{
5512 								entity->fskill[0] += PLAYERWALKSPEED; // move fixed speed when attacking if stationary
5513 							}
5514 							else
5515 							{
5516 								entity->fskill[0] += 0.01; // otherwise move slow idle
5517 							}
5518 
5519 							if ( entity->fskill[0] > PI / 3
5520 								|| ((!moving || PLAYER_ATTACK != 0) && entity->fskill[0] > PI / 5)
5521 								|| (playerRace == CREATURE_IMP && entity->fskill[0] > PI / 8) )
5522 							{
5523 								// switch direction if angle too great, angle is shorter if attacking or stationary
5524 								entity->skill[0] = 1;
5525 							}
5526 						}
5527 						else // reverse of the above
5528 						{
5529 							if ( moving )
5530 							{
5531 								if ( insectoidLevitating[PLAYER_NUM] )
5532 								{
5533 									entity->fskill[0] -= std::min(std::max(0.15, dist * PLAYERWALKSPEED), 2.f * PLAYERWALKSPEED);
5534 								}
5535 								else
5536 								{
5537 									entity->fskill[0] -= std::min(dist * PLAYERWALKSPEED, 2.f * PLAYERWALKSPEED);
5538 								}
5539 							}
5540 							else if ( PLAYER_ATTACK != 0 )
5541 							{
5542 								entity->fskill[0] -= PLAYERWALKSPEED;
5543 							}
5544 							else
5545 							{
5546 								entity->fskill[0] -= 0.007;
5547 							}
5548 
5549 							if ( playerRace == INSECTOID && entity->fskill[0] < -PI / 32 )
5550 							{
5551 								entity->skill[0] = 0;
5552 							}
5553 							else if ( playerRace == CREATURE_IMP && entity->fskill[0] < -PI / 4 )
5554 							{
5555 								entity->skill[0] = 0;
5556 							}
5557 						}
5558 						entity->yaw += entity->fskill[0];
5559 					}
5560 					break;
5561 				case 12:
5562 					entity->focalx = limbs[playerRace][12][0];
5563 					entity->focaly = limbs[playerRace][12][1];
5564 					entity->focalz = limbs[playerRace][12][2];
5565 					entity->flags[INVISIBLE] = true;
5566 					if ( playerRace == INSECTOID || playerRace == CREATURE_IMP )
5567 					{
5568 						entity->flags[INVISIBLE] = my->flags[INVISIBLE];
5569 						if ( playerRace == INSECTOID )
5570 						{
5571 							if ( stats[PLAYER_NUM]->sex == FEMALE )
5572 							{
5573 								entity->sprite = 772;
5574 							}
5575 							else
5576 							{
5577 								entity->sprite = 751;
5578 							}
5579 							if ( torso && torso->sprite != 727 && torso->sprite != 761 && torso->sprite != 458 )
5580 							{
5581 								// wearing armor, offset more.
5582 								entity->x -= 2.25 * cos(my->yaw);
5583 								entity->y -= 2.25 * sin(my->yaw);
5584 							}
5585 							else
5586 							{
5587 								entity->x -= 1.5 * cos(my->yaw);
5588 								entity->y -= 1.5 * sin(my->yaw);
5589 							}
5590 						}
5591 						else if ( playerRace == CREATURE_IMP )
5592 						{
5593 							entity->sprite = 834;
5594 							entity->focalx = limbs[playerRace][6][0];
5595 							entity->focaly = limbs[playerRace][6][1];
5596 							entity->focalz = limbs[playerRace][6][2];
5597 							entity->x += 1 * cos(my->yaw + PI / 2) - 2.5 * cos(my->yaw);
5598 							entity->y += 1 * sin(my->yaw + PI / 2) - 2.5 * sin(my->yaw);
5599 							entity->z += 1;
5600 						}
5601 						if ( additionalLimb ) // follow the yaw of the previous limb.
5602 						{
5603 							entity->yaw -= additionalLimb->fskill[0];
5604 						}
5605 					}
5606 					break;
5607 				default:
5608 					break;
5609 			}
5610 
5611 
5612 			if ( !showEquipment )
5613 			{
5614 				if ( bodypart >= 6 && bodypart <= 10 )
5615 				{
5616 					entity->flags[INVISIBLE] = true;
5617 					if ( playerRace == CREATURE_IMP && bodypart == 7 )
5618 					{
5619 						if ( entity->sprite >= items[SPELLBOOK_LIGHT].index
5620 							&& entity->sprite < (items[SPELLBOOK_LIGHT].index + items[SPELLBOOK_LIGHT].variations) )
5621 						{
5622 							entity->flags[INVISIBLE] = false; // show spellbooks
5623 						}
5624 					}
5625 					else if ( playerRace == CREATURE_IMP && bodypart == 6 )
5626 					{
5627 						if ( entity->sprite >= 59 && entity->sprite < 64 )
5628 						{
5629 							entity->flags[INVISIBLE] = false; // show magicstaffs
5630 						}
5631 						if ( multiplayer != CLIENT && !stats[PLAYER_NUM]->weapon )
5632 						{
5633 							entity->flags[INVISIBLE] = true; // show magicstaffs
5634 						}
5635 					}
5636 				}
5637 			}
5638 		}
5639 		// rotate shield a bit
5640 		node_t* shieldNode = list_Node(&my->children, 7);
5641 		if ( shieldNode )
5642 		{
5643 			Entity* shieldEntity = (Entity*)shieldNode->element;
5644 			if ( shieldEntity->sprite != items[TOOL_TORCH].index && shieldEntity->sprite != items[TOOL_LANTERN].index && shieldEntity->sprite != items[TOOL_CRYSTALSHARD].index )
5645 			{
5646 				shieldEntity->yaw -= PI / 6;
5647 			}
5648 		}
5649 	}
5650 	else
5651 	{
5652 		if ( stats[PLAYER_NUM]->type == RAT )
5653 		{
5654 			playerAnimateRat(my);
5655 		}
5656 		else if ( stats[PLAYER_NUM]->type == SPIDER )
5657 		{
5658 			playerAnimateSpider(my);
5659 		}
5660 	}
5661 	if ( PLAYER_ATTACK != 0 )
5662 	{
5663 		PLAYER_ATTACKTIME++;
5664 	}
5665 	else
5666 	{
5667 		PLAYER_ATTACKTIME = 0;
5668 	}
5669 
5670 	handlePlayerCameraPosition(my, PLAYER_NUM, false);
5671 }
5672 
5673 // client function
actPlayerLimb(Entity * my)5674 void actPlayerLimb(Entity* my)
5675 {
5676 	int i;
5677 
5678 	Entity* parent = uidToEntity(my->parent);
5679 
5680 	if ( multiplayer == CLIENT )
5681 	{
5682 		if ( stats[PLAYER_NUM]->HP <= 0 )
5683 		{
5684 			if ( parent && parent->getMonsterTypeFromSprite() == AUTOMATON )
5685 			{
5686 				if ( parent->playerAutomatonDeathCounter != 0 )
5687 				{
5688 					my->flags[INVISIBLE] = false;
5689 				}
5690 				else
5691 				{
5692 					my->flags[INVISIBLE] = true;
5693 				}
5694 			}
5695 			else
5696 			{
5697 				my->flags[INVISIBLE] = true;
5698 			}
5699 			return;
5700 		}
5701 	}
5702 
5703 	if ( parent && multiplayer != CLIENT )
5704 	{
5705 		for ( i = 0; i < MAXPLAYERS; i++ )
5706 		{
5707 			if ( inrange[i] )
5708 			{
5709 				if ( i == 0 && selectedEntity == my )
5710 				{
5711 					parent->skill[14] = i + 1;
5712 				}
5713 				else if ( client_selected[i] == my )
5714 				{
5715 					parent->skill[14] = i + 1;
5716 				}
5717 			}
5718 		}
5719 	}
5720 
5721 	if ( parent && parent->monsterEntityRenderAsTelepath == 1 )
5722 	{
5723 		my->monsterEntityRenderAsTelepath = 1;
5724 	}
5725 	else
5726 	{
5727 		my->monsterEntityRenderAsTelepath = 0;
5728 	}
5729 
5730 	if (multiplayer != CLIENT)
5731 	{
5732 		return;
5733 	}
5734 
5735 	if (my->skill[2] < 0 || my->skill[2] >= MAXPLAYERS )
5736 	{
5737 		return;
5738 	}
5739 	if (players[my->skill[2]] == nullptr || players[my->skill[2]]->entity == nullptr)
5740 	{
5741 		list_RemoveNode(my->mynode);
5742 		return;
5743 	}
5744 
5745 	//TODO: These three are _NOT_ PLAYERSWAP
5746 	//my->vel_x = players[my->skill[2]]->vel_x;
5747 	//my->vel_y = players[my->skill[2]]->vel_y;
5748 	//my->vel_z = players[my->skill[2]]->vel_z;
5749 
5750 	if ( stats[PLAYER_NUM] )
5751 	{
5752 		if ( stats[PLAYER_NUM]->type == RAT
5753 			|| stats[PLAYER_NUM]->type == SPIDER
5754 			|| stats[PLAYER_NUM]->type == TROLL
5755 			|| stats[PLAYER_NUM]->type == CREATURE_IMP )
5756 		{
5757 			players[PLAYER_NUM]->entity->skill[1] = 0;
5758 			return;
5759 		}
5760 	}
5761 
5762 	// set light size
5763 	if (my->sprite == 93)   // torch
5764 	{
5765 		my->skill[4] = 1;
5766 		players[my->skill[2]]->entity->skill[1] = 6;
5767 	}
5768 	else if (my->sprite == 94)     // lantern
5769 	{
5770 		my->skill[4] = 1;
5771 		players[my->skill[2]]->entity->skill[1] = 9;
5772 	}
5773 	else if ( my->sprite == 529 )	// crystal shard
5774 	{
5775 		my->skill[4] = 1;
5776 		players[my->skill[2]]->entity->skill[1] = 4;
5777 	}
5778 	else
5779 	{
5780 		if (my->skill[4] == 1)
5781 		{
5782 			players[my->skill[2]]->entity->skill[1] = 0;
5783 		}
5784 	}
5785 
5786 }
5787 
playerLevelEntrySpeechSecond()5788 void Entity::playerLevelEntrySpeechSecond()
5789 {
5790 	int timeDiff = playerAliveTime - 300;
5791 	int orangeSpeechVolume = 128;
5792 	int blueSpeechVolume = 112;
5793 	if ( timeDiff > 0 && playerLevelEntrySpeech > 0 && !secretlevel )
5794 	{
5795 		switch ( currentlevel )
5796 		{
5797 			case 26:
5798 				switch ( playerLevelEntrySpeech )
5799 				{
5800 					case 1:
5801 						if ( timeDiff == 200 )
5802 						{
5803 							playSound(342, orangeSpeechVolume);
5804 							messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2616]);
5805 							playerLevelEntrySpeech = 0;
5806 						}
5807 						break;
5808 					case 2:
5809 						if ( timeDiff == 200 )
5810 						{
5811 							playSound(344, blueSpeechVolume);
5812 							messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2618]);
5813 						}
5814 						else if ( timeDiff == 350 )
5815 						{
5816 							playSound(345, orangeSpeechVolume);
5817 							messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2619]);
5818 							playerLevelEntrySpeech = 0;
5819 						}
5820 						break;
5821 					case 3:
5822 						if ( timeDiff == 200 )
5823 						{
5824 							playSound(347, blueSpeechVolume);
5825 							messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2621]);
5826 						}
5827 						else if ( timeDiff == 350 )
5828 						{
5829 							playSound(348, orangeSpeechVolume);
5830 							messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2622]);
5831 							playerLevelEntrySpeech = 0;
5832 						}
5833 						break;
5834 					default:
5835 						break;
5836 				}
5837 				break;
5838 			case 28:
5839 				switch ( playerLevelEntrySpeech )
5840 				{
5841 					case 1:
5842 						if ( timeDiff == 200 )
5843 						{
5844 							playSound(350, orangeSpeechVolume);
5845 							messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2630]);
5846 						}
5847 						else if ( timeDiff == 350 )
5848 						{
5849 							playSound(351, blueSpeechVolume);
5850 							messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2631]);
5851 							playerLevelEntrySpeech = 0;
5852 						}
5853 						break;
5854 					case 2:
5855 						if ( timeDiff == 350 )
5856 						{
5857 							playSound(353, blueSpeechVolume);
5858 							messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2633]);
5859 							playerLevelEntrySpeech = 0;
5860 						}
5861 						break;
5862 					case 3:
5863 						if ( timeDiff == 200 )
5864 						{
5865 							playSound(355, orangeSpeechVolume);
5866 							messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2635]);
5867 							playerLevelEntrySpeech = 0;
5868 						}
5869 						break;
5870 					default:
5871 						break;
5872 				}
5873 				break;
5874 			case 30:
5875 				switch ( playerLevelEntrySpeech )
5876 				{
5877 					case 1:
5878 						if ( timeDiff == 350 )
5879 						{
5880 							playSound(357, orangeSpeechVolume);
5881 							messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2637]);
5882 						}
5883 						else if ( timeDiff == 500 )
5884 						{
5885 							messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2652]);
5886 							playerLevelEntrySpeech = 0;
5887 						}
5888 						break;
5889 					default:
5890 						break;
5891 				}
5892 				break;
5893 			case 31:
5894 				switch ( playerLevelEntrySpeech )
5895 				{
5896 					case 1:
5897 						if ( timeDiff == 350 )
5898 						{
5899 							playSound(359, orangeSpeechVolume);
5900 							messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2639]);
5901 						}
5902 						else if ( timeDiff == 510 )
5903 						{
5904 							messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2653]);
5905 							playerLevelEntrySpeech = 0;
5906 						}
5907 						break;
5908 					default:
5909 						break;
5910 				}
5911 				break;
5912 			case 33:
5913 				switch ( playerLevelEntrySpeech )
5914 				{
5915 					case 1:
5916 						if ( timeDiff == 200 )
5917 						{
5918 							playSound(361, blueSpeechVolume);
5919 							messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2641]);
5920 							playerLevelEntrySpeech = 0;
5921 						}
5922 						break;
5923 					case 2:
5924 						if ( timeDiff == 350 )
5925 						{
5926 							playSound(363, orangeSpeechVolume);
5927 							messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2643]);
5928 							playerLevelEntrySpeech = 0;
5929 						}
5930 						break;
5931 					default:
5932 						break;
5933 				}
5934 				break;
5935 			case 35:
5936 				switch ( playerLevelEntrySpeech )
5937 				{
5938 					case 1:
5939 						if ( timeDiff == 310 )
5940 						{
5941 							playSound(365, blueSpeechVolume);
5942 							messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2645]);
5943 							playerLevelEntrySpeech = 0;
5944 						}
5945 						break;
5946 					default:
5947 						break;
5948 				}
5949 				break;
5950 			case 27:
5951 			case 29:
5952 			case 32:
5953 			case 34:
5954 				if ( minotaurlevel )
5955 				{
5956 					switch ( playerLevelEntrySpeech )
5957 					{
5958 						case 1:
5959 							if ( timeDiff == 200 )
5960 							{
5961 								playSound(367, orangeSpeechVolume);
5962 								messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2624]);
5963 								playerLevelEntrySpeech = 0;
5964 							}
5965 							break;
5966 						case 2:
5967 							if ( timeDiff == 200 )
5968 							{
5969 								playSound(369, blueSpeechVolume);
5970 								messagePlayerColor(clientnum, uint32ColorBaronyBlue(*mainsurface), language[2626]);
5971 								playerLevelEntrySpeech = 0;
5972 							}
5973 							break;
5974 						case 3:
5975 							if ( timeDiff == 200 )
5976 							{
5977 								playSound(371, orangeSpeechVolume);
5978 								messagePlayerColor(clientnum, uint32ColorOrange(*mainsurface), language[2628]);
5979 								playerLevelEntrySpeech = 0;
5980 							}
5981 							break;
5982 						default:
5983 							break;
5984 					}
5985 					break;
5986 				}
5987 				break;
5988 			default:
5989 				break;
5990 		}
5991 
5992 	}
5993 }
5994 
isPlayerHeadSprite()5995 bool Entity::isPlayerHeadSprite()
5996 {
5997 	switch ( sprite )
5998 	{
5999 		case 113:
6000 		case 114:
6001 		case 115:
6002 		case 116:
6003 		case 117:
6004 		case 125:
6005 		case 126:
6006 		case 127:
6007 		case 128:
6008 		case 129:
6009 		case 332:
6010 		case 333:
6011 		case 341:
6012 		case 342:
6013 		case 343:
6014 		case 344:
6015 		case 345:
6016 		case 346:
6017 		case 354:
6018 		case 355:
6019 		case 356:
6020 		case 357:
6021 		case 358:
6022 		case 359:
6023 		case 367:
6024 		case 368:
6025 		case 369:
6026 		case 370:
6027 		case 371:
6028 		case 372:
6029 		case 380:
6030 		case 381:
6031 		case 382:
6032 		case 383:
6033 		case 384:
6034 		case 385:
6035 		case 686:
6036 		case 694:
6037 		case 702:
6038 		case 710:
6039 		case 718:
6040 		case 726:
6041 		case 734:
6042 		case 742:
6043 		case 752:
6044 		case 756:
6045 		case 760:
6046 		case 768:
6047 		case 770:
6048 		case 814:
6049 		case 817:
6050 		case 823:
6051 		case 827:
6052 			// TODO
6053 			return true;
6054 			break;
6055 		default:
6056 			break;
6057 	}
6058 	return false;
6059 }
6060 
getMonsterFromPlayerRace(int playerRace)6061 Monster Entity::getMonsterFromPlayerRace(int playerRace)
6062 {
6063 	switch ( playerRace )
6064 	{
6065 		case RACE_HUMAN:
6066 			return HUMAN;
6067 			break;
6068 		case RACE_SKELETON:
6069 			return SKELETON;
6070 			break;
6071 		case RACE_INCUBUS:
6072 			return INCUBUS;
6073 			/*if ( stats[this->skill[2]]->sex == FEMALE )
6074 			{
6075 				return SUCCUBUS;
6076 			}
6077 			else
6078 			{
6079 			}*/
6080 			break;
6081 		case RACE_GOBLIN:
6082 			return GOBLIN;
6083 			break;
6084 		case RACE_AUTOMATON:
6085 			return AUTOMATON;
6086 			break;
6087 		case RACE_INSECTOID:
6088 			return INSECTOID;
6089 			break;
6090 		case RACE_GOATMAN:
6091 			return GOATMAN;
6092 			break;
6093 		case RACE_VAMPIRE:
6094 			return VAMPIRE;
6095 			break;
6096 		case RACE_SUCCUBUS:
6097 			return SUCCUBUS;
6098 			break;
6099 		case RACE_RAT:
6100 			return RAT;
6101 			break;
6102 		case RACE_TROLL:
6103 			return TROLL;
6104 			break;
6105 		case RACE_SPIDER:
6106 			return SPIDER;
6107 			break;
6108 		case RACE_IMP:
6109 			return CREATURE_IMP;
6110 			break;
6111 		default:
6112 			return HUMAN;
6113 			break;
6114 	}
6115 	return HUMAN;
6116 }
6117 
setDefaultPlayerModel(int playernum,Monster playerRace,int limbType)6118 void Entity::setDefaultPlayerModel(int playernum, Monster playerRace, int limbType)
6119 {
6120 	if ( !players[playernum] || !players[playernum]->entity )
6121 	{
6122 		return;
6123 	}
6124 
6125 	int playerAppearance = stats[playernum]->appearance;
6126 	if ( players[playernum] && players[playernum]->entity && players[playernum]->entity->effectPolymorph > NUMMONSTERS )
6127 	{
6128 		playerAppearance = players[playernum]->entity->effectPolymorph - 100;
6129 	}
6130 
6131 	if ( limbType == LIMB_HUMANOID_TORSO )
6132 	{
6133 		if ( playerRace == HUMAN )
6134 		{
6135 			switch ( playerAppearance / 6 )
6136 			{
6137 				case 1:
6138 					this->sprite = 334 + 13 * stats[playernum]->sex;
6139 					break;
6140 				case 2:
6141 					this->sprite = 360 + 13 * stats[playernum]->sex;
6142 					break;
6143 				default:
6144 					this->sprite = 106 + 12 * stats[playernum]->sex;
6145 					break;
6146 			}
6147 		}
6148 		else
6149 		{
6150 			switch ( playerRace )
6151 			{
6152 				case SKELETON:
6153 					this->sprite = 687;
6154 					break;
6155 				case GOBLIN:
6156 					if ( stats[playernum]->sex == FEMALE )
6157 					{
6158 						this->sprite = 753;
6159 					}
6160 					else
6161 					{
6162 						this->sprite = 695;
6163 					}
6164 					break;
6165 				case CREATURE_IMP:
6166 					this->sprite = 828;
6167 					break;
6168 				case INCUBUS:
6169 					this->sprite = 703;
6170 					break;
6171 				case SUCCUBUS:
6172 					this->sprite = 711;
6173 					break;
6174 				case VAMPIRE:
6175 					if ( stats[playernum]->sex == FEMALE )
6176 					{
6177 						this->sprite = 757;
6178 					}
6179 					else
6180 					{
6181 						this->sprite = 719;
6182 					}
6183 					break;
6184 				case INSECTOID:
6185 					if ( stats[playernum]->sex == FEMALE )
6186 					{
6187 						this->sprite = 761;
6188 					}
6189 					else
6190 					{
6191 						this->sprite = 727;
6192 					}
6193 					break;
6194 				case GOATMAN:
6195 					if ( stats[playernum]->sex == FEMALE )
6196 					{
6197 						this->sprite = 769;
6198 					}
6199 					else
6200 					{
6201 						this->sprite = 735;
6202 					}
6203 					break;
6204 				case AUTOMATON:
6205 					this->sprite = 743;
6206 					break;
6207 				case TROLL:
6208 					this->sprite = 818;
6209 					break;
6210 				default:
6211 					break;
6212 			}
6213 		}
6214 	}
6215 	else if ( limbType == LIMB_HUMANOID_RIGHTLEG )
6216 	{
6217 		if ( playerRace == HUMAN )
6218 		{
6219 			switch ( playerAppearance / 6 )
6220 			{
6221 				case 1:
6222 					this->sprite = 335 + 13 * stats[playernum]->sex;
6223 					break;
6224 				case 2:
6225 					this->sprite = 361 + 13 * stats[playernum]->sex;
6226 					break;
6227 				default:
6228 					this->sprite = 107 + 12 * stats[playernum]->sex;
6229 					break;
6230 			}
6231 		}
6232 		else
6233 		{
6234 			switch ( playerRace )
6235 			{
6236 				case SKELETON:
6237 					this->sprite = 693;
6238 					break;
6239 				case GOBLIN:
6240 					if ( stats[playernum]->sex == FEMALE )
6241 					{
6242 						this->sprite = 755;
6243 					}
6244 					else
6245 					{
6246 						this->sprite = 701;
6247 					}
6248 					break;
6249 				case CREATURE_IMP:
6250 					this->sprite = 830;
6251 					break;
6252 				case INCUBUS:
6253 					this->sprite = 709;
6254 					break;
6255 				case SUCCUBUS:
6256 					this->sprite = 717;
6257 					break;
6258 				case VAMPIRE:
6259 					if ( stats[playernum]->sex == FEMALE )
6260 					{
6261 						this->sprite = 759;
6262 					}
6263 					else
6264 					{
6265 						this->sprite = 725;
6266 					}
6267 					break;
6268 				case INSECTOID:
6269 					if ( stats[playernum]->sex == FEMALE )
6270 					{
6271 						this->sprite = 767;
6272 					}
6273 					else
6274 					{
6275 						this->sprite = 733;
6276 					}
6277 					break;
6278 				case GOATMAN:
6279 					this->sprite = 741;
6280 					break;
6281 				case AUTOMATON:
6282 					this->sprite = 749;
6283 					break;
6284 				case TROLL:
6285 					this->sprite = 822;
6286 					break;
6287 				default:
6288 					break;
6289 			}
6290 		}
6291 	}
6292 	else if ( limbType == LIMB_HUMANOID_LEFTLEG )
6293 	{
6294 		if ( playerRace == HUMAN )
6295 		{
6296 			switch ( playerAppearance / 6 )
6297 			{
6298 				case 1:
6299 					this->sprite = 336 + 13 * stats[playernum]->sex;
6300 					break;
6301 				case 2:
6302 					this->sprite = 362 + 13 * stats[playernum]->sex;
6303 					break;
6304 				default:
6305 					this->sprite = 108 + 12 * stats[playernum]->sex;
6306 					break;
6307 			}
6308 		}
6309 		else
6310 		{
6311 			switch ( playerRace )
6312 			{
6313 				case SKELETON:
6314 					this->sprite = 692;
6315 					break;
6316 				case GOBLIN:
6317 					if ( stats[playernum]->sex == FEMALE )
6318 					{
6319 						this->sprite = 754;
6320 					}
6321 					else
6322 					{
6323 						this->sprite = 700;
6324 					}
6325 					break;
6326 				case CREATURE_IMP:
6327 					this->sprite = 829;
6328 					break;
6329 				case INCUBUS:
6330 					this->sprite = 708;
6331 					break;
6332 				case SUCCUBUS:
6333 					this->sprite = 716;
6334 					break;
6335 				case VAMPIRE:
6336 					if ( stats[playernum]->sex == FEMALE )
6337 					{
6338 						this->sprite = 758;
6339 					}
6340 					else
6341 					{
6342 						this->sprite = 724;
6343 					}
6344 					break;
6345 				case INSECTOID:
6346 					if ( stats[playernum]->sex == FEMALE )
6347 					{
6348 						this->sprite = 766;
6349 					}
6350 					else
6351 					{
6352 						this->sprite = 732;
6353 					}
6354 					break;
6355 				case GOATMAN:
6356 					this->sprite = 740;
6357 					break;
6358 				case AUTOMATON:
6359 					this->sprite = 748;
6360 					break;
6361 				case TROLL:
6362 					this->sprite = 821;
6363 					break;
6364 				default:
6365 					break;
6366 			}
6367 		}
6368 	}
6369 	else if ( limbType == LIMB_HUMANOID_RIGHTARM )
6370 	{
6371 		if ( playerRace == HUMAN )
6372 		{
6373 			switch ( playerAppearance / 6 )
6374 			{
6375 				case 1:
6376 					this->sprite = 337 + 13 * stats[playernum]->sex;
6377 					break;
6378 				case 2:
6379 					this->sprite = 363 + 13 * stats[playernum]->sex;
6380 					break;
6381 				default:
6382 					this->sprite = 109 + 12 * stats[playernum]->sex;
6383 					break;
6384 			}
6385 		}
6386 		else
6387 		{
6388 			switch ( playerRace )
6389 			{
6390 				case SKELETON:
6391 					this->sprite = 689;
6392 					break;
6393 				case GOBLIN:
6394 					this->sprite = 697;
6395 					break;
6396 				case CREATURE_IMP:
6397 					this->sprite = 832;
6398 					break;
6399 				case INCUBUS:
6400 					this->sprite = 705;
6401 					break;
6402 				case SUCCUBUS:
6403 					this->sprite = 713;
6404 					break;
6405 				case VAMPIRE:
6406 					this->sprite = 721;
6407 					break;
6408 				case INSECTOID:
6409 					if ( stats[playernum]->sex == FEMALE )
6410 					{
6411 						this->sprite = 763;
6412 					}
6413 					else
6414 					{
6415 						this->sprite = 729;
6416 					}
6417 					break;
6418 				case GOATMAN:
6419 					this->sprite = 737;
6420 					break;
6421 				case AUTOMATON:
6422 					this->sprite = 745;
6423 					break;
6424 				case TROLL:
6425 					this->sprite = 820;
6426 					break;
6427 				default:
6428 					break;
6429 			}
6430 		}
6431 	}
6432 	else if ( limbType == LIMB_HUMANOID_LEFTARM )
6433 	{
6434 		if ( playerRace == HUMAN )
6435 		{
6436 			switch ( playerAppearance / 6 )
6437 			{
6438 				case 1:
6439 					this->sprite = 338 + 13 * stats[playernum]->sex;
6440 					break;
6441 				case 2:
6442 					this->sprite = 364 + 13 * stats[playernum]->sex;
6443 					break;
6444 				default:
6445 					this->sprite = 110 + 12 * stats[playernum]->sex;
6446 					break;
6447 			}
6448 		}
6449 		else
6450 		{
6451 			switch ( playerRace )
6452 			{
6453 				case SKELETON:
6454 					this->sprite = 688;
6455 					break;
6456 				case GOBLIN:
6457 					this->sprite = 696;
6458 					break;
6459 				case CREATURE_IMP:
6460 					this->sprite = 831;
6461 					break;
6462 				case INCUBUS:
6463 					this->sprite = 704;
6464 					break;
6465 				case SUCCUBUS:
6466 					this->sprite = 712;
6467 					break;
6468 				case VAMPIRE:
6469 					this->sprite = 720;
6470 					break;
6471 				case INSECTOID:
6472 					if ( stats[playernum]->sex == FEMALE )
6473 					{
6474 						this->sprite = 762;
6475 					}
6476 					else
6477 					{
6478 						this->sprite = 728;
6479 					}
6480 					break;
6481 				case GOATMAN:
6482 					this->sprite = 736;
6483 					break;
6484 				case AUTOMATON:
6485 					this->sprite = 744;
6486 					break;
6487 				case TROLL:
6488 					this->sprite = 819;
6489 					break;
6490 				default:
6491 					break;
6492 			}
6493 		}
6494 	}
6495 }
6496 
playerRequiresBloodToSustain()6497 bool Entity::playerRequiresBloodToSustain()
6498 {
6499 	if ( behavior != &actPlayer )
6500 	{
6501 		return false;
6502 	}
6503 	if ( !stats[skill[2]] )
6504 	{
6505 		return false;
6506 	}
6507 
6508 	if ( stats[skill[2]]->type == VAMPIRE )
6509 	{
6510 		return true;
6511 	}
6512 	if ( stats[skill[2]]->EFFECTS[EFF_VAMPIRICAURA] || client_classes[skill[2]] == CLASS_ACCURSED )
6513 	{
6514 		return true;
6515 	}
6516 	if ( stats[skill[2]]->playerRace == VAMPIRE && stats[skill[2]]->appearance == 0 )
6517 	{
6518 		return true;
6519 	}
6520 
6521 	return false;
6522 }
6523 
playerAnimateRat(Entity * my)6524 void playerAnimateRat(Entity* my)
6525 {
6526 	node_t* node = nullptr;
6527 	int bodypart = 0;
6528 	for ( bodypart = 0, node = my->children.first; node != NULL; node = node->next, bodypart++ )
6529 	{
6530 		if ( bodypart == 0 )
6531 		{
6532 			my->focalx = -2;
6533 			continue;
6534 		}
6535 		Entity* entity = (Entity*)node->element;
6536 		entity->x = my->x;
6537 		entity->y = my->y;
6538 		entity->z = my->z;
6539 		if ( bodypart == 1 )
6540 		{
6541 			if ( entity->sprite != 815 && entity->sprite != 816 )
6542 			{
6543 				entity->sprite = 815;
6544 			}
6545 			entity->focalx = -2;
6546 			if ( fabs(PLAYER_VELX) > 0.1 || fabs(PLAYER_VELY) > 0.1 )
6547 			{
6548 				if ( (ticks % 10 == 0) )
6549 				{
6550 					if ( entity->sprite == 815 )
6551 					{
6552 						entity->sprite = 816;
6553 					}
6554 					else
6555 					{
6556 						entity->sprite = 815;
6557 					}
6558 				}
6559 			}
6560 		}
6561 		else if ( bodypart > 1 )
6562 		{
6563 			entity->flags[INVISIBLE] = true;
6564 		}
6565 		if ( multiplayer == SERVER )
6566 		{
6567 			// update sprites for clients
6568 			if ( entity->skill[10] != entity->sprite )
6569 			{
6570 				entity->skill[10] = entity->sprite;
6571 				serverUpdateEntityBodypart(my, bodypart);
6572 			}
6573 			if ( entity->skill[11] != entity->flags[INVISIBLE] )
6574 			{
6575 				entity->skill[11] = entity->flags[INVISIBLE];
6576 				serverUpdateEntityBodypart(my, bodypart);
6577 			}
6578 			if ( PLAYER_ALIVETIME == TICKS_PER_SECOND + bodypart )
6579 			{
6580 				serverUpdateEntityBodypart(my, bodypart);
6581 			}
6582 		}
6583 		entity->yaw = my->yaw;
6584 	}
6585 }
6586 
playerAnimateSpider(Entity * my)6587 void playerAnimateSpider(Entity* my)
6588 {
6589 	node_t* node = nullptr;
6590 	int bodypart = 0;
6591 	for ( bodypart = 0, node = my->children.first; node != NULL; node = node->next, bodypart++ )
6592 	{
6593 		Entity* entity = (Entity*)node->element;
6594 		if ( bodypart == 0 )
6595 		{
6596 			// hudweapon case
6597 			continue;
6598 		}
6599 		if ( bodypart < 11 )
6600 		{
6601 			entity->flags[INVISIBLE] = true;
6602 			if ( multiplayer == SERVER )
6603 			{
6604 				// update sprites for clients
6605 				if ( entity->skill[10] != entity->sprite )
6606 				{
6607 					entity->skill[10] = entity->sprite;
6608 					serverUpdateEntityBodypart(my, bodypart);
6609 				}
6610 				if ( entity->skill[11] != entity->flags[INVISIBLE] )
6611 				{
6612 					entity->skill[11] = entity->flags[INVISIBLE];
6613 					serverUpdateEntityBodypart(my, bodypart);
6614 				}
6615 				if ( PLAYER_ALIVETIME == TICKS_PER_SECOND + bodypart )
6616 				{
6617 					serverUpdateEntityBodypart(my, bodypart);
6618 				}
6619 			}
6620 			continue;
6621 		}
6622 		Entity* previous = NULL; // previous part
6623 		if ( bodypart > 11 )
6624 		{
6625 			previous = (Entity*)node->prev->element;
6626 		}
6627 		entity->x = my->x;
6628 		entity->y = my->y;
6629 		entity->z = my->z;
6630 		entity->yaw = my->yaw;
6631 
6632 		entity->roll = my->roll;
6633 
6634 		if ( bodypart > 12 )
6635 		{
6636 			entity->pitch = -my->pitch;
6637 			entity->pitch = std::max(-PI / 32, std::min(PI / 32, entity->pitch));
6638 			if ( bodypart % 2 == 0 )
6639 			{
6640 				entity->sprite = 826;
6641 				entity->focalx = limbs[SPIDER][4][0]; // 3
6642 				entity->focaly = limbs[SPIDER][4][1]; // 0
6643 				entity->focalz = limbs[SPIDER][4][2]; // 0
6644 			}
6645 			else
6646 			{
6647 				entity->sprite = 825;
6648 				entity->focalx = limbs[SPIDER][3][0]; // 1
6649 				entity->focaly = limbs[SPIDER][3][1]; // 0
6650 				entity->focalz = limbs[SPIDER][3][2]; // -1
6651 			}
6652 		}
6653 
6654 		if ( bodypart == 11 || bodypart == 12 )
6655 		{
6656 			if ( PLAYER_ATTACK >= 1 && PLAYER_ATTACK <= 3 )
6657 			{
6658 				// vertical chop
6659 				if ( PLAYER_ATTACKTIME == 0 )
6660 				{
6661 					entity->pitch = 0;
6662 					entity->roll = 0;
6663 					entity->skill[1] = 0;
6664 				}
6665 				else
6666 				{
6667 					if ( entity->skill[1] == 0 )
6668 					{
6669 						// upswing
6670 						if ( limbAnimateToLimit(entity, ANIMATE_PITCH, -0.5, 5 * PI / 4, false, 0.0) )
6671 						{
6672 							entity->skill[1] = 1;
6673 						}
6674 					}
6675 					else
6676 					{
6677 						if ( entity->pitch >= 3 * PI / 2 )
6678 						{
6679 							PLAYER_ARMBENDED = 1;
6680 						}
6681 						if ( limbAnimateToLimit(entity, ANIMATE_PITCH, 0.3, 0, false, 0.0) )
6682 						{
6683 							entity->skill[1] = 0;
6684 							entity->roll = 0;
6685 							PLAYER_ARMBENDED = 0;
6686 							PLAYER_ATTACK = 0;
6687 						}
6688 					}
6689 				}
6690 			}
6691 		}
6692 
6693 		entity->flags[INVISIBLE] = my->flags[INVISIBLE];
6694 
6695 		switch ( bodypart )
6696 		{
6697 			// right pedipalp
6698 			case 11:
6699 				entity->sprite = 824;
6700 				entity->focalx = limbs[SPIDER][1][0]; // 1
6701 				entity->focaly = limbs[SPIDER][1][1]; // 0
6702 				entity->focalz = limbs[SPIDER][1][2]; // 1
6703 				entity->x += cos(my->yaw) * 2 + cos(my->yaw + PI / 2) * 2;
6704 				entity->y += sin(my->yaw) * 2 + sin(my->yaw + PI / 2) * 2;
6705 				entity->yaw += PI / 10;
6706 				if ( PLAYER_ATTACK == 0 )
6707 				{
6708 					entity->pitch = my->pitch;
6709 					entity->pitch -= PI / 8;
6710 				}
6711 				break;
6712 				// left pedipalp
6713 			case 12:
6714 				entity->sprite = 824;
6715 				entity->focalx = limbs[SPIDER][2][0]; // 1
6716 				entity->focaly = limbs[SPIDER][2][1]; // 0
6717 				entity->focalz = limbs[SPIDER][2][2]; // 1
6718 				entity->x += cos(my->yaw) * 2 - cos(my->yaw + PI / 2) * 2;
6719 				entity->y += sin(my->yaw) * 2 - sin(my->yaw + PI / 2) * 2;
6720 				entity->yaw -= PI / 10;
6721 				if ( PLAYER_ATTACK == 0 )
6722 				{
6723 					entity->pitch = my->pitch;
6724 					entity->pitch -= PI / 8;
6725 				}
6726 				break;
6727 
6728 				// 1st/5th leg:
6729 				// thigh
6730 			case 13:
6731 			case 21:
6732 				entity->x += cos(my->yaw) * 1 + cos(my->yaw + PI / 2) * 2.5 * (1 - 2 * (bodypart > 20));
6733 				entity->y += sin(my->yaw) * 1 + sin(my->yaw + PI / 2) * 2.5 * (1 - 2 * (bodypart > 20));
6734 				if ( (fabs(PLAYER_VELX) > 0.1 || fabs(PLAYER_VELY) > 0.1) )
6735 				{
6736 					if ( !entity->skill[0] )
6737 					{
6738 						entity->fskill[0] += .1;
6739 						if ( entity->fskill[0] >= 1 )
6740 						{
6741 							entity->fskill[0] = 1;
6742 							entity->skill[0] = 1;
6743 						}
6744 					}
6745 					else
6746 					{
6747 						entity->fskill[0] -= .1;
6748 						if ( entity->fskill[0] <= 0 )
6749 						{
6750 							entity->fskill[0] = 0;
6751 							entity->skill[0] = 0;
6752 						}
6753 					}
6754 				}
6755 				entity->z += entity->fskill[0];
6756 				entity->yaw += PI / 6 * (1 - 2 * (bodypart > 20));
6757 				entity->pitch += PI / 4;
6758 				break;
6759 				// shin
6760 			case 14:
6761 			case 22:
6762 				entity->x = previous->x;
6763 				entity->y = previous->y;
6764 				entity->z = previous->z;
6765 				entity->yaw = previous->yaw;
6766 				entity->pitch = previous->pitch;
6767 				entity->x += cos(my->yaw) * 3 + cos(my->yaw + PI / 2) * 2 * (1 - 2 * (bodypart > 20));
6768 				entity->y += sin(my->yaw) * 3 + sin(my->yaw + PI / 2) * 2 * (1 - 2 * (bodypart > 20));
6769 				entity->z += .5;
6770 				entity->pitch += PI / 6 - PI / 4;
6771 				entity->pitch -= (PI / 10) * (previous->z - my->z);
6772 				break;
6773 
6774 				// 2nd/6th leg:
6775 				// thigh
6776 			case 15:
6777 			case 23:
6778 				entity->x += cos(my->yaw + PI / 2) * 3 * (1 - 2 * (bodypart > 20));
6779 				entity->y += sin(my->yaw + PI / 2) * 3 * (1 - 2 * (bodypart > 20));
6780 				if ( (fabs(PLAYER_VELX) > 0.1 || fabs(PLAYER_VELY) > 0.1) )
6781 				{
6782 					if ( !entity->skill[0] )
6783 					{
6784 						entity->fskill[0] += .1;
6785 						if ( entity->fskill[0] >= 1 )
6786 						{
6787 							entity->fskill[0] = 1;
6788 							entity->skill[0] = 1;
6789 						}
6790 					}
6791 					else
6792 					{
6793 						entity->fskill[0] -= .1;
6794 						if ( entity->fskill[0] <= 0 )
6795 						{
6796 							entity->fskill[0] = 0;
6797 							entity->skill[0] = 0;
6798 						}
6799 					}
6800 				}
6801 				entity->z += entity->fskill[0];
6802 				entity->yaw += PI / 3 * (1 - 2 * (bodypart > 20));
6803 				entity->pitch += PI / 4;
6804 				break;
6805 				// shin
6806 			case 16:
6807 			case 24:
6808 				entity->x = previous->x;
6809 				entity->y = previous->y;
6810 				entity->z = previous->z;
6811 				entity->yaw = previous->yaw;
6812 				entity->pitch = previous->pitch;
6813 				entity->x += cos(my->yaw) * 1.75 + cos(my->yaw + PI / 2) * 3 * (1 - 2 * (bodypart > 20));
6814 				entity->y += sin(my->yaw) * 1.75 + sin(my->yaw + PI / 2) * 3 * (1 - 2 * (bodypart > 20));
6815 				entity->z += .5;
6816 				entity->pitch += PI / 6 - PI / 4;
6817 				entity->pitch -= (PI / 10) * (previous->z - my->z);
6818 				break;
6819 
6820 				// 3rd/7th leg:
6821 				// thigh
6822 			case 17:
6823 			case 25:
6824 				entity->x += cos(my->yaw) * -.5 + cos(my->yaw + PI / 2) * 2 * (1 - 2 * (bodypart > 20));
6825 				entity->y += sin(my->yaw) * -.5 + sin(my->yaw + PI / 2) * 2 * (1 - 2 * (bodypart > 20));
6826 				if ( (fabs(PLAYER_VELX) > 0.1 || fabs(PLAYER_VELY) > 0.1) )
6827 				{
6828 					if ( !entity->skill[0] )
6829 					{
6830 						entity->fskill[0] += .1;
6831 						if ( entity->fskill[0] >= 1 )
6832 						{
6833 							entity->fskill[0] = 1;
6834 							entity->skill[0] = 1;
6835 						}
6836 					}
6837 					else
6838 					{
6839 						entity->fskill[0] -= .1;
6840 						if ( entity->fskill[0] <= 0 )
6841 						{
6842 							entity->fskill[0] = 0;
6843 							entity->skill[0] = 0;
6844 						}
6845 					}
6846 				}
6847 				entity->z += entity->fskill[0];
6848 				entity->yaw += (PI / 2 + PI / 8) * (1 - 2 * (bodypart > 20));
6849 				entity->pitch += PI / 4;
6850 				break;
6851 				// shin
6852 			case 18:
6853 			case 26:
6854 				entity->x = previous->x;
6855 				entity->y = previous->y;
6856 				entity->z = previous->z;
6857 				entity->yaw = previous->yaw;
6858 				entity->pitch = previous->pitch;
6859 				entity->x += cos(my->yaw) * -1.25 + cos(my->yaw + PI / 2) * 3.25 * (1 - 2 * (bodypart > 20));
6860 				entity->y += sin(my->yaw) * -1.25 + sin(my->yaw + PI / 2) * 3.25 * (1 - 2 * (bodypart > 20));
6861 				entity->z += .5;
6862 				entity->pitch += PI / 6 - PI / 4;
6863 				entity->pitch -= (PI / 10) * (previous->z - my->z);
6864 				break;
6865 
6866 				// 4th/8th leg:
6867 				// thigh
6868 			case 19:
6869 			case 27:
6870 				entity->x += cos(my->yaw) * -.5 + cos(my->yaw + PI / 2) * 2 * (1 - 2 * (bodypart > 20));
6871 				entity->y += sin(my->yaw) * -.5 + sin(my->yaw + PI / 2) * 2 * (1 - 2 * (bodypart > 20));
6872 				if ( (fabs(PLAYER_VELX) > 0.1 || fabs(PLAYER_VELY) > 0.1) )
6873 				{
6874 					if ( !entity->skill[0] )
6875 					{
6876 						entity->fskill[0] += .1;
6877 						if ( entity->fskill[0] >= 1 )
6878 						{
6879 							entity->fskill[0] = 1;
6880 							entity->skill[0] = 1;
6881 						}
6882 					}
6883 					else
6884 					{
6885 						entity->fskill[0] -= .1;
6886 						if ( entity->fskill[0] <= 0 )
6887 						{
6888 							entity->fskill[0] = 0;
6889 							entity->skill[0] = 0;
6890 						}
6891 					}
6892 				}
6893 				entity->z += entity->fskill[0];
6894 				entity->yaw += (PI / 2 + PI / 3) * (1 - 2 * (bodypart > 20));
6895 				entity->pitch += PI / 4;
6896 				break;
6897 				// shin
6898 			case 20:
6899 			case 28:
6900 				entity->x = previous->x;
6901 				entity->y = previous->y;
6902 				entity->z = previous->z;
6903 				entity->yaw = previous->yaw;
6904 				entity->pitch = previous->pitch;
6905 				entity->x += cos(my->yaw) * -3 + cos(my->yaw + PI / 2) * 1.75 * (1 - 2 * (bodypart > 20));
6906 				entity->y += sin(my->yaw) * -3 + sin(my->yaw + PI / 2) * 1.75 * (1 - 2 * (bodypart > 20));
6907 				entity->z += .5;
6908 				entity->pitch += PI / 6 - PI / 4;
6909 				entity->pitch += (PI / 10) * (previous->z - my->z);
6910 				break;
6911 			default:
6912 				//entity->flags[INVISIBLE] = true; // for debugging
6913 				break;
6914 		}
6915 	}
6916 }