1 /*-------------------------------------------------------------------------------
2 
3 	BARONY
4 	File: actHandMagic.cpp
5 	Desc: the spellcasting animations
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 "../entity.hpp"
16 #include "../interface/interface.hpp"
17 #include "../sound.hpp"
18 #include "../items.hpp"
19 #include "../player.hpp"
20 #include "magic.hpp"
21 #include "../net.hpp"
22 #include "../scores.hpp"
23 
24 //The spellcasting animation stages:
25 #define CIRCLE 0 //One circle
26 #define THROW 1 //Throw spell!
27 
28 spellcasting_animation_manager_t cast_animation;
29 bool overDrawDamageNotify = false;
30 Entity* magicLeftHand = NULL;
31 Entity* magicRightHand = NULL;
32 
33 #define HANDMAGIC_INIT my->skill[0]
34 #define HANDMAGIC_TESTVAR my->skill[1]
35 #define HANDMAGIC_PLAYERNUM my->skill[2]
36 #define HANDMAGIC_YAW my->fskill[3]
37 #define HANDMAGIC_PITCH my->fskill[4]
38 #define HANDMAGIC_ROLL my->fskill[5]
39 #define HANDMAGIC_PARTICLESPRAY1 my->skill[3]
40 #define HANDMAGIC_CIRCLE_RADIUS 0.8
41 #define HANDMAGIC_CIRCLE_SPEED 0.3
42 
fireOffSpellAnimation(spellcasting_animation_manager_t * animation_manager,Uint32 caster_uid,spell_t * spell,bool usingSpellbook)43 void fireOffSpellAnimation(spellcasting_animation_manager_t* animation_manager, Uint32 caster_uid, spell_t* spell, bool usingSpellbook)
44 {
45 	//This function triggers the spellcasting animation and sets up everything.
46 
47 	if (!animation_manager)
48 	{
49 		return;
50 	}
51 	Entity* caster = uidToEntity(caster_uid);
52 	if (!caster)
53 	{
54 		return;
55 	}
56 	if (!spell)
57 	{
58 		return;
59 	}
60 	if (!magicLeftHand)
61 	{
62 		return;
63 	}
64 	if (!magicRightHand)
65 	{
66 		return;
67 	}
68 
69 	playSoundEntity(caster, 170, 128 );
70 	Stat* stat = caster->getStats();
71 
72 	//Save these two very important pieces of data.
73 	animation_manager->caster = caster->getUID();
74 	animation_manager->spell = spell;
75 
76 	if ( !usingSpellbook )
77 	{
78 		animation_manager->active = true;
79 	}
80 	else
81 	{
82 		animation_manager->active_spellbook = true;
83 	}
84 	animation_manager->stage = CIRCLE;
85 
86 	//Make the HUDWEAPON disappear, or somesuch?
87 	if ( stat->type != RAT )
88 	{
89 		if ( !usingSpellbook )
90 		{
91 			magicLeftHand->flags[INVISIBLE] = false;
92 		}
93 		magicRightHand->flags[INVISIBLE] = false;
94 	}
95 
96 	animation_manager->lefthand_angle = 0;
97 	animation_manager->lefthand_movex = 0;
98 	animation_manager->lefthand_movey = 0;
99 	int spellCost = getCostOfSpell(spell, caster);
100 	animation_manager->circle_count = 0;
101 	animation_manager->times_to_circle = (spellCost / 10) + 1; //Circle once for every 10 mana the spell costs.
102 	animation_manager->mana_left = spellCost;
103 	animation_manager->consumeMana = true;
104 	if ( spell->ID == SPELL_FORCEBOLT && caster->skillCapstoneUnlockedEntity(PRO_SPELLCASTING) )
105 	{
106 		animation_manager->consumeMana = false;
107 	}
108 
109 	if (stat->PROFICIENCIES[PRO_SPELLCASTING] < SPELLCASTING_BEGINNER)   //There's a chance that caster is newer to magic (and thus takes longer to cast a spell).
110 	{
111 		int chance = rand() % 10;
112 		if (chance >= stat->PROFICIENCIES[PRO_SPELLCASTING] / 15)
113 		{
114 			int amount = (rand() % 50) / std::max(stat->PROFICIENCIES[PRO_SPELLCASTING] + statGetINT(stat, caster), 1);
115 			amount = std::min(amount, CASTING_EXTRA_TIMES_CAP);
116 			animation_manager->times_to_circle += amount;
117 		}
118 	}
119 	if ( usingSpellbook && stat->shield && itemCategory(stat->shield) == SPELLBOOK )
120 	{
121 		if ( !playerLearnedSpellbook(stat->shield) || (stat->shield->beatitude < 0 && !shouldInvertEquipmentBeatitude(stat)) )
122 		{
123 			// for every tier below the spell you are, add 3 circle for 1 tier, or add 2 for every additional tier.
124 			int casterAbility = std::min(100, std::max(0, stat->PROFICIENCIES[PRO_SPELLCASTING] + statGetINT(stat, caster))) / 20;
125 			if ( stat->shield->beatitude < 0 )
126 			{
127 				casterAbility = 0; // cursed book has cast penalty.
128 			}
129 			int difficulty = spell->difficulty / 20;
130 			if ( difficulty > casterAbility )
131 			{
132 				animation_manager->times_to_circle += (std::min(5, 1 + 2 * (difficulty - casterAbility)));
133 			}
134 		}
135 		else if ( stat->PROFICIENCIES[PRO_SPELLCASTING] >= SPELLCASTING_BEGINNER )
136 		{
137 			animation_manager->times_to_circle = (spellCost / 20) + 1; //Circle once for every 20 mana the spell costs.
138 		}
139 	}
140 	animation_manager->consume_interval = (animation_manager->times_to_circle * ((2 * PI) / HANDMAGIC_CIRCLE_SPEED)) / spellCost;
141 	animation_manager->consume_timer = animation_manager->consume_interval;
142 }
143 
spellcastingAnimationManager_deactivate(spellcasting_animation_manager_t * animation_manager)144 void spellcastingAnimationManager_deactivate(spellcasting_animation_manager_t* animation_manager)
145 {
146 	animation_manager->caster = -1;
147 	animation_manager->spell = NULL;
148 	animation_manager->active = false;
149 	animation_manager->active_spellbook = false;
150 	animation_manager->stage = 0;
151 
152 	//Make the hands invisible (should probably fall away or something, but whatever. That's another project for another day)
153 	if ( magicLeftHand )
154 	{
155 		magicLeftHand->flags[INVISIBLE] = true;
156 	}
157 	if ( magicRightHand )
158 	{
159 		magicRightHand->flags[INVISIBLE] = true;
160 	}
161 }
162 
spellcastingAnimationManager_completeSpell(spellcasting_animation_manager_t * animation_manager)163 void spellcastingAnimationManager_completeSpell(spellcasting_animation_manager_t* animation_manager)
164 {
165 	castSpell(animation_manager->caster, animation_manager->spell, false, false, animation_manager->active_spellbook); //Actually cast the spell.
166 
167 	spellcastingAnimationManager_deactivate(animation_manager);
168 }
169 
170 /*
171 [12:48:29 PM] Sheridan Kane Rathbun: you can move the entities about by modifying their x, y, z, yaw, pitch, and roll parameters.
172 [12:48:43 PM] Sheridan Kane Rathbun: everything's relative to the camera since the OVERDRAW flag is on.
173 [12:49:05 PM] Sheridan Kane Rathbun: so adding x will move it forward, adding y will move it sideways (forget which way) and adding z will move it up and down.
174 [12:49:46 PM] Sheridan Kane Rathbun: the first step is to get the hands visible on the screen when you cast. worry about moving them when that critical part is done.
175 */
176 
actLeftHandMagic(Entity * my)177 void actLeftHandMagic(Entity* my)
178 {
179 	//int c = 0;
180 	if (intro == true)
181 	{
182 		my->flags[INVISIBLE] = true;
183 		return;
184 	}
185 
186 	//Initialize
187 	if (!HANDMAGIC_INIT)
188 	{
189 		HANDMAGIC_INIT = 1;
190 		HANDMAGIC_TESTVAR = 0;
191 		my->focalz = -1.5;
192 	}
193 
194 	if (players[clientnum] == nullptr || players[clientnum]->entity == nullptr
195 		|| (players[clientnum]->entity && players[clientnum]->entity->playerCreatedDeathCam != 0) )
196 	{
197 		magicLeftHand = nullptr;
198 		spellcastingAnimationManager_deactivate(&cast_animation);
199 		list_RemoveNode(my->mynode);
200 		return;
201 	}
202 
203 	//Set the initial values. (For the particle spray)
204 	my->x = 8;
205 	my->y = -3;
206 	my->z = (cameras[HANDMAGIC_PLAYERNUM].z * .5 - players[clientnum]->entity->z) + 7;
207 	my->z -= 4;
208 	my->yaw = HANDMAGIC_YAW - cameravars[HANDMAGIC_PLAYERNUM].shakex2;
209 	double defaultpitch = (0 - 2.2);
210 	my->pitch = defaultpitch + HANDMAGIC_PITCH - cameravars[HANDMAGIC_PLAYERNUM].shakey2 / 200.f;
211 	my->roll = HANDMAGIC_ROLL;
212 	my->scalex = 0.5f;
213 	my->scaley = 0.5f;
214 	my->scalez = 0.5f;
215 	my->z -= 0.75;
216 
217 	//Sprite
218 	Monster playerRace = players[clientnum]->entity->getMonsterFromPlayerRace(stats[clientnum]->playerRace);
219 	int playerAppearance = stats[clientnum]->appearance;
220 	if ( players[clientnum]->entity->effectShapeshift != NOTHING )
221 	{
222 		playerRace = static_cast<Monster>(players[clientnum]->entity->effectShapeshift);
223 	}
224 	else if ( players[clientnum]->entity->effectPolymorph != NOTHING )
225 	{
226 		if ( players[clientnum]->entity->effectPolymorph > NUMMONSTERS )
227 		{
228 			playerRace = HUMAN;
229 			playerAppearance = players[clientnum]->entity->effectPolymorph - 100;
230 		}
231 		else
232 		{
233 			playerRace = static_cast<Monster>(players[clientnum]->entity->effectPolymorph);
234 		}
235 	}
236 
237 	bool noGloves = false;
238 	if ( stats[clientnum]->gloves == NULL
239 		|| playerRace == SPIDER
240 		|| playerRace == RAT
241 		|| playerRace == CREATURE_IMP
242 		|| playerRace == TROLL )
243 	{
244 		noGloves = true;
245 	}
246 	else
247 	{
248 		if ( stats[clientnum]->gloves->type == GLOVES || stats[clientnum]->gloves->type == GLOVES_DEXTERITY )
249 		{
250 			my->sprite = 659;
251 		}
252 		else if ( stats[clientnum]->gloves->type == BRACERS || stats[clientnum]->gloves->type == BRACERS_CONSTITUTION )
253 		{
254 			my->sprite = 660;
255 		}
256 		else if ( stats[clientnum]->gloves->type == GAUNTLETS || stats[clientnum]->gloves->type == GAUNTLETS_STRENGTH )
257 		{
258 			my->sprite = 661;
259 		}
260 		else if ( stats[clientnum]->gloves->type == BRASS_KNUCKLES )
261 		{
262 			my->sprite = 662;
263 		}
264 		else if ( stats[clientnum]->gloves->type == IRON_KNUCKLES )
265 		{
266 			my->sprite = 663;
267 		}
268 		else if ( stats[clientnum]->gloves->type == SPIKED_GAUNTLETS )
269 		{
270 			my->sprite = 664;
271 		}
272 		else if ( stats[clientnum]->gloves->type == CRYSTAL_GLOVES )
273 		{
274 			my->sprite = 666;
275 		}
276 		else if ( stats[clientnum]->gloves->type == ARTIFACT_GLOVES )
277 		{
278 			my->sprite = 665;
279 		}
280 		else if ( stats[clientnum]->gloves->type == SUEDE_GLOVES )
281 		{
282 			my->sprite = 803;
283 		}
284 	}
285 
286 
287 	if ( noGloves )
288 	{
289 
290 		switch ( playerRace )
291 		{
292 			case SKELETON:
293 				my->sprite = 773;
294 				break;
295 			case INCUBUS:
296 				my->sprite = 775;
297 				break;
298 			case SUCCUBUS:
299 				my->sprite = 777;
300 				break;
301 			case GOBLIN:
302 				my->sprite = 779;
303 				break;
304 			case AUTOMATON:
305 				my->sprite = 781;
306 				break;
307 			case INSECTOID:
308 				if ( stats[clientnum]->sex == FEMALE )
309 				{
310 					my->sprite = 785;
311 				}
312 				else
313 				{
314 					my->sprite = 783;
315 				}
316 				break;
317 			case GOATMAN:
318 				my->sprite = 787;
319 				break;
320 			case VAMPIRE:
321 				my->sprite = 789;
322 				break;
323 			case HUMAN:
324 				if ( playerAppearance / 6 == 0 )
325 				{
326 					my->sprite = 656;
327 				}
328 				else if ( playerAppearance / 6 == 1 )
329 				{
330 					my->sprite = 657;
331 				}
332 				else
333 				{
334 					my->sprite = 658;
335 				}
336 				break;
337 			case TROLL:
338 				my->sprite = 856;
339 				break;
340 			case SPIDER:
341 				my->sprite = 854;
342 				break;
343 			case CREATURE_IMP:
344 				my->sprite = 858;
345 				break;
346 			default:
347 				my->sprite = 656;
348 				break;
349 		}
350 		/*}
351 		else if ( playerAppearance / 6 == 0 )
352 		{
353 			my->sprite = 656;
354 		}
355 		else if ( playerAppearance / 6 == 1 )
356 		{
357 			my->sprite = 657;
358 		}
359 		else
360 		{
361 			my->sprite = 658;
362 		}*/
363 	}
364 
365 	if ( playerRace == RAT )
366 	{
367 		my->flags[INVISIBLE] = true;
368 		my->y = 0;
369 		my->z += 1;
370 	}
371 	if ( playerRace == SPIDER && hudarm && players[clientnum]->entity->bodyparts.at(0) )
372 	{
373 		my->x = hudarm->x;
374 		my->y = -hudarm->y;
375 		//my->z = hudArm->z;
376 		my->pitch = hudarm->pitch;
377 		my->roll = -hudarm->roll;
378 		my->yaw = -players[clientnum]->entity->bodyparts.at(0)->yaw;
379 		my->scalex = hudarm->scalex;
380 		my->scaley = hudarm->scaley;
381 		my->scalez = hudarm->scalez;
382 		my->focalz = hudarm->focalz;
383 	}
384 	else
385 	{
386 		my->focalz = -1.5;
387 	}
388 
389 	bool wearingring = false;
390 
391 	//Select model
392 	if (stats[clientnum]->ring != NULL)
393 	{
394 		if (stats[clientnum]->ring->type == RING_INVISIBILITY)
395 		{
396 			wearingring = true;
397 		}
398 	}
399 	if (stats[clientnum]->cloak != NULL)
400 	{
401 		if (stats[clientnum]->cloak->type == CLOAK_INVISIBILITY)
402 		{
403 			wearingring = true;
404 		}
405 	}
406 	if (players[clientnum]->entity->skill[3] == 1 || players[clientnum]->entity->isInvisible() )   // debug cam or player invisible
407 	{
408 		my->flags[INVISIBLE] = true;
409 	}
410 
411 	if ( (cast_animation.active || cast_animation.active_spellbook) )
412 	{
413 		switch (cast_animation.stage)
414 		{
415 			case CIRCLE:
416 				if ( ticks % 5 == 0 && !(players[clientnum]->entity->skill[3] == 1) )
417 				{
418 					Entity* entity = spawnGib(my);
419 					entity->flags[INVISIBLE] = false;
420 					entity->flags[SPRITE] = true;
421 					entity->flags[NOUPDATE] = true;
422 					entity->flags[UPDATENEEDED] = false;
423 					entity->flags[OVERDRAW] = true;
424 					entity->flags[BRIGHT] = true;
425 					entity->scalex = 0.25f; //MAKE 'EM SMALL PLEASE!
426 					entity->scaley = 0.25f;
427 					entity->scalez = 0.25f;
428 					entity->sprite = 16; //TODO: Originally. 22. 16 -- spark sprite instead?
429 					if ( cast_animation.active_spellbook )
430 					{
431 						entity->y -= 1.5;
432 						entity->z += 1;
433 					}
434 					entity->yaw = ((rand() % 6) * 60) * PI / 180.0;
435 					entity->pitch = (rand() % 360) * PI / 180.0;
436 					entity->roll = (rand() % 360) * PI / 180.0;
437 					entity->vel_x = cos(entity->yaw) * .1;
438 					entity->vel_y = sin(entity->yaw) * .1;
439 					entity->vel_z = -.15;
440 					entity->fskill[3] = 0.01;
441 				}
442 				cast_animation.consume_timer--;
443 				if ( cast_animation.consume_timer < 0 && cast_animation.mana_left > 0 )
444 				{
445 					//Time to consume mana and reset the ticker!
446 					cast_animation.consume_timer = cast_animation.consume_interval;
447 					if ( multiplayer == SINGLE && cast_animation.consumeMana )
448 					{
449 						int HP = stats[clientnum]->HP;
450 						players[clientnum]->entity->drainMP(1, false); // don't notify otherwise we'll get spammed each 1 mp
451 						if ( (HP > stats[clientnum]->HP) && !overDrawDamageNotify )
452 						{
453 							overDrawDamageNotify = true;
454 							cameravars[HANDMAGIC_PLAYERNUM].shakex += 0.1;
455 							cameravars[HANDMAGIC_PLAYERNUM].shakey += 10;
456 							playSoundPlayer(clientnum, 28, 92);
457 							Uint32 color = SDL_MapRGB(mainsurface->format, 255, 255, 0);
458 							messagePlayerColor(clientnum, color, language[621]);
459 						}
460 					}
461 					--cast_animation.mana_left;
462 				}
463 
464 				cast_animation.lefthand_angle += HANDMAGIC_CIRCLE_SPEED;
465 				cast_animation.lefthand_movex = cos(cast_animation.lefthand_angle) * HANDMAGIC_CIRCLE_RADIUS;
466 				cast_animation.lefthand_movey = sin(cast_animation.lefthand_angle) * HANDMAGIC_CIRCLE_RADIUS;
467 				if (cast_animation.lefthand_angle >= 2 * PI)   //Completed one loop.
468 				{
469 					cast_animation.lefthand_angle = 0;
470 					cast_animation.circle_count++;
471 					if (cast_animation.circle_count >= cast_animation.times_to_circle)
472 						//Finished circling. Time to move on!
473 					{
474 						cast_animation.stage++;
475 					}
476 				}
477 				break;
478 			case THROW:
479 				//messagePlayer(clientnum, "IN THROW");
480 				//TODO: Throw animation! Or something.
481 				cast_animation.stage++;
482 				break;
483 			default:
484 				//messagePlayer(clientnum, "DEFAULT CASE");
485 				spellcastingAnimationManager_completeSpell(&cast_animation);
486 				break;
487 		}
488 	}
489 	else
490 	{
491 		overDrawDamageNotify = false;
492 	}
493 
494 	//Final position code.
495 	if (players[clientnum] == nullptr || players[clientnum]->entity == nullptr)
496 	{
497 		return;
498 	}
499 	//double defaultpitch = PI / 8.f;
500 	//double defaultpitch = 0;
501 	//double defaultpitch = PI / (0-4.f);
502 	//defaultpitch = (0 - 2.8);
503 	//my->x = 6 + HUDWEAPON_MOVEX;
504 
505 	if ( playerRace == SPIDER && hudarm && players[clientnum]->entity->bodyparts.at(0) )
506 	{
507 		my->x = hudarm->x;
508 		my->y = -hudarm->y;
509 		my->z = hudarm->z;
510 		my->pitch = hudarm->pitch;
511 		my->roll = -hudarm->roll;
512 		my->yaw = -players[clientnum]->entity->bodyparts.at(0)->yaw;
513 		my->scalex = hudarm->scalex;
514 		my->scaley = hudarm->scaley;
515 		my->scalez = hudarm->scalez;
516 		my->focalz = hudarm->focalz;
517 	}
518 	else
519 	{
520 		my->y = -3;
521 		my->z = (cameras[HANDMAGIC_PLAYERNUM].z * .5 - players[clientnum]->entity->z) + 7;
522 		my->z -= 4;
523 		my->yaw = HANDMAGIC_YAW - cameravars[HANDMAGIC_PLAYERNUM].shakex2;
524 		my->pitch = defaultpitch + HANDMAGIC_PITCH - cameravars[HANDMAGIC_PLAYERNUM].shakey2 / 200.f;
525 		my->roll = HANDMAGIC_ROLL;
526 		my->focalz = -1.5;
527 	}
528 
529 	//my->y = 3 + HUDWEAPON_MOVEY;
530 	//my->z = (camera.z*.5-players[clientnum]->z)+7+HUDWEAPON_MOVEZ; //TODO: NOT a PLAYERSWAP
531 	my->x += cast_animation.lefthand_movex;
532 	my->y += cast_animation.lefthand_movey;
533 }
534 
actRightHandMagic(Entity * my)535 void actRightHandMagic(Entity* my)
536 {
537 	if (intro == true)
538 	{
539 		my->flags[INVISIBLE] = true;
540 		return;
541 	}
542 
543 	//Initialize
544 	if ( !HANDMAGIC_INIT )
545 	{
546 		HANDMAGIC_INIT = 1;
547 		my->focalz = -1.5;
548 	}
549 
550 	if (players[clientnum] == nullptr || players[clientnum]->entity == nullptr
551 		|| (players[clientnum]->entity && players[clientnum]->entity->playerCreatedDeathCam != 0) )
552 	{
553 		magicRightHand = nullptr;
554 		list_RemoveNode(my->mynode);
555 		return;
556 	}
557 
558 	my->x = 8;
559 	my->y = 3;
560 	my->z = (cameras[HANDMAGIC_PLAYERNUM].z * .5 - players[clientnum]->entity->z) + 7;
561 	my->z -= 4;
562 	my->yaw = HANDMAGIC_YAW - cameravars[HANDMAGIC_PLAYERNUM].shakex2;
563 	double defaultpitch = (0 - 2.2);
564 	my->pitch = defaultpitch + HANDMAGIC_PITCH - cameravars[HANDMAGIC_PLAYERNUM].shakey2 / 200.f;
565 	my->roll = HANDMAGIC_ROLL;
566 	my->scalex = 0.5f;
567 	my->scaley = 0.5f;
568 	my->scalez = 0.5f;
569 	my->z -= 0.75;
570 
571 	//Sprite
572 	Monster playerRace = players[clientnum]->entity->getMonsterFromPlayerRace(stats[clientnum]->playerRace);
573 	int playerAppearance = stats[clientnum]->appearance;
574 	if ( players[clientnum]->entity->effectShapeshift != NOTHING )
575 	{
576 		playerRace = static_cast<Monster>(players[clientnum]->entity->effectShapeshift);
577 	}
578 	else if ( players[clientnum]->entity->effectPolymorph != NOTHING )
579 	{
580 		if ( players[clientnum]->entity->effectPolymorph > NUMMONSTERS )
581 		{
582 			playerRace = HUMAN;
583 			playerAppearance = players[clientnum]->entity->effectPolymorph - 100;
584 		}
585 		else
586 		{
587 			playerRace = static_cast<Monster>(players[clientnum]->entity->effectPolymorph);
588 		}
589 	}
590 
591 	bool noGloves = false;
592 	if ( stats[clientnum]->gloves == NULL
593 		|| playerRace == SPIDER
594 		|| playerRace == RAT
595 		|| playerRace == CREATURE_IMP
596 		|| playerRace == TROLL )
597 	{
598 		noGloves = true;
599 	}
600 	else
601 	{
602 		if ( stats[clientnum]->gloves->type == GLOVES || stats[clientnum]->gloves->type == GLOVES_DEXTERITY )
603 		{
604 			my->sprite = 637;
605 		}
606 		else if ( stats[clientnum]->gloves->type == BRACERS || stats[clientnum]->gloves->type == BRACERS_CONSTITUTION )
607 		{
608 			my->sprite = 638;
609 		}
610 		else if ( stats[clientnum]->gloves->type == GAUNTLETS || stats[clientnum]->gloves->type == GAUNTLETS_STRENGTH )
611 		{
612 			my->sprite = 639;
613 		}
614 		else if ( stats[clientnum]->gloves->type == BRASS_KNUCKLES )
615 		{
616 			my->sprite = 640;
617 		}
618 		else if ( stats[clientnum]->gloves->type == IRON_KNUCKLES )
619 		{
620 			my->sprite = 641;
621 		}
622 		else if ( stats[clientnum]->gloves->type == SPIKED_GAUNTLETS )
623 		{
624 			my->sprite = 642;
625 		}
626 		else if ( stats[clientnum]->gloves->type == CRYSTAL_GLOVES )
627 		{
628 			my->sprite = 591;
629 		}
630 		else if ( stats[clientnum]->gloves->type == ARTIFACT_GLOVES )
631 		{
632 			my->sprite = 590;
633 		}
634 		else if ( stats[clientnum]->gloves->type == SUEDE_GLOVES )
635 		{
636 			my->sprite = 802;
637 		}
638 	}
639 
640 	if ( noGloves )
641 	{
642 		switch ( playerRace )
643 		{
644 			case SKELETON:
645 				my->sprite = 774;
646 				break;
647 			case INCUBUS:
648 				my->sprite = 776;
649 				break;
650 			case SUCCUBUS:
651 				my->sprite = 778;
652 				break;
653 			case GOBLIN:
654 				my->sprite = 780;
655 				break;
656 			case AUTOMATON:
657 				my->sprite = 782;
658 				break;
659 			case INSECTOID:
660 				if ( stats[clientnum]->sex == FEMALE )
661 				{
662 					my->sprite = 786;
663 				}
664 				else
665 				{
666 					my->sprite = 784;
667 				}
668 				break;
669 			case GOATMAN:
670 				my->sprite = 788;
671 				break;
672 			case VAMPIRE:
673 				my->sprite = 790;
674 				break;
675 			case HUMAN:
676 				if ( playerAppearance / 6 == 0 )
677 				{
678 					my->sprite = 634;
679 				}
680 				else if ( playerAppearance / 6 == 1 )
681 				{
682 					my->sprite = 635;
683 				}
684 				else
685 				{
686 					my->sprite = 636;
687 				}
688 				break;
689 			case TROLL:
690 				my->sprite = 855;
691 				break;
692 			case SPIDER:
693 				my->sprite = 853;
694 				break;
695 			case CREATURE_IMP:
696 				my->sprite = 857;
697 				break;
698 			default:
699 				my->sprite = 634;
700 				break;
701 		}
702 		/*else if ( playerAppearance / 6 == 0 )
703 		{
704 			my->sprite = 634;
705 		}
706 		else if ( playerAppearance / 6 == 1 )
707 		{
708 			my->sprite = 635;
709 		}
710 		else
711 		{
712 			my->sprite = 636;
713 		}*/
714 	}
715 
716 	if ( playerRace == RAT )
717 	{
718 		my->flags[INVISIBLE] = true;
719 		my->y = 0;
720 		my->z += 1;
721 	}
722 	if ( playerRace == SPIDER && hudarm && players[clientnum]->entity->bodyparts.at(0) )
723 	{
724 		my->x = hudarm->x;
725 		my->y = hudarm->y;
726 		//my->z = hudArm->z;
727 		my->pitch = hudarm->pitch;
728 		my->roll = hudarm->roll;
729 		my->yaw = players[clientnum]->entity->bodyparts.at(0)->yaw;
730 		my->scalex = hudarm->scalex;
731 		my->scaley = hudarm->scaley;
732 		my->scalez = hudarm->scalez;
733 		my->focalz = hudarm->focalz;
734 	}
735 	else
736 	{
737 		my->focalz = -1.5;
738 	}
739 
740 	bool wearingring = false;
741 
742 	//Select model
743 	if (stats[clientnum]->ring != NULL)
744 	{
745 		if (stats[clientnum]->ring->type == RING_INVISIBILITY)
746 		{
747 			wearingring = true;
748 		}
749 	}
750 	if (stats[clientnum]->cloak != NULL)
751 	{
752 		if (stats[clientnum]->cloak->type == CLOAK_INVISIBILITY)
753 		{
754 			wearingring = true;
755 		}
756 	}
757 	if ( players[clientnum]->entity->skill[3] == 1 || players[clientnum]->entity->isInvisible() )   // debug cam or player invisible
758 	{
759 		my->flags[INVISIBLE] = true;
760 	}
761 
762 	if ( (cast_animation.active || cast_animation.active_spellbook) )
763 	{
764 		switch (cast_animation.stage)
765 		{
766 			case CIRCLE:
767 				if ( ticks % 5 == 0 && !(players[clientnum]->entity->skill[3] == 1) )
768 				{
769 					//messagePlayer(0, "Pingas!");
770 					Entity* entity = spawnGib(my);
771 					entity->flags[INVISIBLE] = false;
772 					entity->flags[SPRITE] = true;
773 					entity->flags[NOUPDATE] = true;
774 					entity->flags[UPDATENEEDED] = false;
775 					entity->flags[OVERDRAW] = true;
776 					entity->flags[BRIGHT] = true;
777 					//entity->sizex = 1; //MAKE 'EM SMALL PLEASE!
778 					//entity->sizey = 1;
779 					entity->scalex = 0.25f; //MAKE 'EM SMALL PLEASE!
780 					entity->scaley = 0.25f;
781 					entity->scalez = 0.25f;
782 					entity->sprite = 16; //TODO: Originally. 22. 16 -- spark sprite instead?
783 					entity->yaw = ((rand() % 6) * 60) * PI / 180.0;
784 					entity->pitch = (rand() % 360) * PI / 180.0;
785 					entity->roll = (rand() % 360) * PI / 180.0;
786 					entity->vel_x = cos(entity->yaw) * .1;
787 					entity->vel_y = sin(entity->yaw) * .1;
788 					entity->vel_z = -.15;
789 					entity->fskill[3] = 0.01;
790 				}
791 				break;
792 			case THROW:
793 				break;
794 			default:
795 				break;
796 		}
797 	}
798 
799 	//Final position code.
800 	if (players[clientnum] == nullptr || players[clientnum]->entity == nullptr)
801 	{
802 		return;
803 	}
804 
805 	if ( playerRace == SPIDER && hudarm && players[clientnum]->entity->bodyparts.at(0) )
806 	{
807 		my->x = hudarm->x;
808 		my->y = hudarm->y;
809 		my->z = hudarm->z;
810 		my->pitch = hudarm->pitch;
811 		my->roll = hudarm->roll;
812 		my->yaw = players[clientnum]->entity->bodyparts.at(0)->yaw;
813 		my->scalex = hudarm->scalex;
814 		my->scaley = hudarm->scaley;
815 		my->scalez = hudarm->scalez;
816 		my->focalz = hudarm->focalz;
817 	}
818 	else
819 	{
820 		my->x = 8;
821 		my->y = 3;
822 		my->z = (cameras[HANDMAGIC_PLAYERNUM].z * .5 - players[clientnum]->entity->z) + 7;
823 		my->z -= 4;
824 		my->yaw = HANDMAGIC_YAW - cameravars[HANDMAGIC_PLAYERNUM].shakex2;
825 		my->pitch = defaultpitch + HANDMAGIC_PITCH - cameravars[HANDMAGIC_PLAYERNUM].shakey2 / 200.f;
826 		my->roll = HANDMAGIC_ROLL;
827 		my->focalz = -1.5;
828 	}
829 
830 	my->x += cast_animation.lefthand_movex;
831 	my->y -= cast_animation.lefthand_movey;
832 }
833