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