1 /*-------------------------------------------------------------------------------
2 
3 	BARONY
4 	File: spell.cpp
5 	Desc: contains spell definitions
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 "../net.hpp"
20 #include "../player.hpp"
21 #include "magic.hpp"
22 
23 list_t spellList;
24 list_t channeledSpells[MAXPLAYERS];
25 spell_t* selected_spell = NULL;
26 spell_t* selected_spell_alternate[NUM_HOTBAR_ALTERNATES] = { NULL, NULL, NULL, NULL, NULL };
27 int selected_spell_last_appearance = -1;
28 
29 spellElement_t spellElement_unintelligible;
30 spellElement_t spellElement_missile;
31 spellElement_t spellElement_missile_trio;
32 spellElement_t spellElement_force;
33 spellElement_t spellElement_fire;
34 spellElement_t spellElement_lightning;
35 spellElement_t spellElement_light;
36 spellElement_t spellElement_dig;
37 spellElement_t spellElement_invisible;
38 spellElement_t spellElement_identify;
39 spellElement_t spellElement_magicmapping;
40 spellElement_t spellElement_heal;
41 spellElement_t spellElement_confuse;
42 spellElement_t spellElement_cure_ailment;
43 spellElement_t spellElement_locking;
44 spellElement_t spellElement_opening;
45 spellElement_t spellElement_sleep;
46 spellElement_t spellElement_cold;
47 spellElement_t spellElement_slow;
48 spellElement_t spellElement_levitation;
49 spellElement_t spellElement_teleportation;
50 spellElement_t spellElement_magicmissile;
51 spellElement_t spellElement_removecurse;
52 spellElement_t spellElement_summon;
53 spellElement_t spellElement_stoneblood;
54 spellElement_t spellElement_bleed;
55 spellElement_t spellElement_dominate;
56 spellElement_t spellElement_reflectMagic;
57 spellElement_t spellElement_acidSpray;
58 spellElement_t spellElement_stealWeapon;
59 spellElement_t spellElement_drainSoul;
60 spellElement_t spellElement_vampiricAura;
61 spellElement_t spellElement_charmMonster;
62 spellElement_t spellElement_shapeshift;
63 spellElement_t spellElement_sprayWeb;
64 spellElement_t spellElement_poison;
65 spellElement_t spellElement_speed;
66 spellElement_t spellElement_fear;
67 spellElement_t spellElement_strike;
68 spellElement_t spellElement_detectFood;
69 spellElement_t spellElement_weakness;
70 spellElement_t spellElement_amplifyMagic;
71 spellElement_t spellElement_shadowTag;
72 spellElement_t spellElement_telePull;
73 spellElement_t spellElement_demonIllusion;
74 spellElement_t spellElement_trollsBlood;
75 spellElement_t spellElement_salvageItem;
76 spellElement_t spellElement_flutter;
77 spellElement_t spellElement_dash;
78 spellElement_t spellElement_selfPolymorph;
79 
80 spell_t spell_forcebolt;
81 spell_t spell_magicmissile;
82 spell_t spell_cold;
83 spell_t spell_fireball;
84 spell_t spell_lightning;
85 spell_t spell_removecurse;
86 spell_t spell_light;
87 spell_t spell_identify;
88 spell_t spell_magicmapping;
89 spell_t spell_sleep;
90 spell_t spell_confuse;
91 spell_t spell_slow;
92 spell_t spell_opening;
93 spell_t spell_locking;
94 spell_t spell_levitation;
95 spell_t spell_invisibility;
96 spell_t spell_teleportation;
97 spell_t spell_healing;
98 spell_t spell_extrahealing;
99 //spell_t spell_restoreability;
100 spell_t spell_cureailment;
101 spell_t spell_dig;
102 spell_t spell_summon;
103 spell_t spell_stoneblood;
104 spell_t spell_bleed;
105 spell_t spell_dominate;
106 spell_t spell_reflectMagic;
107 spell_t spell_acidSpray;
108 spell_t spell_stealWeapon;
109 spell_t spell_drainSoul;
110 spell_t spell_vampiricAura;
111 spell_t spell_charmMonster;
112 spell_t spell_revertForm;
113 spell_t spell_ratForm;
114 spell_t spell_spiderForm;
115 spell_t spell_trollForm;
116 spell_t spell_impForm;
117 spell_t spell_sprayWeb;
118 spell_t spell_poison;
119 spell_t spell_speed;
120 spell_t spell_fear;
121 spell_t spell_strike;
122 spell_t spell_detectFood;
123 spell_t spell_weakness;
124 spell_t spell_amplifyMagic;
125 spell_t spell_shadowTag;
126 spell_t spell_telePull;
127 spell_t spell_demonIllusion;
128 spell_t spell_trollsBlood;
129 spell_t spell_salvageItem;
130 spell_t spell_flutter;
131 spell_t spell_dash;
132 spell_t spell_polymorph;
133 
addSpell(int spell,int player,bool ignoreSkill)134 bool addSpell(int spell, int player, bool ignoreSkill)
135 {
136 	node_t* node = nullptr;
137 
138 	// this is a local function
139 	if ( player != clientnum )
140 	{
141 		return false;
142 	}
143 
144 	spell_t* new_spell = nullptr;
145 
146 	switch ( spell )
147 	{
148 		case SPELL_FORCEBOLT:
149 			new_spell = copySpell(&spell_forcebolt);
150 			break;
151 		case SPELL_MAGICMISSILE:
152 			new_spell = copySpell(&spell_magicmissile);
153 			break;
154 		case SPELL_COLD:
155 			new_spell = copySpell(&spell_cold);
156 			break;
157 		case SPELL_FIREBALL:
158 			new_spell = copySpell(&spell_fireball);
159 			break;
160 		case SPELL_LIGHTNING:
161 			new_spell = copySpell(&spell_lightning);
162 			break;
163 		case SPELL_REMOVECURSE:
164 			new_spell = copySpell(&spell_removecurse);
165 			break;
166 		case SPELL_LIGHT:
167 			new_spell = copySpell(&spell_light);
168 			break;
169 		case SPELL_IDENTIFY:
170 			new_spell = copySpell(&spell_identify);
171 			break;
172 		case SPELL_MAGICMAPPING:
173 			new_spell = copySpell(&spell_magicmapping);
174 			break;
175 		case SPELL_SLEEP:
176 			new_spell = copySpell(&spell_sleep);
177 			break;
178 		case SPELL_CONFUSE:
179 			new_spell = copySpell(&spell_confuse);
180 			break;
181 		case SPELL_SLOW:
182 			new_spell = copySpell(&spell_slow);
183 			break;
184 		case SPELL_OPENING:
185 			new_spell = copySpell(&spell_opening);
186 			break;
187 		case SPELL_LOCKING:
188 			new_spell = copySpell(&spell_locking);
189 			break;
190 		case SPELL_LEVITATION:
191 			new_spell = copySpell(&spell_levitation);
192 			break;
193 		case SPELL_INVISIBILITY:
194 			new_spell = copySpell(&spell_invisibility);
195 			break;
196 		case SPELL_TELEPORTATION:
197 			new_spell = copySpell(&spell_teleportation);
198 			break;
199 		case SPELL_HEALING:
200 			new_spell = copySpell(&spell_healing);
201 			break;
202 		case SPELL_EXTRAHEALING:
203 			new_spell = copySpell(&spell_extrahealing);
204 			break;
205 		case SPELL_CUREAILMENT:
206 			new_spell = copySpell(&spell_cureailment);
207 			break;
208 		case SPELL_DIG:
209 			new_spell = copySpell(&spell_dig);
210 			break;
211 		case SPELL_STONEBLOOD:
212 			new_spell = copySpell(&spell_stoneblood);
213 			break;
214 		case SPELL_BLEED:
215 			new_spell = copySpell(&spell_bleed);
216 			break;
217 		case SPELL_SUMMON:
218 			new_spell = copySpell(&spell_summon);
219 			break;
220 		case SPELL_DOMINATE:
221 			new_spell = copySpell(&spell_dominate);
222 			break;
223 		case SPELL_REFLECT_MAGIC:
224 			new_spell = copySpell(&spell_reflectMagic);
225 			break;
226 		case SPELL_ACID_SPRAY:
227 			new_spell = copySpell(&spell_acidSpray);
228 			break;
229 		case SPELL_STEAL_WEAPON:
230 			new_spell = copySpell(&spell_stealWeapon);
231 			break;
232 		case SPELL_DRAIN_SOUL:
233 			new_spell = copySpell(&spell_drainSoul);
234 			break;
235 		case SPELL_VAMPIRIC_AURA:
236 			new_spell = copySpell(&spell_vampiricAura);
237 			break;
238 		case SPELL_CHARM_MONSTER:
239 			new_spell = copySpell(&spell_charmMonster);
240 			break;
241 		case SPELL_REVERT_FORM:
242 			new_spell = copySpell(&spell_revertForm);
243 			break;
244 		case SPELL_RAT_FORM:
245 			new_spell = copySpell(&spell_ratForm);
246 			break;
247 		case SPELL_SPIDER_FORM:
248 			new_spell = copySpell(&spell_spiderForm);
249 			break;
250 		case SPELL_TROLL_FORM:
251 			new_spell = copySpell(&spell_trollForm);
252 			break;
253 		case SPELL_IMP_FORM:
254 			new_spell = copySpell(&spell_impForm);
255 			break;
256 		case SPELL_SPRAY_WEB:
257 			new_spell = copySpell(&spell_sprayWeb);
258 			break;
259 		case SPELL_POISON:
260 			new_spell = copySpell(&spell_poison);
261 			break;
262 		case SPELL_SPEED:
263 			new_spell = copySpell(&spell_speed);
264 			break;
265 		case SPELL_FEAR:
266 			new_spell = copySpell(&spell_fear);
267 			break;
268 		case SPELL_STRIKE:
269 			new_spell = copySpell(&spell_strike);
270 			break;
271 		case SPELL_DETECT_FOOD:
272 			new_spell = copySpell(&spell_detectFood);
273 			break;
274 		case SPELL_WEAKNESS:
275 			new_spell = copySpell(&spell_weakness);
276 			break;
277 		case SPELL_AMPLIFY_MAGIC:
278 			new_spell = copySpell(&spell_amplifyMagic);
279 			break;
280 		case SPELL_SHADOW_TAG:
281 			new_spell = copySpell(&spell_shadowTag);
282 			break;
283 		case SPELL_TELEPULL:
284 			new_spell = copySpell(&spell_telePull);
285 			break;
286 		case SPELL_DEMON_ILLUSION:
287 			new_spell = copySpell(&spell_demonIllusion);
288 			break;
289 		case SPELL_TROLLS_BLOOD:
290 			new_spell = copySpell(&spell_trollsBlood);
291 			break;
292 		case SPELL_SALVAGE:
293 			new_spell = copySpell(&spell_salvageItem);
294 			break;
295 		case SPELL_FLUTTER:
296 			new_spell = copySpell(&spell_flutter);
297 			break;
298 		case SPELL_DASH:
299 			new_spell = copySpell(&spell_dash);
300 			break;
301 		case SPELL_SELF_POLYMORPH:
302 			new_spell = copySpell(&spell_polymorph);
303 			break;
304 		case SPELL_9:
305 		case SPELL_10:
306 			new_spell = copySpell(&spell_weakness);
307 			break;
308 		default:
309 			return false;
310 	}
311 	if ( spellInList(&spellList, new_spell) )
312 	{
313 		// check inventory for shapeshift spells
314 		bool foundShapeshiftSpell = false;
315 		bool foundNormalSpell = false;
316 		if ( !ignoreSkill ) // learning the proper way, not being forced at character creation or debug.
317 		{
318 			for ( node = stats[player]->inventory.first; node != NULL; node = node->next )
319 			{
320 				Item* item = (Item*)node->element;
321 				if ( item->type == SPELL_ITEM )
322 				{
323 					if ( item->appearance >= 1000 )
324 					{
325 						if ( item->appearance - 1000 == spell )
326 						{
327 							foundShapeshiftSpell = true;
328 						}
329 					}
330 					else
331 					{
332 						if ( item->appearance == spell )
333 						{
334 							foundNormalSpell = true;
335 						}
336 					}
337 				}
338 				if ( foundNormalSpell && foundShapeshiftSpell )
339 				{
340 					// found both varieties, no point searching rest of inventory.
341 					break;
342 				}
343 			}
344 			if ( !foundNormalSpell )
345 			{
346 				// can learn. proceed.
347 			}
348 			else if ( foundNormalSpell )
349 			{
350 				// can't learn, already have it.
351 				messagePlayer(player, language[439], new_spell->name);
352 				spellDeconstructor((void*)new_spell);
353 				return false;
354 			}
355 		}
356 		else
357 		{
358 			// can't learn, already have it.
359 			messagePlayer(player, language[439], new_spell->name);
360 			spellDeconstructor((void*)new_spell);
361 			return false;
362 		}
363 	}
364 	int skillLVL = stats[player]->PROFICIENCIES[PRO_MAGIC] + statGetINT(stats[player], players[player]->entity);
365 	if ( stats[player]->PROFICIENCIES[PRO_MAGIC] >= 100 )
366 	{
367 		skillLVL = 100;
368 	}
369 	if ( !ignoreSkill && skillLVL < new_spell->difficulty )
370 	{
371 		messagePlayer(player, language[440]);
372 		spellDeconstructor((void*)new_spell);
373 		return false;
374 	}
375 	if ( !intro )
376 	{
377 		messagePlayer(player, language[441], new_spell->name);
378 	}
379 	node = list_AddNodeLast(&spellList);
380 	node->element = new_spell;
381 	node->size = sizeof(spell_t);
382 	node->deconstructor = &spellDeconstructor;
383 
384 	if ( !ignoreSkill )
385 	{
386 		players[player]->entity->increaseSkill(PRO_MAGIC);
387 	}
388 
389 	Item* item = newItem(SPELL_ITEM, SERVICABLE, 0, 1, spell, true, nullptr);
390 	itemPickup(player, item);
391 	free(item);
392 
393 	return true;
394 }
395 
newSpell()396 spell_t* newSpell()
397 {
398 	spell_t* spell = (spell_t*) malloc(sizeof(spell_t));
399 	spellConstructor(spell);
400 	return spell;
401 }
402 
spellConstructor(spell_t * spell)403 void spellConstructor(spell_t* spell)
404 {
405 	spell->ID = -1;
406 	strcpy(spell->name, "Spell");
407 	spell->elements.first = NULL;
408 	spell->elements.last = NULL;
409 	spell->sustain = true;
410 	spell->magicstaff = false;
411 	spell->sustain_node = NULL;
412 	spell->magic_effects_node = NULL;
413 	spell->caster = -1;
414 	spell->channel_duration = 0;
415 	//spell->timer = 0;
416 	allGameSpells.push_back(spell);
417 }
418 
spellDeconstructor(void * data)419 void spellDeconstructor(void* data)
420 {
421 	spell_t* spell;
422 
423 	if ( data != NULL )
424 	{
425 		spell = (spell_t*) data;
426 
427 		if ( spell_isChanneled(spell) )
428 		{
429 			if ( spell->sustain_node )
430 			{
431 				list_RemoveNode(spell->sustain_node);
432 			}
433 		}
434 
435 		list_FreeAll(&spell->elements);
436 		free(spell);
437 	}
438 }
439 
spellElementConstructor(spellElement_t * element)440 void spellElementConstructor(spellElement_t* element)
441 {
442 	element->mana = 0;
443 	element->base_mana = 0;
444 	element->overload_multiplier = 1;
445 	element->damage = 0;
446 	element->duration = 0;
447 	element->can_be_learned = true;
448 	strcpy(element->name, "New Element");
449 	element->elements.first = NULL;
450 	element->elements.last = NULL;
451 	element->node = NULL;
452 	element->channeled = false;
453 }
454 
spellElementDeconstructor(void * data)455 void spellElementDeconstructor(void* data)
456 {
457 	spellElement_t* spellElement;
458 	if (data != NULL)
459 	{
460 		spellElement = (spellElement_t*) data;
461 
462 		list_FreeAll(&spellElement->elements);
463 		free(spellElement);
464 	}
465 }
466 
newSpellelement()467 spellElement_t* newSpellelement()
468 {
469 	spellElement_t* element = (spellElement_t*) malloc(sizeof(spellElement_t));
470 	spellElementConstructor(element);
471 	return element;
472 }
473 
copySpell(spell_t * spell)474 spell_t* copySpell(spell_t* spell)
475 {
476 	node_t* node;
477 
478 	spell_t* result = (spell_t*) malloc(sizeof(spell_t));
479 	*result = *spell; // copy over all the static data members.
480 
481 	result->sustain_node = NULL;
482 	result->magic_effects_node = NULL;
483 	result->elements.first = NULL;
484 	result->elements.last = NULL;
485 
486 	for ( node = spell->elements.first; node != NULL; node = node->next )
487 	{
488 		spellElement_t* tempElement = (spellElement_t*) node->element;
489 
490 		node_t* tempNode = list_AddNodeLast(&result->elements);
491 		tempNode->deconstructor = &spellElementDeconstructor;
492 		tempNode->size = sizeof(spellElement_t);
493 		tempNode->element = copySpellElement(tempElement);
494 
495 		spellElement_t* newElement = (spellElement_t*)tempNode->element;
496 		newElement->node = tempNode;
497 	}
498 
499 	return result;
500 }
501 
copySpellElement(spellElement_t * spellElement)502 spellElement_t* copySpellElement(spellElement_t* spellElement)
503 {
504 	node_t* node;
505 
506 	spellElement_t* result = (spellElement_t*) malloc(sizeof(spellElement_t));
507 	*result = *spellElement; // copy over all the static data members.
508 
509 	result->node = NULL;
510 	result->elements.first = NULL;
511 	result->elements.last = NULL;
512 
513 	for ( node = spellElement->elements.first; node != NULL; node = node->next )
514 	{
515 		spellElement_t* tempElement = (spellElement_t*) node->element;
516 
517 		node_t* tempNode = list_AddNodeLast(&result->elements);
518 		tempNode->deconstructor = &spellElementDeconstructor;
519 		tempNode->size = sizeof(spellElement_t);
520 		tempNode->element = copySpellElement(tempElement);
521 
522 		spellElement_t* newElement = (spellElement_t*)tempNode->element;
523 		newElement->node = tempNode;
524 	}
525 
526 	return result;
527 }
528 
getCostOfSpell(spell_t * spell,Entity * caster)529 int getCostOfSpell(spell_t* spell, Entity* caster)
530 {
531 	int cost = 0;
532 
533 	node_t* node;
534 	for ( node = spell->elements.first; node != NULL; node = node->next )
535 	{
536 		spellElement_t* spellElement = (spellElement_t*)node->element;
537 		cost += getCostOfSpellElement(spellElement);
538 	}
539 
540 	if ( spell->ID == SPELL_FORCEBOLT && caster && caster->skillCapstoneUnlockedEntity(PRO_SPELLCASTING) )
541 	{
542 		cost = 0;
543 	}
544 	else if ( spell->ID == SPELL_SUMMON && caster )
545 	{
546 		Stat* casterStats = caster->getStats();
547 		if ( casterStats )
548 		{
549 			int summonLevel = casterStats->playerSummonLVLHP >> 16;
550 			cost += 5 * (summonLevel / 5);
551 		}
552 	}
553 	else if ( caster && (spell->ID == SPELL_TELEPORTATION || spell->ID == SPELL_TELEPULL) )
554 	{
555 		if ( caster->creatureShadowTaggedThisUid != 0 && uidToEntity(caster->creatureShadowTaggedThisUid) )
556 		{
557 			cost /= 2;
558 		}
559 	}
560 
561 	return cost;
562 }
563 
getCostOfSpellElement(spellElement_t * spellElement)564 int getCostOfSpellElement(spellElement_t* spellElement)
565 {
566 	int cost = spellElement->mana;
567 
568 	node_t* node;
569 	for ( node = spellElement->elements.first; node != NULL; node = node->next )
570 	{
571 		spellElement_t* spellElement2 = (spellElement_t*)node->element;
572 		cost += getCostOfSpellElement(spellElement2);
573 	}
574 
575 	return cost;
576 }
577 
spell_isChanneled(spell_t * spell)578 bool spell_isChanneled(spell_t* spell)
579 {
580 	node_t* node = NULL;
581 
582 	for ( node = spell->elements.first; node != NULL; node = node->next )
583 	{
584 		spellElement_t* spellElement = (spellElement_t*)node->element;
585 		if ( spellElement_isChanneled(spellElement) )
586 		{
587 			return true;
588 		}
589 	}
590 
591 	return false;
592 }
593 
getBonusFromCasterOfSpellElement(Entity * caster,spellElement_t * spellElement)594 real_t getBonusFromCasterOfSpellElement(Entity* caster, spellElement_t* spellElement)
595 {
596 	if ( !caster || caster->behavior != &actPlayer )
597 	{
598 		return 0;
599 	}
600 
601 	int INT = caster->getINT();
602 	if ( INT > 0 )
603 	{
604 		return INT / 100.0;
605 	}
606 	return 0;
607 }
608 
spellElement_isChanneled(spellElement_t * spellElement)609 bool spellElement_isChanneled(spellElement_t* spellElement)
610 {
611 	node_t* node = NULL;
612 
613 	if ( spellElement->channeled )
614 	{
615 		return true;
616 	}
617 	for ( node = spellElement->elements.first; node != NULL; node = node->next )
618 	{
619 		spellElement_t* tempElement = (spellElement_t*)node->element;
620 		if ( spellElement_isChanneled(tempElement) )
621 		{
622 			return true;
623 		}
624 	}
625 
626 	return false;
627 }
628 
equipSpell(spell_t * spell,int playernum,Item * spellItem)629 void equipSpell(spell_t* spell, int playernum, Item* spellItem)
630 {
631 	if ( playernum == clientnum )
632 	{
633 		selected_spell = spell;
634 		messagePlayer(playernum, language[442], spell->name);
635 		selected_spell_last_appearance = spellItem->appearance; // to keep track of shapeshift/normal spells.
636 	}
637 }
638 
getSpellFromID(int ID)639 spell_t* getSpellFromID(int ID)
640 {
641 	spell_t* spell = nullptr;
642 
643 	switch (ID)
644 	{
645 		case SPELL_FORCEBOLT:
646 			spell = &spell_forcebolt;
647 			break;
648 		case SPELL_MAGICMISSILE:
649 			spell = &spell_magicmissile;
650 			break;
651 		case SPELL_COLD:
652 			spell = &spell_cold;
653 			break;
654 		case SPELL_FIREBALL:
655 			spell = &spell_fireball;
656 			break;
657 		case SPELL_LIGHTNING:
658 			spell = &spell_lightning;
659 			break;
660 		case SPELL_REMOVECURSE:
661 			spell = &spell_removecurse;
662 			break;
663 		case SPELL_LIGHT:
664 			spell = &spell_light;
665 			break;
666 		case SPELL_IDENTIFY:
667 			spell = &spell_identify;
668 			break;
669 		case SPELL_MAGICMAPPING:
670 			spell = &spell_magicmapping;
671 			break;
672 		case SPELL_SLEEP:
673 			spell = &spell_sleep;
674 			break;
675 		case SPELL_CONFUSE:
676 			spell = &spell_confuse;
677 			break;
678 		case SPELL_SLOW:
679 			spell = &spell_slow;
680 			break;
681 		case SPELL_OPENING:
682 			spell = &spell_opening;
683 			break;
684 		case SPELL_LOCKING:
685 			spell = &spell_locking;
686 			break;
687 		case SPELL_LEVITATION:
688 			spell = &spell_levitation;
689 			break;
690 		case SPELL_INVISIBILITY:
691 			spell = &spell_invisibility;
692 			break;
693 		case SPELL_TELEPORTATION:
694 			spell = &spell_teleportation;
695 			break;
696 		case SPELL_HEALING:
697 			spell = &spell_healing;
698 			break;
699 		case SPELL_EXTRAHEALING:
700 			spell = &spell_extrahealing;
701 			break;
702 		/*case SPELL_RESTOREABILITY:
703 			spell = &spell_restoreability;
704 			break;*/
705 		case SPELL_CUREAILMENT:
706 			spell = &spell_cureailment;
707 			break;
708 		case SPELL_DIG:
709 			spell = &spell_dig;
710 			break;
711 		case SPELL_SUMMON:
712 			spell = &spell_summon;
713 			break;
714 		case SPELL_STONEBLOOD:
715 			spell = &spell_stoneblood;
716 			break;
717 		case SPELL_BLEED:
718 			spell = &spell_bleed;
719 			break;
720 		case SPELL_DOMINATE:
721 			spell = &spell_dominate;
722 			break;
723 		case SPELL_REFLECT_MAGIC:
724 			spell = &spell_reflectMagic;
725 			break;
726 		case SPELL_ACID_SPRAY:
727 			spell = &spell_acidSpray;
728 			break;
729 		case SPELL_STEAL_WEAPON:
730 			spell = &spell_stealWeapon;
731 			break;
732 		case SPELL_DRAIN_SOUL:
733 			spell = &spell_drainSoul;
734 			break;
735 		case SPELL_VAMPIRIC_AURA:
736 			spell = &spell_vampiricAura;
737 			break;
738 		case SPELL_CHARM_MONSTER:
739 			spell = &spell_charmMonster;
740 			break;
741 		case SPELL_REVERT_FORM:
742 			spell = &spell_revertForm;
743 			break;
744 		case SPELL_RAT_FORM:
745 			spell = &spell_ratForm;
746 			break;
747 		case SPELL_SPIDER_FORM:
748 			spell = &spell_spiderForm;
749 			break;
750 		case SPELL_TROLL_FORM:
751 			spell = &spell_trollForm;
752 			break;
753 		case SPELL_IMP_FORM:
754 			spell = &spell_impForm;
755 			break;
756 		case SPELL_SPRAY_WEB:
757 			spell = &spell_sprayWeb;
758 			break;
759 		case SPELL_POISON:
760 			spell = &spell_poison;
761 			break;
762 		case SPELL_SPEED:
763 			spell = &spell_speed;
764 			break;
765 		case SPELL_FEAR:
766 			spell = &spell_fear;
767 			break;
768 		case SPELL_STRIKE:
769 			spell = &spell_strike;
770 			break;
771 		case SPELL_DETECT_FOOD:
772 			spell = &spell_detectFood;
773 			break;
774 		case SPELL_WEAKNESS:
775 			spell = &spell_weakness;
776 			break;
777 		case SPELL_AMPLIFY_MAGIC:
778 			spell = &spell_amplifyMagic;
779 			break;
780 		case SPELL_SHADOW_TAG:
781 			spell = &spell_shadowTag;
782 			break;
783 		case SPELL_TELEPULL:
784 			spell = &spell_telePull;
785 			break;
786 		case SPELL_DEMON_ILLUSION:
787 			spell = &spell_demonIllusion;
788 			break;
789 		case SPELL_TROLLS_BLOOD:
790 			spell = &spell_trollsBlood;
791 			break;
792 		case SPELL_SALVAGE:
793 			spell = &spell_salvageItem;
794 			break;
795 		case SPELL_FLUTTER:
796 			spell = &spell_flutter;
797 			break;
798 		case SPELL_DASH:
799 			spell = &spell_dash;
800 			break;
801 		case SPELL_SELF_POLYMORPH:
802 			spell = &spell_polymorph;
803 			break;
804 		case SPELL_9:
805 		case SPELL_10:
806 			spell = &spell_weakness;
807 			break;
808 		default:
809 			break;
810 	}
811 
812 	return spell;
813 }
814 
getSpellbookFromSpellID(int spellID)815 int getSpellbookFromSpellID(int spellID)
816 {
817 	ItemType itemType = WOODEN_SHIELD;
818 	switch (spellID)
819 	{
820 		case SPELL_FORCEBOLT:
821 			itemType = SPELLBOOK_FORCEBOLT;
822 			break;
823 		case SPELL_MAGICMISSILE:
824 			itemType = SPELLBOOK_MAGICMISSILE;
825 			break;
826 		case SPELL_COLD:
827 			itemType = SPELLBOOK_COLD;
828 			break;
829 		case SPELL_FIREBALL:
830 			itemType = SPELLBOOK_FIREBALL;
831 			break;
832 		case SPELL_LIGHTNING:
833 			itemType = SPELLBOOK_LIGHTNING;
834 			break;
835 		case SPELL_REMOVECURSE:
836 			itemType = SPELLBOOK_REMOVECURSE;
837 			break;
838 		case SPELL_LIGHT:
839 			itemType = SPELLBOOK_LIGHT;
840 			break;
841 		case SPELL_IDENTIFY:
842 			itemType = SPELLBOOK_IDENTIFY;
843 			break;
844 		case SPELL_MAGICMAPPING:
845 			itemType = SPELLBOOK_MAGICMAPPING;
846 			break;
847 		case SPELL_SLEEP:
848 			itemType = SPELLBOOK_SLEEP;
849 			break;
850 		case SPELL_CONFUSE:
851 			itemType = SPELLBOOK_CONFUSE;
852 			break;
853 		case SPELL_SLOW:
854 			itemType = SPELLBOOK_SLOW;
855 			break;
856 		case SPELL_OPENING:
857 			itemType = SPELLBOOK_OPENING;
858 			break;
859 		case SPELL_LOCKING:
860 			itemType = SPELLBOOK_LOCKING;
861 			break;
862 		case SPELL_LEVITATION:
863 			itemType = SPELLBOOK_LEVITATION;
864 			break;
865 		case SPELL_INVISIBILITY:
866 			itemType = SPELLBOOK_INVISIBILITY;
867 			break;
868 		case SPELL_TELEPORTATION:
869 			itemType = SPELLBOOK_TELEPORTATION;
870 			break;
871 		case SPELL_HEALING:
872 			itemType = SPELLBOOK_HEALING;
873 			break;
874 		case SPELL_EXTRAHEALING:
875 			itemType = SPELLBOOK_EXTRAHEALING;
876 			break;
877 		case SPELL_CUREAILMENT:
878 			itemType = SPELLBOOK_CUREAILMENT;
879 			break;
880 		case SPELL_DIG:
881 			itemType = SPELLBOOK_DIG;
882 			break;
883 		case SPELL_SUMMON:
884 			itemType = SPELLBOOK_SUMMON;
885 			break;
886 		case SPELL_STONEBLOOD:
887 			itemType = SPELLBOOK_STONEBLOOD;
888 			break;
889 		case SPELL_BLEED:
890 			itemType = SPELLBOOK_BLEED;
891 			break;
892 		/*case SPELL_DOMINATE:
893 			itemType = SPELLBOOK_DOMINATE;
894 			break;*/
895 		case SPELL_REFLECT_MAGIC:
896 			itemType = SPELLBOOK_REFLECT_MAGIC;
897 			break;
898 		case SPELL_ACID_SPRAY:
899 			itemType = SPELLBOOK_ACID_SPRAY;
900 			break;
901 		case SPELL_STEAL_WEAPON:
902 			itemType = SPELLBOOK_STEAL_WEAPON;
903 			break;
904 		case SPELL_DRAIN_SOUL:
905 			itemType = SPELLBOOK_DRAIN_SOUL;
906 			break;
907 		case SPELL_VAMPIRIC_AURA:
908 			itemType = SPELLBOOK_VAMPIRIC_AURA;
909 			break;
910 		case SPELL_CHARM_MONSTER:
911 			itemType = SPELLBOOK_CHARM_MONSTER;
912 			break;
913 		case SPELL_REVERT_FORM:
914 			itemType = SPELLBOOK_REVERT_FORM;
915 			break;
916 		case SPELL_RAT_FORM:
917 			itemType = SPELLBOOK_RAT_FORM;
918 			break;
919 		case SPELL_SPIDER_FORM:
920 			itemType = SPELLBOOK_SPIDER_FORM;
921 			break;
922 		case SPELL_TROLL_FORM:
923 			itemType = SPELLBOOK_TROLL_FORM;
924 			break;
925 		case SPELL_IMP_FORM:
926 			itemType = SPELLBOOK_IMP_FORM;
927 			break;
928 		case SPELL_SPRAY_WEB:
929 			itemType = SPELLBOOK_SPRAY_WEB;
930 			break;
931 		case SPELL_POISON:
932 			itemType = SPELLBOOK_POISON;
933 			break;
934 		case SPELL_SPEED:
935 			itemType = SPELLBOOK_SPEED;
936 			break;
937 		case SPELL_FEAR:
938 			itemType = SPELLBOOK_FEAR;
939 			break;
940 		case SPELL_STRIKE:
941 			itemType = SPELLBOOK_STRIKE;
942 			break;
943 		case SPELL_DETECT_FOOD:
944 			itemType = SPELLBOOK_DETECT_FOOD;
945 			break;
946 		case SPELL_WEAKNESS:
947 			itemType = SPELLBOOK_WEAKNESS;
948 			break;
949 		case SPELL_AMPLIFY_MAGIC:
950 			itemType = SPELLBOOK_AMPLIFY_MAGIC;
951 			break;
952 		case SPELL_SHADOW_TAG:
953 			itemType = SPELLBOOK_SHADOW_TAG;
954 			break;
955 		case SPELL_TELEPULL:
956 			itemType = SPELLBOOK_TELEPULL;
957 			break;
958 		case SPELL_DEMON_ILLUSION:
959 			itemType = SPELLBOOK_DEMON_ILLU;
960 			break;
961 		case SPELL_TROLLS_BLOOD:
962 			itemType = SPELLBOOK_TROLLS_BLOOD;
963 			break;
964 		case SPELL_SALVAGE:
965 			itemType = SPELLBOOK_SALVAGE;
966 			break;
967 		case SPELL_FLUTTER:
968 			itemType = SPELLBOOK_FLUTTER;
969 			break;
970 		case SPELL_DASH:
971 			itemType = SPELLBOOK_DASH;
972 			break;
973 		case SPELL_SELF_POLYMORPH:
974 			itemType = SPELLBOOK_SELF_POLYMORPH;
975 			break;
976 		case SPELL_9:
977 			itemType = SPELLBOOK_9;
978 			break;
979 		case SPELL_10:
980 			itemType = SPELLBOOK_10;
981 			break;
982 		default:
983 			break;
984 	}
985 
986 	return itemType;
987 }
988 
getSpellIDFromSpellbook(int spellbookType)989 int getSpellIDFromSpellbook(int spellbookType)
990 {
991 	switch (spellbookType )
992 	{
993 		case SPELLBOOK_FORCEBOLT:
994 			return spell_forcebolt.ID;
995 		case SPELLBOOK_MAGICMISSILE:
996 			return spell_magicmissile.ID;
997 		case SPELLBOOK_COLD:
998 			return spell_cold.ID;
999 		case SPELLBOOK_FIREBALL:
1000 			return spell_fireball.ID;
1001 		case SPELLBOOK_LIGHTNING:
1002 			return spell_lightning.ID;
1003 		case SPELLBOOK_REMOVECURSE:
1004 			return spell_removecurse.ID;
1005 		case SPELLBOOK_LIGHT:
1006 			return spell_light.ID;
1007 		case SPELLBOOK_IDENTIFY:
1008 			return spell_identify.ID;
1009 		case SPELLBOOK_MAGICMAPPING:
1010 			return spell_magicmapping.ID;
1011 		case SPELLBOOK_SLEEP:
1012 			return spell_sleep.ID;
1013 		case SPELLBOOK_CONFUSE:
1014 			return spell_confuse.ID;
1015 		case SPELLBOOK_SLOW:
1016 			return spell_slow.ID;
1017 		case SPELLBOOK_OPENING:
1018 			return spell_opening.ID;
1019 		case SPELLBOOK_LOCKING:
1020 			return spell_locking.ID;
1021 		case SPELLBOOK_LEVITATION:
1022 			return spell_levitation.ID;
1023 		case SPELLBOOK_INVISIBILITY:
1024 			return spell_invisibility.ID;
1025 		case SPELLBOOK_TELEPORTATION:
1026 			return spell_teleportation.ID;
1027 		case SPELLBOOK_HEALING:
1028 			return spell_healing.ID;
1029 		case SPELLBOOK_EXTRAHEALING:
1030 			return spell_extrahealing.ID;
1031 		case SPELLBOOK_CUREAILMENT:
1032 			return spell_cureailment.ID;
1033 		case SPELLBOOK_DIG:
1034 			return spell_dig.ID;
1035 		case SPELLBOOK_SUMMON:
1036 			return spell_summon.ID;
1037 		case SPELLBOOK_STONEBLOOD:
1038 			return spell_stoneblood.ID;
1039 		case SPELLBOOK_BLEED:
1040 			return spell_bleed.ID;
1041 		case SPELLBOOK_REFLECT_MAGIC:
1042 			return spell_reflectMagic.ID;
1043 		case SPELLBOOK_ACID_SPRAY:
1044 			return spell_acidSpray.ID;
1045 		case SPELLBOOK_STEAL_WEAPON:
1046 			return spell_stealWeapon.ID;
1047 		case SPELLBOOK_DRAIN_SOUL:
1048 			return spell_drainSoul.ID;
1049 		case SPELLBOOK_VAMPIRIC_AURA:
1050 			return spell_vampiricAura.ID;
1051 		case SPELLBOOK_CHARM_MONSTER:
1052 			return spell_charmMonster.ID;
1053 		case SPELLBOOK_REVERT_FORM:
1054 			return spell_revertForm.ID;
1055 		case SPELLBOOK_RAT_FORM:
1056 			return spell_ratForm.ID;
1057 		case SPELLBOOK_SPIDER_FORM:
1058 			return spell_spiderForm.ID;
1059 		case SPELLBOOK_TROLL_FORM:
1060 			return spell_trollForm.ID;
1061 		case SPELLBOOK_IMP_FORM:
1062 			return spell_impForm.ID;
1063 		case SPELLBOOK_SPRAY_WEB:
1064 			return spell_sprayWeb.ID;
1065 		case SPELLBOOK_POISON:
1066 			return spell_poison.ID;
1067 		case SPELLBOOK_SPEED:
1068 			return spell_speed.ID;
1069 		case SPELLBOOK_FEAR:
1070 			return spell_fear.ID;
1071 		case SPELLBOOK_STRIKE:
1072 			return spell_strike.ID;
1073 		case SPELLBOOK_DETECT_FOOD:
1074 			return spell_detectFood.ID;
1075 		case SPELLBOOK_WEAKNESS:
1076 			return spell_weakness.ID;
1077 		case SPELLBOOK_AMPLIFY_MAGIC:
1078 			return spell_amplifyMagic.ID;
1079 		case SPELLBOOK_SHADOW_TAG:
1080 			return spell_shadowTag.ID;
1081 		case SPELLBOOK_TELEPULL:
1082 			return spell_telePull.ID;
1083 		case SPELLBOOK_DEMON_ILLU:
1084 			return spell_demonIllusion.ID;
1085 		case SPELLBOOK_TROLLS_BLOOD:
1086 			return spell_trollsBlood.ID;
1087 		case SPELLBOOK_SALVAGE:
1088 			return spell_salvageItem.ID;
1089 		case SPELLBOOK_FLUTTER:
1090 			return spell_flutter.ID;
1091 		case SPELLBOOK_DASH:
1092 			return spell_dash.ID;
1093 		case SPELLBOOK_SELF_POLYMORPH:
1094 			return spell_polymorph.ID;
1095 		case SPELL_9:
1096 			return spell_weakness.ID;
1097 		case SPELL_10:
1098 			return spell_weakness.ID;
1099 		default:
1100 			return SPELL_NONE;
1101 	}
1102 }
1103 
spellInList(list_t * list,spell_t * spell)1104 bool spellInList(list_t* list, spell_t* spell)
1105 {
1106 	if ( !spell )
1107 	{
1108 		return false;
1109 	}
1110 	node_t* node;
1111 	for ( node = list->first; node != NULL; node = node->next )
1112 	{
1113 		spell_t* current = (spell_t*)node->element;
1114 		if (current)
1115 		{
1116 			if (current->ID == spell->ID)
1117 			{
1118 				return true;
1119 			}
1120 		}
1121 	}
1122 
1123 	return false;
1124 }
1125 
spell_changeHealth(Entity * entity,int amount,bool overdrewFromHP)1126 void spell_changeHealth(Entity* entity, int amount, bool overdrewFromHP)
1127 {
1128 	if (!entity)
1129 	{
1130 		return;
1131 	}
1132 
1133 	entity->modHP(amount);
1134 
1135 	int player = -1;
1136 	int i = 0;
1137 	for (i = 0; i < MAXPLAYERS; ++i)
1138 	{
1139 		if (entity == players[i]->entity)
1140 		{
1141 			player = i;
1142 		}
1143 	}
1144 
1145 	if (player > -1 && player < MAXPLAYERS)
1146 	{
1147 		if (amount > 0)
1148 		{
1149 			if ( overdrewFromHP )
1150 			{
1151 				Uint32 color = SDL_MapRGB(mainsurface->format, 255, 255, 255);
1152 				messagePlayerColor(player, color, language[3400]);
1153 			}
1154 			else
1155 			{
1156 				Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
1157 				messagePlayerColor(player, color, language[443]);
1158 			}
1159 		}
1160 		else
1161 		{
1162 			Uint32 color = SDL_MapRGB(mainsurface->format, 255, 255, 0);
1163 			if (amount == 0)
1164 			{
1165 				messagePlayerColor(player, color, language[444]);
1166 			}
1167 			else
1168 			{
1169 				messagePlayerColor(player, color, language[445]);
1170 			}
1171 		}
1172 
1173 		if ( multiplayer == SERVER && player > 0 )
1174 		{
1175 			strcpy((char*)net_packet->data, "UPHP");
1176 			SDLNet_Write32((Uint32)stats[player]->HP, &net_packet->data[4]);
1177 			SDLNet_Write32(0, &net_packet->data[8]);
1178 			net_packet->address.host = net_clients[player - 1].host;
1179 			net_packet->address.port = net_clients[player - 1].port;
1180 			net_packet->len = 12;
1181 			sendPacketSafe(net_sock, net_packet->channel, net_packet, player - 1);
1182 		}
1183 	}
1184 }
1185 
getSpellFromItem(Item * item)1186 spell_t* getSpellFromItem(Item* item)
1187 {
1188 	spell_t* spell = nullptr;
1189 	node_t* node = nullptr;
1190 	if ( !item )
1191 	{
1192 		return nullptr;
1193 	}
1194 	for ( node = spellList.first; node; node = node->next )
1195 	{
1196 		if ( node->element )
1197 		{
1198 			spell = (spell_t*) node->element;
1199 			Uint32 appearance = item->appearance;
1200 			if ( item->type == SPELL_ITEM && item->appearance >= 1000 )
1201 			{
1202 				appearance -= 1000; // hack for normally uncontrollable spells.
1203 			}
1204 			if ( spell->ID == appearance )
1205 			{
1206 				return spell;    //Found the spell.
1207 			}
1208 		}
1209 	}
1210 
1211 	return nullptr;
1212 }
1213 
canUseShapeshiftSpellInCurrentForm(Item & item)1214 int canUseShapeshiftSpellInCurrentForm(Item& item)
1215 {
1216 	if ( itemCategory(&item) != SPELL_CAT )
1217 	{
1218 		return -1;
1219 	}
1220 	if ( item.appearance < 1000 )
1221 	{
1222 		return -1;
1223 	}
1224 	if ( !stats[clientnum] )
1225 	{
1226 		return -1;
1227 	}
1228 	spell_t* spell = getSpellFromItem(&item);
1229 	if ( !spell )
1230 	{
1231 		return -1;
1232 	}
1233 	if ( !stats[clientnum]->EFFECTS[EFF_SHAPESHIFT] )
1234 	{
1235 		return 0;
1236 	}
1237 	switch ( spell->ID )
1238 	{
1239 		case SPELL_SPEED:
1240 		case SPELL_DETECT_FOOD:
1241 			if ( stats[clientnum]->type == RAT )
1242 			{
1243 				return 1;
1244 			}
1245 			break;
1246 		case SPELL_POISON:
1247 		case SPELL_SPRAY_WEB:
1248 			if ( stats[clientnum]->type == SPIDER )
1249 			{
1250 				return 1;
1251 			}
1252 			break;
1253 		case SPELL_STRIKE:
1254 		case SPELL_FEAR:
1255 		case SPELL_TROLLS_BLOOD:
1256 			if ( stats[clientnum]->type == TROLL )
1257 			{
1258 				return 1;
1259 			}
1260 			break;
1261 		case SPELL_LIGHTNING:
1262 		case SPELL_CONFUSE:
1263 		case SPELL_AMPLIFY_MAGIC:
1264 			if ( stats[clientnum]->type == CREATURE_IMP )
1265 			{
1266 				return 1;
1267 			}
1268 			break;
1269 		default:
1270 			break;
1271 	}
1272 	return 0;
1273 }
1274