World of Might and Magic  0.2.0
Open reimplementation of Might and Magic 6 7 8 game engine
CastSpellInfo.cpp
См. документацию.
2 
3 #include "Engine/Awards.h"
4 #include "Engine/Engine.h"
5 #include "Engine/Events.h"
6 #include "Engine/LOD.h"
7 #include "Engine/Localization.h"
8 #include "Engine/OurMath.h"
9 #include "Engine/Party.h"
10 #include "Engine/SpellFxRenderer.h"
11 #include "Engine/Time.h"
12 #include "Engine/stru123.h"
13 
18 
19 #include "Engine/Objects/Actor.h"
22 
24 
26 
27 #include "GUI/GUIButton.h"
28 #include "GUI/GUIWindow.h"
29 
30 #include "GUI/UI/UIGame.h"
31 #include "GUI/UI/UIStatusBar.h"
32 
33 #include "IO/Mouse.h"
34 
36 
38 
41 
42 const size_t CastSpellInfoCount = 10;
43 std::array<CastSpellInfo, CastSpellInfoCount> pCastSpellInfo;
44 
45 //----- (00427E01) --------------------------------------------------------
47  CastSpellInfo *pCastSpell; // ebx@2
48  signed int spell_pointed_target; // eax@14
49 
50  int monster_id; // ecx@184
51  int spell_overlay_id; // eax@274
52  int dist_X; // eax@278
53  int dist_Z;
54  int spell_spray_angle_start; // esi@369
55  int spell_spray_angle_end; // edi@369
56  double spell_recharge_factor; // st7@478
57  ItemGen *spell_item_to_enchant; // edi@492
58 
59  int v258; // ecx@514
60  char v259; // al@516
61  int v260; // eax@518
62  int v261; // esi@519
63  int v262; // edx@521
64  int *v263; // ecx@521
65  int v264; // esi@521
66  int v265; // edx@521
67 
68  int v267; // eax@524
69  int v268; // eax@524
70  int v278; // ecx@548
71  char v279; // al@550
72  int v280; // eax@552
73  int *v281; // esi@553
74  int v282; // edx@555
75  int *v283; // ecx@555
76  int v284; // esi@555
77  int v285; // edx@555
78  int *l; // eax@556
79  int v295; // edx@575
80  char v313; // al@606pGame->GetStru6()
81  const char *v317; // ecx@617
82  // int v396; // eax@752
83  __int16 v448; // ax@864
84  DDM_DLV_Header *v613; // eax@1108
85  int v642; // edi@1156
86  int v643; // eax@1156
87  int v659; // [sp+0h] [bp-E84h]@123
88  // unsigned __int64 v663; // [sp+0h] [bp-E84h]@639
89  int target_undead; // [sp+4h] [bp-E80h]@12
90  PLAYER_SKILL_TYPE which_skill; // [sp+4h] [bp-E80h]@25
91  int v679[800]; // [sp+14h] [bp-E70h]@515
92  unsigned __int64 v685; // [sp+D08h] [bp-17Ch]@416
93  unsigned __int64 v687; // [sp+D24h] [bp-160h]@327
94  Vec3_int_ v688; // [sp+D2Ch] [bp-158h]@943
95  Vec3_int_ v691; // [sp+D38h] [bp-14Ch]@137
96  Vec3_int_ v694; // [sp+D44h] [bp-140h]@982
97  Vec3_int_ v697; // [sp+D50h] [bp-134h]@129
98  Vec3_int_ v700; // [sp+D5Ch] [bp-128h]@339
99  Vec3_int_ v701; // [sp+D68h] [bp-11Ch]@286
100  Vec3_int_ v704; // [sp+D74h] [bp-110h]@132
101  Vec3_int_ v707; // [sp+D80h] [bp-104h]@1127
102  // int v710; // [sp+D8Ch] [bp-F8h]@1156
103 
104  AIDirection target_direction; // [sp+DA4h] [bp-E0h]@21
105 
106  int dist_Y; // [sp+DD8h] [bp-ACh]@163
107  int spell_level = 0; // [sp+E4Ch] [bp-38h]@1
108  ItemGen *_this = 0; // [sp+E50h] [bp-34h]@23
109  int v725 = 0; // [sp+E54h] [bp-30h]@23
110  int buff_resist;
111  bool spell_sound_flag = false; // [sp+E5Ch] [bp-28h]@1
112  Player *pPlayer; // [sp+E64h] [bp-20h]@8
113  int v730; // [sp+E68h] [bp-1Ch]@53
114  ItemGen *v730c;
115  int skill_level = 0; // [sp+E6Ch] [bp-18h]@48
116  signed int v732; // [sp+E70h] [bp-14h]@325
117 
118  int spellduration;
119  signed int spell_targeted_at = 0; // [sp+E7Ch] [bp-8h]@14
120  int amount = 0; // [sp+E80h] [bp-4h]@1
121  int obj_type;
122  ItemDesc *_item;
123 
124  SpriteObject pSpellSprite; // [sp+DDCh] [bp-A8h]@1
125 
126  for (int n = 0; n < CastSpellInfoCount; ++n) { // cycle through spell queue
127  pCastSpell = &pCastSpellInfo[n];
128  if (pCastSpell->uSpellID == 0)
129  continue; // spell item blank skip to next
130 
131  if (pParty->Invisible())
133  .Reset(); // no longer invisible
134 
135  if (pCastSpell->uFlags & ON_CAST_CastingInProgress) {
136  if (!pParty->pPlayers[pCastSpell->uPlayerID].CanAct())
137  Cancel_Spell_Cast_In_Progress(); // this cancels the spell cast if the player can no
138  // longer act
139 
140  continue;
141  }
142 
143  pPlayer = &pParty->pPlayers[pCastSpell->uPlayerID];
144 
145  spell_targeted_at = pCastSpell->spell_target_pid;
146 
147  if (spell_targeted_at == 0) { // no target ?? test
148  if (pCastSpell->uSpellID == SPELL_LIGHT_DESTROY_UNDEAD ||
149  pCastSpell->uSpellID == SPELL_SPIRIT_TURN_UNDEAD ||
150  pCastSpell->uSpellID == SPELL_DARK_CONTROL_UNDEAD)
151  target_undead = 1;
152  else
153  target_undead = 0;
154 
155  spell_targeted_at = stru_50C198.FindClosestActor(
156  5120, 1, target_undead); // find closest target
157  spell_pointed_target = mouse->uPointingObjectID;
158 
159  if (mouse->uPointingObjectID &&
160  PID_TYPE(spell_pointed_target) == OBJECT_Actor &&
161  pActors[PID_ID(spell_pointed_target)].CanAct()) // check can act
162  spell_targeted_at = mouse->uPointingObjectID;
163  }
164 
165  pSpellSprite.uType = spell_sprite_mapping[pCastSpell->uSpellID].uSpriteType;
166 
167  if (pSpellSprite.uType != SPRITE_NULL) {
168  if (PID_TYPE(spell_targeted_at) == OBJECT_Actor) {
170  PID(OBJECT_Player, pCastSpell->uPlayerID + 1),
171  spell_targeted_at, &target_direction,
172  0); // target direciton
173  } else {
174  target_direction.uYawAngle = pParty->sRotationY; // spray infront of party
175  target_direction.uPitchAngle = -pParty->sRotationX;
176  }
177  }
178 
179  if (pCastSpell->forced_spell_skill_level) { // for spell scrolls - decode
180  // spell power and mastery
181  spell_level = (pCastSpell->forced_spell_skill_level) & 0x3F; // 6 bytes
182  skill_level = ((pCastSpell->forced_spell_skill_level) & 0x1C0) / 64 + 1;
183  } else {
184  if (pCastSpell->uSpellID < SPELL_AIR_WIZARD_EYE)
185  which_skill = PLAYER_SKILL_FIRE;
186  else if (pCastSpell->uSpellID < SPELL_WATER_AWAKEN)
187  which_skill = PLAYER_SKILL_AIR;
188  else if (pCastSpell->uSpellID < SPELL_EARTH_STUN)
189  which_skill = PLAYER_SKILL_WATER;
190  else if (pCastSpell->uSpellID < SPELL_SPIRIT_DETECT_LIFE)
191  which_skill = PLAYER_SKILL_EARTH;
192  else if (pCastSpell->uSpellID < SPELL_MIND_REMOVE_FEAR)
193  which_skill = PLAYER_SKILL_SPIRIT;
194  else if (pCastSpell->uSpellID < SPELL_BODY_CURE_WEAKNESS)
195  which_skill = PLAYER_SKILL_MIND;
196  else if (pCastSpell->uSpellID < SPELL_LIGHT_LIGHT_BOLT)
197  which_skill = PLAYER_SKILL_BODY;
198  else if (pCastSpell->uSpellID < SPELL_DARK_REANIMATE)
199  which_skill = PLAYER_SKILL_LIGHT;
200  else if (pCastSpell->uSpellID < SPELL_BOW_ARROW)
201  which_skill = PLAYER_SKILL_DARK;
202  else if (pCastSpell->uSpellID == SPELL_BOW_ARROW)
203  which_skill = PLAYER_SKILL_BOW;
204  else if (pCastSpell->uSpellID == SPELL_101 ||
205  pCastSpell->uSpellID == SPELL_LASER_PROJECTILE)
206  which_skill = PLAYER_SKILL_BLASTER;
207  else
208  assert(false && "Unknown spell");
209 
210  spell_level = pPlayer->GetActualSkillLevel(which_skill);
211  skill_level = pPlayer->GetActualSkillMastery(which_skill);
212 
213  if (engine->config->debug_all_magic) {
214  spell_level = 10;
215  skill_level = 4;
216  }
217  }
218 
219  if (pCastSpell->uSpellID < SPELL_BOW_ARROW) {
220  if (pCastSpell->forced_spell_skill_level || engine->config->debug_all_magic)
221  uRequiredMana = 0;
222  else
223  uRequiredMana = pSpellDatas[pCastSpell->uSpellID].mana_per_skill[skill_level - 1];
224 
225  sRecoveryTime = pSpellDatas[pCastSpell->uSpellID].recovery_per_skill[skill_level - 1];
226  }
227 
228  if (!pCastSpell->forced_spell_skill_level) {
229  if (which_skill == PLAYER_SKILL_DARK && pParty->uCurrentHour == 0 &&
230  pParty->uCurrentMinute == 0 ||
231  which_skill == PLAYER_SKILL_LIGHT && pParty->uCurrentHour == 12 &&
232  pParty->uCurrentMinute == 0) // free spells at midnight or midday
233  uRequiredMana = 0;
234  }
235 
236  if (pCastSpell->uSpellID < SPELL_BOW_ARROW &&
237  pPlayer->sMana < uRequiredMana) {
239  localization->GetString(586)); // "Not enough spell points"
240  pCastSpell->uSpellID = 0;
241  continue;
242  }
243 
244  if (pPlayer->IsCursed() && pCastSpell->uSpellID < SPELL_BOW_ARROW &&
245  rand() % 100 < 50) { //неудачное кастование - player is cursed
246  if (!pParty->bTurnBasedModeOn) {
247  pPlayer->SetRecoveryTime(
248  (int64_t)(flt_6BE3A4_debug_recmod1 * 213.3333333333333));
249  } else {
251  pPlayer->SetRecoveryTime(sRecoveryTime);
253  }
254 
256  localization->GetString(428)); // "Spell failed"
257  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
258  pCastSpellInfo[n].uSpellID = 0;
259  pPlayer->sMana -= uRequiredMana;
260  return;
261  }
262 
263  // do mana check here?
264 
265  switch (pCastSpell->uSpellID) {
266  case SPELL_101:
267  assert(false &&
268  "Unknown spell effect #101 (prolly flaming bow arrow");
269 
270  case SPELL_BOW_ARROW: //стрельба из лука
271  {
272  amount = 1;
273  if (skill_level >= 3) amount = 2;
274 
275  sRecoveryTime = pPlayer->GetAttackRecoveryTime(true);
276  pSpellSprite.containing_item.Reset();
277  pSpellSprite.spell_level = spell_level;
278  pSpellSprite.spell_id = pCastSpell->uSpellID;
279  pSpellSprite.spell_skill = skill_level;
280  pSpellSprite.uObjectDescID = pObjectList->ObjectIDByItemID(pSpellSprite.uType);
282  pSpellSprite.uObjectDescID = pObjectList->ObjectIDByItemID(0xBD6u);
283  pSpellSprite.vPosition.x = pParty->vPosition.x;
284  pSpellSprite.vPosition.y = pParty->vPosition.y;
285  pSpellSprite.uAttributes = 0;
286  pSpellSprite.uSpriteFrameID = 0;
287  pSpellSprite.vPosition.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
288  pSpellSprite.spell_caster_pid = PID(OBJECT_Player, pCastSpell->uPlayerID);
289  pSpellSprite.spell_target_pid = spell_targeted_at;
290  pSpellSprite.field_60_distance_related_prolly_lod = target_direction.uDistance;
291  pSpellSprite.uFacing = target_direction.uYawAngle;
292  pSpellSprite.uSoundID = pCastSpell->sound_id;
293  pPlayer = &pParty->pPlayers[pCastSpell->uPlayerID];
294  memcpy(
295  &pSpellSprite.containing_item,
296  &pPlayer->pInventoryItemList[pPlayer->pEquipment.uBow - 1],
297  sizeof(pSpellSprite.containing_item));
298  pSpellSprite.uAttributes = 256;
299  if (pParty->bTurnBasedModeOn) {
300  pSpellSprite.uAttributes = 260;
301  }
302  for (int i = 0; i < amount; ++i) {
303  if (i)
304  pSpellSprite.vPosition.z += 32;
305  pSpellSprite.uSectorID = pIndoor->GetSector(
306  pSpellSprite.vPosition.x, pSpellSprite.vPosition.y,
307  pSpellSprite.vPosition.z);
308  if (pSpellSprite.Create(target_direction.uYawAngle,
309  target_direction.uPitchAngle,
310  pObjectList->pObjects[pSpellSprite.uObjectDescID].uSpeed,
311  pCastSpell->uPlayerID + 1) != -1 &&
314  }
315  }
316  break;
317  }
318 
319  case SPELL_LASER_PROJECTILE: //стрельба из бластера
320  {
321  sRecoveryTime = pPlayer->GetAttackRecoveryTime(0);
322  pSpellSprite.containing_item.Reset();
323  pSpellSprite.spell_id = pCastSpell->uSpellID;
324  pSpellSprite.spell_level = spell_level;
325  pSpellSprite.spell_skill = skill_level;
326  pSpellSprite.uObjectDescID = pObjectList->ObjectIDByItemID(pSpellSprite.uType);
327  pSpellSprite.vPosition.x = pParty->vPosition.x;
328  pSpellSprite.vPosition.y = pParty->vPosition.y;
329  pSpellSprite.uAttributes = 0;
330  pSpellSprite.uSpriteFrameID = 0;
331  pSpellSprite.vPosition.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 2;
332  pSpellSprite.spell_caster_pid = PID(OBJECT_Player, pCastSpell->uPlayerID);
333  pSpellSprite.spell_target_pid = spell_targeted_at;
334  pSpellSprite.field_60_distance_related_prolly_lod = target_direction.uDistance;
335  pSpellSprite.uFacing = target_direction.uYawAngle;
336  pSpellSprite.uSoundID = pCastSpell->sound_id;
337  pPlayer = &pParty->pPlayers[pCastSpell->uPlayerID];
338  memcpy(
339  &pSpellSprite.containing_item,
340  &pPlayer->pInventoryItemList[pPlayer->pEquipment.uMainHand -
341  1],
342  sizeof(pSpellSprite.containing_item));
343  // &pParty->pPlayers[pCastSpell->uPlayerID].spellbook.pDarkSpellbook.bIsSpellAvailable[36
344  // *
345  // pParty->pPlayers[pCastSpell->uPlayerID].pEquipment.uMainHand +
346  // 5], );
347  pSpellSprite.uSectorID =
349  pSpellSprite.vPosition.z);
350  pSpellSprite.uAttributes |= 0x100;
351  if (pParty->bTurnBasedModeOn) {
352  pSpellSprite.uAttributes |= 4;
353  }
354  if (pSpellSprite.Create(
355  target_direction.uYawAngle,
356  target_direction.uPitchAngle,
357  pObjectList->pObjects[pSpellSprite.uObjectDescID]
358  .uSpeed,
359  pCastSpell->uPlayerID + 1) != -1 &&
362  }
363  break;
364  }
365 
366  case SPELL_FIRE_TORCH_LIGHT: //свет факела
367  {
368  switch (skill_level) {
369  case 1:
370  amount = 2;
371  break;
372  case 2:
373  amount = 3;
374  break;
375  case 3:
376  case 4:
377  amount = 4;
378  break;
379  default:
380  assert(false);
381  }
382  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
383 
386  (GameTime::FromSeconds(3600 * spell_level))),
387  skill_level, amount, 0, 0);
388  spell_sound_flag = true;
389  break;
390  }
391 
392  case SPELL_FIRE_FIRE_SPIKE: //огненный шип
393  {
394  switch (skill_level) {
395  case 1:
396  amount = 3;
397  break;
398  case 2:
399  amount = 5;
400  break;
401  case 3:
402  amount = 7;
403  break;
404  case 4:
405  amount = 9;
406  break;
407  default:
408  assert(false);
409  }
410  int _v733 = 0;
411  for (uint i = 0; i < uNumSpriteObjects; ++i) {
412  SpriteObject *object = &pSpriteObjects[i];
413  if (object->uType &&
414  object->spell_id == SPELL_FIRE_FIRE_SPIKE &&
415  object->spell_caster_pid ==
416  PID(OBJECT_Player, pCastSpell->uPlayerID))
417  ++_v733;
418  }
419  if (_v733 > amount) {
421  localization->GetString(428)); // Spell failed
422  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
423  pCastSpell->uSpellID = 0;
424  continue;
425  }
426  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
427  pSpellSprite.containing_item.Reset();
428  pSpellSprite.spell_id = pCastSpell->uSpellID;
429  pSpellSprite.spell_level = spell_level;
430  pSpellSprite.spell_skill = skill_level;
431  pSpellSprite.uObjectDescID =
432  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
433  pSpellSprite.vPosition.y = pParty->vPosition.y;
434  pSpellSprite.vPosition.x = pParty->vPosition.x;
435  pSpellSprite.uAttributes = 0;
436  pSpellSprite.vPosition.z =
437  pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
438  pSpellSprite.uSectorID = pIndoor->GetSector(
440  pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3);
441  pSpellSprite.uSpriteFrameID = 0;
442  pSpellSprite.spell_caster_pid =
443  PID(OBJECT_Player, pCastSpell->uPlayerID);
444  pSpellSprite.spell_target_pid = spell_targeted_at;
446  target_direction.uDistance;
447  pSpellSprite.uFacing = (short)target_direction.uYawAngle;
448  pSpellSprite.uSoundID = (short)pCastSpell->sound_id;
449  if (pParty->bTurnBasedModeOn) {
450  pSpellSprite.uAttributes |= 4;
451  }
452  v659 = pObjectList->pObjects[pSpellSprite.uObjectDescID].uSpeed;
453  if (pSpellSprite.Create(pParty->sRotationY,
454  pParty->sRotationX + 10, v659,
455  pCastSpell->uPlayerID + 1) != -1 &&
458  }
459  spell_sound_flag = true;
460  break;
461  }
462 
463  case SPELL_AIR_IMPLOSION: //Точный взрыв
464  {
465  monster_id = PID_ID(spell_targeted_at);
466  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
467  if (!spell_targeted_at) {
469  localization->GetString(428)); // Spell failed
470  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
471  pCastSpell->uSpellID = 0;
472  continue;
473  }
474  if (PID_TYPE(spell_targeted_at) == OBJECT_Actor) {
475  v697.x = 0;
476  v697.y = 0;
477  v697.z = 0;
478  pSpellSprite.containing_item.Reset();
479  pSpellSprite.spell_id = pCastSpell->uSpellID;
480  pSpellSprite.spell_level = spell_level;
481  pSpellSprite.spell_skill = skill_level;
482  pSpellSprite.uObjectDescID =
483  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
484  pSpellSprite.uAttributes = 0;
485  pSpellSprite.uSectorID = 0;
486  pSpellSprite.uSpriteFrameID = 0;
487  pSpellSprite.field_60_distance_related_prolly_lod = 0;
488  pSpellSprite.uFacing = 0;
489  pSpellSprite.spell_caster_pid =
490  PID(OBJECT_Player, pCastSpell->uPlayerID);
491  pSpellSprite.uSoundID = (short)pCastSpell->sound_id;
492  pSpellSprite.vPosition.x = pActors[monster_id].vPosition.x;
493  pSpellSprite.vPosition.z = pActors[monster_id].vPosition.z;
494  pSpellSprite.vPosition.y = pActors[monster_id].vPosition.y;
495  pSpellSprite.spell_target_pid =
496  PID(OBJECT_Actor, monster_id);
498  PID(OBJECT_Item, pSpellSprite.Create(0, 0, 0, 0)),
499  monster_id, &v697);
500  }
501  spell_sound_flag = true;
502  break;
503  }
504 
505  case SPELL_EARTH_MASS_DISTORTION: //Изменение веса
506  {
507  monster_id = PID_ID(spell_targeted_at);
508  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
509  if (pActors[monster_id].DoesDmgTypeDoDamage((DAMAGE_TYPE)3)) {
510  pActors[monster_id]
511  .pActorBuffs[ACTOR_BUFF_MASS_DISTORTION]
512  .Apply(GameTime(pMiscTimer->uTotalGameTimeElapsed + 128), 0, 0, 0,
513  0);
514  v704.x = 0;
515  v704.y = 0;
516  v704.z = 0;
517  pSpellSprite.containing_item.Reset();
518  pSpellSprite.spell_id = pCastSpell->uSpellID;
519  pSpellSprite.spell_level = spell_level;
520  pSpellSprite.spell_skill = skill_level;
521  pSpellSprite.uObjectDescID =
522  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
523  pSpellSprite.uAttributes = 0;
524  pSpellSprite.uSectorID = 0;
525  pSpellSprite.uSpriteFrameID = 0;
526  pSpellSprite.field_60_distance_related_prolly_lod = 0;
527  pSpellSprite.uFacing = 0;
528  pSpellSprite.spell_caster_pid =
529  PID(OBJECT_Player, pCastSpell->uPlayerID);
530  pSpellSprite.uSoundID = (short)pCastSpell->sound_id;
531  pSpellSprite.vPosition.x = pActors[monster_id].vPosition.x;
532  pSpellSprite.vPosition.y = pActors[monster_id].vPosition.y;
533  pSpellSprite.vPosition.z = pActors[monster_id].vPosition.z;
534  pSpellSprite.spell_target_pid =
535  PID(OBJECT_Actor, monster_id);
537  PID(OBJECT_Item, pSpellSprite.Create(0, 0, 0, 0)),
538  monster_id, &v704);
539  }
540  spell_sound_flag = true;
541  break;
542  }
543 
544  case SPELL_LIGHT_DESTROY_UNDEAD: //Уничтожение нежити
545  {
546  if (!pPlayer->CanCastSpell(uRequiredMana) ||
547  !spell_targeted_at ||
548  PID_TYPE(spell_targeted_at) != OBJECT_Actor)
549  break;
550  // v730 = spell_targeted_at >> 3;
551  // HIDWORD(spellduration) =
552  // (int)&pActors[PID_ID(spell_targeted_at)];
553  v691.x = 0;
554  v691.y = 0;
555  v691.z = 0;
556  pSpellSprite.containing_item.Reset();
557  pSpellSprite.spell_id = pCastSpell->uSpellID;
558  pSpellSprite.spell_level = spell_level;
559  pSpellSprite.spell_skill = skill_level;
560  pSpellSprite.uObjectDescID =
561  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
562  pSpellSprite.vPosition.x =
563  pActors[PID_ID(spell_targeted_at)].vPosition.x;
564  pSpellSprite.vPosition.y =
565  pActors[PID_ID(spell_targeted_at)].vPosition.y;
566  pSpellSprite.vPosition.z =
567  pActors[PID_ID(spell_targeted_at)].vPosition.z;
568  pSpellSprite.uAttributes = 0;
569  pSpellSprite.uSectorID = pIndoor->GetSector(
570  pSpellSprite.vPosition.x, pSpellSprite.vPosition.y,
571  pSpellSprite.vPosition.z);
572  pSpellSprite.uSpriteFrameID = 0;
573  pSpellSprite.spell_caster_pid =
574  PID(OBJECT_Player, pCastSpell->uPlayerID);
575  pSpellSprite.spell_target_pid = spell_targeted_at;
577  target_direction.uDistance;
578  pSpellSprite.uFacing = target_direction.uYawAngle;
579  pSpellSprite.uAttributes |= 0x80u;
580  pSpellSprite.uSoundID = pCastSpell->sound_id;
581  int obj_id = pSpellSprite.Create(0, 0, 0, 0);
583  pActors[PID_ID(spell_targeted_at)].pMonsterInfo.uID,
586  localization->GetString(428)); // Spell failed
587  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
588  pCastSpell->uSpellID = 0;
589  continue;
590  }
592  PID_ID(spell_targeted_at), &v691);
593  spell_sound_flag = true;
594  break;
595  }
596 
597  case SPELL_FIRE_FIRE_BOLT: //Удар огня
598  case SPELL_FIRE_FIREBALL: //Огненный шар
599  case SPELL_FIRE_INCINERATE: //Испепеление
600  case SPELL_AIR_LIGHNING_BOLT: //Удар молнии
601  case SPELL_WATER_ICE_BOLT: //Льдяная молния
602  case SPELL_WATER_ICE_BLAST: //Льдяной взрыв
603  case SPELL_EARTH_STUN: //Оглушить
604  case SPELL_EARTH_DEADLY_SWARM: //Рой смерти
605  case SPELL_MIND_MIND_BLAST: //Удар мысли
606  case SPELL_MIND_PSYCHIC_SHOCK: //Психический шок
607  case SPELL_BODY_HARM: //Вред
608  case SPELL_LIGHT_LIGHT_BOLT: //Луч света
609  case SPELL_DARK_DRAGON_BREATH: //Дыхание дракона
610  {
611  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
612  pSpellSprite.containing_item.Reset();
613  pSpellSprite.spell_id = pCastSpell->uSpellID;
614  pSpellSprite.spell_level = spell_level;
615  pSpellSprite.spell_skill = skill_level;
616  pSpellSprite.uObjectDescID =
617  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
618  pSpellSprite.vPosition.y = pParty->vPosition.y;
619  pSpellSprite.vPosition.x = pParty->vPosition.x;
620  pSpellSprite.vPosition.z =
621  pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
622  pSpellSprite.uAttributes = 0;
624  pSpellSprite.uSectorID = pIndoor->GetSector(
626  pParty->vPosition.z +
627  (signed int)pParty->uPartyHeight / 3);
628  else
629  pSpellSprite.uSectorID = 0;
630  pSpellSprite.uSpriteFrameID = 0;
631  pSpellSprite.spell_caster_pid =
632  PID(OBJECT_Player, pCastSpell->uPlayerID);
633  pSpellSprite.spell_target_pid = spell_targeted_at;
635  target_direction.uDistance;
636  pSpellSprite.uFacing = target_direction.uYawAngle;
637  pSpellSprite.uSoundID = pCastSpell->sound_id;
638  if (pParty->bTurnBasedModeOn) {
639  pSpellSprite.uAttributes |= 4;
640  }
641  if (pCastSpell->uSpellID == SPELL_AIR_LIGHNING_BOLT)
642  pSpellSprite.uAttributes |= 0x40;
643  v659 = pObjectList->pObjects[pSpellSprite.uObjectDescID].uSpeed;
644  if (pSpellSprite.Create(target_direction.uYawAngle,
645  target_direction.uPitchAngle, v659,
646  pCastSpell->uPlayerID + 1) != -1 &&
649  }
650  spell_sound_flag = true;
651  break;
652  }
653 
654  case SPELL_WATER_ACID_BURST: //Всплеск кислоты
655  case SPELL_EARTH_BLADES: //Лезвия
656  case SPELL_BODY_FLYING_FIST: //Летающий кулак
657  case SPELL_DARK_TOXIC_CLOUD: //Облако-токсин
658  {
659  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
660  pSpellSprite.containing_item.Reset();
661  pSpellSprite.spell_id = pCastSpell->uSpellID;
662  pSpellSprite.spell_level = spell_level;
663  pSpellSprite.spell_skill = skill_level;
664  pSpellSprite.uObjectDescID =
665  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
666  pSpellSprite.uAttributes = 0;
667  pSpellSprite.vPosition.x = pParty->vPosition.x;
668  pSpellSprite.vPosition.y = pParty->vPosition.y;
669  pSpellSprite.vPosition.z =
670  pParty->vPosition.z + (signed int)pParty->uPartyHeight / 2;
671  pSpellSprite.uSectorID =
673  pSpellSprite.vPosition.z);
674  pSpellSprite.uSpriteFrameID = 0;
675  pSpellSprite.spell_caster_pid =
676  PID(OBJECT_Player, pCastSpell->uPlayerID);
677  pSpellSprite.spell_target_pid = spell_targeted_at;
679  target_direction.uDistance;
680  pSpellSprite.uFacing = target_direction.uYawAngle;
681  pSpellSprite.uSoundID = pCastSpell->sound_id;
682  if (pParty->bTurnBasedModeOn) {
683  pSpellSprite.uAttributes |= 4;
684  }
685  v659 = pObjectList->pObjects[pSpellSprite.uObjectDescID].uSpeed;
686  if (pSpellSprite.Create(target_direction.uYawAngle,
687  target_direction.uPitchAngle, v659,
688  pCastSpell->uPlayerID + 1) != -1 &&
691  }
692  spell_sound_flag = true;
693  break;
694  }
695 
696  case SPELL_LIGHT_SUNRAY: { //Луч Солнца
699  (pParty->uCurrentHour < 5 ||
700  pParty->uCurrentHour >= 21)) { //только в дневное время
702  localization->GetString(428)); // Spell failed
703  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
704  pCastSpell->uSpellID = 0;
705  continue;
706  }
707  if (pPlayer->CanCastSpell(uRequiredMana)) {
708  pSpellSprite.containing_item.Reset();
709  pSpellSprite.spell_id = pCastSpell->uSpellID;
710  pSpellSprite.spell_skill = skill_level;
711  pSpellSprite.spell_level = spell_level;
712  pSpellSprite.uObjectDescID =
713  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
714  pSpellSprite.uAttributes = 0;
715  pSpellSprite.vPosition.x = pParty->vPosition.x;
716  pSpellSprite.vPosition.y = pParty->vPosition.y;
717  pSpellSprite.vPosition.z =
718  pParty->vPosition.z +
719  (signed int)pParty->uPartyHeight / 3;
720  pSpellSprite.uSectorID = pIndoor->GetSector(
722  pSpellSprite.vPosition.z);
723  pSpellSprite.uSpriteFrameID = 0;
724  pSpellSprite.spell_caster_pid =
725  PID(OBJECT_Player, pCastSpell->uPlayerID);
726  pSpellSprite.spell_target_pid = spell_targeted_at;
728  target_direction.uDistance;
729  pSpellSprite.uFacing = target_direction.uYawAngle;
730  pSpellSprite.uSoundID = pCastSpell->sound_id;
731  if (pParty->bTurnBasedModeOn) {
732  pSpellSprite.uAttributes |= 4;
733  }
734  v659 = pObjectList->pObjects[pSpellSprite.uObjectDescID]
735  .uSpeed;
736  if (pSpellSprite.Create(target_direction.uYawAngle,
737  target_direction.uPitchAngle, v659,
738  pCastSpell->uPlayerID + 1) != -1 &&
741  }
742  spell_sound_flag = true;
743  }
744  break;
745  }
746 
747  case SPELL_LIGHT_PARALYZE: //Паралич
748  {
749  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
750  monster_id = PID_ID(spell_targeted_at);
751  if (PID_TYPE(spell_targeted_at) == OBJECT_Actor &&
752  pActors[monster_id].DoesDmgTypeDoDamage((DAMAGE_TYPE)9)) {
753  Actor::AI_Stand(PID_ID(spell_targeted_at), 4, 0x80, 0);
754  pActors[monster_id].pActorBuffs[ACTOR_BUFF_PARALYZED].Apply(
756  GameTime::FromSeconds(3 * 60 * spell_level)),
757  skill_level, 0, 0, 0);
758  pActors[monster_id].uAttributes |= ACTOR_AGGRESSOR;
759  pActors[monster_id].vVelocity.x = 0;
760  pActors[monster_id].vVelocity.y = 0;
762  }
763  spell_sound_flag = true;
764  break;
765  }
766 
767  case SPELL_EARTH_SLOW: //Замедление
768  {
769  switch (skill_level) {
770  case 1:
771  spellduration = 180 * spell_level;
772  amount = 2;
773  break; // LODWORD(spellduration)???не применяется далее
774  case 2:
775  spellduration = 300 * spell_level;
776  amount = 2;
777  break;
778  case 3:
779  spellduration = 300 * spell_level;
780  amount = 4;
781  break;
782  case 4:
783  spellduration = 300 * spell_level;
784  amount = 8;
785  break;
786  default:
787  assert(false);
788  }
789  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
790  // v721 = 836 * PID_ID(spell_targeted_at);
791  monster_id = PID_ID(spell_targeted_at);
792  if (PID_TYPE(spell_targeted_at) == OBJECT_Actor &&
793  pActors[monster_id].DoesDmgTypeDoDamage((DAMAGE_TYPE)3)) {
794  pActors[monster_id].pActorBuffs[ACTOR_BUFF_SLOWED].Apply(
796  GameTime::FromSeconds(spellduration)),
797  skill_level, amount, 0, 0);
798  pActors[monster_id].uAttributes |= ACTOR_AGGRESSOR;
800  }
801  spell_sound_flag = true;
802  break;
803  }
804 
805  case SPELL_MIND_CHARM: // Очарование
806  {
807  monster_id = PID_ID(spell_targeted_at);
808  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
809  if (pActors[monster_id].DoesDmgTypeDoDamage((DAMAGE_TYPE)7)) {
810  uint power = 300 * spell_level;
811  if (skill_level == 2)
812  power = 600 * spell_level;
813  else if (skill_level == 3)
814  power = 29030400;
815 
816  pActors[monster_id].pActorBuffs[ACTOR_BUFF_BERSERK].Reset();
817  pActors[monster_id]
818  .pActorBuffs[ACTOR_BUFF_ENSLAVED]
819  .Reset();
820  pActors[monster_id].pActorBuffs[ACTOR_BUFF_CHARM].Apply(
822  GameTime::FromSeconds(power << 7)),
823  skill_level, 0, 0, 0);
824  pSpellSprite.containing_item.Reset();
825  pSpellSprite.spell_id = pCastSpell->uSpellID;
826  pSpellSprite.spell_level = spell_level;
827  pSpellSprite.spell_skill = skill_level;
828  pSpellSprite.uObjectDescID =
829  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
830  pSpellSprite.vPosition.x = pActors[monster_id].vPosition.x;
831  pSpellSprite.vPosition.y = pActors[monster_id].vPosition.y;
832  pSpellSprite.vPosition.z = pActors[monster_id].vPosition.z +
833  pActors[monster_id].uActorHeight;
834  pSpellSprite.uAttributes = 0;
835  pSpellSprite.uSectorID =
836  pIndoor->GetSector(pActors[monster_id].vPosition.x,
837  pActors[monster_id].vPosition.y,
838  pSpellSprite.vPosition.z);
839  pSpellSprite.uSpriteFrameID = 0;
840  pSpellSprite.spell_caster_pid =
841  PID(OBJECT_Player, pCastSpell->uPlayerID);
842  pSpellSprite.spell_target_pid = spell_targeted_at;
844  target_direction.uDistance;
845  pSpellSprite.uFacing = target_direction.uYawAngle;
846  pSpellSprite.uAttributes |= 0x80u;
847  pSpellSprite.uSoundID = pCastSpell->sound_id;
848  pSpellSprite.Create(0, 0, 0, pCastSpell->uPlayerID + 1);
849  }
850  spell_sound_flag = true;
851  break;
852  }
853 
854  case SPELL_DARK_SHRINKING_RAY: //Сжимающий луч
855  {
856  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
857  pSpellSprite.containing_item.Reset();
858  pSpellSprite.uObjectDescID =
859  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
860  pSpellSprite.vPosition.x = pParty->vPosition.x;
861  pSpellSprite.vPosition.y = pParty->vPosition.y;
862  pSpellSprite.uAttributes = 0;
863  pSpellSprite.vPosition.z =
864  pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
865  pSpellSprite.uSectorID = pIndoor->GetSector(
867  pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3);
868  pSpellSprite.uSpriteFrameID = 0;
869  pSpellSprite.spell_caster_pid =
870  PID(OBJECT_Player, pCastSpell->uPlayerID);
871  pSpellSprite.spell_target_pid = spell_targeted_at;
873  target_direction.uDistance;
874  pSpellSprite.uFacing = target_direction.uYawAngle;
875  pSpellSprite.uSoundID = pCastSpell->sound_id;
876  pSpellSprite.spell_skill = skill_level;
878  pSpellSprite.spell_level = 300 * spell_level;
879  if (pParty->bTurnBasedModeOn) {
880  pSpellSprite.uAttributes |= 4;
881  }
882  v659 = pObjectList->pObjects[pSpellSprite.uObjectDescID].uSpeed;
883  if (pSpellSprite.Create(target_direction.uYawAngle,
884  target_direction.uPitchAngle, v659,
885  pCastSpell->uPlayerID + 1) != -1 &&
888  }
889  spell_sound_flag = true;
890  break;
891  }
892 
893  case SPELL_FIRE_FIRE_AURA: //Аура огня
894  {
895  switch (skill_level) {
896  case 1:
897  spellduration = 3600 * spell_level;
898  amount = 10;
899  break; //Огня
900  case 2:
901  spellduration = 3600 * spell_level;
902  amount = 11;
903  break; //Огненного жара
904  case 3:
905  spellduration = 3600 * spell_level;
906  amount = 12;
907  break;
908  case 4:
909  spellduration = 0;
910  amount = 12;
911  break;
912  default:
913  assert(false);
914  }
915  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
916  v730c = &pParty->pPlayers[pCastSpell->uPlayerID_2]
917  .pInventoryItemList[spell_targeted_at - 1];
918  _item = &pItemsTable->pItems[v730c->uItemID];
920  if (v730c->uItemID < 64 ||
921  v730c->uItemID > 65 && !v730c->IsBroken() &&
922  !v730c->special_enchantment &&
923  !v730c->uEnchantmentType &&
924  (_item->uEquipType == EQUIP_SINGLE_HANDED ||
925  _item->uEquipType == EQUIP_TWO_HANDED ||
926  _item->uEquipType == EQUIP_BOW) &&
927  !pItemsTable->IsMaterialNonCommon(v730c)) {
928  v730c->special_enchantment = (ITEM_ENCHANTMENT)amount;
929  if (skill_level != 4) {
930  v730c->expirte_time =
932  GameTime::FromSeconds(spellduration));
933  v730c->uAttributes |= ITEM_TEMP_BONUS;
934  }
937  spell_sound_flag = true;
938  break;
939  }
944  localization->GetString(428)); // Spell failed
946  0);
947  pCastSpell->uSpellID = 0;
948  continue;
949  }
950 
951  case SPELL_BODY_REGENERATION: //Регенерация
952  {
953  switch (skill_level) {
954  case 1:
955  amount = 1;
956  break;
957  case 2:
958  amount = 1;
959  break;
960  case 3:
961  amount = 3;
962  break;
963  case 4:
964  amount = 10;
965  break;
966  default:
967  assert(false);
968  }
969  if (!pPlayer->CanCastSpell(uRequiredMana))
970  break;
971  spell_fx_renderer->SetPlayerBuffAnim(pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
972  pParty->pPlayers[pCastSpell->uPlayerID_2]
973  .pPlayerBuffs[PLAYER_BUFF_REGENERATION]
974  .Apply(GameTime(pParty->GetPlayingTime() +
975  GameTime::FromSeconds(3600 * spell_level)),
976  skill_level, amount, 0, 0);
977  spell_sound_flag = true;
978  break;
979  }
980 
981  case SPELL_FIRE_PROTECTION_FROM_FIRE: //Защита от Огня
982  case SPELL_AIR_PROTECTION_FROM_AIR: //Звщита от Воздуха
983  case SPELL_WATER_PROTECTION_FROM_WATER: //Защита от Воды
984  case SPELL_EARTH_PROTECTION_FROM_EARTH: //Защита от Земли
985  case SPELL_MIND_PROTECTION_FROM_MIND: //Защита от Мысли
986  case SPELL_BODY_PROTECTION_FROM_BODY: //Защита от Тела
987  {
988  switch (skill_level) {
989  case 1:
990  case 2:
991  case 3:
992  case 4:
993  amount = skill_level * spell_level;
994  break;
995  default:
996  assert(false);
997  }
998  switch (pCastSpell->uSpellID) {
1000  buff_resist = PARTY_BUFF_RESIST_FIRE;
1001  break;
1003  buff_resist = PARTY_BUFF_RESIST_AIR;
1004  break;
1006  buff_resist = PARTY_BUFF_RESIST_WATER;
1007  break;
1009  buff_resist = PARTY_BUFF_RESIST_EARTH;
1010  break;
1012  buff_resist = PARTY_BUFF_RESIST_MIND;
1013  break;
1015  buff_resist = PARTY_BUFF_RESIST_BODY;
1016  break;
1017  default:
1018  assert(false);
1019  continue;
1020  }
1021  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
1023  pCastSpell->uSpellID, 0);
1025  pCastSpell->uSpellID, 1);
1027  pCastSpell->uSpellID, 2);
1029  pCastSpell->uSpellID, 3);
1030 
1031  pParty->pPartyBuffs[buff_resist].Apply(
1033  GameTime::FromSeconds(3600 * spell_level)),
1034  skill_level, amount, 0, 0);
1035  spell_sound_flag = true;
1036  break;
1037  }
1038 
1039  case SPELL_FIRE_HASTE: //Спешка
1040  {
1041  switch (skill_level) {
1042  case 1:
1043  spellduration = 60 * (spell_level + 60);
1044  break;
1045  case 2:
1046  spellduration = 60 * (spell_level + 60);
1047  break;
1048  case 3:
1049  spellduration = 180 * (spell_level + 20);
1050  break;
1051  case 4:
1052  spellduration = 240 * (spell_level + 15);
1053  break;
1054  default:
1055  assert(false);
1056  }
1057  if (pPlayer->CanCastSpell(uRequiredMana)) {
1058  spell_sound_flag = true;
1059  for (uint pl_id = 0; pl_id < 4; pl_id++) {
1060  if (pParty->pPlayers[pl_id]
1061  .conditions_times[Condition_Weak]
1062  .Valid())
1063  spell_sound_flag = false;
1064  }
1065  if (spell_sound_flag) {
1068  GameTime::FromSeconds(spellduration)),
1069  skill_level, 0, 0, 0);
1071  pCastSpell->uSpellID, 0);
1073  pCastSpell->uSpellID, 1);
1075  pCastSpell->uSpellID, 2);
1077  pCastSpell->uSpellID, 3);
1078  }
1079  }
1080  break;
1081  }
1082 
1083  case SPELL_SPIRIT_BLESS: //Благословение
1084  {
1085  switch (skill_level) {
1086  case 1:
1087  spellduration = 300 * (spell_level + 12);
1088  break;
1089  case 2:
1090  spellduration = 300 * (spell_level + 12);
1091  break;
1092  case 3:
1093  spellduration = 900 * (spell_level + 4);
1094  break;
1095  case 4:
1096  spellduration = 3600 * (spell_level + 1);
1097  break;
1098  default:
1099  assert(false);
1100  }
1101  amount = spell_level + 5;
1102  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
1103  if (skill_level == 1) {
1105  pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
1106  spell_overlay_id = pOtherOverlayList->_4418B1(
1107  10000, pCastSpell->uPlayerID_2 + 310, 0, 65536);
1108  pParty->pPlayers[pCastSpell->uPlayerID_2]
1109  .pPlayerBuffs[PLAYER_BUFF_BLESS]
1110  .Apply(GameTime(pParty->GetPlayingTime() +
1111  GameTime::FromSeconds(spellduration)),
1112  1, amount, spell_overlay_id, 0);
1113  spell_sound_flag = true;
1114  break;
1115  }
1116  for (uint pl_id = 0; pl_id < 4; pl_id++) {
1118  pCastSpell->uSpellID, pl_id);
1119  spell_overlay_id = pOtherOverlayList->_4418B1(
1120  10000, pl_id + 310, 0, 65536);
1121  pParty->pPlayers[pl_id].pPlayerBuffs[1].Apply(
1123  GameTime::FromSeconds(spellduration)),
1124  skill_level, amount, spell_overlay_id, 0);
1125  }
1126  spell_sound_flag = true;
1127  break;
1128  }
1129 
1130  case SPELL_SPIRIT_SPIRIT_LASH: //Плеть Духа
1131  {
1132  if (pPlayer->CanCastSpell(uRequiredMana) && spell_targeted_at &&
1133  PID_TYPE(spell_targeted_at) == OBJECT_Actor) {
1134  int monster_id = PID_ID(spell_targeted_at);
1135  dist_X = abs(pActors[monster_id].vPosition.x -
1136  pParty->vPosition.x);
1137  dist_Y = abs(pActors[monster_id].vPosition.y -
1138  pParty->vPosition.y);
1139  dist_Z = abs(pActors[monster_id].vPosition.z -
1140  pParty->vPosition.z);
1141  int count = int_get_vector_length(dist_X, dist_Y, dist_Z);
1142  if ((double)count <= 307.2) {
1143  v701.x = 0;
1144  v701.y = 0;
1145  v701.z = 0;
1146  pSpellSprite.containing_item.Reset();
1147  pSpellSprite.spell_id = pCastSpell->uSpellID;
1148  pSpellSprite.spell_level = spell_level;
1149  pSpellSprite.spell_skill = skill_level;
1150  pSpellSprite.uObjectDescID =
1151  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
1152  pSpellSprite.uAttributes = 0;
1153  pSpellSprite.uSectorID = 0;
1154  pSpellSprite.uSpriteFrameID = 0;
1155  pSpellSprite.field_60_distance_related_prolly_lod = 0;
1156  pSpellSprite.spell_caster_pid =
1157  PID(OBJECT_Player, pCastSpell->uPlayerID);
1158  pSpellSprite.uFacing = 0;
1159  pSpellSprite.uSoundID = (short)pCastSpell->sound_id;
1160  pSpellSprite.vPosition.x =
1161  pActors[monster_id].vPosition.x;
1162  pSpellSprite.vPosition.y =
1163  pActors[monster_id].vPosition.y;
1164  pSpellSprite.vPosition.z =
1165  pActors[monster_id].vPosition.z -
1166  (int)((double)pActors[monster_id].uActorHeight *
1167  -0.8);
1168  pSpellSprite.spell_target_pid =
1169  PID(OBJECT_Actor, spell_targeted_at);
1171  PID(OBJECT_Item, pSpellSprite.Create(0, 0, 0, 0)),
1172  monster_id, &v701);
1173  spell_sound_flag = true;
1174  } else {
1176  428)); // Spell failed Не получилось!!!
1177  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
1178  pCastSpell->uSpellID = 0;
1179  }
1180  }
1181  break;
1182  }
1183 
1184  case SPELL_AIR_SHIELD: //Щит
1185  case SPELL_EARTH_STONESKIN: //Каменная кожа
1186  case SPELL_SPIRIT_HEROISM: //Героизм
1187  {
1188  switch (skill_level) {
1189  case 1:
1190  spellduration = 300 * (spell_level + 12);
1191  break;
1192  case 2:
1193  spellduration = 300 * (spell_level + 12);
1194  break;
1195  case 3:
1196  spellduration = 900 * (spell_level + 4);
1197  break;
1198  case 4:
1199  spellduration = 3600 * (spell_level + 1);
1200  break;
1201  default:
1202  assert(false);
1203  }
1204  switch (pCastSpell->uSpellID) {
1205  case SPELL_AIR_SHIELD:
1206  amount = 0;
1207  buff_resist = PARTY_BUFF_SHIELD;
1208  break;
1209  case SPELL_EARTH_STONESKIN:
1210  amount = spell_level + 5;
1211  buff_resist = PARTY_BUFF_STONE_SKIN;
1212  break;
1213  case SPELL_SPIRIT_HEROISM:
1214  amount = spell_level + 5;
1215  buff_resist = PARTY_BUFF_HEROISM;
1216  break;
1217  default:
1218  assert(false);
1219  continue;
1220  }
1221  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
1223  pCastSpell->uSpellID, 0);
1225  pCastSpell->uSpellID, 1);
1227  pCastSpell->uSpellID, 2);
1229  pCastSpell->uSpellID, 3);
1230  pParty->pPartyBuffs[buff_resist].Apply(
1232  GameTime::FromSeconds(spellduration)),
1233  skill_level, amount, 0, 0);
1234  spell_sound_flag = true;
1235  break;
1236  }
1237 
1238  case SPELL_FIRE_IMMOLATION: //Кольцо огня
1239  {
1240  if (skill_level == 4)
1241  spellduration = 600 * spell_level;
1242  else
1243  spellduration = 60 * spell_level;
1244  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
1246  pCastSpell->uSpellID, 0);
1248  pCastSpell->uSpellID, 1);
1250  pCastSpell->uSpellID, 2);
1252  pCastSpell->uSpellID, 3);
1255  GameTime::FromSeconds(spellduration)),
1256  skill_level, spell_level, 0, 0);
1257  spell_sound_flag = true;
1258  break;
1259  }
1260 
1261  case SPELL_FIRE_METEOR_SHOWER: //Поток метеоров
1262  {
1263  // if (skill_level < 3)//для мастера и магистра
1264  // break;
1265  int meteor_num;
1266  if (skill_level == 4)
1267  meteor_num = 20;
1268  else
1269  meteor_num = 16;
1272  491)); // Can't cast Meteor Shower indoors!
1273  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
1274  pCastSpell->uSpellID = 0;
1275  continue;
1276  }
1277  if (!pPlayer->CanCastSpell(uRequiredMana))
1278  break;
1279  obj_type = PID_TYPE(spell_targeted_at);
1280  monster_id = PID_ID(spell_targeted_at);
1281  if (obj_type ==
1282  OBJECT_Actor) { // если закл поставить на быстрое закл., то
1283  // можно указывать куда кидать метеоры
1284  dist_X = pActors[monster_id].vPosition.x;
1285  dist_Y = pActors[monster_id].vPosition.y;
1286  dist_Z = pActors[monster_id].vPosition.z;
1287  } else {
1288  dist_X = pParty->vPosition.x +
1289  fixpoint_mul(2048,
1291  dist_Y = pParty->vPosition.y +
1292  fixpoint_mul(2048,
1294  dist_Z = pParty->vPosition.z;
1295  }
1296  unsigned __int64 k = 0;
1297  int j = 0;
1298  if (meteor_num > 0) {
1299  v730 = obj_type == OBJECT_Actor ? spell_targeted_at : 0;
1300  for (meteor_num; meteor_num; meteor_num--) {
1301  spell_targeted_at = rand() % 1000;
1302  if (sqrt(((double)spell_targeted_at - 2500) *
1303  ((double)spell_targeted_at - 2500) +
1304  j * j + k * k) <= 1.0) {
1305  HEXRAYS_LODWORD(v687) = 0;
1306  HEXRAYS_HIDWORD(v687) = 0;
1307  } else {
1308  HEXRAYS_HIDWORD(v687) = stru_5C6E00->Atan2(
1309  (signed __int64)sqrt((float)(j * j + k * k)),
1310  (double)spell_targeted_at - 2500);
1311  HEXRAYS_LODWORD(v687) = stru_5C6E00->Atan2(j, k);
1312  }
1313  pSpellSprite.containing_item.Reset();
1314  pSpellSprite.spell_id = pCastSpell->uSpellID;
1315  pSpellSprite.spell_level = spell_level;
1316  pSpellSprite.spell_skill = skill_level;
1317  pSpellSprite.uObjectDescID =
1318  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
1319  pSpellSprite.uAttributes = 0;
1320  pSpellSprite.vPosition.x = dist_X;
1321  pSpellSprite.vPosition.y = dist_Y;
1322  pSpellSprite.vPosition.z = spell_targeted_at + dist_Z;
1323  pSpellSprite.uSectorID = 0;
1324  pSpellSprite.uSpriteFrameID = 0;
1325  pSpellSprite.spell_caster_pid =
1326  PID(OBJECT_Player, pCastSpell->uPlayerID);
1327  pSpellSprite.spell_target_pid = v730;
1329  stru_50C198._427546(spell_targeted_at + 2500);
1330  pSpellSprite.uFacing = v687;
1331  pSpellSprite.uSoundID = (short)pCastSpell->sound_id;
1332  if (pParty->bTurnBasedModeOn) {
1333  pSpellSprite.uAttributes = 4;
1334  }
1335  if (pSpellSprite.Create(v687, HEXRAYS_SHIDWORD(v687),
1336  pObjectList->pObjects[pSpellSprite.uObjectDescID].uSpeed, 0) != -1 &&
1339  }
1340  j = rand() % 1024 - 512;
1341  k = rand() % 1024 - 512;
1342  }
1343  }
1344  spell_sound_flag = true;
1345  break;
1346  }
1347 
1348  case SPELL_FIRE_INFERNO: //Адский огонь
1349  {
1352  492)); // Can't cast Inferno outdoors!
1353  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
1354  pCastSpell->uSpellID = 0;
1355  continue;
1356  }
1357  if (!pPlayer->CanCastSpell(uRequiredMana))
1358  break;
1359  int mon_num = render->GetActorsInViewport(4096);
1360  v700.x = 0;
1361  v700.y = 0;
1362  v700.z = 0;
1363  pSpellSprite.containing_item.Reset();
1364  pSpellSprite.spell_id = pCastSpell->uSpellID;
1365  pSpellSprite.spell_level = spell_level;
1366  pSpellSprite.spell_skill = skill_level;
1367  pSpellSprite.uObjectDescID =
1368  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
1369  pSpellSprite.uAttributes = 0;
1370  pSpellSprite.uSectorID = 0;
1371  pSpellSprite.uSpriteFrameID = 0;
1372  pSpellSprite.field_60_distance_related_prolly_lod = 0;
1373  pSpellSprite.uFacing = 0;
1374  pSpellSprite.spell_caster_pid =
1375  PID(OBJECT_Player, pCastSpell->uPlayerID);
1376  pSpellSprite.uSoundID = (short)pCastSpell->sound_id;
1377  for (uint i = 0; i < mon_num; i++) {
1378  pSpellSprite.vPosition.x =
1379  pActors[_50BF30_actors_in_viewport_ids[i]].vPosition.x;
1380  pSpellSprite.vPosition.y =
1381  pActors[_50BF30_actors_in_viewport_ids[i]].vPosition.y;
1382  pSpellSprite.vPosition.z =
1383  pActors[_50BF30_actors_in_viewport_ids[i]].vPosition.z -
1384  (unsigned int)(signed __int64)((double)pActors
1386  [i]]
1387  .uActorHeight *
1388  -0.8);
1389  pSpellSprite.spell_target_pid =
1392  PID(OBJECT_Item, pSpellSprite.Create(0, 0, 0, 0)),
1393  _50BF30_actors_in_viewport_ids[i], &v700);
1395  &pSpellSprite);
1398  0xFF3C1E, 0x40);
1399  }
1400  spell_sound_flag = true;
1401  break;
1402  }
1403 
1404  case SPELL_AIR_WIZARD_EYE: //Око чародея
1405  {
1406  spellduration = 3600 * spell_level;
1407  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
1408  for (uint pl_id = 0; pl_id < 4; pl_id++)
1409  spell_overlay_id =
1410  pOtherOverlayList->_4418B1(2000, pl_id + 100, 0, 65536);
1413  GameTime::FromSeconds(spellduration)),
1414  skill_level, 0, spell_overlay_id, 0);
1415  spell_sound_flag = true;
1416  break;
1417  }
1418 
1419  case SPELL_AIR_FEATHER_FALL: //Падение пера(пёрышком)
1420  {
1421  switch (skill_level) {
1422  case 1:
1423  spellduration = 300 * spell_level;
1424  break;
1425  case 2:
1426  spellduration = 600 * spell_level;
1427  break;
1428  case 3:
1429  spellduration = 3600 * spell_level;
1430  break;
1431  case 4:
1432  spellduration = 3600 * spell_level;
1433  break;
1434  default:
1435  assert(false);
1436  }
1437  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
1438  for (uint pl_id = 0; pl_id < 4; pl_id++)
1439  pOtherOverlayList->_4418B1(2010, pl_id + 100, 0, 65536);
1441  pCastSpell->uSpellID, 0);
1443  pCastSpell->uSpellID, 1);
1445  pCastSpell->uSpellID, 2);
1447  pCastSpell->uSpellID, 3);
1448 
1451  GameTime::FromSeconds(spellduration)),
1452  skill_level, 0, 0, 0);
1453  spell_sound_flag = true;
1454  break;
1455  }
1456 
1457  case SPELL_AIR_SPARKS: // Искры
1458  {
1459  switch (skill_level) {
1460  case 1:
1461  amount = 3;
1462  break;
1463  case 2:
1464  amount = 5;
1465  break;
1466  case 3:
1467  amount = 7;
1468  break;
1469  case 4:
1470  amount = 9;
1471  break;
1472  default:
1473  assert(false);
1474  }
1475  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
1476  int _v726 = (int)(60 * stru_5C6E00->uIntegerDoublePi) / 360;
1477  pSpellSprite.containing_item.Reset();
1478  pSpellSprite.spell_id = pCastSpell->uSpellID;
1479  pSpellSprite.spell_level = spell_level;
1480  pSpellSprite.spell_skill = skill_level;
1481  pSpellSprite.uObjectDescID =
1482  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
1483  pSpellSprite.vPosition.y = pParty->vPosition.y;
1484  pSpellSprite.vPosition.x = pParty->vPosition.x;
1485  pSpellSprite.uAttributes = 0;
1486  pSpellSprite.vPosition.z =
1487  pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
1488  pSpellSprite.uSectorID = pIndoor->GetSector(
1490  pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3);
1491  pSpellSprite.uSpriteFrameID = 0;
1492  pSpellSprite.spell_caster_pid =
1493  PID(OBJECT_Player, pCastSpell->uPlayerID);
1494  pSpellSprite.spell_target_pid = spell_targeted_at;
1496  target_direction.uDistance;
1497  pSpellSprite.uSoundID = pCastSpell->sound_id;
1498  if (pParty->bTurnBasedModeOn) {
1499  pSpellSprite.uAttributes |= 4;
1500  }
1501  spell_spray_angle_start = (int)_v726 / -2;
1502  spell_spray_angle_end = (int)_v726 / 2;
1503  while (spell_spray_angle_start <= spell_spray_angle_end) {
1504  pSpellSprite.uFacing = spell_spray_angle_start + (short)target_direction.uYawAngle;
1505  if (pSpellSprite.Create(
1506  (int16_t)(spell_spray_angle_start + (short)target_direction.uYawAngle),
1507  target_direction.uPitchAngle,
1508  pObjectList->pObjects[pSpellSprite.uObjectDescID].uSpeed,
1509  pCastSpell->uPlayerID + 1) != -1 &&
1512  }
1513  spell_spray_angle_start += _v726 / (amount - 1);
1514  }
1515  spell_sound_flag = true;
1516  break;
1517  }
1518 
1519  case SPELL_AIR_JUMP: //Прыжок
1520  {
1523  493)); // Can't cast Jump while airborne!
1524  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
1525  break;
1526  }
1527  if (!pPlayer->CanCastSpell(uRequiredMana))
1528  break;
1529  for (uint pl_id = 0; pl_id < 4; pl_id++)
1530  pOtherOverlayList->_4418B1(2040, pl_id + 100, 0, 65536);
1531  pParty->uFlags |= 0x100;
1532  pParty->uFallSpeed = 1000;
1533  spell_sound_flag = true;
1534  break;
1535  }
1536 
1537  case SPELL_AIR_INVISIBILITY: //Невидимость
1538  {
1539  switch (skill_level) {
1540  case 1:
1541  spellduration = 600 * spell_level;
1542  amount = spell_level;
1543  break;
1544  case 2:
1545  spellduration = 600 * spell_level;
1546  amount = 2 * spell_level;
1547  break;
1548  case 3:
1549  spellduration = 600 * spell_level;
1550  amount = 3 * spell_level;
1551  break;
1552  case 4:
1553  spellduration = 3600 * spell_level;
1554  amount = 4 * spell_level;
1555  break;
1556  default:
1557  assert(false);
1558  }
1559  if (pParty->uFlags &
1562  638)); // There are hostile creatures nearby!
1563  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
1564  pCastSpell->uSpellID = 0;
1565  continue;
1566  }
1567  if (pPlayer->CanCastSpell(uRequiredMana)) {
1569  pCastSpell->uSpellID, 0);
1571  pCastSpell->uSpellID, 1);
1573  pCastSpell->uSpellID, 2);
1575  pCastSpell->uSpellID, 3);
1578  GameTime::FromSeconds(spellduration)),
1579  skill_level, amount, 0, 0);
1580  spell_sound_flag = true;
1581  }
1582  break;
1583  }
1584 
1585  case SPELL_AIR_FLY: //Полёт
1586  {
1589  494)); // Can not cast Fly indoors!
1590  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
1591  break;
1592  }
1593  if (!pPlayers[pCastSpell->uPlayerID + 1]->GetMaxMana() && !engine->config->debug_all_magic) {
1595  localization->GetString(428)); // Spell failed
1596  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
1597  break;
1598  }
1599  if (skill_level == 1 || skill_level == 2 || skill_level == 3)
1600  amount = 1;
1601  else
1602  amount = 0;
1603  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
1604  for (uint pl_id = 0; pl_id < 4; pl_id++)
1605  pOtherOverlayList->_4418B1(2090, pl_id + 100, 0, 65536);
1606  spell_overlay_id =
1607  pOtherOverlayList->_4418B1(10008, 203, 0, 65536);
1610  GameTime::FromSeconds(3600 * spell_level)),
1611  skill_level, amount, spell_overlay_id,
1612  pCastSpell->uPlayerID + 1);
1613  spell_sound_flag = true;
1614  break;
1615  }
1616 
1617  case SPELL_AIR_STARBURST: //Звездопад
1618  {
1621  495)); // Can't cast Starburst indoors!
1622  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
1623  pCastSpell->uSpellID = 0;
1624  continue;
1625  }
1626  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
1627  obj_type = PID_TYPE(spell_targeted_at);
1628  monster_id = PID_ID(spell_targeted_at);
1629  if (obj_type == OBJECT_Actor) {
1630  dist_X = pActors[monster_id].vPosition.x;
1631  dist_Y = pActors[monster_id].vPosition.y;
1632  dist_Z = pActors[monster_id].vPosition.z;
1633  } else {
1634  dist_X = pParty->vPosition.x +
1635  fixpoint_mul(2048,
1637  dist_Y = pParty->vPosition.y +
1638  fixpoint_mul(2048,
1640  dist_Z = pParty->vPosition.z;
1641  }
1642  unsigned __int64 k = 0;
1643  int j = 0;
1644  v730 = obj_type == OBJECT_Actor ? spell_targeted_at : 0;
1645  for (uint star_num = 20; star_num; star_num--) {
1646  spell_targeted_at = rand() % 1000;
1647  if (sqrt(((double)spell_targeted_at + (double)dist_Z -
1648  (double)(dist_Z + 2500)) *
1649  ((double)spell_targeted_at + (double)dist_Z -
1650  (double)(dist_Z + 2500)) +
1651  j * j + k * k) <= 1.0) {
1652  HEXRAYS_LODWORD(v685) = 0;
1653  HEXRAYS_HIDWORD(v685) = 0;
1654  } else {
1655  HEXRAYS_HIDWORD(v685) = stru_5C6E00->Atan2(
1656  (signed __int64)sqrt((float)(j * j + k * k)),
1657  ((double)spell_targeted_at + (double)dist_Z -
1658  (double)(dist_Z + 2500)));
1659  HEXRAYS_LODWORD(v685) = stru_5C6E00->Atan2(j, k);
1660  }
1661  pSpellSprite.containing_item.Reset();
1662  pSpellSprite.spell_id = pCastSpell->uSpellID;
1663  pSpellSprite.spell_level = spell_level;
1664  pSpellSprite.spell_skill = skill_level;
1665  pSpellSprite.uObjectDescID =
1666  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
1667  pSpellSprite.uAttributes = 0;
1668  pSpellSprite.vPosition.x = dist_X;
1669  pSpellSprite.vPosition.y = dist_Y;
1670  pSpellSprite.vPosition.z =
1671  (int)(spell_targeted_at + (dist_Z + 2500));
1672  pSpellSprite.uSectorID = 0;
1673  pSpellSprite.uSpriteFrameID = 0;
1674  pSpellSprite.spell_caster_pid =
1675  PID(OBJECT_Player, pCastSpell->uPlayerID);
1676  pSpellSprite.spell_target_pid = v730;
1678  stru_50C198._427546(spell_targeted_at + 2500);
1679  pSpellSprite.uFacing = v685;
1680  pSpellSprite.uSoundID = (short)pCastSpell->sound_id;
1681  if (pParty->bTurnBasedModeOn) {
1682  pSpellSprite.uAttributes = 4;
1683  }
1684  if (pSpellSprite.Create(v685, HEXRAYS_SHIDWORD(v685),
1685  pObjectList->pObjects[pSpellSprite.uObjectDescID].uSpeed, 0) != -1 &&
1688  }
1689  j = rand() % 1024 - 512;
1690  k = rand() % 1024 - 512;
1691  }
1692  spell_sound_flag = true;
1693  break;
1694  }
1695 
1696  case SPELL_WATER_AWAKEN: //Пробуждение
1697  {
1698  switch (skill_level) {
1699  case 1:
1700  amount = 180 * spell_level;
1701  break;
1702  case 2:
1703  amount = 3600 * spell_level;
1704  break;
1705  case 3:
1706  amount = 86400 * spell_level;
1707  break;
1708  case 4:
1709  amount = 0;
1710  break;
1711  default:
1712  assert(false);
1713  }
1714  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
1715  for (int i = 0; i < 4; i++) {
1716  if (skill_level == 4) {
1717  if (pParty->pPlayers[i]
1718  .conditions_times[Condition_Sleep]
1719  .Valid()) {
1720  pParty->pPlayers[i]
1721  .conditions_times[Condition_Sleep]
1722  .Reset();
1723  pParty->pPlayers[i].PlaySound(SPEECH_103, 0);
1724  }
1725  } else {
1726  if (pParty->pPlayers[i]
1727  .DiscardConditionIfLastsLongerThan(
1730  pParty->pPlayers[i].PlaySound(SPEECH_103, 0);
1731  }
1732  }
1733  spell_sound_flag = true;
1734  break;
1735  }
1736 
1737  case SPELL_WATER_POISON_SPRAY: // Распыление яда
1738  {
1739  switch (skill_level) {
1740  case 1:
1741  amount = 1;
1742  break;
1743  case 2:
1744  amount = 3;
1745  break;
1746  case 3:
1747  amount = 5;
1748  break;
1749  case 4:
1750  amount = 7;
1751  break;
1752  default:
1753  assert(false);
1754  }
1755  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
1756  int _v733 = (int)(60 * stru_5C6E00->uIntegerDoublePi) / 360;
1757  if (amount == 1) {
1758  pSpellSprite.containing_item.Reset();
1759  pSpellSprite.spell_id = pCastSpell->uSpellID;
1760  pSpellSprite.spell_skill = skill_level;
1761  pSpellSprite.spell_level = spell_level;
1762  pSpellSprite.uObjectDescID =
1763  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
1764  pSpellSprite.uAttributes = 0;
1765  pSpellSprite.vPosition.x = pParty->vPosition.x;
1766  pSpellSprite.vPosition.y = pParty->vPosition.y;
1767  pSpellSprite.vPosition.z = pParty->vPosition.z + (int)pParty->uPartyHeight / 3;
1768  pSpellSprite.uSectorID = pIndoor->GetSector(
1770  pSpellSprite.vPosition.z);
1771  pSpellSprite.uSpriteFrameID = 0;
1772  pSpellSprite.spell_caster_pid = PID(OBJECT_Player, pCastSpell->uPlayerID);
1773  pSpellSprite.spell_target_pid = spell_targeted_at;
1774  pSpellSprite.field_60_distance_related_prolly_lod = target_direction.uDistance;
1775  pSpellSprite.uFacing = target_direction.uYawAngle;
1776  pSpellSprite.uSoundID = pCastSpell->sound_id;
1777  if (pParty->bTurnBasedModeOn) {
1778  pSpellSprite.uAttributes |= 4;
1779  }
1780  v659 = pObjectList->pObjects[pSpellSprite.uObjectDescID].uSpeed;
1781  if (pSpellSprite.Create(target_direction.uYawAngle,
1782  target_direction.uPitchAngle, v659,
1783  pCastSpell->uPlayerID + 1) != -1 &&
1786  }
1787  } else {
1788  pSpellSprite.containing_item.Reset();
1789  pSpellSprite.spell_id = pCastSpell->uSpellID;
1790  pSpellSprite.spell_level = spell_level;
1791  pSpellSprite.spell_skill = skill_level;
1792  pSpellSprite.uObjectDescID =
1793  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
1794  pSpellSprite.vPosition.y = pParty->vPosition.y;
1795  pSpellSprite.vPosition.x = pParty->vPosition.x;
1796  pSpellSprite.uAttributes = 0;
1797  pSpellSprite.vPosition.z =
1798  pParty->vPosition.z +
1799  (signed int)pParty->uPartyHeight / 3;
1800  pSpellSprite.uSectorID = pIndoor->GetSector(
1802  pParty->vPosition.z +
1803  (signed int)pParty->uPartyHeight / 3);
1804  pSpellSprite.uSpriteFrameID = 0;
1805  pSpellSprite.spell_caster_pid =
1806  PID(OBJECT_Player, pCastSpell->uPlayerID);
1807  pSpellSprite.spell_target_pid = spell_targeted_at;
1809  target_direction.uDistance;
1810  pSpellSprite.uSoundID = pCastSpell->sound_id;
1811  if (pParty->bTurnBasedModeOn) {
1812  pSpellSprite.uAttributes |= 4;
1813  }
1814  spell_spray_angle_start = _v733 / -2;
1815  spell_spray_angle_end = _v733 / 2;
1816  if (spell_spray_angle_start <= spell_spray_angle_end) {
1817  do {
1818  pSpellSprite.uFacing = spell_spray_angle_start +
1819  target_direction.uYawAngle;
1820  if (pSpellSprite.Create(
1821  pSpellSprite.uFacing,
1822  target_direction.uPitchAngle,
1823  pObjectList
1824  ->pObjects[pSpellSprite.uObjectDescID]
1825  .uSpeed,
1826  pCastSpell->uPlayerID + 1) != -1 &&
1829  }
1830  spell_spray_angle_start += _v733 / (amount - 1);
1831  } while (spell_spray_angle_start <=
1832  spell_spray_angle_end);
1833  }
1834  }
1835  spell_sound_flag = true;
1836  break;
1837  }
1838 
1839  case SPELL_WATER_WATER_WALK: //Хождение по воде
1840  {
1841  if (!pPlayers[pCastSpell->uPlayerID + 1]->GetMaxMana()) {
1843  localization->GetString(428)); // Spell failed
1844  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
1845  break;
1846  }
1847  switch (skill_level) {
1848  case 1: // break;
1849  case 2:
1850  spellduration = 600 * spell_level;
1851  break;
1852  case 3:
1853  case 4:
1854  spellduration = 3600 * spell_level;
1855  break;
1856  default:
1857  assert(false);
1858  }
1859  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
1860  spell_overlay_id =
1861  pOtherOverlayList->_4418B1(10005, 201, 0, 65536);
1862  spell_fx_renderer->SetPlayerBuffAnim(pCastSpell->uSpellID, 0);
1863  spell_fx_renderer->SetPlayerBuffAnim(pCastSpell->uSpellID, 1);
1864  spell_fx_renderer->SetPlayerBuffAnim(pCastSpell->uSpellID, 2);
1865  spell_fx_renderer->SetPlayerBuffAnim(pCastSpell->uSpellID, 3);
1868  GameTime::FromSeconds(spellduration)),
1869  skill_level, amount, spell_overlay_id,
1870  pCastSpell->uPlayerID + 1);
1871  if (skill_level == 4)
1873  spell_sound_flag = true;
1874  break;
1875  }
1876 
1877  case SPELL_WATER_RECHARGE_ITEM: //Перезарядка
1878  {
1879  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
1880  v730c = &pParty->pPlayers[pCastSpell->uPlayerID_2]
1881  .pInventoryItemList[spell_targeted_at];
1882  if (v730c->GetItemEquipType() != 12 || v730c->uAttributes & 2) {
1887  localization->GetString(428)); // Spell failed
1888  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
1889  pCastSpell->uSpellID = 0;
1890  continue;
1891  }
1892  if (skill_level == 1 || skill_level == 2)
1893  spell_recharge_factor =
1894  (double)spell_level * 0.0099999998 + 0.5; // 50 %
1895  else if (skill_level == 3)
1896  spell_recharge_factor = (double)spell_level * 0.0099999998 + 0.69999999; // 30 %
1897  else if (skill_level == 4)
1898  spell_recharge_factor = (double)spell_level * 0.0099999998 + 0.80000001; // 20 %
1899  else
1900  spell_recharge_factor = 0.0;
1901  if (spell_recharge_factor > 1.0) spell_recharge_factor = 1.0;
1902  int uNewCharges = v730c->uMaxCharges * spell_recharge_factor;
1903  v730c->uMaxCharges = uNewCharges;
1904  v730c->uNumCharges = uNewCharges;
1905  if (uNewCharges <= 0) {
1906  v730c = 0;
1911  428)); // Spell failed Не получилось!!!
1912  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
1913  pCastSpell->uSpellID = 0;
1914  spell_level = spell_level;
1915  continue;
1916  }
1917  v730c->uAttributes |= 0x40u;
1919  spell_sound_flag = true;
1920  break;
1921  }
1922 
1923  case SPELL_WATER_ENCHANT_ITEM: { // Талисман
1924  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
1925  uRequiredMana = 0;
1926  amount = 10 * spell_level;
1927  bool item_not_broken = true;
1928  int rnd = rand() % 100;
1929  pPlayer = &pParty->pPlayers[pCastSpell->uPlayerID_2];
1930  spell_item_to_enchant =
1931  &pPlayer->pInventoryItemList[spell_targeted_at - 1];
1932  ItemDesc *_v725 =
1933  &pItemsTable->pItems[spell_item_to_enchant->uItemID];
1934  if ((skill_level == 1 ||
1935  skill_level == 2 /*&& _v725->uEquipType > EQUIP_BOW*/ ||
1936  skill_level == 3 || skill_level == 4) &&
1937  spell_item_to_enchant->uItemID <= 134 &&
1938  spell_item_to_enchant->special_enchantment == 0 &&
1939  spell_item_to_enchant->uEnchantmentType == 0 &&
1940  spell_item_to_enchant->m_enchantmentStrength == 0 &&
1941  !spell_item_to_enchant->IsBroken()) { // требования к предмету
1942  if ((spell_item_to_enchant->GetValue() < 450 &&
1943  (skill_level == 1 || skill_level == 2)) ||
1944  (spell_item_to_enchant->GetValue() < 450 &&
1945  (skill_level == 3 || skill_level == 4) &&
1946  _v725->uEquipType >= EQUIP_SINGLE_HANDED &&
1947  _v725->uEquipType <= EQUIP_BOW) ||
1948  (spell_item_to_enchant->GetValue() < 250 &&
1949  (skill_level == 3 || skill_level == 4) &&
1950  _v725->uEquipType > EQUIP_BOW)) { // Условия поломки
1951  if (!(spell_item_to_enchant->uAttributes &
1952  ITEM_HARDENED)) { // предмет не сломан
1953  spell_item_to_enchant->uAttributes |=
1954  ITEM_BROKEN; //теперь сломан
1955  }
1956  item_not_broken = false;
1957  } else {
1958  if (rnd >= 10 * spell_level) { // шанс на срабатывание
1959  if (!(spell_item_to_enchant->uAttributes &
1960  0x200)) // предмет не сломан
1961  spell_item_to_enchant->uAttributes |=
1962  2; //теперь сломан
1963  } else {
1964  if ((rnd < 80 &&
1965  (skill_level == 3 || skill_level == 4)) ||
1966  spell_item_to_enchant->GetValue() < 450 ||
1967  (spell_item_to_enchant->GetValue() < 250 &&
1968  (skill_level == 3 || skill_level == 4) &&
1969  _v725->uEquipType >= EQUIP_SINGLE_HANDED &&
1970  _v725->uEquipType <= EQUIP_BOW)) {
1971  v313 = _v725->uEquipType;
1972  if (_v725->uEquipType >= EQUIP_ARMOUR &&
1973  _v725->uEquipType <= EQUIP_AMULET) {
1974  v295 =
1975  rand() %
1976  10; // pItemsTable->field_116D8[pItemsTable->pItems[_this->uItemID].uEquipType];
1977  /*spell_item_to_enchant->uEnchantmentType =
1978  0;
1979  __debugbreak(); // castspellinfo.cpp(1971):
1980  warning C4700: uninitialized local variable
1981  'v294' used for ( kk =
1982  pItemsTable->pEnchantments[0].to_item[spell_item_to_enchant->GetItemEquipType()
1983  + 1];
1984  ;
1985  kk +=
1986  pItemsTable->pEnchantments[v294->uEnchantmentType].to_item[spell_item_to_enchant->GetItemEquipType()
1987  + 1] )
1988  {
1989  ++spell_item_to_enchant->uEnchantmentType;
1990  if ( kk >= v295 )
1991  break;
1992  }
1993  v255 = 10;//pItemsTable->field_116D8[17];
1994  v256 = 10;//pItemsTable->field_116D8[16];
1995  spell_item_to_enchant->m_enchantmentStrength
1996  = v256 + rand() % (v255 - v256 + 1);*/
1997  spell_item_to_enchant->uEnchantmentType =
1998  v295;
1999  spell_item_to_enchant
2001  pItemsTable->pEnchantments[v295]
2002  .to_item[_v725->uEquipType -
2003  EQUIP_ARMOUR];
2004  spell_item_to_enchant->uAttributes |= 0x20u;
2006  spell_sound_flag = true;
2007  break;
2008  } else if (skill_level == 3 ||
2009  skill_level ==
2010  4) { // for master & GM not
2011  // refactored(для мастера и
2012  // гранда не отрефакторено)
2013  v258 = 0;
2014  v725 = 0;
2015  int _v733;
2016  if (pItemsTable
2017  ->pSpecialEnchantments_count > 0) {
2018  v730 = (int)&v679;
2019  for (_v733 = 0;
2020  _v733 <
2021  pItemsTable
2023  ++_v733) {
2024  v259 = (int)pItemsTable
2025  ->pSpecialEnchantments
2026  [v258 + 1]
2027  .pBonusStatement;
2028  if (!v259 || v259 == 1) {
2029  v260 = *(
2030  &pItemsTable
2032  [0]
2033  .to_item_apply
2034  [spell_item_to_enchant
2035  ->GetItemEquipType() +
2036  4] +
2037  v258 * 28);
2038  v725 += v260;
2039  if (v260) {
2040  v261 = v730;
2041  v730 += 4;
2042  *(int *)v261 = _v733;
2043  }
2044  }
2045  ++v258;
2046  }
2047  }
2048  v262 = rand() % v725;
2049  v263 = v679;
2050  spell_item_to_enchant->special_enchantment =
2051  (ITEM_ENCHANTMENT)v679[0];
2052  v264 =
2054  .to_item_apply
2055  [spell_item_to_enchant
2056  ->GetItemEquipType() +
2057  4];
2058  v265 = v262 + 1;
2059  if (v264 < v265) {
2060  for (int *ii = v679;;
2061  ii = (int *)v732) {
2062  v267 = (int)(ii + 1);
2063  v732 = v267;
2064  v268 = *(int *)v267;
2065  *(int *)(spell_item_to_enchant +
2066  12) = v268;
2067  v264 +=
2068  pItemsTable
2069  ->pSpecialEnchantments[v268]
2070  .to_item_apply
2071  [spell_item_to_enchant
2072  ->GetItemEquipType() +
2073  4];
2074  if (v264 >= v265) break;
2075  }
2076  }
2077  v278 = 0;
2078  v725 = 0;
2079  if (pItemsTable
2080  ->pSpecialEnchantments_count > 0) {
2081  int *_v730 = v679;
2082  for (_v733 = 0;
2083  _v733 <
2084  pItemsTable
2086  ++_v733) {
2087  v279 =
2088  (char)pItemsTable
2089  ->pSpecialEnchantments[v278]
2090  .pBonusStatement;
2091  if (!v279 || v279 == 1) {
2092  v280 = *(
2093  &pItemsTable
2095  [v278]
2096  .to_item_apply
2097  [spell_item_to_enchant
2098  ->GetItemEquipType()]);
2099  _v733 += v280;
2100  if (v280) {
2101  v281 = _v730;
2102  ++_v730;
2103  *v281 = _v733;
2104  }
2105  }
2106  ++v278;
2107  }
2108  }
2109  v282 = rand() % _v733;
2110  v283 = v679;
2111  spell_item_to_enchant->special_enchantment =
2112  (ITEM_ENCHANTMENT)v679[0];
2113  v284 =
2115  .to_item_apply
2116  [spell_item_to_enchant
2117  ->GetItemEquipType()];
2118  v285 = v282 + 1;
2119  for (l = v679; v284 < v285; ++l) {
2120  spell_item_to_enchant
2122  (ITEM_ENCHANTMENT) * (l + 1);
2123  v284 +=
2124  pItemsTable
2125  ->pSpecialEnchantments[*(l + 1)]
2126  .to_item_apply
2127  [spell_item_to_enchant
2128  ->GetItemEquipType()];
2129  }
2130  spell_item_to_enchant->special_enchantment =
2131  (ITEM_ENCHANTMENT)(
2132  spell_item_to_enchant
2133  ->special_enchantment +
2134  1);
2135  spell_item_to_enchant->uAttributes |= 0x20u;
2137  spell_sound_flag = true;
2138  break;
2139  }
2140  }
2141  }
2142  }
2143  }
2144  if (spell_sound_flag == 0) {
2145  v317 = localization->GetString(
2146  428); // Spell failed Не получилось!!!
2147  if (item_not_broken == false)
2148  v317 = localization->GetString(
2149  585); // Item too lame Предмет недостаточно
2150  // высокого качества
2151  GameUI_StatusBar_OnEvent(v317, 2);
2153  0, 0);
2154  // v318 = &pParty->pPlayers[pCastSpell->uPlayerID_2];
2155  pCastSpell->uSpellID = 0;
2156  pParty->pPlayers[pCastSpell->uPlayerID_2].PlaySound(
2157  SPEECH_43, 0);
2158  }
2159  break;
2160  }
2161 
2162  case SPELL_WATER_TOWN_PORTAL: //Портал города
2163  {
2164  amount = 10 * spell_level;
2165  if (pPlayer->sMana < (signed int)uRequiredMana) break;
2168  skill_level != 4 ||
2169  rand() % 100 >= amount && skill_level != 4) {
2171  localization->GetString(428)); // Spell failed
2173  0, 0);
2174  pCastSpell->uSpellID = 0;
2175  continue;
2176  }
2177  town_portal_caster_id = pCastSpell->uPlayerID;
2178  pMessageQueue_50CBD0->AddGUIMessage(UIMSG_OnCastTownPortal, 0,
2179  0);
2180  spell_sound_flag = true;
2181  break;
2182  }
2183 
2185  if (pCurrentMapName == "d05.blv") { // Arena
2186  GameUI_StatusBar_OnEvent(localization->GetString(428)); // Spell failed
2187  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
2188  pCastSpell->uSpellID = 0;
2189  continue;
2190  }
2191  if (pPlayer->sMana >= (signed int)uRequiredMana) {
2192  pEventTimer->Pause();
2193  pMessageQueue_50CBD0->AddGUIMessage(
2194  UIMSG_OnCastLloydsBeacon, 0, 0);
2196  (signed int)(604800 * spell_level);
2200  lloyds_beacon_sound_id = pCastSpell->sound_id;
2201  lloyds_beacon_spell_id = pCastSpell->uSpellID;
2202  pCastSpell->uFlags |= ON_CAST_NoRecoverySpell;
2203  }
2204  break;
2205  }
2206 
2208  switch (skill_level) {
2209  case 1:
2210  amount = 3600 * spell_level;
2211  break;
2212  case 2:
2213  amount = 3600 * spell_level;
2214  break;
2215  case 3:
2216  amount = 86400 * spell_level;
2217  break;
2218  case 4:
2219  break;
2220  default:
2221  assert(false);
2222  }
2223  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2224  if (pParty->pPlayers[pCastSpell->uPlayerID_2]
2225  .conditions_times[Condition_Pertified]
2226  .Valid()) {
2227  if (skill_level == 4) { // for GM
2228  pParty->pPlayers[pCastSpell->uPlayerID_2]
2229  .conditions_times[Condition_Pertified]
2230  .Reset();
2231  spell_sound_flag = true;
2232  break;
2233  }
2234 
2235  pParty->pPlayers[pCastSpell->uPlayerID_2]
2236  .DiscardConditionIfLastsLongerThan(
2239  GameTime::FromSeconds(amount)));
2240  }
2241  spell_sound_flag = true;
2242  break;
2243  }
2244 
2245  case SPELL_EARTH_ROCK_BLAST: { // Взрыв камня
2246  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2247  pSpellSprite.containing_item.Reset();
2248  pSpellSprite.spell_id = pCastSpell->uSpellID;
2249  pSpellSprite.spell_level = spell_level;
2250  pSpellSprite.spell_skill = skill_level;
2251  pSpellSprite.uObjectDescID =
2252  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
2253  pSpellSprite.vPosition.y = pParty->vPosition.y;
2254  pSpellSprite.vPosition.x = pParty->vPosition.x;
2255  pSpellSprite.uAttributes = 0;
2256  pSpellSprite.vPosition.z =
2257  pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
2258  pSpellSprite.uSectorID = pIndoor->GetSector(
2260  pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3);
2261  pSpellSprite.uSpriteFrameID = 0;
2262  pSpellSprite.spell_caster_pid =
2263  PID(OBJECT_Player, pCastSpell->uPlayerID);
2264  pSpellSprite.spell_target_pid = spell_targeted_at;
2266  target_direction.uDistance;
2267  pSpellSprite.uFacing = pParty->sRotationY;
2268  pSpellSprite.uSoundID = pCastSpell->sound_id;
2269  if (pParty->bTurnBasedModeOn) {
2270  pSpellSprite.uAttributes |= 4;
2271  }
2272  v659 = pObjectList->pObjects[pSpellSprite.uObjectDescID].uSpeed;
2273  if (pSpellSprite.Create(pParty->sRotationY, pParty->sRotationX,
2274  v659,
2275  pCastSpell->uPlayerID + 1) != -1 &&
2278  }
2279  spell_sound_flag = true;
2280  break;
2281  }
2282 
2286  localization->GetString(428)); // Spell failed
2288  0, 0);
2289  pCastSpell->uSpellID = 0;
2290  continue;
2291  }
2292  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2293  pSpellSprite.uType = SPRITE_SPELL_EARTH_DEATH_BLOSSOM;
2294  pSpellSprite.containing_item.Reset();
2295  pSpellSprite.spell_id = pCastSpell->uSpellID;
2296  pSpellSprite.spell_level = spell_level;
2297  pSpellSprite.spell_skill = skill_level;
2298  pSpellSprite.uObjectDescID =
2299  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
2300  pSpellSprite.vPosition.x = pParty->vPosition.x;
2301  pSpellSprite.vPosition.y = pParty->vPosition.y;
2302  pSpellSprite.uAttributes = 0;
2303  pSpellSprite.uSectorID = 0;
2304  pSpellSprite.uSpriteFrameID = 0;
2305  pSpellSprite.vPosition.z =
2306  pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
2307  pSpellSprite.field_60_distance_related_prolly_lod = 0;
2308  pSpellSprite.spell_caster_pid =
2309  PID(OBJECT_Player, pCastSpell->uPlayerID);
2310  pSpellSprite.spell_target_pid = spell_targeted_at;
2311  pSpellSprite.uFacing = (short)pParty->sRotationY;
2312  pSpellSprite.uSoundID = (short)pCastSpell->sound_id;
2313  if (pParty->bTurnBasedModeOn) {
2314  pSpellSprite.uAttributes = 4;
2315  }
2316  v659 = pObjectList->pObjects[pSpellSprite.uObjectDescID].uSpeed;
2317  if (pSpellSprite.Create(pParty->sRotationY, stru_5C6E00->uIntegerHalfPi / 2, v659, 0) != -1 &&
2320  }
2321  spell_sound_flag = true;
2322  break;
2323  }
2324 
2325  case SPELL_SPIRIT_DETECT_LIFE: // Детектор жизни
2326  {
2327  switch (skill_level) {
2328  case 1:
2329  amount = 600 * spell_level;
2330  break;
2331  case 2:
2332  amount = 1800 * spell_level;
2333  break;
2334  case 3:
2335  case 4:
2336  amount = 3600 * spell_level;
2337  break;
2338  default:
2339  assert(false);
2340  }
2341  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2343  pCastSpell->uSpellID, 0);
2345  pCastSpell->uSpellID, 1);
2347  pCastSpell->uSpellID, 2);
2349  pCastSpell->uSpellID, 3);
2352  skill_level, 0, 0, 0);
2353  spell_sound_flag = true;
2354  break;
2355  }
2356 
2357  case SPELL_SPIRIT_FATE: // Судьба
2358  {
2359  switch (skill_level) {
2360  case 1:
2361  amount = spell_level;
2362  break;
2363  case 2:
2364  amount = 2 * spell_level;
2365  break;
2366  case 3:
2367  amount = 4 * spell_level;
2368  break;
2369  case 4:
2370  amount = 6 * spell_level;
2371  break;
2372  default:
2373  assert(false);
2374  }
2375  // LODWORD(spellduration) = 300;
2376  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2377  if (pCastSpell->spell_target_pid == 0) {
2379  pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
2380  pParty->pPlayers[pCastSpell->uPlayerID_2]
2381  .pPlayerBuffs[PLAYER_BUFF_FATE]
2382  .Apply(
2384  skill_level, amount, 0, 0);
2385  spell_sound_flag = true;
2386  break;
2387  }
2388  if (PID_TYPE(pCastSpell->spell_target_pid) == OBJECT_Actor) {
2389  monster_id = PID_ID(pCastSpell->spell_target_pid);
2390  pActors[monster_id].pActorBuffs[ACTOR_BUFF_FATE].Apply(
2392  skill_level, amount, 0, 0);
2393  pActors[monster_id].uAttributes |= ACTOR_AGGRESSOR;
2396  &pActors[monster_id], 0);
2397  }
2398  spell_sound_flag = true;
2399  break;
2400  }
2401 
2402  case SPELL_SPIRIT_REMOVE_CURSE: // Снятие порчи
2403  {
2404  switch (skill_level) {
2405  case 1:
2406  amount = 3600 * spell_level;
2407  break;
2408  case 2:
2409  amount = 3600 * spell_level;
2410  break;
2411  case 3:
2412  amount = 86400 * spell_level;
2413  break;
2414  case 4:
2415  amount = 0;
2416  break;
2417  default:
2418  assert(false);
2419  }
2420  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2421  if (!pParty->pPlayers[pCastSpell->uPlayerID_2]
2422  .conditions_times[Condition_Cursed]
2423  .Valid()) {
2424  spell_sound_flag = true;
2425  break;
2426  }
2427  if (skill_level == 4) { // GM
2428  pParty->pPlayers[pCastSpell->uPlayerID_2]
2429  .conditions_times[Condition_Cursed]
2430  .Reset();
2431  } else {
2432  pParty->pPlayers[pCastSpell->uPlayerID_2]
2433  .DiscardConditionIfLastsLongerThan(
2436  GameTime::FromSeconds(amount)));
2437  if (pParty->pPlayers[pCastSpell->uPlayerID_2]
2438  .conditions_times[Condition_Cursed]
2439  .Valid()) {
2440  spell_sound_flag = true;
2441  break;
2442  }
2443  }
2445  pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
2446  spell_sound_flag = true;
2447  break;
2448  }
2449 
2450  case SPELL_SPIRIT_PRESERVATION: //Сохранение
2451  {
2452  if (skill_level == 4)
2453  spellduration = 900 * (spell_level + 4);
2454  else
2455  spellduration = 300 * (spell_level + 12);
2456  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2457  if (skill_level == 1 || skill_level == 2) {
2459  pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
2460  pParty->pPlayers[pCastSpell->uPlayerID_2]
2461  .pPlayerBuffs[PLAYER_BUFF_PRESERVATION]
2462  .Apply(GameTime(pParty->GetPlayingTime() +
2463  GameTime::FromSeconds(spellduration)),
2464  skill_level, 0, 0, 0);
2465  spell_sound_flag = true;
2466  break;
2467  }
2468  for (uint pl_id = 0; pl_id < 4; pl_id++) {
2470  pCastSpell->uSpellID, pl_id);
2471  pParty->pPlayers[pl_id]
2472  .pPlayerBuffs[PLAYER_BUFF_PRESERVATION]
2473  .Apply(GameTime(pParty->GetPlayingTime() +
2474  GameTime::FromSeconds(spellduration)),
2475  skill_level, 0, 0, 0);
2476  }
2477  spell_sound_flag = true;
2478  break;
2479  }
2480 
2481  case SPELL_SPIRIT_TURN_UNDEAD: //Бег мертвецов
2482  {
2483  if (skill_level == 1 || skill_level == 2)
2484  spellduration = 60 * (spell_level + 3);
2485  else
2486  spellduration = 300 * spell_level + 180;
2487  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2488  int mon_num = render->GetActorsInViewport(4096);
2491  192);
2492  // ++pSpellSprite.uType;
2494  pSpellSprite.containing_item.Reset();
2495  pSpellSprite.spell_id = pCastSpell->uSpellID;
2496  pSpellSprite.spell_level = spell_level;
2497  pSpellSprite.spell_skill = skill_level;
2498  pSpellSprite.uObjectDescID =
2499  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
2500  pSpellSprite.uAttributes = 0;
2501  pSpellSprite.uSectorID = 0;
2502  pSpellSprite.uSpriteFrameID = 0;
2503  pSpellSprite.field_60_distance_related_prolly_lod = 0;
2504  pSpellSprite.uFacing = 0;
2505  pSpellSprite.spell_caster_pid =
2506  PID(OBJECT_Player, pCastSpell->uPlayerID);
2507  pSpellSprite.uSoundID = (short)pCastSpell->sound_id;
2508  for (spell_targeted_at = 0; spell_targeted_at < mon_num;
2509  ++spell_targeted_at) {
2512  [spell_targeted_at]]
2513  .pMonsterInfo.uID,
2515  pSpellSprite.vPosition.x =
2517  [spell_targeted_at]]
2518  .vPosition.x;
2519  pSpellSprite.vPosition.y =
2521  [spell_targeted_at]]
2522  .vPosition.y;
2523  pSpellSprite.vPosition.z =
2525  [spell_targeted_at]]
2526  .vPosition.z -
2528  [spell_targeted_at]]
2529  .uActorHeight *
2530  -0.8;
2531  pSpellSprite.spell_target_pid = PID(
2532  OBJECT_Actor,
2533  _50BF30_actors_in_viewport_ids[spell_targeted_at]);
2534  pSpellSprite.Create(0, 0, 0, 0);
2535  pActors
2536  [_50BF30_actors_in_viewport_ids[spell_targeted_at]]
2537  .pActorBuffs[ACTOR_BUFF_AFRAID]
2538  .Apply(GameTime(pParty->GetPlayingTime() +
2539  GameTime::FromSeconds(spellduration)),
2540  skill_level, 0, 0, 0);
2541  }
2542  }
2543  spell_sound_flag = true;
2544  break;
2545  }
2546 
2547  case SPELL_SPIRIT_RAISE_DEAD: //Оживление
2548  {
2549  if (skill_level == 4)
2550  amount = 0;
2551  else
2552  amount = 86400 * spell_level;
2553  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2554  pOtherOverlayList->_4418B1(5080, pCastSpell->uPlayerID_2 + 100,
2555  0, 65536);
2556  if (!pParty->pPlayers[pCastSpell->uPlayerID_2]
2557  .conditions_times[Condition_Dead]
2558  .Valid()) {
2559  spell_sound_flag = true;
2560  break;
2561  }
2562  pParty->pPlayers[pCastSpell->uPlayerID_2].sHealth = 1;
2563  if (skill_level == 4) {
2564  pParty->pPlayers[pCastSpell->uPlayerID_2]
2565  .conditions_times[Condition_Dead]
2566  .Reset();
2567  pParty->pPlayers[pCastSpell->uPlayerID_2]
2568  .conditions_times[Condition_Unconcious]
2569  .Reset();
2570  } else {
2571  pParty->pPlayers[pCastSpell->uPlayerID_2]
2572  .DiscardConditionIfLastsLongerThan(
2574  GameTime::FromSeconds(amount)));
2575  pParty->pPlayers[pCastSpell->uPlayerID_2]
2576  .DiscardConditionIfLastsLongerThan(
2579  GameTime::FromSeconds(amount)));
2580  }
2581  pParty->pPlayers[pCastSpell->uPlayerID_2].SetCondition(
2582  Condition_Weak, 0);
2583  spell_sound_flag = true;
2584  break;
2585  }
2586 
2587  case SPELL_SPIRIT_SHARED_LIFE: //Общая жизнь
2588  {
2589  if (skill_level == 4)
2590  amount = 4 * spell_level;
2591  else
2592  amount = 3 * spell_level;
2593  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2594  int active_pl_num = 0;
2595  signed int shared_life_count = amount;
2596  int mean_life = 0;
2597  int pl_array[4];
2598  for (uint pl_id = 1; pl_id <= 4; pl_id++) {
2599  if (!pPlayers[pl_id]
2600  ->conditions_times[Condition_Dead]
2601  .Valid() &&
2602  !pPlayers[pl_id]
2603  ->conditions_times[Condition_Pertified]
2604  .Valid() &&
2605  !pPlayers[pl_id]
2606  ->conditions_times[Condition_Eradicated]
2607  .Valid())
2608  pl_array[active_pl_num++] = pl_id;
2609  }
2610  for (uint i = 0; i < active_pl_num; i++)
2611  shared_life_count += pPlayers[pl_array[i]]->sHealth;
2612  mean_life = (int64_t)((double)shared_life_count /
2613  (double)active_pl_num);
2614  for (uint i = 0; i < active_pl_num; i++) {
2615  pPlayers[pl_array[i]]->sHealth = mean_life;
2616  if (pPlayers[pl_array[i]]->sHealth >
2617  pPlayers[pl_array[i]]->GetMaxHealth())
2618  pPlayers[pl_array[i]]->sHealth =
2619  pPlayers[pl_array[i]]->GetMaxHealth();
2620  if (pPlayers[pl_array[i]]->sHealth > 0)
2621  pPlayers[pl_array[i]]->SetUnconcious(GameTime(0));
2623  pCastSpell->uSpellID, pl_array[i] - 1);
2624  }
2625  spell_sound_flag = true;
2626  break;
2627  }
2628 
2629  case SPELL_SPIRIT_RESSURECTION: //Воскресение
2630  {
2631  switch (skill_level) {
2632  case 1:
2633  amount = 180 * spell_level;
2634  break;
2635  case 2:
2636  amount = 10800 * spell_level;
2637  break;
2638  case 3:
2639  amount = 259200 * spell_level;
2640  break;
2641  case 4:
2642  amount = 0;
2643  break;
2644  default:
2645  assert(false);
2646  }
2647  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2648  if (pParty->pPlayers[pCastSpell->uPlayerID_2]
2649  .conditions_times[Condition_Eradicated]
2650  .Valid() ||
2651  pParty->pPlayers[pCastSpell->uPlayerID_2]
2652  .conditions_times[Condition_Dead]
2653  .Valid()) {
2654  if (!pParty->pPlayers[pCastSpell->uPlayerID_2]
2655  .conditions_times[Condition_Weak]
2656  .Valid())
2657  pParty->pPlayers[pCastSpell->uPlayerID_2].PlaySound(
2658  SPEECH_25, 0);
2659  if (skill_level == 4) {
2660  pParty->pPlayers[pCastSpell->uPlayerID_2]
2661  .conditions_times[Condition_Eradicated]
2662  .Reset();
2663  pParty->pPlayers[pCastSpell->uPlayerID_2]
2664  .conditions_times[Condition_Dead]
2665  .Reset();
2666  pParty->pPlayers[pCastSpell->uPlayerID_2]
2667  .conditions_times[Condition_Unconcious]
2668  .Reset();
2669  } else {
2670  pParty->pPlayers[pCastSpell->uPlayerID_2]
2671  .DiscardConditionIfLastsLongerThan(
2674  GameTime::FromSeconds(amount)));
2675  pParty->pPlayers[pCastSpell->uPlayerID_2]
2676  .DiscardConditionIfLastsLongerThan(
2679  GameTime::FromSeconds(amount)));
2680  pParty->pPlayers[pCastSpell->uPlayerID_2]
2681  .DiscardConditionIfLastsLongerThan(
2684  GameTime::FromSeconds(amount)));
2685  }
2686  pParty->pPlayers[pCastSpell->uPlayerID_2].SetCondition(
2687  Condition_Weak, 1);
2688  pParty->pPlayers[pCastSpell->uPlayerID_2].sHealth = 1;
2690  pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
2691  }
2692  spell_sound_flag = true;
2693  break;
2694  }
2695 
2696  case SPELL_MIND_CURE_PARALYSIS: //лечение паралича
2697  {
2698  switch (skill_level) {
2699  case 1:
2700  amount = 3600 * spell_level;
2701  break;
2702  case 2:
2703  amount = 3600 * spell_level;
2704  break;
2705  case 3:
2706  amount = 86400 * spell_level;
2707  break;
2708  case 4:
2709  amount = 0;
2710  break;
2711  default:
2712  assert(false);
2713  }
2714  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2716  pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
2717  if (!pParty->pPlayers[pCastSpell->uPlayerID_2]
2718  .conditions_times[Condition_Paralyzed]
2719  .Valid()) {
2720  spell_sound_flag = true;
2721  break;
2722  }
2723  if (skill_level == 4) {
2724  pParty->pPlayers[pCastSpell->uPlayerID_2]
2725  .conditions_times[Condition_Paralyzed]
2726  .Reset();
2727  spell_sound_flag = true;
2728  break;
2729  }
2730 
2731  pParty->pPlayers[pCastSpell->uPlayerID_2]
2732  .DiscardConditionIfLastsLongerThan(
2734  GameTime::FromSeconds(amount)));
2735 
2736  spell_sound_flag = true;
2737  break;
2738  }
2739 
2740  case SPELL_MIND_REMOVE_FEAR: //Снять страх
2741  {
2742  switch (skill_level) {
2743  case 1:
2744  amount = 180 * spell_level;
2745  break;
2746  case 2:
2747  amount = 3600 * spell_level;
2748  break;
2749  case 3:
2750  amount = 86400 * spell_level;
2751  break;
2752  case 4:
2753  amount = 0;
2754  break;
2755  default:
2756  assert(false);
2757  }
2758  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2760  pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
2761  if (!pParty->pPlayers[pCastSpell->uPlayerID_2]
2762  .conditions_times[Condition_Fear]
2763  .Valid()) {
2764  spell_sound_flag = true;
2765  break;
2766  }
2767  if (skill_level == 4) {
2768  pParty->pPlayers[pCastSpell->uPlayerID_2]
2769  .conditions_times[Condition_Fear]
2770  .Reset();
2771  spell_sound_flag = true;
2772  break;
2773  }
2774 
2775  pParty->pPlayers[pCastSpell->uPlayerID_2]
2776  .DiscardConditionIfLastsLongerThan(
2778  GameTime::FromSeconds(amount)));
2779 
2780  spell_sound_flag = true;
2781  break;
2782  }
2783 
2784  case SPELL_MIND_TELEPATHY: //Телепатия
2785  {
2786  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2787  if (PID_TYPE(spell_targeted_at) == OBJECT_Actor) {
2788  monster_id = PID_ID(spell_targeted_at);
2789  if (!pActors[monster_id].ActorHasItem())
2790  pActors[monster_id].SetRandomGoldIfTheresNoItem();
2791  int gold_num = 0;
2792  if (pItemsTable
2793  ->pItems
2794  [pActors[monster_id].ActorHasItems[3].uItemID]
2795  .uEquipType == EQUIP_GOLD)
2796  gold_num = pActors[monster_id]
2797  .ActorHasItems[3]
2798  .special_enchantment;
2799  ItemGen item;
2800  item.Reset();
2801  if (pActors[monster_id].uCarriedItemID) {
2802  item.uItemID = pActors[monster_id].uCarriedItemID;
2803  } else {
2804  for (uint i = 0; i < 4; ++i) {
2805  if (pActors[monster_id].ActorHasItems[i].uItemID >
2806  0 &&
2807  pItemsTable
2808  ->pItems[pActors[monster_id]
2809  .ActorHasItems[i]
2810  .uItemID]
2811  .uEquipType != EQUIP_GOLD) {
2812  memcpy(&item,
2813  &pActors[monster_id].ActorHasItems[i],
2814  sizeof(item));
2815  spell_level = spell_level;
2816  }
2817  }
2818  }
2819  if (gold_num > 0) {
2820  if (item.uItemID)
2822  "(%s), and %d gold",
2823  item.GetDisplayName().c_str(), gold_num));
2824  else
2826  StringPrintf("%d gold", gold_num));
2827  } else {
2828  if (item.uItemID) {
2830  "(%s)", item.GetDisplayName().c_str()));
2831  } else {
2832  GameUI_StatusBar_OnEvent("nothing");
2833  }
2834  }
2835 
2836  pSpellSprite.containing_item.Reset();
2837  pSpellSprite.spell_id = pCastSpell->uSpellID;
2838  pSpellSprite.spell_level = spell_level;
2839  pSpellSprite.spell_skill = skill_level;
2840  pSpellSprite.uObjectDescID =
2841  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
2842  pSpellSprite.vPosition.x = pActors[monster_id].vPosition.x;
2843  pSpellSprite.vPosition.y = pActors[monster_id].vPosition.y;
2844  pSpellSprite.vPosition.z = pActors[monster_id].uActorHeight;
2845  pSpellSprite.uAttributes = 0;
2846  pSpellSprite.uSectorID = pIndoor->GetSector(
2847  pSpellSprite.vPosition.x, pSpellSprite.vPosition.y,
2848  pSpellSprite.vPosition.z);
2849  pSpellSprite.uSpriteFrameID = 0;
2850  pSpellSprite.spell_caster_pid =
2851  PID(OBJECT_Player, pCastSpell->uPlayerID);
2852  pSpellSprite.spell_target_pid = spell_targeted_at;
2854  target_direction.uDistance;
2855  pSpellSprite.uFacing = target_direction.uYawAngle;
2856  pSpellSprite.uAttributes |= 0x80;
2857  pSpellSprite.uSoundID = pCastSpell->sound_id;
2858  pSpellSprite.Create(0, 0, 0, pCastSpell->uPlayerID + 1);
2859  }
2860  spell_sound_flag = true;
2861  break;
2862  }
2863 
2864  case SPELL_MIND_BERSERK: //Берсерк
2865  {
2866  switch (skill_level) {
2867  case 1:
2868  amount = 300 * spell_level;
2869  break;
2870  case 2:
2871  amount = 300 * spell_level;
2872  break;
2873  case 3:
2874  amount = 600 * spell_level;
2875  break;
2876  case 4:
2877  amount = 3600;
2878  break;
2879  default:
2880  assert(false);
2881  }
2882  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2883  monster_id = PID_ID(spell_targeted_at);
2884  if (PID_TYPE(spell_targeted_at) == OBJECT_Actor) {
2885  // v730 = 836 * monster_id;
2886  if (pActors[monster_id].DoesDmgTypeDoDamage(
2887  (DAMAGE_TYPE)7)) {
2888  pActors[monster_id]
2889  .pActorBuffs[ACTOR_BUFF_CHARM]
2890  .Reset();
2891  pActors[monster_id]
2892  .pActorBuffs[ACTOR_BUFF_ENSLAVED]
2893  .Reset();
2894  pActors[monster_id]
2895  .pActorBuffs[ACTOR_BUFF_BERSERK]
2896  .Apply(GameTime(pParty->GetPlayingTime() +
2897  GameTime::FromSeconds(amount)),
2898  skill_level, 0, 0, 0);
2899  pActors[monster_id].pMonsterInfo.uHostilityType =
2901  }
2902  pSpellSprite.containing_item.Reset();
2903  pSpellSprite.spell_id = pCastSpell->uSpellID;
2904  pSpellSprite.spell_level = spell_level;
2905  pSpellSprite.spell_skill = skill_level;
2906  pSpellSprite.uObjectDescID =
2907  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
2908  pSpellSprite.vPosition.x = pActors[monster_id].vPosition.x;
2909  pSpellSprite.vPosition.y = pActors[monster_id].vPosition.y;
2910  pSpellSprite.vPosition.z = pActors[monster_id].vPosition.z +
2911  pActors[monster_id].uActorHeight;
2912  pSpellSprite.uAttributes = 0;
2913  pSpellSprite.uSectorID =
2914  pIndoor->GetSector(pActors[monster_id].vPosition.x,
2915  pActors[monster_id].vPosition.y,
2916  pSpellSprite.vPosition.z);
2917  pSpellSprite.uSpriteFrameID = 0;
2918  pSpellSprite.spell_caster_pid =
2919  PID(OBJECT_Player, pCastSpell->uPlayerID);
2920  pSpellSprite.spell_target_pid = spell_targeted_at;
2922  target_direction.uDistance;
2923  pSpellSprite.uFacing = target_direction.uYawAngle;
2924  pSpellSprite.uAttributes |= 0x80;
2925  pSpellSprite.uSoundID = pCastSpell->sound_id;
2926  pSpellSprite.Create(0, 0, 0, pCastSpell->uPlayerID + 1);
2927  }
2928  spell_sound_flag = true;
2929  break;
2930  }
2931 
2932  case SPELL_MIND_ENSLAVE: //Порабощение
2933  {
2934  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2935  amount = 600 * spell_level;
2936  if (PID_TYPE(spell_targeted_at) == OBJECT_Actor) {
2937  monster_id = PID_ID(spell_targeted_at);
2938  // v730 = 836 * monster_id;
2940  pActors[monster_id].pMonsterInfo.uID,
2942  break;
2943  if (pActors[monster_id].DoesDmgTypeDoDamage(
2944  (DAMAGE_TYPE)7)) {
2945  pActors[monster_id]
2946  .pActorBuffs[ACTOR_BUFF_BERSERK]
2947  .Reset();
2948  pActors[monster_id]
2949  .pActorBuffs[ACTOR_BUFF_CHARM]
2950  .Reset();
2951  pActors[monster_id]
2952  .pActorBuffs[ACTOR_BUFF_ENSLAVED]
2953  .Apply(GameTime(pParty->GetPlayingTime() +
2954  GameTime::FromSeconds(amount)),
2955  skill_level, 0, 0, 0);
2956  }
2957  pSpellSprite.containing_item.Reset();
2958  pSpellSprite.spell_id = pCastSpell->uSpellID;
2959  pSpellSprite.spell_level = spell_level;
2960  pSpellSprite.spell_skill = skill_level;
2961  pSpellSprite.uObjectDescID =
2962  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
2963  pSpellSprite.vPosition.x = pActors[monster_id].vPosition.x;
2964  pSpellSprite.vPosition.y = pActors[monster_id].vPosition.y;
2965  pSpellSprite.vPosition.z = pActors[monster_id].vPosition.z +
2966  pActors[monster_id].uActorHeight;
2967  pSpellSprite.uAttributes = 0;
2968  pSpellSprite.uSectorID =
2969  pIndoor->GetSector(pActors[monster_id].vPosition.x,
2970  pActors[monster_id].vPosition.y,
2971  pSpellSprite.vPosition.z);
2972  pSpellSprite.uSpriteFrameID = 0;
2973  pSpellSprite.spell_caster_pid =
2974  PID(OBJECT_Player, pCastSpell->uPlayerID);
2975  pSpellSprite.spell_target_pid = spell_targeted_at;
2977  target_direction.uDistance;
2978  pSpellSprite.uFacing = target_direction.uYawAngle;
2979  pSpellSprite.uAttributes |= 0x80;
2980  pSpellSprite.uSoundID = pCastSpell->sound_id;
2981  pSpellSprite.Create(0, 0, 0, pCastSpell->uPlayerID + 1);
2982  }
2983  spell_sound_flag = true;
2984  break;
2985  }
2986 
2987  case SPELL_MIND_MASS_FEAR: { // Массовый страх
2988  if (skill_level == 4)
2989  amount = 300 * spell_level;
2990  else
2991  amount = 180 * spell_level;
2992  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
2993  int mon_num = render->GetActorsInViewport(4096);
2996  192);
2997  // ++pSpellSprite.uType;
2998  pSpellSprite.uType = SPRITE_SPELL_MIND_MASS_FEAR_1;
2999  pSpellSprite.containing_item.Reset();
3000  pSpellSprite.spell_id = pCastSpell->uSpellID;
3001  pSpellSprite.spell_level = spell_level;
3002  pSpellSprite.spell_skill = skill_level;
3003  pSpellSprite.uObjectDescID =
3004  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
3005  pSpellSprite.uAttributes = 0;
3006  pSpellSprite.uSectorID = 0;
3007  pSpellSprite.uSpriteFrameID = 0;
3008  pSpellSprite.field_60_distance_related_prolly_lod = 0;
3009  pSpellSprite.uFacing = 0;
3010  pSpellSprite.spell_caster_pid =
3011  PID(OBJECT_Player, pCastSpell->uPlayerID);
3012  pSpellSprite.uSoundID = (short)pCastSpell->sound_id;
3013  for (spell_targeted_at = 0; spell_targeted_at < mon_num;
3014  ++spell_targeted_at) {
3017  [spell_targeted_at]]
3018  .pMonsterInfo.uID,
3020  break;
3021  pSpellSprite.vPosition.x =
3022  pActors
3023  [_50BF30_actors_in_viewport_ids[spell_targeted_at]]
3024  .vPosition.x;
3025  pSpellSprite.vPosition.y =
3026  pActors
3027  [_50BF30_actors_in_viewport_ids[spell_targeted_at]]
3028  .vPosition.y;
3029  pSpellSprite.vPosition.z =
3030  pActors
3031  [_50BF30_actors_in_viewport_ids[spell_targeted_at]]
3032  .vPosition.z -
3033  (unsigned int)(int64_t)((double)pActors
3035  [spell_targeted_at]]
3036  .uActorHeight *
3037  -0.8);
3038  pSpellSprite.spell_target_pid =
3039  PID(OBJECT_Actor,
3040  _50BF30_actors_in_viewport_ids[spell_targeted_at]);
3041  pSpellSprite.Create(0, 0, 0, 0);
3042  if (pActors
3043  [_50BF30_actors_in_viewport_ids[spell_targeted_at]]
3044  .DoesDmgTypeDoDamage((DAMAGE_TYPE)7)) {
3045  pActors
3046  [_50BF30_actors_in_viewport_ids[spell_targeted_at]]
3047  .pActorBuffs[ACTOR_BUFF_AFRAID]
3048  .Apply(GameTime(pParty->GetPlayingTime() +
3049  GameTime::FromSeconds(amount)),
3050  skill_level, 0, 0, 0);
3051  }
3052  }
3053  spell_sound_flag = true;
3054  break;
3055  }
3056 
3057  case SPELL_MIND_CURE_INSANITY: //Лечение Безумия
3058  {
3059  if (skill_level == 4)
3060  amount = 0;
3061  else
3062  amount = 86400 * spell_level;
3063  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3065  pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
3066  if (pParty->pPlayers[pCastSpell->uPlayerID_2]
3067  .conditions_times[Condition_Insane]
3068  .Valid()) {
3069  if (!pParty->pPlayers[pCastSpell->uPlayerID_2]
3070  .conditions_times[Condition_Weak]
3071  .Valid())
3072  pParty->pPlayers[pCastSpell->uPlayerID_2].PlaySound(
3073  SPEECH_25, 0);
3074  if (skill_level == 4)
3075  pParty->pPlayers[pCastSpell->uPlayerID_2]
3076  .conditions_times[Condition_Insane]
3077  .Reset();
3078  else
3079  pParty->pPlayers[pCastSpell->uPlayerID_2]
3080  .DiscardConditionIfLastsLongerThan(
3083  GameTime::FromSeconds(amount)));
3084  pParty->pPlayers[pCastSpell->uPlayerID_2].SetCondition(
3085  Condition_Weak, 0);
3086  }
3087  spell_sound_flag = true;
3088  break;
3089  }
3090 
3091  case SPELL_EARTH_TELEKINESIS: //Телекинез
3092  {
3093  switch (skill_level) {
3094  case 1:
3095  amount = 2 * spell_level;
3096  break;
3097  case 2:
3098  amount = 2 * spell_level;
3099  break;
3100  case 3:
3101  amount = 3 * spell_level;
3102  break;
3103  case 4:
3104  amount = 4 * spell_level;
3105  break;
3106  default:
3107  assert(false);
3108  }
3109  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3110  int obj_id = PID_ID(spell_targeted_at);
3111  if (PID_TYPE(spell_targeted_at) == OBJECT_Item) {
3112  if (pItemsTable
3113  ->pItems[pSpriteObjects[obj_id]
3114  .containing_item.uItemID]
3115  .uEquipType == EQUIP_GOLD) {
3117  pSpriteObjects[obj_id]
3118  .containing_item.special_enchantment,
3119  0);
3120  viewparams->bRedrawGameUI = true;
3121  } else {
3123  471, pItemsTable
3124  ->pItems[pSpriteObjects[obj_id]
3125  .containing_item.uItemID]
3126  .pUnidentifiedName)); // You find %s! Вы
3127  // нашли ^Pv[%s]!
3128  if (!pParty->AddItemToParty(
3129  &pSpriteObjects[obj_id].containing_item))
3131  &pSpriteObjects[obj_id].containing_item);
3132  }
3134  }
3135  if (PID_TYPE(spell_targeted_at) == OBJECT_Actor)
3136  pActors[obj_id].LootActor();
3137  if (PID_TYPE(spell_targeted_at) == OBJECT_Decoration) {
3138  OpenedTelekinesis = true;
3139  if (pLevelDecorations[obj_id].uEventID)
3140  EventProcessor(pLevelDecorations[obj_id].uEventID,
3141  spell_targeted_at, 1);
3142  if (pLevelDecorations[pSpriteObjects[obj_id]
3143  .containing_item.uItemID]
3144  .IsInteractive()) {
3148  [pLevelDecorations[obj_id]._idx_in_stru123 -
3149  75] +
3150  380,
3151  0, 1);
3152  activeLevelDecoration = nullptr;
3153  }
3154  }
3155  if (PID_TYPE(spell_targeted_at) == OBJECT_BModel) {
3156  OpenedTelekinesis = true;
3158  v448 = pIndoor
3159  ->pFaceExtras[pIndoor->pFaces[obj_id]
3160  .uFaceExtraID]
3161  .uEventID;
3162  else
3163  v448 = pOutdoor->pBModels[spell_targeted_at >> 9]
3164  .pFaces[obj_id & 0x3F]
3165  .sCogTriggeredID;
3166  EventProcessor(v448, spell_targeted_at, 1);
3167  }
3168  spell_sound_flag = true;
3169  break;
3170  }
3171 
3172  case SPELL_BODY_CURE_WEAKNESS: //Лечить Слабость
3173  {
3174  switch (skill_level) {
3175  case 1:
3176  amount = 180 * spell_level;
3177  break; // 3 минуты * количество очков навыка
3178  case 2:
3179  amount = 3600 * spell_level;
3180  break; // 1 час * количество очков навыка
3181  case 3:
3182  amount = 86400 * spell_level;
3183  break;
3184  case 4:
3185  amount = 0;
3186  break;
3187  default:
3188  assert(false);
3189  }
3190  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3192  pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
3193  if (pParty->pPlayers[pCastSpell->uPlayerID_2]
3194  .conditions_times[Condition_Weak]
3195  .Valid()) {
3196  if (skill_level == 4) {
3197  pParty->pPlayers[pCastSpell->uPlayerID_2]
3198  .conditions_times[Condition_Weak]
3199  .Reset();
3200  spell_sound_flag = true;
3201  break;
3202  }
3203  pParty->pPlayers[pCastSpell->uPlayerID_2]
3204  .DiscardConditionIfLastsLongerThan(
3206  GameTime::FromSeconds(amount)));
3207  }
3208  spell_sound_flag = true;
3209  break;
3210  }
3211 
3212  case SPELL_BODY_FIRST_AID: //Первая помощь
3213  {
3214  switch (skill_level) {
3215  case 1:
3216  amount = 2 * spell_level + 5;
3217  break;
3218  case 2:
3219  amount = 3 * spell_level + 5;
3220  break;
3221  case 3:
3222  amount = 4 * spell_level + 5;
3223  break;
3224  case 4:
3225  amount = 5 * spell_level + 5;
3226  break;
3227  default:
3228  assert(false);
3229  }
3230  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3231  if (!pCastSpell->spell_target_pid) {
3232  pParty->pPlayers[pCastSpell->uPlayerID_2].Heal(amount);
3234  pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
3235  }
3236  if (PID_TYPE(pCastSpell->spell_target_pid) == OBJECT_Actor) {
3237  monster_id = PID_ID(pCastSpell->spell_target_pid);
3238  if (pActors[monster_id].uAIState != Dead &&
3239  pActors[monster_id].uAIState != Dying &&
3240  pActors[monster_id].uAIState != Disabled &&
3241  pActors[monster_id].uAIState != Removed) {
3242  pActors[monster_id].sCurrentHP += amount;
3243  if (pActors[monster_id].sCurrentHP >
3244  pActors[monster_id].pMonsterInfo.uHP)
3245  pActors[monster_id].sCurrentHP =
3246  pActors[monster_id].pMonsterInfo.uHP;
3247  }
3248  }
3249  spell_sound_flag = true;
3250  break;
3251  }
3252 
3253  case SPELL_BODY_CURE_POISON: //Лечение Отравления(Противоядие)
3254  {
3255  switch (skill_level) {
3256  case 1:
3257  amount = 3600 * spell_level;
3258  break;
3259  case 2:
3260  amount = 3600 * spell_level;
3261  break;
3262  case 3:
3263  amount = 86400 * spell_level;
3264  break;
3265  case 4:
3266  amount = 0;
3267  break;
3268  default:
3269  assert(false);
3270  }
3271 
3272  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3273 
3275  pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
3276  if (pParty->pPlayers[pCastSpell->uPlayerID_2]
3277  .conditions_times[Condition_Poison_Weak]
3278  .Valid() ||
3279  pParty->pPlayers[pCastSpell->uPlayerID_2]
3280  .conditions_times[Condition_Poison_Medium]
3281  .Valid() ||
3282  pParty->pPlayers[pCastSpell->uPlayerID_2]
3283  .conditions_times[Condition_Poison_Severe]
3284  .Valid()) {
3285  if (skill_level == 4) {
3286  pParty->pPlayers[pCastSpell->uPlayerID_2]
3287  .conditions_times[Condition_Poison_Weak]
3288  .Reset();
3289  pParty->pPlayers[pCastSpell->uPlayerID_2]
3290  .conditions_times[Condition_Poison_Medium]
3291  .Reset();
3292  pParty->pPlayers[pCastSpell->uPlayerID_2]
3293  .conditions_times[Condition_Poison_Severe]
3294  .Reset();
3295  spell_sound_flag = true;
3296  break;
3297  }
3298 
3299  pParty->pPlayers[pCastSpell->uPlayerID_2]
3300  .DiscardConditionIfLastsLongerThan(
3303  GameTime::FromSeconds(amount)));
3304  pParty->pPlayers[pCastSpell->uPlayerID_2]
3305  .DiscardConditionIfLastsLongerThan(
3308  GameTime::FromSeconds(amount)));
3309  pParty->pPlayers[pCastSpell->uPlayerID_2]
3310  .DiscardConditionIfLastsLongerThan(
3313  GameTime::FromSeconds(amount)));
3314  }
3315  spell_sound_flag = true;
3316  break;
3317  }
3318 
3319  case SPELL_BODY_PROTECTION_FROM_MAGIC: //Защита от магии
3320  {
3321  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3322 
3324  pCastSpell->uSpellID, 0);
3326  pCastSpell->uSpellID, 1);
3328  pCastSpell->uSpellID, 2);
3330  pCastSpell->uSpellID, 3);
3333  GameTime::FromSeconds(3600 * spell_level)),
3334  skill_level, spell_level, 0, 0);
3335  spell_sound_flag = true;
3336  break;
3337  }
3338 
3339  case SPELL_BODY_HAMMERHANDS: //Руки-Молоты
3340  {
3341  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3342  if (skill_level == 4) {
3344  pCastSpell->uSpellID, 0);
3346  pCastSpell->uSpellID, 1);
3348  pCastSpell->uSpellID, 2);
3350  pCastSpell->uSpellID, 3);
3351  for (uint pl_id = 0; pl_id < 4; pl_id++) {
3352  pParty->pPlayers[pl_id]
3353  .pPlayerBuffs[PLAYER_BUFF_HAMMERHANDS]
3354  .Apply(
3356  GameTime::FromSeconds(3600 * spell_level)),
3357  4, spell_level, spell_level, 0);
3358  }
3359  spell_sound_flag = true;
3360  break;
3361  }
3363  pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
3364  pParty->pPlayers[pCastSpell->uPlayerID_2]
3365  .pPlayerBuffs[PLAYER_BUFF_HAMMERHANDS]
3366  .Apply(GameTime(pParty->GetPlayingTime() +
3367  GameTime::FromSeconds(3600 * spell_level)),
3368  skill_level, spell_level, spell_level, 0);
3369  spell_sound_flag = true;
3370  break;
3371  }
3372 
3373  case SPELL_BODY_POWER_CURE: //Исцеление
3374  {
3375  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3376  for (uint pl_id = 0; pl_id < 4; ++pl_id) {
3378  pCastSpell->uSpellID, pl_id);
3379  pParty->pPlayers[pl_id].Heal(5 * spell_level + 10);
3380  }
3381  spell_sound_flag = true;
3382  break;
3383  }
3384 
3385  case SPELL_LIGHT_DISPEL_MAGIC: { // Снятие чар
3386  sRecoveryTime -= spell_level;
3387  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3390  192);
3391  int mon_num = render->GetActorsInViewport(4096);
3392  // ++pSpellSprite.uType;
3394  v688.x = 0;
3395  v688.y = 0;
3396  v688.z = 0;
3397  pSpellSprite.containing_item.Reset();
3398  pSpellSprite.spell_id = pCastSpell->uSpellID;
3399  pSpellSprite.spell_level = spell_level;
3400  pSpellSprite.spell_skill = skill_level;
3401  pSpellSprite.uObjectDescID =
3402  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
3403  pSpellSprite.uAttributes = 0;
3404  pSpellSprite.uSectorID = 0;
3405  pSpellSprite.uSpriteFrameID = 0;
3406  pSpellSprite.field_60_distance_related_prolly_lod = 0;
3407  pSpellSprite.uFacing = 0;
3408  pSpellSprite.spell_caster_pid =
3409  PID(OBJECT_Player, pCastSpell->uPlayerID);
3410  pSpellSprite.uSoundID = (short)pCastSpell->sound_id;
3411  for (spell_targeted_at = 0; spell_targeted_at < mon_num;
3412  ++spell_targeted_at) {
3413  pSpellSprite.vPosition.x =
3414  pActors
3415  [_50BF30_actors_in_viewport_ids[spell_targeted_at]]
3416  .vPosition.x;
3417  pSpellSprite.vPosition.y =
3418  pActors
3419  [_50BF30_actors_in_viewport_ids[spell_targeted_at]]
3420  .vPosition.y;
3421  pSpellSprite.vPosition.z =
3422  pActors
3423  [_50BF30_actors_in_viewport_ids[spell_targeted_at]]
3424  .vPosition.z -
3426  [spell_targeted_at]]
3427  .uActorHeight *
3428  -0.8);
3429  pSpellSprite.spell_target_pid =
3430  PID(OBJECT_Actor,
3431  _50BF30_actors_in_viewport_ids[spell_targeted_at]);
3433  PID(OBJECT_Item, pSpellSprite.Create(0, 0, 0, 0)),
3434  _50BF30_actors_in_viewport_ids[spell_targeted_at],
3435  &v688);
3436  }
3437  for (spell_targeted_at = 0; spell_targeted_at < mon_num;
3438  ++spell_targeted_at) {
3439  pSpellSprite.vPosition.x =
3440  pActors
3441  [_50BF30_actors_in_viewport_ids[spell_targeted_at]]
3442  .vPosition.x;
3443  pSpellSprite.vPosition.y =
3444  pActors
3445  [_50BF30_actors_in_viewport_ids[spell_targeted_at]]
3446  .vPosition.y;
3447  pSpellSprite.vPosition.z =
3448  pActors
3449  [_50BF30_actors_in_viewport_ids[spell_targeted_at]]
3450  .vPosition.z -
3451  (unsigned int)(signed __int64)((double)pActors
3453  [spell_targeted_at]]
3454  .uActorHeight *
3455  -0.8);
3456  pSpellSprite.spell_target_pid =
3457  PID(OBJECT_Actor,
3458  _50BF30_actors_in_viewport_ids[spell_targeted_at]);
3459  pSpellSprite.Create(0, 0, 0, 0);
3460  for (int i = 0; i < 22; ++i)
3461  pActors
3462  [_50BF30_actors_in_viewport_ids[spell_targeted_at]]
3463  .pActorBuffs[i]
3464  .Reset();
3465  }
3466  spell_sound_flag = true;
3467  break;
3468  }
3469 
3470  case SPELL_LIGHT_SUMMON_ELEMENTAL: //Элементал
3471  {
3472  switch (skill_level) {
3473  case 1:
3474  spellduration = 300 * spell_level;
3475  amount = 1;
3476  break;
3477  case 2:
3478  spellduration = 300 * spell_level;
3479  amount = 1;
3480  break;
3481  case 3:
3482  spellduration = 900 * spell_level;
3483  amount = 3;
3484  break;
3485  case 4:
3486  spellduration = 900 * spell_level;
3487  amount = 5;
3488  break;
3489  default:
3490  assert(false);
3491  }
3492  int mon_num = 0;
3493  for (uint monster_id = 0; monster_id < uNumActors;
3494  monster_id++) {
3495  if (pActors[monster_id].uAIState != Dead &&
3496  pActors[monster_id].uAIState != Removed &&
3497  pActors[monster_id].uAIState != Disabled &&
3498  PID(OBJECT_Player, pCastSpell->uPlayerID) ==
3499  pActors[monster_id].uSummonerID)
3500  ++mon_num;
3501  }
3502  if (mon_num >= amount) {
3504  648)); // This character can't summon any more
3505  // monsters!
3507  0, 0);
3508  pCastSpell->uSpellID = 0;
3509  continue;
3510  }
3511  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3513  skill_level, spellduration);
3514  spell_sound_flag = true;
3515  break;
3516  }
3517 
3518  case SPELL_LIGHT_DAY_OF_THE_GODS: //День богов
3519  {
3520  switch (skill_level) {
3521  case 1:
3522  spellduration = 10800 * spell_level;
3523  amount = 3 * spell_level + 10;
3524  break;
3525  case 2:
3526  spellduration = 10800 * spell_level;
3527  amount = 3 * spell_level + 10;
3528  break;
3529  case 3:
3530  spellduration = 14400 * spell_level;
3531  amount = 4 * spell_level + 10;
3532  break;
3533  case 4:
3534  spellduration = 18000 * spell_level;
3535  amount = 5 * spell_level + 10;
3536  break;
3537  default:
3538  assert(false);
3539  }
3540  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3542  pCastSpell->uSpellID, 0);
3544  pCastSpell->uSpellID, 1);
3546  pCastSpell->uSpellID, 2);
3548  pCastSpell->uSpellID, 3);
3551  GameTime::FromSeconds(spellduration)),
3552  skill_level, amount, 0, 0);
3553  spell_sound_flag = true;
3554  break;
3555  }
3556 
3557  case SPELL_LIGHT_PRISMATIC_LIGHT: { // Свет призмы
3560  497)); // Can't cast Prismatic Light outdoors!
3562  0, 0);
3563  pCastSpell->uSpellID = 0;
3564  continue;
3565  }
3566  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3567  int mon_num = render->GetActorsInViewport(4096);
3568  // ++pSpellSprite.uType;
3570  v694.x = 0;
3571  v694.y = 0;
3572  v694.z = 0;
3573  pSpellSprite.containing_item.Reset();
3574  pSpellSprite.spell_id = pCastSpell->uSpellID;
3575  pSpellSprite.spell_level = spell_level;
3576  pSpellSprite.spell_skill = skill_level;
3577  pSpellSprite.uObjectDescID =
3578  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
3579  pSpellSprite.uAttributes = 0;
3580  pSpellSprite.uSectorID = 0;
3581  pSpellSprite.uSpriteFrameID = 0;
3582  pSpellSprite.field_60_distance_related_prolly_lod = 0;
3583  pSpellSprite.uFacing = 0;
3584  pSpellSprite.spell_caster_pid =
3585  PID(OBJECT_Player, pCastSpell->uPlayerID);
3586  pSpellSprite.uSoundID = (short)pCastSpell->sound_id;
3587  for (uint monster_id = 0; monster_id < mon_num; monster_id++) {
3588  pSpellSprite.vPosition.x =
3590  .vPosition.x;
3591  pSpellSprite.vPosition.y =
3593  .vPosition.y;
3594  pSpellSprite.vPosition.z =
3596  .vPosition.z -
3598  .uActorHeight *
3599  -0.8;
3600  pSpellSprite.spell_target_pid =
3601  PID(OBJECT_Actor,
3602  _50BF30_actors_in_viewport_ids[monster_id]);
3604  PID(OBJECT_Item, pSpellSprite.Create(0, 0, 0, 0)),
3605  _50BF30_actors_in_viewport_ids[monster_id], &v694);
3606  }
3607  // v537 = spell_fx_renderer;
3609  spell_sound_flag = true;
3610  break;
3611  }
3612 
3613  case SPELL_LIGHT_DAY_OF_PROTECTION: //День защиты
3614  {
3615  switch (skill_level) {
3616  case 1:
3617  spellduration = 14400 * spell_level;
3618  amount = 4 * spell_level;
3619  break;
3620  case 2:
3621  spellduration = 14400 * spell_level;
3622  amount = 4 * spell_level;
3623  break;
3624  case 3:
3625  spellduration = 14400 * spell_level;
3626  amount = 4 * spell_level;
3627  break;
3628  case 4:
3629  spellduration = 18000 * spell_level;
3630  amount = 5 * spell_level;
3631  break;
3632  default:
3633  assert(false);
3634  }
3635  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3637  pCastSpell->uSpellID, 0);
3639  pCastSpell->uSpellID, 1);
3641  pCastSpell->uSpellID, 2);
3643  pCastSpell->uSpellID, 3);
3646  GameTime::FromSeconds(spellduration)),
3647  skill_level, amount, 0, 0);
3650  GameTime::FromSeconds(spellduration)),
3651  skill_level, amount, 0, 0);
3654  GameTime::FromSeconds(spellduration)),
3655  skill_level, amount, 0, 0);
3658  GameTime::FromSeconds(spellduration)),
3659  skill_level, amount, 0, 0);
3662  GameTime::FromSeconds(spellduration)),
3663  skill_level, amount, 0, 0);
3666  GameTime::FromSeconds(spellduration)),
3667  skill_level, amount, 0, 0);
3670  GameTime::FromSeconds(spellduration)),
3671  skill_level, spell_level + 5, 0, 0);
3674  GameTime::FromSeconds(spellduration)),
3675  skill_level, spell_level + 5, 0, 0);
3676  spell_sound_flag = true;
3677  break;
3678  }
3679 
3680  case SPELL_LIGHT_HOUR_OF_POWER: //Час могущества
3681  {
3682  switch (skill_level) {
3683  case 1:
3684  spellduration = 4;
3685  amount = 4;
3686  break;
3687  case 2:
3688  spellduration = 4;
3689  amount = 4;
3690  break;
3691  case 3:
3692  spellduration = 12;
3693  amount = 12;
3694  break;
3695  case 4:
3696  spellduration = 20;
3697  amount = 15;
3698  break;
3699  default:
3700  assert(false);
3701  }
3702  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3703  bool player_weak = false;
3704  for (uint pl_id = 0; pl_id < 4; pl_id++) {
3706  pCastSpell->uSpellID, 0);
3708  pCastSpell->uSpellID, 1);
3710  pCastSpell->uSpellID, 2);
3712  pCastSpell->uSpellID, 3);
3713  pParty->pPlayers[pl_id]
3714  .pPlayerBuffs[PLAYER_BUFF_BLESS]
3715  .Apply(GameTime(pParty->GetPlayingTime() +
3717  300 * amount * spell_level + 60)),
3718  skill_level, spell_level + 5, 0, 0);
3719  if (pParty->pPlayers[pl_id]
3720  .conditions_times[Condition_Weak]
3721  .Valid())
3722  player_weak = true;
3723  }
3724 
3727  GameTime::FromSeconds(300 * amount * spell_level + 60)),
3728  skill_level, spell_level + 5, 0, 0);
3731  GameTime::FromSeconds(300 * amount * spell_level + 60)),
3732  skill_level, 0, 0, 0);
3735  GameTime::FromSeconds(300 * amount * spell_level + 60)),
3736  skill_level, spell_level + 5, 0, 0);
3737  if (!player_weak)
3741  60 * (spell_level * spellduration + 60))),
3742  skill_level, spell_level + 5, 0, 0);
3743  spell_sound_flag = true;
3744  break;
3745  }
3746 
3748  // amount = 3;
3749  if (pPlayer->uNumDivineInterventionCastsThisDay >= 3) {
3751  localization->GetString(428)); // Spell failed
3753  0, 0);
3754  pCastSpell->uSpellID = 0;
3755  continue;
3756  }
3757  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3758  for (uint pl_id = 0; pl_id < 4; pl_id++) {
3759  for (uint buff_id = 0; buff_id <= 19; buff_id++)
3760  pParty->pPlayers[pl_id]
3761  .conditions_times[buff_id]
3762  .Reset();
3763  pParty->pPlayers[pl_id].sHealth =
3764  pParty->pPlayers[pl_id].GetMaxHealth();
3765  pParty->pPlayers[pl_id].sMana =
3766  pParty->pPlayers[pl_id].GetMaxMana();
3768  pCastSpell->uSpellID, pl_id);
3769  }
3770  if (pPlayer->sAgeModifier + 10 >= 120)
3771  pPlayer->sAgeModifier = 120;
3772  else
3773  pPlayer->sAgeModifier = pPlayer->sAgeModifier + 10;
3774  sRecoveryTime += -5 * spell_level;
3776  spell_sound_flag = true;
3777  break;
3778  }
3779 
3780  case SPELL_DARK_REANIMATE: //Реанимация
3781  {
3782  switch (skill_level) {
3783  case 1:
3784  amount = 2 * spell_level;
3785  break;
3786  case 2:
3787  amount = 3 * spell_level;
3788  break;
3789  case 3:
3790  amount = 4 * spell_level;
3791  break;
3792  case 4:
3793  amount = 5 * spell_level;
3794  break;
3795  default:
3796  assert(false);
3797  }
3798  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3799  if (!pCastSpell->spell_target_pid) {
3801  pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
3802  if (pParty->pPlayers[pCastSpell->uPlayerID_2]
3803  .conditions_times[Condition_Dead]
3804  .Valid()) {
3805  pParty->pPlayers[pCastSpell->uPlayerID_2].SetCondition(
3806  Condition_Zombie, 1);
3808  pCastSpell->uPlayerID_2,
3809  (pParty->pPlayers[pCastSpell->uPlayerID_2]
3810  .GetSexByVoice() != 0) +
3811  23);
3812  pParty->pPlayers[pCastSpell->uPlayerID_2]
3813  .conditions_times[Condition_Zombie] =
3815  }
3816  break;
3817  }
3818  monster_id = PID_ID(pCastSpell->spell_target_pid);
3819  if (monster_id == -1) {
3821  496)); // No valid target exists!
3823  0, 0);
3824  pCastSpell->uSpellID = 0;
3825  continue;
3826  }
3827  if (pActors[monster_id].sCurrentHP > 0 ||
3828  pActors[monster_id].uAIState != Dead &&
3829  pActors[monster_id].uAIState != Dying) {
3831  localization->GetString(428)); // Spell failed
3833  0, 0);
3834  pCastSpell->uSpellID = 0;
3835  continue;
3836  }
3837  // ++pSpellSprite.uType;
3838  pSpellSprite.uType = SPRITE_SPELL_DARK_REANIMATE_1;
3839  pSpellSprite.containing_item.Reset();
3840  pSpellSprite.spell_id = pCastSpell->uSpellID;
3841  pSpellSprite.spell_level = spell_level;
3842  pSpellSprite.spell_skill = skill_level;
3843  pSpellSprite.uObjectDescID =
3844  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
3845  pSpellSprite.uAttributes = 0;
3846  pSpellSprite.uSectorID = 0;
3847  pSpellSprite.uSpriteFrameID = 0;
3848  pSpellSprite.field_60_distance_related_prolly_lod = 0;
3849  pSpellSprite.uFacing = 0;
3850  pSpellSprite.spell_caster_pid =
3851  PID(OBJECT_Player, pCastSpell->uPlayerID);
3852  pSpellSprite.uSoundID = (short)pCastSpell->sound_id;
3853  pSpellSprite.vPosition.x = pActors[monster_id].vPosition.x;
3854  pSpellSprite.vPosition.y = pActors[monster_id].vPosition.y;
3855  pSpellSprite.vPosition.z =
3856  pActors[monster_id].vPosition.z -
3857  (int)((double)pActors[monster_id].uActorHeight * -0.8);
3858  pSpellSprite.spell_target_pid = PID(OBJECT_Actor, monster_id);
3859  pSpellSprite.Create(0, 0, 0, 0);
3860  if (pActors[monster_id].pMonsterInfo.uLevel > amount) break;
3861  Actor::Resurrect(monster_id);
3862  pActors[monster_id].pMonsterInfo.uHostilityType =
3864  pActors[monster_id].pMonsterInfo.uTreasureDropChance = 0;
3865  pActors[monster_id].pMonsterInfo.uTreasureDiceRolls = 0;
3866  pActors[monster_id].pMonsterInfo.uTreasureDiceSides = 0;
3867  pActors[monster_id].pMonsterInfo.uTreasureLevel = 0;
3868  pActors[monster_id].pMonsterInfo.uTreasureType = 0;
3869  pActors[monster_id].uAlly = 9999;
3870  pActors[monster_id].ResetAggressor(); // ~0x80000
3871  pActors[monster_id].uGroup = 0;
3872  pActors[monster_id].pActorBuffs[ACTOR_BUFF_BERSERK].Reset();
3873  pActors[monster_id].pActorBuffs[ACTOR_BUFF_CHARM].Reset();
3874  pActors[monster_id].pActorBuffs[ACTOR_BUFF_ENSLAVED].Reset();
3875  if (pActors[monster_id].sCurrentHP > 10 * amount)
3876  pActors[monster_id].sCurrentHP = 10 * amount;
3877  spell_sound_flag = true;
3878  break;
3879  }
3880 
3881  case SPELL_DARK_VAMPIRIC_WEAPON: // Оружие-вампир
3882  {
3883  amount = 16;
3884  if (skill_level == 4)
3885  spellduration = 0;
3886  else
3887  spellduration = 3600 * spell_level;
3888  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3889  ItemGen *item = &pParty->pPlayers[pCastSpell->uPlayerID_2]
3890  .pInventoryItemList[spell_targeted_at];
3892  if (item->uItemID >= 64 && item->uItemID <= 65 // blasters
3893  || item->uAttributes & 2 ||
3894  item->special_enchantment != 0 ||
3895  item->uEnchantmentType != 0 ||
3896  pItemsTable->pItems[item->uItemID].uEquipType !=
3898  pItemsTable->pItems[item->uItemID].uEquipType !=
3899  EQUIP_TWO_HANDED &&
3900  pItemsTable->pItems[item->uItemID].uEquipType !=
3901  EQUIP_BOW ||
3907  localization->GetString(428)); // Spell failed
3909  0, 0);
3910  pCastSpell->uSpellID = 0;
3911  continue;
3912  }
3914  if (skill_level != 4) {
3916  GameTime::FromSeconds(spellduration));
3917  item->uAttributes |= 8;
3918  }
3919  item->uAttributes |= 0x80;
3921  spell_sound_flag = true;
3922  break;
3923  }
3924 
3925  case SPELL_DARK_SHARPMETAL: //Шрапнель
3926  {
3927  switch (skill_level) {
3928  case 1:
3929  amount = 5;
3930  break;
3931  case 2:
3932  amount = 5;
3933  break;
3934  case 3:
3935  amount = 7;
3936  break;
3937  case 4:
3938  amount = 9;
3939  break;
3940  default:
3941  assert(false);
3942  }
3943  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3944  signed int _v726 =
3945  ((signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360);
3946  pSpellSprite.containing_item.Reset();
3947  pSpellSprite.spell_id = pCastSpell->uSpellID;
3948  pSpellSprite.spell_level = spell_level;
3949  pSpellSprite.spell_skill = skill_level;
3950  pSpellSprite.uObjectDescID =
3951  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
3952  pSpellSprite.vPosition.x = pParty->vPosition.x;
3953  pSpellSprite.vPosition.y = pParty->vPosition.y;
3954  pSpellSprite.uAttributes = 0;
3955  pSpellSprite.vPosition.z =
3956  pParty->vPosition.z + (signed int)pParty->uPartyHeight / 2;
3957  pSpellSprite.uSectorID = pIndoor->GetSector(
3959  pParty->vPosition.z + (signed int)pParty->uPartyHeight / 2);
3960  pSpellSprite.uSpriteFrameID = 0;
3961  pSpellSprite.spell_caster_pid =
3962  PID(OBJECT_Player, pCastSpell->uPlayerID);
3963  pSpellSprite.spell_target_pid = spell_targeted_at;
3965  target_direction.uDistance;
3966  pSpellSprite.uSoundID = pCastSpell->sound_id;
3967  if (pParty->bTurnBasedModeOn) {
3968  pSpellSprite.uAttributes |= 4;
3969  }
3970  spell_spray_angle_start = (signed int)_v726 / -2;
3971  spell_spray_angle_end = (signed int)_v726 / 2;
3972  if (spell_spray_angle_start <= spell_spray_angle_end) {
3973  do {
3974  pSpellSprite.uFacing = spell_spray_angle_start +
3975  target_direction.uYawAngle;
3976  if (pSpellSprite.Create(
3977  pSpellSprite.uFacing,
3978  target_direction.uPitchAngle,
3979  pObjectList
3980  ->pObjects[pSpellSprite.uObjectDescID]
3981  .uSpeed,
3982  pCastSpell->uPlayerID + 1) != -1 &&
3985  }
3986  spell_spray_angle_start += _v726 / (amount - 1);
3987  } while (spell_spray_angle_start <= spell_spray_angle_end);
3988  }
3989  spell_sound_flag = true;
3990  break;
3991  }
3992 
3993  case SPELL_DARK_CONTROL_UNDEAD: //Глава нежити
3994  {
3995  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
3996  switch (skill_level) {
3997  case 1:
3998  spellduration = 180 * spell_level;
3999  break;
4000  case 2:
4001  spellduration = 180 * spell_level;
4002  break;
4003  case 3:
4004  spellduration = 300 * spell_level;
4005  break;
4006  case 4:
4007  spellduration = 29030400;
4008  break;
4009  default:
4010  assert(false);
4011  }
4012  if (PID_TYPE(spell_targeted_at) == OBJECT_Actor) {
4013  monster_id = PID_ID(spell_targeted_at);
4015  pActors[monster_id].pMonsterInfo.uID,
4017  break;
4018  if (!pActors[monster_id].DoesDmgTypeDoDamage(
4019  (DAMAGE_TYPE)10)) {
4021  localization->GetString(428)); // Spell failed
4022  pAudioPlayer->PlaySound(SOUND_spellfail0201, 0, 0, -1, 0, 0);
4023  pCastSpell->uSpellID = 0;
4024  continue;
4025  }
4026  pActors[monster_id].pActorBuffs[ACTOR_BUFF_BERSERK].Reset();
4027  pActors[monster_id].pActorBuffs[ACTOR_BUFF_CHARM].Reset();
4028  pActors[monster_id].pActorBuffs[ACTOR_BUFF_ENSLAVED].Apply(
4030  GameTime::FromSeconds(spellduration)),
4031  skill_level, 0, 0, 0);
4032  pSpellSprite.containing_item.Reset();
4033  pSpellSprite.spell_id = pCastSpell->uSpellID;
4034  pSpellSprite.spell_level = spell_level;
4035  pSpellSprite.spell_skill = skill_level;
4036  pSpellSprite.uObjectDescID =
4037  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
4038  pSpellSprite.vPosition.x = pActors[monster_id].vPosition.x;
4039  pSpellSprite.vPosition.y = pActors[monster_id].vPosition.y;
4040  pSpellSprite.vPosition.z = pActors[monster_id].vPosition.z +
4041  pActors[monster_id].uActorHeight;
4042  pSpellSprite.uAttributes = 0;
4043  pSpellSprite.uSectorID =
4044  pIndoor->GetSector(pActors[monster_id].vPosition.x,
4045  pActors[monster_id].vPosition.y,
4046  pSpellSprite.vPosition.z);
4047  pSpellSprite.uSpriteFrameID = 0;
4048  pSpellSprite.spell_caster_pid =
4049  PID(OBJECT_Player, pCastSpell->uPlayerID);
4050  pSpellSprite.spell_target_pid = spell_targeted_at;
4052  target_direction.uDistance;
4053  pSpellSprite.uFacing = target_direction.uYawAngle;
4054  pSpellSprite.uAttributes |= 0x80;
4055  pSpellSprite.uSoundID = pCastSpell->sound_id;
4056  pSpellSprite.Create(0, 0, 0, pCastSpell->uPlayerID + 1);
4057  }
4058  spell_sound_flag = true;
4059  break;
4060  }
4061 
4062  case SPELL_DARK_SACRIFICE: //Жертва
4063  {
4064  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
4065  int hired_npc = 0;
4066  memset(&achieved_awards, 0, 4000);
4067  for (uint npc_id = 0; npc_id < 2;
4068  npc_id++) { // количество нанятых НПС
4069  if (pParty->pHirelings[npc_id].pName != 0)
4070  achieved_awards[hired_npc++] = (AwardType)(npc_id + 1);
4071  }
4072 
4073  if (pCastSpell->uPlayerID_2 != 4 &&
4074  pCastSpell->uPlayerID_2 != 5 ||
4075  achieved_awards[pCastSpell->uPlayerID_2 - 4] <= 0 ||
4076  achieved_awards[pCastSpell->uPlayerID_2 - 4] >= 3) {
4078  localization->GetString(428)); // Spell failed
4080  0, 0);
4081  pCastSpell->uSpellID = 0;
4082  continue;
4083  }
4084  pParty
4085  ->pHirelings[achieved_awards[pCastSpell->uPlayerID_2 - 4] -
4086  1]
4087  .evt_A = 1;
4088  pParty
4089  ->pHirelings[achieved_awards[pCastSpell->uPlayerID_2 - 4] -
4090  1]
4091  .evt_B = 0;
4092  pParty
4093  ->pHirelings[achieved_awards[pCastSpell->uPlayerID_2 - 4] -
4094  1]
4095  .evt_C =
4096  pIconsFrameTable->GetIcon("spell96")->GetAnimLength();
4097  for (uint pl_id = 0; pl_id < 4; pl_id++) {
4098  pParty->pPlayers[pl_id].sHealth =
4099  pParty->pPlayers[pl_id].GetMaxHealth();
4100  pParty->pPlayers[pl_id].sMana =
4101  pParty->pPlayers[pl_id].GetMaxMana();
4102  }
4103  v613 = &pOutdoor->ddm;
4105  v613 = &pIndoor->dlv;
4106  v613->uReputation += 15;
4107  if (v613->uReputation > 10000) v613->uReputation = 10000;
4108  spell_sound_flag = true;
4109  break;
4110  }
4111  case SPELL_DARK_PAIN_REFLECTION: //Отражение боли
4112  {
4113  switch (skill_level) {
4114  case 1:
4115  spellduration = 300 * (spell_level + 12);
4116  break;
4117  case 2:
4118  spellduration = 300 * (spell_level + 12);
4119  break;
4120  case 3:
4121  spellduration = 300 * (spell_level + 12);
4122  break;
4123  case 4:
4124  spellduration = 900 * (spell_level + 4);
4125  break;
4126  default:
4127  assert(false);
4128  }
4129  amount = spell_level + 5;
4130  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
4131  if (skill_level != 3 && skill_level != 4) {
4133  pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
4134  pParty->pPlayers[pCastSpell->uPlayerID_2]
4135  .pPlayerBuffs[PLAYER_BUFF_PAIN_REFLECTION]
4136  .Apply(GameTime(pParty->GetPlayingTime() +
4137  GameTime::FromSeconds(spellduration)),
4138  skill_level, amount, 0, 0);
4139  spell_sound_flag = true;
4140  break;
4141  }
4142  for (uint pl_id = 0; pl_id < 4; pl_id++) {
4144  pCastSpell->uSpellID, pl_id);
4145  pParty->pPlayers[pl_id]
4146  .pPlayerBuffs[PLAYER_BUFF_PAIN_REFLECTION]
4147  .Apply(GameTime(pParty->GetPlayingTime() +
4148  GameTime::FromSeconds(spellduration)),
4149  skill_level, amount, 0, 0);
4150  }
4151  spell_sound_flag = true;
4152  break;
4153  }
4154  case SPELL_DARK_SOULDRINKER: //Испить душу
4155  {
4156  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
4157 
4158  int mon_num = render->GetActorsInViewport(
4160  v707.x = 0;
4161  v707.y = 0;
4162  v707.z = 0;
4163  pSpellSprite.containing_item.Reset();
4164  pSpellSprite.spell_id = pCastSpell->uSpellID;
4165  pSpellSprite.spell_level = spell_level;
4166  pSpellSprite.spell_skill = skill_level;
4167  pSpellSprite.uObjectDescID =
4168  pObjectList->ObjectIDByItemID(pSpellSprite.uType);
4169  pSpellSprite.uAttributes = 0;
4170  pSpellSprite.uSectorID = 0;
4171  pSpellSprite.uSpriteFrameID = 0;
4172  pSpellSprite.field_60_distance_related_prolly_lod = 0;
4173  pSpellSprite.uFacing = 0;
4174  pSpellSprite.spell_caster_pid =
4175  PID(OBJECT_Player, pCastSpell->uPlayerID);
4176  pSpellSprite.uSoundID = (short)pCastSpell->sound_id;
4177  amount = 0;
4178  if (mon_num > 0) {
4179  amount = (mon_num * (7 * spell_level + 25));
4180  for (uint monster_id = 0; monster_id < mon_num;
4181  monster_id++) {
4182  pSpellSprite.vPosition.x =
4184  .vPosition.x;
4185  pSpellSprite.vPosition.y =
4187  .vPosition.y;
4188  pSpellSprite.vPosition.z =
4190  .vPosition.z -
4192  [monster_id]]
4193  .uActorHeight *
4194  -0.8);
4195  pSpellSprite.spell_target_pid =
4196  PID(OBJECT_Actor,
4197  _50BF30_actors_in_viewport_ids[monster_id]);
4199  PID(OBJECT_Item, pSpellSprite.Create(0, 0, 0, 0)),
4200  _50BF30_actors_in_viewport_ids[monster_id], &v707);
4201  }
4202  }
4203  int pl_num = 0;
4204  int pl_array[4];
4205  for (uint pl_id = 1; pl_id <= 4; ++pl_id) {
4206  if (!pPlayers[pl_id]
4207  ->conditions_times[Condition_Sleep]
4208  .Valid() &&
4209  !pPlayers[pl_id]
4210  ->conditions_times[Condition_Paralyzed]
4211  .Valid() &&
4212  !pPlayers[pl_id]
4213  ->conditions_times[Condition_Unconcious]
4214  .Valid() &&
4215  !pPlayers[pl_id]
4216  ->conditions_times[Condition_Dead]
4217  .Valid() &&
4218  !pPlayers[pl_id]
4219  ->conditions_times[Condition_Pertified]
4220  .Valid() &&
4221  !pPlayers[pl_id]
4222  ->conditions_times[Condition_Eradicated]
4223  .Valid()) {
4224  pl_array[pl_num++] = pl_id;
4225  }
4226  }
4227  for (uint j = 0; j < pl_num; j++) {
4228  pPlayers[pl_array[j]]->sHealth +=
4229  (signed __int64)((double)(signed int)amount /
4230  (double)pl_num);
4231  if (pPlayers[pl_array[j]]->sHealth >
4232  pPlayers[pl_array[j]]->GetMaxHealth())
4233  pPlayers[pl_array[j]]->sHealth =
4234  pPlayers[pl_array[j]]->GetMaxHealth();
4236  pCastSpell->uSpellID, pl_array[j]);
4237  }
4240  spell_sound_flag = true;
4241  break;
4242  }
4243 
4244  case SPELL_DARK_ARMAGEDDON: //Армагеддон
4245  {
4248  499)); // Can't cast Armageddon indoors!
4250  0, 0);
4251  pCastSpell->uSpellID = 0;
4252  continue;
4253  }
4254  if (skill_level == 4)
4255  amount = 4;
4256  else
4257  amount = 3;
4258  if (pPlayer->uNumArmageddonCasts >= amount ||
4259  pParty->armageddon_timer > 0) {
4261  localization->GetString(428)); // Spell failed
4263  0, 0);
4264  pCastSpell->uSpellID = 0;
4265  continue;
4266  }
4267  if (!pPlayer->CanCastSpell(uRequiredMana)) break;
4268  pParty->armageddon_timer = 256;
4269  pParty->armageddonDamage = spell_level;
4270  ++pPlayer->uNumArmageddonCasts;
4271  if (pParty->bTurnBasedModeOn) {
4273  }
4274  for (uint i = 0; i < 50; i++) {
4275  v642 = rand() % 4096 - 2048;
4276  v643 = rand();
4277  bool bOnWater = false;
4279  v642 + pParty->vPosition.x,
4280  pParty->vPosition.y + (v643 % 4096 - 2048), &bOnWater, 0);
4283  v642 + pParty->vPosition.x,
4284  pParty->vPosition.y + (v643 % 4096 - 2048), v732 + 16,
4285  rand() % 500 + 500, 1, 0, 0, 0);
4286  }
4287  spell_sound_flag = true;
4288  break;
4289  }
4290  default:
4291  break;
4292  }
4293 
4294  if (~pCastSpell->uFlags & ON_CAST_NoRecoverySpell) {
4295  if (sRecoveryTime < 0) sRecoveryTime = 0;
4296 
4297  pPlayer =
4298  &pParty
4299  ->pPlayers[pCastSpell->uPlayerID]; // reset to player who
4300  // actually cast spell
4301 
4302  if (pParty->bTurnBasedModeOn) {
4303  // v645 = sRecoveryTime;
4305  sRecoveryTime;
4306 
4307  pPlayer->SetRecoveryTime(sRecoveryTime);
4308 
4310  } else {
4312  (double)sRecoveryTime * 2.133333333333333));
4313  }
4314  pPlayer->PlaySound(SPEECH_49, 0);
4315  }
4316  if (spell_sound_flag) {
4317  // pAudioPlayer->PlaySound((SoundID)word_4EE088_sound_ids[pCastSpell->uSpellID],
4318  // 0, 0, -1, 0, pCastSpell->sound_id, 0, 0);
4319  pAudioPlayer->PlaySpellSound(pCastSpell->uSpellID, 0);
4320  }
4321 
4322  pCastSpell->uSpellID = 0;
4323  // spell_level = spell_level;
4324  continue;
4325  }
4326 }
4327 
4328 //----- (00427DA0) --------------------------------------------------------
4329 size_t PushCastSpellInfo(uint16_t uSpellID, uint16_t uPlayerID,
4330  __int16 skill_level, uint16_t uFlags,
4331  int spell_sound_id) {
4332  // uFlags: ON_CAST_*
4333  for (size_t i = 0; i < CastSpellInfoCount; i++) {
4334  if (!pCastSpellInfo[i].uSpellID) {
4335  pCastSpellInfo[i].uSpellID = uSpellID;
4336  pCastSpellInfo[i].uPlayerID = uPlayerID;
4337  if (uFlags & 0x10) pCastSpellInfo[i].uPlayerID_2 = uPlayerID;
4338  pCastSpellInfo[i].field_6 = 0;
4339  pCastSpellInfo[i].spell_target_pid = 0;
4340  pCastSpellInfo[i].uFlags = uFlags;
4341  pCastSpellInfo[i].forced_spell_skill_level = skill_level;
4342  pCastSpellInfo[i].sound_id = spell_sound_id;
4343  return i;
4344  }
4345  }
4346  return -1;
4347 }
4348 
4349 //----- (00427D48) --------------------------------------------------------
4350 void CastSpellInfoHelpers::Cancel_Spell_Cast_In_Progress() { // reset failed/cancelled spell
4351  for (size_t i = 0; i < CastSpellInfoCount; i++) {
4352  if (pCastSpellInfo[i].uSpellID &&
4353  pCastSpellInfo[i].uFlags & ON_CAST_CastingInProgress) {
4354  pCastSpellInfo[i].uSpellID = 0;
4355 
4358  pGUIWindow_CastTargetedSpell = nullptr;
4359  }
4360  mouse->SetCursorImage("MICON1");
4363  back_to_game();
4364  }
4365  }
4366 }
4367 
4368 //----- (0042777D) --------------------------------------------------------
4370  unsigned int uPlayerID,
4371  unsigned int a4, __int16 flags,
4372  int a6) {
4373  unsigned __int16 v9; // cx@16
4374  unsigned int v10; // eax@18
4375  unsigned __int8 v11; // sf@18
4376  unsigned __int8 v12; // of@18
4377  unsigned __int16 v13; // cx@21
4378  unsigned int v14; // eax@23
4379 
4380  // if (!pParty->bTurnBasedModeOn
4381  // || (result = pTurnEngine->field_4, pTurnEngine->field_4 != 1) &&
4382  // pTurnEngine->field_4 != 3 )
4383  if (pParty->bTurnBasedModeOn) {
4384  if (pTurnEngine->turn_stage == TE_WAIT ||
4386  return;
4387  }
4388 
4389  // spell_pointed_target = a5;
4390  // v7 = &pParty->pPlayers[uPlayerID];
4391  assert(uPlayerID < 4);
4392  Player *player = &pParty->pPlayers[uPlayerID];
4393  if (!(flags & 0x10)) {
4394  switch (spell) {
4395  case SPELL_SPIRIT_FATE:
4396  case SPELL_BODY_FIRST_AID:
4397  case SPELL_DARK_REANIMATE:
4398  // HIBYTE(spell_pointed_target) = HIBYTE(a5) | 1;
4399  flags |= ON_CAST_MonsterSparkles;
4400  break;
4401 
4402  case SPELL_FIRE_FIRE_AURA:
4406  flags |= ON_CAST_Enchantment;
4407  break;
4408 
4409  case SPELL_FIRE_FIRE_BOLT:
4410  case SPELL_FIRE_FIREBALL:
4411  case SPELL_FIRE_INCINERATE:
4413  case SPELL_AIR_IMPLOSION:
4415  case SPELL_WATER_ICE_BOLT:
4417  case SPELL_WATER_ICE_BLAST:
4418  case SPELL_EARTH_STUN:
4419  case SPELL_EARTH_SLOW:
4421  case SPELL_EARTH_BLADES:
4424  case SPELL_MIND_MIND_BLAST:
4425  case SPELL_MIND_CHARM:
4427  case SPELL_BODY_HARM:
4431  case SPELL_LIGHT_SUNRAY:
4434  case SPELL_DARK_SHARPMETAL:
4436  if (!a6) flags |= ON_CAST_TargetCrosshair;
4437  break;
4438  case SPELL_MIND_TELEPATHY:
4439  case SPELL_MIND_BERSERK:
4440  case SPELL_MIND_ENSLAVE:
4441  case SPELL_LIGHT_PARALYZE:
4443  flags |= ON_CAST_TargetCrosshair;
4444  break;
4445 
4447  flags |= ON_CAST_Telekenesis;
4448  break;
4449 
4450  case SPELL_SPIRIT_BLESS:
4451  if (a4 && ~a4 & 0x01C0) {
4452  flags |= ON_CAST_WholeParty_BigImprovementAnim;
4453  break;
4454  } else if ((player->pActiveSkills[PLAYER_SKILL_SPIRIT] &
4455  0x1C0) == 0) {
4456  flags |= ON_CAST_WholeParty_BigImprovementAnim;
4457  break;
4458  }
4459  break;
4460 
4462  v9 = a4;
4463  if (!a4) v9 = player->pActiveSkills[PLAYER_SKILL_SPIRIT];
4464  // goto LABEL_18;
4465  v10 = SkillToMastery(v9);
4466  v12 = __OFSUB__(v10, 3);
4467  v11 = ((v10 - 3) & 0x80000000u) != 0;
4468  // goto LABEL_24;
4469  if (v11 ^ v12) {
4470  flags |= ON_CAST_WholeParty_BigImprovementAnim;
4471  break;
4472  }
4473  break;
4474 
4476  v9 = a4;
4477  if (!a4) v9 = player->pActiveSkills[PLAYER_SKILL_DARK];
4478  // LABEL_18:
4479  v10 = SkillToMastery(v9);
4480  v12 = __OFSUB__(v10, 3);
4481  v11 = ((v10 - 3) & 0x80000000u) != 0;
4482  // goto LABEL_24;
4483  if (v11 ^ v12) {
4484  flags |= ON_CAST_WholeParty_BigImprovementAnim;
4485  break;
4486  }
4487  break;
4488 
4490  v13 = a4;
4491  if (!a4) v13 = player->pActiveSkills[PLAYER_SKILL_BODY];
4492  v14 = SkillToMastery(v13);
4493  v12 = __OFSUB__(v14, 4);
4494  v11 = ((v14 - 4) & 0x80000000u) != 0;
4495  // LABEL_24:
4496  if (v11 ^ v12) {
4497  flags |= ON_CAST_WholeParty_BigImprovementAnim;
4498  break;
4499  }
4500  break;
4501 
4513  flags |= ON_CAST_WholeParty_BigImprovementAnim;
4514  break;
4515 
4516  case SPELL_DARK_SACRIFICE:
4517  flags |= ON_CAST_DarkSacrifice;
4518  break;
4519  default:
4520  break;
4521  }
4522  }
4523 
4524  // clear previous casts
4525  if (flags & ON_CAST_CastingInProgress) {
4526  for (uint i = 0; i < CastSpellInfoCount; ++i)
4527  if (pCastSpellInfo[i].uFlags & ON_CAST_CastingInProgress) {
4528  pCastSpellInfo[i].uSpellID = 0;
4529  break;
4530  }
4531  }
4532 
4534 
4535  int result = PushCastSpellInfo(spell, uPlayerID, a4, flags, a6);
4536  if (result != -1) {
4537  if (flags & ON_CAST_WholeParty_BigImprovementAnim) {
4538  if (pGUIWindow_CastTargetedSpell) return;
4540  0, 0, window->GetWidth(), window->GetHeight(),
4541  (int)&pCastSpellInfo[result]);
4543  52, 422, 35, 0, 2, 0, UIMSG_CastSpell_Character_Big_Improvement,
4544  0, 49, "");
4546  165, 422, 35, 0, 2, 0,
4549  280, 422, 35, 0, 2, 0,
4552  390, 422, 35, 0, 2, 0,
4555  return;
4556  }
4557  if (flags & ON_CAST_TargetCrosshair) {
4558  if (pGUIWindow_CastTargetedSpell) return;
4559 
4561  0, 0, window->GetWidth(), window->GetHeight(),
4562  (int)&pCastSpellInfo[result]);
4566  "");
4568  return;
4569  }
4570  if (flags & ON_CAST_Telekenesis) {
4571  if (pGUIWindow_CastTargetedSpell) return;
4572 
4574  0, 0, window->GetWidth(), window->GetHeight(),
4575  (int)&pCastSpellInfo[result]);
4579  "");
4581  return;
4582  }
4583  if (flags & ON_CAST_Enchantment) {
4584  if (pGUIWindow_CastTargetedSpell) return;
4585 
4587  pCastSpellInfo[result].GetCastSpellInInventoryWindow();
4591  return;
4592  }
4593  if (flags & ON_CAST_MonsterSparkles) {
4594  if (pGUIWindow_CastTargetedSpell) return;
4596  0, 0, window->GetWidth(), window->GetHeight(),
4597  (int)&pCastSpellInfo[result]);
4599  0x34u, 0x1A6u, 0x23u, 0, 2, 0,
4602  0xA5u, 0x1A6u, 0x23u, 0, 2, 0,
4605  0x118u, 0x1A6u, 0x23u, 0, 2, 0,
4608  0x186u, 0x1A6u, 0x23u, 0, 2, 0,
4614  }
4615  if (flags & ON_CAST_DarkSacrifice && !pGUIWindow_CastTargetedSpell) {
4617  0, 0, window->GetWidth(), window->GetHeight(),
4618  (int)&pCastSpellInfo[result]);
4620  469, 178, ui_btn_npc_left->GetWidth(),
4622  "", {{ui_btn_npc_left}});
4624  626, 178, ui_btn_npc_right->GetWidth(),
4626  "", {{ui_btn_npc_right}});
4628  491, 149, 64, 74, 1, 0, UIMSG_HiredNPC_CastSpell, 4, 0x35u, "");
4630  561, 149, 64, 74, 1, 0, UIMSG_HiredNPC_CastSpell, 5, 0x36u, "");
4631  }
4632  }
4633 }
UIGame.h
uint16_t
unsigned __int16 uint16_t
Definition: SDL_config.h:37
SpriteObject
Definition: SpriteObject.h:189
PARTY_FLAGS_1_FALLING
@ PARTY_FLAGS_1_FALLING
Definition: Party.h:58
MONSTER_SUPERTYPE_UNDEAD
@ MONSTER_SUPERTYPE_UNDEAD
Definition: Monsters.h:70
TE_MOVEMENT
@ TE_MOVEMENT
Definition: TurnEngine.h:22
spell_sprite_mapping
std::array< stru324_spell_id_to_sprite_mapping, 103 > spell_sprite_mapping
Definition: Spells.cpp:35
SPELL_LIGHT_PARALYZE
@ SPELL_LIGHT_PARALYZE
Definition: Spells.h:100
SOUND_spellfail0201
@ SOUND_spellfail0201
Definition: AudioPlayer.h:79
ItemsTable::IsMaterialNonCommon
bool IsMaterialNonCommon(ItemGen *pItem)
Definition: Items.cpp:487
ObjectDesc::uSpeed
int16_t uSpeed
Definition: ObjectList.h:31
Player::SetRecoveryTime
void SetRecoveryTime(signed int sRecoveryTime)
Definition: Player.cpp:2593
IconFrameTable.h
Player
Definition: Player.h:401
SPELL_EARTH_STONESKIN
@ SPELL_EARTH_STONESKIN
Definition: Spells.h:53
PLAYER_SKILL_BLASTER
@ PLAYER_SKILL_BLASTER
Definition: Player.h:178
pCastSpellInfo
std::array< CastSpellInfo, CastSpellInfoCount > pCastSpellInfo
Definition: CastSpellInfo.cpp:43
uNumActors
size_t uNumActors
Definition: Actor.cpp:39
Party::vPosition
Vec3_int_ vPosition
Definition: Party.h:250
Engine_::IocContainer
Definition: IocContainer.h:15
PARTY_BUFF_DAY_OF_GODS
@ PARTY_BUFF_DAY_OF_GODS
Definition: Party.h:73
SPELL_SPIRIT_RESSURECTION
@ SPELL_SPIRIT_RESSURECTION
Definition: Spells.h:71
PARTY_BUFF_SHIELD
@ PARTY_BUFF_SHIELD
Definition: Party.h:85
ITEM_ARTEFACT_ULLYSES
@ ITEM_ARTEFACT_ULLYSES
Definition: Items.h:163
int_get_vector_length
uint32_t int_get_vector_length(int32_t x, int32_t y, int32_t z)
Definition: VectorTypes.cpp:8
PLAYER_BUFF_PAIN_REFLECTION
@ PLAYER_BUFF_PAIN_REFLECTION
Definition: Player.h:24
Condition_Poison_Medium
@ Condition_Poison_Medium
Definition: Conditions.h:16
Player::sAgeModifier
__int16 sAgeModifier
Definition: Player.h:659
Localization::GetString
const char * GetString(unsigned int index) const
Definition: Localization.cpp:13
SPELL_SPIRIT_SHARED_LIFE
@ SPELL_SPIRIT_SHARED_LIFE
Definition: Spells.h:70
pLevelDecorations
std::array< LevelDecoration, 3000 > pLevelDecorations
Definition: Decoration.cpp:8
stru193_math::uIntegerDoublePi
static const unsigned int uIntegerDoublePi
Definition: OurMath.h:90
SPELL_SPIRIT_TURN_UNDEAD
@ SPELL_SPIRIT_TURN_UNDEAD
Definition: Spells.h:64
Party::uFallSpeed
int uFallSpeed
Definition: Party.h:259
Dying
@ Dying
Definition: Actor.h:79
int16_t
signed __int16 int16_t
Definition: SDL_config.h:36
Viewport.h
n
GLdouble n
Definition: SDL_opengl_glext.h:1955
SpriteObject::uFacing
unsigned __int16 uFacing
Definition: SpriteObject.h:220
SPELL_LIGHT_DESTROY_UNDEAD
@ SPELL_LIGHT_DESTROY_UNDEAD
Definition: Spells.h:98
PARTY_FLAGS_1_ALERT_RED
@ PARTY_FLAGS_1_ALERT_RED
Definition: Party.h:59
Player::GetAttackRecoveryTime
int GetAttackRecoveryTime(bool bRangedAttack)
Definition: Player.cpp:2203
LOD.h
Image::GetHeight
unsigned int GetHeight()
Definition: Image.cpp:230
SPELL_101
@ SPELL_101
Definition: Spells.h:122
SPELL_DARK_VAMPIRIC_WEAPON
@ SPELL_DARK_VAMPIRIC_WEAPON
Definition: Spells.h:111
Party::GetPlayingTime
GameTime & GetPlayingTime()
Definition: Party.h:230
ui_btn_npc_right
Image * ui_btn_npc_right
Definition: GUIWindow.cpp:97
SPELL_LIGHT_LIGHT_BOLT
@ SPELL_LIGHT_LIGHT_BOLT
Definition: Spells.h:97
SPELL_DARK_ARMAGEDDON
@ SPELL_DARK_ARMAGEDDON
Definition: Spells.h:118
SPELL_SPIRIT_PRESERVATION
@ SPELL_SPIRIT_PRESERVATION
Definition: Spells.h:66
CastSpellInfo::sound_id
int sound_id
Definition: CastSpellInfo.h:31
Party::uCurrentMinute
unsigned int uCurrentMinute
Definition: Party.h:276
Mouse
Definition: Mouse.h:279
SPELL_MIND_PSYCHIC_SHOCK
@ SPELL_MIND_PSYCHIC_SHOCK
Definition: Spells.h:82
Player::GetActualSkillMastery
int GetActualSkillMastery(PLAYER_SKILL_TYPE uSkillType)
Definition: Player.cpp:3179
SPEECH_49
@ SPEECH_49
Definition: Player.h:95
CastSpellInfo::uFlags
uint16_t uFlags
Definition: CastSpellInfo.h:28
CastSpellInfo
Definition: CastSpellInfo.h:17
OutdoorLocation::pBModels
BSPModelList pBModels
Definition: Outdoor.h:119
pSpriteObjects
std::array< SpriteObject, MAX_SPRITE_OBJECTS > pSpriteObjects
Definition: SpriteObject.cpp:34
SPELL_DARK_PAIN_REFLECTION
@ SPELL_DARK_PAIN_REFLECTION
Definition: Spells.h:115
SpriteObject::field_60_distance_related_prolly_lod
char field_60_distance_related_prolly_lod
Definition: SpriteObject.h:234
PARTY_BUFF_PROTECTION_FROM_MAGIC
@ PARTY_BUFF_PROTECTION_FROM_MAGIC
Definition: Party.h:84
OBJECT_Item
@ OBJECT_Item
Definition: Actor.h:66
SPELL_WATER_POISON_SPRAY
@ SPELL_WATER_POISON_SPRAY
Definition: Spells.h:38
ItemDesc::uEquipType
ITEM_EQUIP_TYPE uEquipType
Definition: Items.h:373
PARTY_BUFF_IMMOLATION
@ PARTY_BUFF_IMMOLATION
Definition: Party.h:81
ItemGen::GetItemEquipType
ITEM_EQUIP_TYPE GetItemEquipType()
Definition: Items.cpp:1504
Party::sRotationX
int sRotationX
Definition: Party.h:252
lloyds_beacon_spell_id
int lloyds_beacon_spell_id
Definition: mm7_data.cpp:513
GUIWindow::CreateButton
GUIButton * CreateButton(int x, int y, int width, int height, int a6, int a7, UIMessageType msg, unsigned int msg_param, uint8_t hotkey, const String &label, const std::vector< Image * > &textures=std::vector< Image * >())
Definition: GUIWindow.cpp:717
pIconsFrameTable
struct IconFrameTable * pIconsFrameTable
Definition: mm7_data.cpp:168
SPELL_LIGHT_HOUR_OF_POWER
@ SPELL_LIGHT_HOUR_OF_POWER
Definition: Spells.h:105
SPEECH_25
@ SPEECH_25
Definition: Player.h:71
OtherOverlayList::_4418B1
int _4418B1(int a2, int a3, int a4, int a5)
Definition: Overlays.cpp:29
Player::uNumDivineInterventionCastsThisDay
char uNumDivineInterventionCastsThisDay
Definition: Player.h:795
UIMSG_CastSpell_Character_Big_Improvement
@ UIMSG_CastSpell_Character_Big_Improvement
Definition: GUIWindow.h:55
SkillToMastery
unsigned int SkillToMastery(unsigned int skill_value)
Definition: Player.cpp:7854
SPELL_AIR_WIZARD_EYE
@ SPELL_AIR_WIZARD_EYE
Definition: Spells.h:25
SPELL_LIGHT_DAY_OF_PROTECTION
@ SPELL_LIGHT_DAY_OF_PROTECTION
Definition: Spells.h:104
SPELL_EARTH_ROCK_BLAST
@ SPELL_EARTH_ROCK_BLAST
Definition: Spells.h:56
SPELL_WATER_WATER_WALK
@ SPELL_WATER_WATER_WALK
Definition: Spells.h:41
SpriteObject::uSectorID
__int16 uSectorID
Definition: SpriteObject.h:223
AudioPlayer::PlaySound
void PlaySound(SoundID eSoundID, int pid, unsigned int uNumRepeats, int x, int y, int a7)
Definition: AudioPlayer.cpp:195
SpriteObject.h
Icon::GetAnimLength
unsigned int GetAnimLength() const
Definition: IconFrameTable.h:20
UIMSG_CastSpell_Character_Small_Improvement
@ UIMSG_CastSpell_Character_Small_Improvement
Definition: GUIWindow.h:121
engine
std::shared_ptr< Engine > engine
Definition: Engine.cpp:130
IndoorLocation::pFaceExtras
struct BLVFaceExtra * pFaceExtras
Definition: Indoor.h:632
SpellFxRenderer::_4A8BFC
int _4A8BFC()
Definition: SpellFxRenderer.cpp:1230
count
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
UIMSG_CastSpell_Shoot_Monster
@ UIMSG_CastSpell_Shoot_Monster
Definition: GUIWindow.h:56
game_viewport_width
unsigned int game_viewport_width
Definition: mm7_data.cpp:194
ITEM_HARDENED
@ ITEM_HARDENED
Definition: Items.h:35
PLAYER_SKILL_EARTH
@ PLAYER_SKILL_EARTH
Definition: Player.h:186
stru193_math::uIntegerHalfPi
static const unsigned int uIntegerHalfPi
Definition: OurMath.h:89
PlayerEquipment::uBow
unsigned int uBow
Definition: Player.h:321
BLVFaceExtra::uEventID
uint16_t uEventID
Definition: Indoor.h:512
stru262_TurnBased::ApplyPlayerAction
void ApplyPlayerAction()
Definition: TurnEngine.cpp:101
SPELL_EARTH_DEADLY_SWARM
@ SPELL_EARTH_DEADLY_SWARM
Definition: Spells.h:52
SPEECH_103
@ SPEECH_103
Definition: Player.h:149
IndoorCameraD3D::GetPickDepth
float GetPickDepth()
Definition: IndoorCameraD3D.cpp:61
SPELL_FIRE_FIRE_SPIKE
@ SPELL_FIRE_FIRE_SPIKE
Definition: Spells.h:19
PLAYER_SKILL_MIND
@ PLAYER_SKILL_MIND
Definition: Player.h:188
UIMSG_CastSpell_Monster_Improvement
@ UIMSG_CastSpell_Monster_Improvement
Definition: GUIWindow.h:120
localization
Localization * localization
Definition: Localization.cpp:11
SPELL_BODY_HARM
@ SPELL_BODY_HARM
Definition: Spells.h:88
PARTY_BUFF_STONE_SKIN
@ PARTY_BUFF_STONE_SKIN
Definition: Party.h:86
game_viewport_x
int game_viewport_x
Definition: mm7_data.cpp:196
Overlays.h
PARTY_BUFF_WATER_WALK
@ PARTY_BUFF_WATER_WALK
Definition: Party.h:89
Party::uCurrentHour
unsigned int uCurrentHour
Definition: Party.h:275
ObjectList::ObjectIDByItemID
unsigned int ObjectIDByItemID(unsigned int uItemID)
Definition: ObjectList.cpp:7
SPELL_AIR_JUMP
@ SPELL_AIR_JUMP
Definition: Spells.h:29
PLAYER_SKILL_BOW
@ PLAYER_SKILL_BOW
Definition: Player.h:176
SPELL_EARTH_PROTECTION_FROM_EARTH
@ SPELL_EARTH_PROTECTION_FROM_EARTH
Definition: Spells.h:51
int64_t
__int64 int64_t
Definition: alext.h:31
Party::pPlayers
std::array< Player, 4 > pPlayers
Definition: Party.h:310
SPELL_EARTH_DEATH_BLOSSOM
@ SPELL_EARTH_DEATH_BLOSSOM
Definition: Spells.h:58
EQUIP_GOLD
@ EQUIP_GOLD
Definition: Items.h:246
SPELL_EARTH_STONE_TO_FLESH
@ SPELL_EARTH_STONE_TO_FLESH
Definition: Spells.h:55
SPELL_MIND_TELEPATHY
@ SPELL_MIND_TELEPATHY
Definition: Spells.h:76
GUIWindow::Release
virtual void Release()
Definition: GUIWindow.cpp:292
SPELL_FIRE_TORCH_LIGHT
@ SPELL_FIRE_TORCH_LIGHT
Definition: Spells.h:13
PARTY_BUFF_RESIST_AIR
@ PARTY_BUFF_RESIST_AIR
Definition: Party.h:71
CastSpellInfo::uPlayerID
uint16_t uPlayerID
Definition: CastSpellInfo.h:25
SpriteObject::uType
SPRITE_OBJECT_TYPE uType
Definition: SpriteObject.h:215
ACTOR_BUFF_SLOWED
@ ACTOR_BUFF_SLOWED
Definition: Actor.h:45
SPELL_MIND_MIND_BLAST
@ SPELL_MIND_MIND_BLAST
Definition: Spells.h:74
Party::sub_421B2C_PlaceInInventory_or_DropPickedItem
void sub_421B2C_PlaceInInventory_or_DropPickedItem()
Definition: Party.cpp:1048
SpellFxRenderer.h
SPELL_FIRE_PROTECTION_FROM_FIRE
@ SPELL_FIRE_PROTECTION_FROM_FIRE
Definition: Spells.h:15
OBJECT_Decoration
@ OBJECT_Decoration
Definition: Actor.h:69
UIMSG_CastSpell_Telekinesis
@ UIMSG_CastSpell_Telekinesis
Definition: GUIWindow.h:157
SPELL_WATER_TOWN_PORTAL
@ SPELL_WATER_TOWN_PORTAL
Definition: Spells.h:45
lloyds_beacon_sound_id
int lloyds_beacon_sound_id
Definition: mm7_data.cpp:514
SPELL_MIND_PROTECTION_FROM_MIND
@ SPELL_MIND_PROTECTION_FROM_MIND
Definition: Spells.h:75
lloyds_beacon_spell_level
__int64 lloyds_beacon_spell_level
Definition: mm7_data.cpp:518
SPELL_DARK_SHARPMETAL
@ SPELL_DARK_SHARPMETAL
Definition: Spells.h:113
SPELL_WATER_ICE_BOLT
@ SPELL_WATER_ICE_BOLT
Definition: Spells.h:40
SPELL_FIRE_METEOR_SHOWER
@ SPELL_FIRE_METEOR_SHOWER
Definition: Spells.h:21
ItemGen::Reset
void Reset()
Definition: Items.cpp:133
PARTY_BUFF_RESIST_MIND
@ PARTY_BUFF_RESIST_MIND
Definition: Party.h:83
SPELL_TYPE
SPELL_TYPE
Definition: Spells.h:10
SPRITE_SPELL_EARTH_ROCK_BLAST
@ SPRITE_SPELL_EARTH_ROCK_BLAST
Definition: SpriteObject.h:100
Player::pActiveSkills
std::array< unsigned __int16, 37 > pActiveSkills
Definition: Player.h:711
Condition_Paralyzed
@ Condition_Paralyzed
Definition: Conditions.h:20
pPlayers
NZIArray< struct Player *, 5 > pPlayers
Definition: Player.cpp:46
TurnEngine.h
SpriteObject::uSpriteFrameID
unsigned __int16 uSpriteFrameID
Definition: SpriteObject.h:224
game_viewport_height
unsigned int game_viewport_height
Definition: mm7_data.cpp:195
SPELL_AIR_PROTECTION_FROM_AIR
@ SPELL_AIR_PROTECTION_FROM_AIR
Definition: Spells.h:27
PLAYER_SKILL_FIRE
@ PLAYER_SKILL_FIRE
Definition: Player.h:183
Actor::AI_Stand
static void AI_Stand(unsigned int uActorID, unsigned int object_to_face_pid, unsigned int uActionLength, struct AIDirection *a4)
Definition: Actor.cpp:1109
pIndoor
IndoorLocation * pIndoor
Definition: Indoor.cpp:49
PARTY_BUFF_WIZARD_EYE
@ PARTY_BUFF_WIZARD_EYE
Definition: Party.h:90
Condition_Insane
@ Condition_Insane
Definition: Conditions.h:13
Engine.h
ItemGen::uEnchantmentType
int uEnchantmentType
Definition: Items.h:327
SPELL_MIND_ENSLAVE
@ SPELL_MIND_ENSLAVE
Definition: Spells.h:83
ACTOR_BUFF_AFRAID
@ ACTOR_BUFF_AFRAID
Definition: Actor.h:42
PARTY_BUFF_TORCHLIGHT
@ PARTY_BUFF_TORCHLIGHT
Definition: Party.h:87
pTurnEngine
struct stru262_TurnBased * pTurnEngine
Definition: TurnEngine.cpp:21
ACTOR_BUFF_FATE
@ ACTOR_BUFF_FATE
Definition: Actor.h:49
Dead
@ Dead
Definition: Actor.h:80
result
GLuint64EXT * result
Definition: SDL_opengl_glext.h:9435
SpriteObject::uObjectDescID
unsigned __int16 uObjectDescID
Definition: SpriteObject.h:217
SPELL_FIRE_FIRE_BOLT
@ SPELL_FIRE_FIRE_BOLT
Definition: Spells.h:14
AIDirection
Definition: Actor.h:126
SPRITE_SPELL_MIND_MASS_FEAR_1
@ SPRITE_SPELL_MIND_MASS_FEAR_1
Definition: SpriteObject.h:130
SPRITE_SPELL_LIGHT_PRISMATIC_LIGHT_1
@ SPRITE_SPELL_LIGHT_PRISMATIC_LIGHT_1
Definition: SpriteObject.h:159
Party::pPartyBuffs
std::array< SpellBuff, 20 > pPartyBuffs
Definition: Party.h:309
_42777D_CastSpell_UseWand_ShootArrow
void _42777D_CastSpell_UseWand_ShootArrow(SPELL_TYPE spell, unsigned int uPlayerID, unsigned int a4, __int16 flags, int a6)
Definition: CastSpellInfo.cpp:4369
OBJECT_Actor
@ OBJECT_Actor
Definition: Actor.h:67
PLAYER_SKILL_LIGHT
@ PLAYER_SKILL_LIGHT
Definition: Player.h:190
Events.h
Party::uPartyHeight
unsigned int uPartyHeight
Definition: Party.h:237
SPELL_FIRE_INFERNO
@ SPELL_FIRE_INFERNO
Definition: Spells.h:22
sub_44FA4C_spawn_light_elemental
int sub_44FA4C_spawn_light_elemental(int spell_power, int caster_skill_level, int duration_game_seconds)
Definition: Actor.cpp:4969
Actor.h
game_viewport_y
int game_viewport_y
Definition: mm7_data.cpp:197
Party::AddItemToParty
bool AddItemToParty(ItemGen *pItem)
Definition: Party.cpp:1096
SPELL_EARTH_TELEKINESIS
@ SPELL_EARTH_TELEKINESIS
Definition: Spells.h:57
pItemsTable
struct ItemsTable * pItemsTable
Definition: Items.cpp:37
Party::PartyFindsGold
void PartyFindsGold(unsigned int uNumGold, int _1_dont_share_with_followers___2_the_same_but_without_a_message__else_normal)
Definition: Party.cpp:976
MonsterInfo::HostilityRadius
HostilityRadius
Definition: Monsters.h:110
Localization.h
ItemGen::uAttributes
unsigned int uAttributes
Definition: Items.h:349
GameUI_StatusBar_Update
void GameUI_StatusBar_Update(bool force_hide)
Definition: Engine.cpp:1507
ItemGen::special_enchantment
ITEM_ENCHANTMENT special_enchantment
Definition: Items.h:330
IconFrameTable::GetIcon
Icon * GetIcon(unsigned int idx)
Definition: IconFrameTable.cpp:17
Image::GetWidth
unsigned int GetWidth()
Definition: Image.cpp:217
ItemGen::uMaxCharges
char uMaxCharges
Definition: Items.h:351
AIDirection::uYawAngle
unsigned int uYawAngle
Definition: Actor.h:130
SPELL_BODY_FIRST_AID
@ SPELL_BODY_FIRST_AID
Definition: Spells.h:86
SPELL_DARK_SOULDRINKER
@ SPELL_DARK_SOULDRINKER
Definition: Spells.h:119
Condition_Fear
@ Condition_Fear
Definition: Conditions.h:11
PARTY_FLAGS_1_ALERT_YELLOW
@ PARTY_FLAGS_1_ALERT_YELLOW
Definition: Party.h:60
SPRITE_SPELL_EARTH_DEATH_BLOSSOM
@ SPRITE_SPELL_EARTH_DEATH_BLOSSOM
Definition: SpriteObject.h:103
SPELL_LASER_PROJECTILE
@ SPELL_LASER_PROJECTILE
Definition: Spells.h:123
GUIButton.h
SPELL_AIR_FEATHER_FALL
@ SPELL_AIR_FEATHER_FALL
Definition: Spells.h:26
DAMAGE_TYPE
DAMAGE_TYPE
Definition: Items.h:10
SpriteObject::vPosition
struct Vec3_int_ vPosition
Definition: SpriteObject.h:218
activeLevelDecoration
LevelDecoration * activeLevelDecoration
Definition: Decoration.cpp:10
pParty
Party * pParty
Definition: Party.cpp:30
object
GLuint object
Definition: SDL_opengl_glext.h:6060
SPELL_BODY_CURE_POISON
@ SPELL_BODY_CURE_POISON
Definition: Spells.h:90
SPELL_WATER_ICE_BLAST
@ SPELL_WATER_ICE_BLAST
Definition: Spells.h:46
PLAYER_SKILL_SPIRIT
@ PLAYER_SKILL_SPIRIT
Definition: Player.h:187
ACTOR_BUFF_CHARM
@ ACTOR_BUFF_CHARM
Definition: Actor.h:39
_50C9D0_AfterEnchClickEventId
int _50C9D0_AfterEnchClickEventId
Definition: mm7_data.cpp:580
EQUIP_ARMOUR
@ EQUIP_ARMOUR
Definition: Items.h:230
ACTOR_BUFF_PARALYZED
@ ACTOR_BUFF_PARALYZED
Definition: Actor.h:44
CastSpellInfoCount
const size_t CastSpellInfoCount
Definition: CastSpellInfo.cpp:42
SPELL_DARK_CONTROL_UNDEAD
@ SPELL_DARK_CONTROL_UNDEAD
Definition: Spells.h:114
spell_fx_renderer
static SpellFxRenderer * spell_fx_renderer
Definition: CastSpellInfo.cpp:40
ACTOR_BUFF_MASS_DISTORTION
@ ACTOR_BUFF_MASS_DISTORTION
Definition: Actor.h:48
ItemGen::GetDisplayName
String GetDisplayName()
Definition: Items.cpp:610
PARTY_BUFF_RESIST_WATER
@ PARTY_BUFF_RESIST_WATER
Definition: Party.h:88
OBJECT_BModel
@ OBJECT_BModel
Definition: Actor.h:70
ITEM_TEMP_BONUS
@ ITEM_TEMP_BONUS
Definition: Items.h:28
EQUIP_SINGLE_HANDED
@ EQUIP_SINGLE_HANDED
Definition: Items.h:227
GameTime::FromMinutes
static GameTime FromMinutes(int minutes)
Definition: Time.h:86
AudioPlayer::PlaySpellSound
void PlaySpellSound(unsigned int spell, unsigned int pid)
Definition: AudioPlayer.cpp:476
Player::IsCursed
bool IsCursed() const
Definition: Player.cpp:7428
viewparams
struct ViewingParams * viewparams
Definition: mm7_data.cpp:22
SPELL_MIND_CHARM
@ SPELL_MIND_CHARM
Definition: Spells.h:77
Disabled
@ Disabled
Definition: Actor.h:94
PLAYER_SKILL_TYPE
PLAYER_SKILL_TYPE
Definition: Player.h:170
SPELL_WATER_AWAKEN
@ SPELL_WATER_AWAKEN
Definition: Spells.h:37
Condition_Dead
@ Condition_Dead
Definition: Conditions.h:22
stru123.h
SPELL_FIRE_IMMOLATION
@ SPELL_FIRE_IMMOLATION
Definition: Spells.h:20
CastSpellInfo::uPlayerID_2
uint16_t uPlayerID_2
Definition: CastSpellInfo.h:26
UIMSG_OnCastLloydsBeacon
@ UIMSG_OnCastLloydsBeacon
Definition: GUIWindow.h:144
Player::WearsItem
bool WearsItem(int item_id, ITEM_EQUIP_TYPE equip_type)
Definition: Player.cpp:1603
PARTY_BUFF_HASTE
@ PARTY_BUFF_HASTE
Definition: Party.h:79
ItemGen::uItemID
int uItemID
Definition: Items.h:326
PARTY_BUFF_FEATHER_FALL
@ PARTY_BUFF_FEATHER_FALL
Definition: Party.h:76
pSpellDatas
std::array< SpellData, 100 > pSpellDatas
Definition: Spells.cpp:170
Actor::Resurrect
static void Resurrect(unsigned int uActorID)
Definition: Actor.cpp:1890
SPELL_LIGHT_DISPEL_MAGIC
@ SPELL_LIGHT_DISPEL_MAGIC
Definition: Spells.h:99
stru123::_decor_events
std::array< unsigned char, 125 > _decor_events
Definition: stru123.h:8
EQUIP_BOW
@ EQUIP_BOW
Definition: Items.h:229
PLAYER_BUFF_BLESS
@ PLAYER_BUFF_BLESS
Definition: Player.h:15
PLAYER_SKILL_AIR
@ PLAYER_SKILL_AIR
Definition: Player.h:184
SPELL_BODY_REGENERATION
@ SPELL_BODY_REGENERATION
Definition: Spells.h:89
mouse
static Mouse * mouse
Definition: CastSpellInfo.cpp:39
SpriteObject::spell_id
int spell_id
Definition: SpriteObject.h:228
Engine_::IocContainer::ResolveMouse
static Mouse * ResolveMouse()
Definition: IocContainer.cpp:88
SPELL_FIRE_FIRE_AURA
@ SPELL_FIRE_FIRE_AURA
Definition: Spells.h:16
SPELL_BODY_HAMMERHANDS
@ SPELL_BODY_HAMMERHANDS
Definition: Spells.h:91
IndoorLocation::dlv
struct DDM_DLV_Header dlv
Definition: Indoor.h:648
ItemGen::expirte_time
GameTime expirte_time
Definition: Items.h:354
Actor::GetDirectionInfo
static void GetDirectionInfo(unsigned int uObj1ID, unsigned int uObj2ID, struct AIDirection *pOut, int a4)
Definition: Actor.cpp:890
fixpoint_mul
__int64 fixpoint_mul(int a1, int a2)
Definition: OurMath.cpp:138
pActors
std::array< Actor, 500 > pActors
Definition: Actor.cpp:38
Mouse::uPointingObjectID
unsigned int uPointingObjectID
Definition: Mouse.h:315
ItemDesc
Definition: Items.h:360
Condition_Zombie
@ Condition_Zombie
Definition: Conditions.h:25
achieved_awards
std::array< AwardType, 1000 > achieved_awards
Definition: mm7_data.cpp:27
Party.h
SPELL_LIGHT_SUMMON_ELEMENTAL
@ SPELL_LIGHT_SUMMON_ELEMENTAL
Definition: Spells.h:101
SPEECH_43
@ SPEECH_43
Definition: Player.h:89
back_to_game
void back_to_game()
Definition: Engine.cpp:1609
SPELL_EARTH_SLOW
@ SPELL_EARTH_SLOW
Definition: Spells.h:50
window
EGLSurface EGLNativeWindowType * window
Definition: SDL_egl.h:1580
PARTY_BUFF_HEROISM
@ PARTY_BUFF_HEROISM
Definition: Party.h:80
SPELL_EARTH_STUN
@ SPELL_EARTH_STUN
Definition: Spells.h:49
GameUI_ReloadPlayerPortraits
void GameUI_ReloadPlayerPortraits(int player_id, int face_id)
Definition: UIGame.cpp:199
SPELL_AIR_SHIELD
@ SPELL_AIR_SHIELD
Definition: Spells.h:30
Party::uFlags
unsigned int uFlags
Definition: Party.h:313
PLAYER_SKILL_WATER
@ PLAYER_SKILL_WATER
Definition: Player.h:185
pBtn_NPCLeft
GUIButton * pBtn_NPCLeft
Definition: GUIButton.cpp:51
SPELL_DARK_SACRIFICE
@ SPELL_DARK_SACRIFICE
Definition: Spells.h:116
DDM_DLV_Header::uReputation
int uReputation
Definition: Indoor.h:96
SPELL_BODY_POWER_CURE
@ SPELL_BODY_POWER_CURE
Definition: Spells.h:95
Player::sMana
int sMana
Definition: Player.h:767
stru_50C198
stru319 stru_50C198
Definition: Actor.cpp:41
_506348_current_lloyd_playerid
int _506348_current_lloyd_playerid
Definition: mm7_data.cpp:517
l
uint64_t l
Definition: intreadwrite.h:1
CastSpellInfo::forced_spell_skill_level
__int16 forced_spell_skill_level
Definition: CastSpellInfo.h:29
LEVEL_Outdoor
@ LEVEL_Outdoor
Definition: Indoor.h:287
DDM_DLV_Header
Definition: Indoor.h:82
Timer::Pause
void Pause()
Definition: Time.cpp:19
_50BF30_actors_in_viewport_ids
std::array< int, 100 > _50BF30_actors_in_viewport_ids
Definition: mm7_data.cpp:567
OpenedTelekinesis
bool OpenedTelekinesis
Definition: mm7_data.cpp:561
_50C9A0_IsEnchantingInProgress
bool _50C9A0_IsEnchantingInProgress
Definition: mm7_data.cpp:578
ui_btn_npc_left
Image * ui_btn_npc_left
Definition: GUIWindow.cpp:98
SPELL_MIND_MASS_FEAR
@ SPELL_MIND_MASS_FEAR
Definition: Spells.h:80
MonsterInfo::Hostility_Long
@ Hostility_Long
Definition: Monsters.h:115
ItemsTable::pSpecialEnchantments_count
unsigned int pSpecialEnchantments_count
Definition: Items.h:481
TE_WAIT
@ TE_WAIT
Definition: TurnEngine.h:20
AIDirection::uDistance
unsigned int uDistance
Definition: Actor.h:128
ITEM_ENCHANTMENT
ITEM_ENCHANTMENT
Definition: Items.h:38
pCurrentMapName
String pCurrentMapName
Definition: mm7_data.cpp:712
Removed
@ Removed
Definition: Actor.h:86
SPRITE_SPELL_DARK_REANIMATE_1
@ SPRITE_SPELL_DARK_REANIMATE_1
Definition: SpriteObject.h:167
SPELL_MIND_CURE_INSANITY
@ SPELL_MIND_CURE_INSANITY
Definition: Spells.h:81
Condition_Poison_Severe
@ Condition_Poison_Severe
Definition: Conditions.h:18
GetTerrainHeightsAroundParty2
int GetTerrainHeightsAroundParty2(int a1, int a2, bool *pIsOnWater, int bFloatAboveWater)
Definition: Outdoor.cpp:4044
EQUIP_AMULET
@ EQUIP_AMULET
Definition: Items.h:238
ITEM_AURA_EFFECT_RED
@ ITEM_AURA_EFFECT_RED
Definition: Items.h:29
stru319::FindClosestActor
int FindClosestActor(int a2, int a3, int a4)
Definition: Actor.cpp:3876
AIDirection::uPitchAngle
signed int uPitchAngle
Definition: Actor.h:131
ITEM_ENCHANTMENT_VAMPIRIC
@ ITEM_ENCHANTMENT_VAMPIRIC
Definition: Items.h:53
CastSpellInfo::uSpellID
uint16_t uSpellID
Definition: CastSpellInfo.h:24
Player::pInventoryItemList
ItemGen pInventoryItemList[126]
Definition: Player.h:727
PlayerEquipment::uMainHand
unsigned int uMainHand
Definition: Player.h:320
AwardType
AwardType
Definition: Awards.h:15
pMiscTimer
Timer * pMiscTimer
Definition: Time.cpp:7
Party::pTurnBasedPlayerRecoveryTimes
std::array< int, 4 > pTurnBasedPlayerRecoveryTimes
Definition: Party.h:322
SPELL_LIGHT_SUNRAY
@ SPELL_LIGHT_SUNRAY
Definition: Spells.h:106
SpellFxRenderer::RenderAsSprite
bool RenderAsSprite(struct SpriteObject *a2)
Definition: SpellFxRenderer.cpp:671
Outdoor.h
OutdoorLocation::ddm
struct DDM_DLV_Header ddm
Definition: Outdoor.h:131
Condition_Cursed
@ Condition_Cursed
Definition: Conditions.h:8
stru319::_427546
int _427546(int a2)
Definition: Actor.cpp:3862
LEVEL_Indoor
@ LEVEL_Indoor
Definition: Indoor.h:286
town_portal_caster_id
char town_portal_caster_id
Definition: mm7_data.cpp:568
ItemGen::IsBroken
bool IsBroken()
Definition: Items.h:304
SpriteObject::Create
int Create(int yaw, int pitch, int a4, int a5)
Definition: SpriteObject.cpp:56
SpriteObject::containing_item
struct ItemGen containing_item
Definition: SpriteObject.h:227
ItemsTable::pSpecialEnchantments
ItemSpecialEnchantment pSpecialEnchantments[72]
Definition: Items.h:462
SPELL_FIRE_FIREBALL
@ SPELL_FIRE_FIREBALL
Definition: Spells.h:18
EQUIP_TWO_HANDED
@ EQUIP_TWO_HANDED
Definition: Items.h:228
Party::pHirelings
std::array< NPCData, 2 > pHirelings
Definition: Party.h:311
AudioPlayer.h
OBJECT_Player
@ OBJECT_Player
Definition: Actor.h:68
Party::bTurnBasedModeOn
bool bTurnBasedModeOn
Definition: Party.h:305
ItemGen::uNumCharges
int uNumCharges
Definition: Items.h:348
SPELL_SPIRIT_RAISE_DEAD
@ SPELL_SPIRIT_RAISE_DEAD
Definition: Spells.h:69
SPELL_SPIRIT_BLESS
@ SPELL_SPIRIT_BLESS
Definition: Spells.h:62
MonsterStats::BelongsToSupertype
static bool BelongsToSupertype(unsigned int uMonsterInfoID, enum MONSTER_SUPERTYPE eSupertype)
Definition: Monsters.cpp:1200
SpriteObject::uSoundID
unsigned __int16 uSoundID
Definition: SpriteObject.h:221
PARTY_BUFF_INVISIBILITY
@ PARTY_BUFF_INVISIBILITY
Definition: Party.h:82
Party::armageddon_timer
int armageddon_timer
Definition: Party.h:320
UIMSG_HiredNPC_CastSpell
@ UIMSG_HiredNPC_CastSpell
Definition: GUIWindow.h:123
SPELL_BODY_PROTECTION_FROM_BODY
@ SPELL_BODY_PROTECTION_FROM_BODY
Definition: Spells.h:87
uNumSpriteObjects
size_t uNumSpriteObjects
Definition: SpriteObject.cpp:33
PLAYER_BUFF_FATE
@ PLAYER_BUFF_FATE
Definition: Player.h:18
SpellFxRenderer
Definition: SpellFxRenderer.h:97
SPELL_SPIRIT_REMOVE_CURSE
@ SPELL_SPIRIT_REMOVE_CURSE
Definition: Spells.h:65
stru193_math::Atan2
unsigned int Atan2(int x, int y)
Definition: OurMath.cpp:46
CastSpellInfo::spell_target_pid
int spell_target_pid
Definition: CastSpellInfo.h:30
pOtherOverlayList
struct OtherOverlayList * pOtherOverlayList
Definition: Overlays.cpp:19
SPRITE_NULL
@ SPRITE_NULL
Definition: SpriteObject.h:6
PARTY_BUFF_RESIST_EARTH
@ PARTY_BUFF_RESIST_EARTH
Definition: Party.h:75
SPELL_SPIRIT_SPIRIT_LASH
@ SPELL_SPIRIT_SPIRIT_LASH
Definition: Spells.h:68
SPELL_AIR_SPARKS
@ SPELL_AIR_SPARKS
Definition: Spells.h:28
SpriteObject::spell_level
int spell_level
Definition: SpriteObject.h:229
Condition_Weak
@ Condition_Weak
Definition: Conditions.h:9
SPELL_EARTH_MASS_DISTORTION
@ SPELL_EARTH_MASS_DISTORTION
Definition: Spells.h:59
uRequiredMana
unsigned int uRequiredMana
Definition: mm7_data.cpp:516
UIStatusBar.h
UIMSG_OnCastTownPortal
@ UIMSG_OnCastTownPortal
Definition: GUIWindow.h:163
Awards.h
SpriteObject::spell_target_pid
int spell_target_pid
Definition: SpriteObject.h:233
SPELL_BODY_CURE_WEAKNESS
@ SPELL_BODY_CURE_WEAKNESS
Definition: Spells.h:85
SPELL_SPIRIT_FATE
@ SPELL_SPIRIT_FATE
Definition: Spells.h:63
flt_6BE3A4_debug_recmod1
float flt_6BE3A4_debug_recmod1
Definition: mm7_data.cpp:716
SPELL_WATER_ACID_BURST
@ SPELL_WATER_ACID_BURST
Definition: Spells.h:43
SPELL_DARK_DRAGON_BREATH
@ SPELL_DARK_DRAGON_BREATH
Definition: Spells.h:117
uint
unsigned int uint
Definition: MM7.h:4
UIMSG_ScrollNPCPanel
@ UIMSG_ScrollNPCPanel
Definition: GUIWindow.h:155
Condition_Poison_Weak
@ Condition_Poison_Weak
Definition: Conditions.h:14
ITEM_BROKEN
@ ITEM_BROKEN
Definition: Items.h:27
uActiveCharacter
unsigned int uActiveCharacter
Definition: mm7_data.cpp:555
Localization::FormatString
String FormatString(unsigned int index,...) const
Definition: Localization.cpp:17
SPELL_AIR_IMPLOSION
@ SPELL_AIR_IMPLOSION
Definition: Spells.h:33
SPELL_WATER_PROTECTION_FROM_WATER
@ SPELL_WATER_PROTECTION_FROM_WATER
Definition: Spells.h:39
SpriteObject::sub_42F7EB_DropItemAt
static bool sub_42F7EB_DropItemAt(SPRITE_OBJECT_TYPE sprite, int x, int y, int z, int a4, int count, int a7, unsigned __int16 attributes, ItemGen *a9)
Definition: SpriteObject.cpp:937
SPELL_AIR_STARBURST
@ SPELL_AIR_STARBURST
Definition: Spells.h:35
GameUI_StatusBar_OnEvent
void GameUI_StatusBar_OnEvent(const String &str, unsigned int num_seconds)
Definition: UIStatusBar.cpp:33
PLAYER_BUFF_REGENERATION
@ PLAYER_BUFF_REGENERATION
Definition: Player.h:26
ItemsTable::pEnchantments
ItemEnchantment pEnchantments[24]
Definition: Items.h:461
flags
EGLSyncKHR EGLint flags
Definition: SDL_egl.h:898
PARTY_BUFF_FLY
@ PARTY_BUFF_FLY
Definition: Party.h:78
Party::SetHoldingItem
void SetHoldingItem(ItemGen *pItem)
Definition: Party.cpp:150
SPELL_BODY_CURE_DISEASE
@ SPELL_BODY_CURE_DISEASE
Definition: Spells.h:92
Player::PlaySound
void PlaySound(PlayerSpeech speech, int a3)
Definition: Player.cpp:7874
SpriteObject::spell_skill
int spell_skill
Definition: SpriteObject.h:230
SPELL_LIGHT_PRISMATIC_LIGHT
@ SPELL_LIGHT_PRISMATIC_LIGHT
Definition: Spells.h:103
SPELL_EARTH_BLADES
@ SPELL_EARTH_BLADES
Definition: Spells.h:54
stru193_math::Cos
int Cos(int angle)
Definition: OurMath.cpp:28
SPELL_LIGHT_DIVINE_INTERVENTION
@ SPELL_LIGHT_DIVINE_INTERVENTION
Definition: Spells.h:107
Condition_Unconcious
@ Condition_Unconcious
Definition: Conditions.h:21
SPELL_BOW_ARROW
@ SPELL_BOW_ARROW
Definition: Spells.h:121
Decoration.h
stru_5C6E00
struct stru193_math * stru_5C6E00
Definition: mm7_data.cpp:19
ItemEnchantment::to_item
unsigned char to_item[12]
Definition: Items.h:419
SPELL_WATER_LLOYDS_BEACON
@ SPELL_WATER_LLOYDS_BEACON
Definition: Spells.h:47
ViewingParams::bRedrawGameUI
int bRedrawGameUI
Definition: Viewport.h:74
PARTY_BUFF_RESIST_BODY
@ PARTY_BUFF_RESIST_BODY
Definition: Party.h:72
PARTY_BUFF_DETECT_LIFE
@ PARTY_BUFF_DETECT_LIFE
Definition: Party.h:74
SPELL_SPIRIT_DETECT_LIFE
@ SPELL_SPIRIT_DETECT_LIFE
Definition: Spells.h:61
PARTY_BUFF_RESIST_FIRE
@ PARTY_BUFF_RESIST_FIRE
Definition: Party.h:77
OurMath.h
PushCastSpellInfo
size_t PushCastSpellInfo(uint16_t uSpellID, uint16_t uPlayerID, __int16 skill_level, uint16_t uFlags, int spell_sound_id)
Definition: CastSpellInfo.cpp:4329
EventProcessor
void EventProcessor(int uEventID, int targetObj, int canShowMessages, int entry_line)
Definition: Events.cpp:260
Mouse::SetCursorImage
void SetCursorImage(const String &name)
Definition: Mouse.cpp:38
uCurrentlyLoadedLevelType
LEVEL_TYPE uCurrentlyLoadedLevelType
Definition: Indoor.cpp:52
PLAYER_SKILL_DARK
@ PLAYER_SKILL_DARK
Definition: Player.h:191
ItemGen::UpdateTempBonus
void UpdateTempBonus(GameTime time)
Definition: Items.cpp:146
_50C9D8_AfterEnchClickEventTimeout
int _50C9D8_AfterEnchClickEventTimeout
Definition: mm7_data.cpp:582
PLAYER_SKILL_BODY
@ PLAYER_SKILL_BODY
Definition: Player.h:189
IndoorLocation::GetSector
int GetSector(int sX, int sY, int sZ)
Definition: Indoor.cpp:1279
IndoorLocation::pFaces
struct BLVFace * pFaces
Definition: Indoor.h:630
SPELL_MIND_BERSERK
@ SPELL_MIND_BERSERK
Definition: Spells.h:79
SPELL_WATER_ENCHANT_ITEM
@ SPELL_WATER_ENCHANT_ITEM
Definition: Spells.h:44
ObjectList::pObjects
struct ObjectDesc * pObjects
Definition: ObjectList.h:54
SPRITE_SPELL_LIGHT_DISPEL_MAGIC_1
@ SPRITE_SPELL_LIGHT_DISPEL_MAGIC_1
Definition: SpriteObject.h:154
stru193_math::Sin
int Sin(int angle)
Definition: OurMath.cpp:133
SPELL_AIR_LIGHNING_BOLT
@ SPELL_AIR_LIGHNING_BOLT
Definition: Spells.h:31
pAudioPlayer
AudioPlayer * pAudioPlayer
Definition: AudioPlayer.cpp:20
Player::CanCastSpell
bool CanCastSpell(unsigned int uRequiredMana)
Definition: Player.cpp:280
Player::GetActualSkillLevel
int GetActualSkillLevel(PLAYER_SKILL_TYPE uSkillType)
Definition: Player.cpp:3017
Condition_Eradicated
@ Condition_Eradicated
Definition: Conditions.h:24
SpriteObject::OnInteraction
static void OnInteraction(unsigned int uLayingItemID)
Definition: SpriteObject.cpp:872
pBtn_NPCRight
GUIButton * pBtn_NPCRight
Definition: GUIButton.cpp:50
SpellFxRenderer::FadeScreen__like_Turn_Undead_and_mb_Armageddon
void FadeScreen__like_Turn_Undead_and_mb_Armageddon(unsigned int uDiffuseColor, unsigned int uFadeTime)
Definition: SpellFxRenderer.cpp:1222
_50C9D4_AfterEnchClickEventSecondParam
int _50C9D4_AfterEnchClickEventSecondParam
Definition: mm7_data.cpp:581
GUIWindow.h
__OFSUB__
int8 __OFSUB__(T x, U y)
Definition: MM7.h:209
ItemGen
Definition: Items.h:263
ItemGen::GetValue
unsigned int GetValue()
Definition: Items.cpp:588
SPELL_BODY_FLYING_FIST
@ SPELL_BODY_FLYING_FIST
Definition: Spells.h:94
SPELL_MIND_REMOVE_FEAR
@ SPELL_MIND_REMOVE_FEAR
Definition: Spells.h:73
ObjectList.h
pMessageQueue_50CBD0
struct GUIMessageQueue * pMessageQueue_50CBD0
Definition: GUIWindow.cpp:86
SPELL_AIR_INVISIBILITY
@ SPELL_AIR_INVISIBILITY
Definition: Spells.h:32
CastSpellInfoHelpers::Cancel_Spell_Cast_In_Progress
void Cancel_Spell_Cast_In_Progress()
Definition: CastSpellInfo.cpp:4350
sRecoveryTime
signed int sRecoveryTime
Definition: mm7_data.cpp:515
stru_5E4C90_MapPersistVars
stru123 stru_5E4C90_MapPersistVars
Definition: mm7_data.cpp:23
SpellFxRenderer::SetPlayerBuffAnim
void SetPlayerBuffAnim(uint16_t uSpellID, uint16_t uPlayerID)
Definition: SpellFxRenderer.cpp:1103
PLAYER_BUFF_HAMMERHANDS
@ PLAYER_BUFF_HAMMERHANDS
Definition: Player.h:20
SPELL_DARK_TOXIC_CLOUD
@ SPELL_DARK_TOXIC_CLOUD
Definition: Spells.h:110
SPELL_WATER_RECHARGE_ITEM
@ SPELL_WATER_RECHARGE_ITEM
Definition: Spells.h:42
Condition_Pertified
@ Condition_Pertified
Definition: Conditions.h:23
Engine_::IocContainer::ResolveSpellFxRenderer
static SpellFxRenderer * ResolveSpellFxRenderer()
Definition: IocContainer.cpp:74
ItemGen::m_enchantmentStrength
int m_enchantmentStrength
Definition: Items.h:328
pOutdoor
OutdoorLocation * pOutdoor
Definition: Outdoor.cpp:48
SPELL_DARK_REANIMATE
@ SPELL_DARK_REANIMATE
Definition: Spells.h:109
_50C9A8_item_enchantment_timer
int _50C9A8_item_enchantment_timer
Definition: mm7_data.cpp:579
OnCastTargetedSpell
Definition: GUIWindow.h:598
ACTOR_BUFF_BERSERK
@ ACTOR_BUFF_BERSERK
Definition: Actor.h:47
SpriteObject::uAttributes
unsigned __int16 uAttributes
Definition: SpriteObject.h:222
some_active_character
int some_active_character
Definition: mm7_data.cpp:569
Player::uNumArmageddonCasts
char uNumArmageddonCasts
Definition: Player.h:796
Actor::DamageMonsterFromParty
static void DamageMonsterFromParty(int a1, unsigned int uActorID_Monster, struct Vec3_int_ *pVelocity)
Definition: Actor.cpp:3379
pIndoorCameraD3D
IndoorCameraD3D * pIndoorCameraD3D
Definition: IndoorCameraD3D.cpp:21
SPRITE_SPELL_SPIRIT_TURN_UNDEAD_1
@ SPRITE_SPELL_SPIRIT_TURN_UNDEAD_1
Definition: SpriteObject.h:112
SPELL_DARK_SHRINKING_RAY
@ SPELL_DARK_SHRINKING_RAY
Definition: Spells.h:112
pGUIWindow_CastTargetedSpell
GUIWindow * pGUIWindow_CastTargetedSpell
Definition: GUIWindow.cpp:56
StringPrintf
String StringPrintf(const char *fmt,...)
Definition: Strings.cpp:9
stru262_TurnBased::pending_actions
int pending_actions
Definition: TurnEngine.h:81
SPELL_FIRE_HASTE
@ SPELL_FIRE_HASTE
Definition: Spells.h:17
SPELL_AIR_FLY
@ SPELL_AIR_FLY
Definition: Spells.h:34
SPELL_MIND_CURE_PARALYSIS
@ SPELL_MIND_CURE_PARALYSIS
Definition: Spells.h:78
Player::pEquipment
PlayerEquipment pEquipment
Definition: Player.h:769
SpellFxRenderer::_4A7E89_sparkles_on_actor_after_it_casts_buff
void _4A7E89_sparkles_on_actor_after_it_casts_buff(struct Actor *pActor, unsigned int uDiffuse)
Definition: SpellFxRenderer.cpp:576
Party::sRotationY
int sRotationY
Definition: Party.h:251
PLAYER_BUFF_PRESERVATION
@ PLAYER_BUFF_PRESERVATION
Definition: Player.h:25
stru262_TurnBased::turn_stage
int turn_stage
Definition: TurnEngine.h:75
Timer::uTotalGameTimeElapsed
unsigned int uTotalGameTimeElapsed
Definition: Time.h:135
pEventTimer
Timer * pEventTimer
Definition: Time.cpp:8
GameTime
Definition: Time.h:14
SPELL_FIRE_INCINERATE
@ SPELL_FIRE_INCINERATE
Definition: Spells.h:23
pObjectList
struct ObjectList * pObjectList
Definition: ObjectList.cpp:5
SPELL_SPIRIT_HEROISM
@ SPELL_SPIRIT_HEROISM
Definition: Spells.h:67
Party::Invisible
bool Invisible()
Definition: Party.h:217
GameTime::FromSeconds
static GameTime FromSeconds(int seconds)
Definition: Time.h:83
ItemsTable::pItems
NZIArray< ItemDesc, 800 > pItems
Definition: Items.h:460
Mouse.h
SPELL_BODY_PROTECTION_FROM_MAGIC
@ SPELL_BODY_PROTECTION_FROM_MAGIC
Definition: Spells.h:93
CastSpellInfo.h
SpriteObject::spell_caster_pid
int spell_caster_pid
Definition: SpriteObject.h:232
Party::armageddonDamage
int armageddonDamage
Definition: Party.h:321
SPELL_LIGHT_DAY_OF_THE_GODS
@ SPELL_LIGHT_DAY_OF_THE_GODS
Definition: Spells.h:102
BLVFace::uFaceExtraID
uint16_t uFaceExtraID
Definition: Indoor.h:482
CastSpellInfoHelpers::_427E01_cast_spell
void _427E01_cast_spell()
Definition: CastSpellInfo.cpp:46
Time.h
Condition_Sleep
@ Condition_Sleep
Definition: Conditions.h:10
ItemSpecialEnchantment::to_item_apply
char to_item_apply[12]
Definition: Items.h:433
ACTOR_BUFF_ENSLAVED
@ ACTOR_BUFF_ENSLAVED
Definition: Actor.h:50
render
std::shared_ptr< IRender > render
Definition: RenderOpenGL.cpp:52