changeset 2189:0e2bee275f60

CastSpell continue
author Ritor1
date Wed, 29 Jan 2014 17:26:24 +0600
parents 0ae56373cc35
children 0acbf1f82c70
files CastSpellInfo.cpp Party.cpp
diffstat 2 files changed, 372 insertions(+), 433 deletions(-) [+]
line wrap: on
line diff
--- a/CastSpellInfo.cpp	Tue Jan 28 22:41:49 2014 +0600
+++ b/CastSpellInfo.cpp	Wed Jan 29 17:26:24 2014 +0600
@@ -1617,20 +1617,19 @@
           pSpellSprite.uSoundID = LOWORD(pCastSpell->sound_id);
           if ( pParty->bTurnBasedModeOn == 1 )
             LOBYTE(pSpellSprite.uAttributes) |= 4;
-          v227 = _v733 / -2;
-          signed int _y = _v733 / 2;
-          if ( v227 <= _y )
+          v188 = _v733 / -2;
+          v189 = _v733 / 2;
+          if ( v188 <= v189 )
           {
-            v228 = v715.uYawAngle;
             do
             {
-              pSpellSprite.uFacing = v227 + v228;
+              pSpellSprite.uFacing = v188 + v715.uYawAngle;
               if ( pSpellSprite.Create(pSpellSprite.uFacing, v715.uPitchAngle, pObjectList->pObjects[(signed __int16)pSpellSprite.uObjectDescID].uSpeed,
                          pCastSpell->uPlayerID + 1) != -1 && pParty->bTurnBasedModeOn == 1 )
                 ++pTurnEngine->pending_actions;
-              v227 += _v733 / (amount - 1);
+              v188 += _v733 / (amount - 1);
             }
-            while ( v227 <= _y );
+            while ( v188 <= v189 );
           }
         }
         LODWORD(v727) = 1;
@@ -3089,431 +3088,371 @@
       {
         amount = 16;
         if ( skill_level == 4 )
-			{
-				LODWORD(v733) = 0;
-			}
-			else
-			{
-				LODWORD(v733) = 3600 * spell_level;
-			}
-			if ( !pPlayer->CanCastSpell(uRequiredMana) )
-				break;
-			__debugbreak();
-			//HIDWORD(v733) = (int)(char *)&pParty + 6972 * pCastSpell->uPlayerID_2 + 36 * a2 + 3040;
-			ItemGen *_v733 = &pParty->pPlayers[pCastSpell->uPlayerID_2].pInventoryItemList[a2];
-			ItemDesc *_v732 = &pItemsTable->pItems[_v733->uItemID];
-			_v733->UpdateTempBonus(pParty->uTimePlayed);
-			if ( _v733->uItemID >= 64 && _v733->uItemID <= 65
-				|| LOBYTE(_v733->uAttributes) & 2
-				|| _v733->uSpecEnchantmentType != 0
-				|| _v733->uEnchantmentType != 0
-				|| (v591 = _v732->uEquipType) != 0 && v591 != 1 && v591 != 2
-				|| pItemsTable->IsMaterialNonCommon(_v733) )
-			{
-				_50C9D0_AfterEnchClickEventId = 113;
-				_50C9D4_AfterEnchClickEventSecondParam = 0;
-				_50C9D8_AfterEnchClickEventTimeout = 1;
-
-				ShowStatusBarString(pGlobalTXT_LocalizationStrings[428], 2); // Spell failed
-				pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, 0, 0, -1, 0, 0, 0, 0);
-				pCastSpell->uSpellID = 0;
-				continue;
-			}
-			v592 = _v733;
-			//v14 = skill_level == 4;
-			_v733->uSpecEnchantmentType = 16;
-			if ( skill_level != 4 )
-			{
-				v732 = (int)v733 << 7;
-				v592->uExpireTime = pParty->uTimePlayed + (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
-				v592->uAttributes |= 8u;
-			}
-			LOBYTE(v592->uAttributes) |= 0x80u;
-			_50C9A8_item_enchantment_timer = 256;
-			LODWORD(v727) = 1;
-			break;
-		}
-		case SPELL_DARK_SHARPMETAL:
-		{
-			switch (skill_level)
-			{
-				case 1: amount = 5; break;
-				case 2: amount = 5; break;
-				case 3: amount = 7; break;
-				case 4: amount = 9; break;
-				default:
-				assert(false);
-			}
-			if ( !pPlayer->CanCastSpell(uRequiredMana) )
-				break;
-			signed int _v726 = ((signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360);
-			pSpellSprite.stru_24.Reset();
-			pSpellSprite.spell_id = pCastSpell->uSpellID;
-			pSpellSprite.spell_level = spell_level;
-			pSpellSprite.spell_skill = skill_level;
-			pSpellSprite.uObjectDescID = pObjectList->ObjectIDByItemID(pSpellSprite.uType);
-			pSpellSprite.vPosition.x = pParty->vPosition.x;
-			pSpellSprite.vPosition.y = pParty->vPosition.y;
-			pSpellSprite.uAttributes = 0;
-			pSpellSprite.vPosition.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 2;
-			pSpellSprite.uSectorID = pIndoor->GetSector(
-								pParty->vPosition.x,
-								pParty->vPosition.y,
-								pParty->vPosition.z + (signed int)pParty->uPartyHeight / 2);
-			pSpellSprite.uSpriteFrameID = 0;
-			pSpellSprite.spell_caster_pid = PID(OBJECT_Player, pCastSpell->uPlayerID);
-			pSpellSprite.spell_target_pid = a2;
-			pSpellSprite.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
-			pSpellSprite.uSoundID = LOWORD(pCastSpell->sound_id);
-			if ( pParty->bTurnBasedModeOn == 1 )
-				LOBYTE(pSpellSprite.uAttributes) |= 4u;
-			v596 = (signed int)_v726 / -2;
-			y = (char *)((signed int)_v726 / 2);
-			if ( (signed int)_v726 / -2 <= (signed int)_v726 / 2 )
-			{
-				v597 = v715.uYawAngle;
-				do
-				{
-					pSpellSprite.uFacing = v596 + v597;
-					if ( pSpellSprite.Create(
-							v596 + v597,
-							v715.uPitchAngle,
-							pObjectList->pObjects[(signed __int16)pSpellSprite.uObjectDescID].uSpeed,
-							pCastSpell->uPlayerID + 1) != -1
-							&& pParty->bTurnBasedModeOn == 1 )
-						++pTurnEngine->pending_actions;
-					v596 += _v726 / (amount - 1);
-				}
-				while ( v596 <= (signed int)y );
-			}
-			LODWORD(v727) = 1;
-			break;
-		}
-		case SPELL_DARK_CONTROL_UNDEAD:
-		{
-			if ( !pPlayer->CanCastSpell(uRequiredMana) )
-				break;
-			switch (skill_level)
-			{
-				case 1: LODWORD(v733) = 180 * spell_level; break;
-				case 2: LODWORD(v733) = 180 * spell_level; break;
-				case 3: LODWORD(v733) = 300 * spell_level; break;
-				case 4: LODWORD(v733) = 29030400; break;
-				default:
-				assert(false);
-			}
-			if (PID_TYPE(a2) != OBJECT_Actor)
-			{
-				LODWORD(v727) = 1;
-				break;
-			}
-			pActor = &pActors[PID_ID(a2)];
-			if ( !MonsterStats::BelongsToSupertype(pActor->pMonsterInfo.uID, MONSTER_SUPERTYPE_UNDEAD) )
-				break;
-			if ( !stru_50C198.GetMagicalResistance(pActor, 0xAu) )
-			{
-				ShowStatusBarString(pGlobalTXT_LocalizationStrings[428], 2); // Spell failed
-				pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, 0, 0, -1, 0, 0, 0, 0);
-				pCastSpell->uSpellID = 0;
-				continue;
-			}
-			pActor->pActorBuffs[ACTOR_BUFF_BERSERK].Reset();
-			pActor->pActorBuffs[ACTOR_BUFF_CHARM].Reset();
-			pActor->pActorBuffs[ACTOR_BUFF_ENSLAVED].Apply(pParty->uTimePlayed + (signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335),
-				skill_level, 0, 0, 0);
-			pSpellSprite.stru_24.Reset();
-			pSpellSprite.spell_id = pCastSpell->uSpellID;
-			pSpellSprite.spell_level = spell_level;
-			pSpellSprite.spell_skill = skill_level;
-			v60 = pObjectList->ObjectIDByItemID(pSpellSprite.uType);
-			
-			pSpellSprite.uObjectDescID = v60;
-			pSpellSprite.vPosition.x = pActor->vPosition.x;
-			pSpellSprite.vPosition.y = pActor->vPosition.y;
-			pSpellSprite.vPosition.z = pActor->vPosition.z + pActor->uActorHeight;
-			pSpellSprite.uAttributes = 0;
-			pSpellSprite.uSectorID = pIndoor->GetSector(pActor->vPosition.x, pActor->vPosition.y, pSpellSprite.vPosition.z);
-			pSpellSprite.uSpriteFrameID = 0;
-			pSpellSprite.spell_caster_pid = PID(OBJECT_Player, pCastSpell->uPlayerID);
-			pSpellSprite.spell_target_pid = a2;
-			pSpellSprite.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
-			pSpellSprite.uFacing = LOWORD(v715.uYawAngle);
-			LOBYTE(pSpellSprite.uAttributes) |= 0x80u;
-			pSpellSprite.uSoundID = LOWORD(pCastSpell->sound_id);
-			pSpellSprite.Create(0, 0, 0, pCastSpell->uPlayerID + 1);
-			LODWORD(v727) = 1;
-			break;
-		}
-		case SPELL_DARK_SACRIFICE:
-		{
-			if ( !pPlayer->CanCastSpell(uRequiredMana) )
-				break;
-			int _v733 = 0;
-			memset(&achieved_awards, 0, 4000);
-			int i = 0;
-			pNPCData = pParty->pHirelings.data();
-			do
-			{
-				if ( pNPCData->pName != 0)
-				{
-					v606 = _v733++;
-					achieved_awards[v606] = (AwardType)(i + 1);
-				}
-				++i;
-				++pNPCData;
-			}
-			while ( pNPCData <= &pParty->pHirelings[1] );
-			i = 0;
-			if ( (signed int)pNPCStats->uNumNewNPCs > 0)
-			{
-				pNPCData = pNPCStats->pNewNPCData;
-				//__debugbreak(); // data offset
-				AwardType *_v734 = &achieved_awards[_v733];
-				do
-				{
-					if ( pNPCData->uFlags & 0x80
-						&& (!pParty->pHirelings[0].pName || strcmp(pNPCData->pName, pParty->pHirelings[0].pName))
-						&& (!pParty->pHirelings[1].pName || strcmp(pNPCData->pName, pParty->pHirelings[1].pName)) )
-					{
-						v607 = _v734;
-						++_v734;
-						*v607 = (AwardType)(i + 3);
-					}
-					++i;
-					++pNPCData;
-				}
-				while ( (signed int)i < (signed int)pNPCStats->uNumNewNPCs );
-			}
-			v608 = pCastSpell->uPlayerID_2;
-			if ( v608 != 4 && v608 != 5
-				|| (v609 = (signed int)*(&pFontCChar + v608 + pParty->hirelingScrollPosition), v609 <= 0)
-				|| v609 >= 3 )
-			{
-				ShowStatusBarString(pGlobalTXT_LocalizationStrings[428], 2); // Spell failed
-				pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, 0, 0, -1, 0, 0, 0, 0);
-				pCastSpell->uSpellID = 0;
-				continue;
-			}
-			v610 = 76 * v609;
-			//*((int *)&pParty->pPlayers[3].pInstalledBeacons[4].uBeaconTime + 19 * v609) = 0;
-			pParty->pHirelings[v609-1].evt_B = 0;
-			v611 = pIconsFrameTable->FindIcon("spell96");
-			//*(int *)((char *)&pParty->pPlayers[3].pInstalledBeacons[4].uBeaconTime + v610 + 4) = pIconsFrameTable->GetIconAnimLength(v611);
-			pParty->pHirelings[v609-1].evt_C = pIconsFrameTable->GetIconAnimLength(v611);
-			//*(int *)((char *)&pParty->pPlayers[3].pInstalledBeacons[3].field_18 + v610) = 1;
-			pParty->pHirelings[v609-1].evt_A = 1;
-
-			v612 = pParty->pPlayers.data();
-			do
-			{
-				v612->sHealth = v612->GetMaxHealth();
-				v612->sMana = v612->GetMaxMana();
-				++v612;
-			}
-			while ( v612 <= &pParty->pPlayers[3] );
-			v613 = &pOutdoor->ddm;
-			if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor)
-				v613 = &pIndoor->dlv;
-			v613->uReputation += 15;
-			if ( v613->uReputation > 10000 )
-				v613->uReputation = 10000;
-			LODWORD(v727) = 1;
-			break;
-		}
-		case SPELL_DARK_PAIN_REFLECTION:
-		{
-			switch (skill_level)
-			{
-				case 1: LODWORD(v733) = 300 * (spell_level + 12); break;
-				case 2: LODWORD(v733) = 300 * (spell_level + 12); break;
-				case 3: LODWORD(v733) = 300 * (spell_level + 12); break;
-				case 4: LODWORD(v733) = 900 * (spell_level + 4); break;
-				default:
-				assert(false);
-			}
-			amount = spell_level + 5;
-			if ( !pPlayer->CanCastSpell(uRequiredMana) )
-				break;
-			if ( skill_level != 3 && skill_level != 4 )
-			{
-				pGame->GetStru6()->SetPlayerBuffAnim(pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
-				pParty->pPlayers[pCastSpell->uPlayerID_2].pPlayerBuffs[PLAYER_BUFF_PAIN_REFLECTION].Apply(pParty->uTimePlayed + (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335), skill_level, amount, 0, 0);
-				LODWORD(v727) = 1;
-				break;
-			}
-			for ( uint pl_id = 0; pl_id , 4; pl_id++ )
-			{
-				pGame->GetStru6()->SetPlayerBuffAnim(pCastSpell->uSpellID, pl_id);
-				pParty->pPlayers[pl_id].pPlayerBuffs[PLAYER_BUFF_PAIN_REFLECTION].Apply(pParty->uTimePlayed + 
-                            (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335), skill_level, amount, 0, 0);
-			}
-			LODWORD(v727) = 1;
-			break;
-		}
-		case SPELL_DARK_SOULDRINKER:
-		{
-			if ( !pPlayer->CanCastSpell(uRequiredMana) )
-				break;
-			pGame->GetIndoorCamera();
-			v623 = (signed __int64)pGame->pIndoorCameraD3D->GetPickDepth();
-			signed int _v733 = pRenderer->_46А6АС_GetActorsInViewport(v623);
-			v707.x = 0;
-			v707.y = 0;
-			v707.z = 0;
-			pSpellSprite.stru_24.Reset();
-			pSpellSprite.spell_id = pCastSpell->uSpellID;
-			pSpellSprite.spell_level = spell_level;
-			pSpellSprite.spell_skill = skill_level;
-			pSpellSprite.uObjectDescID = pObjectList->ObjectIDByItemID(pSpellSprite.uType);
-			pSpellSprite.uAttributes = 0;
-			pSpellSprite.uSectorID = 0;
-			pSpellSprite.uSpriteFrameID = 0;
-			pSpellSprite.field_60_distance_related_prolly_lod = 0;
-			pSpellSprite.uFacing = 0;
-			pSpellSprite.spell_caster_pid = PID(OBJECT_Player, pCastSpell->uPlayerID);
-			pSpellSprite.uSoundID = LOWORD(pCastSpell->sound_id);
-			a2 = 0;
-			int _v726 = 0;
-			if ( _v733 > 0 )
-			{
-				_v726 = (_v733 * (7 * spell_level + 25));
-				do
-				{
-					v625 = _50BF30_actors_in_viewport_ids[a2];
-					pSpellSprite.vPosition.x = pActors[v625].vPosition.x;
-					pSpellSprite.vPosition.y = pActors[v625].vPosition.y;
-					//v732 = pActors[v625].uActorHeight;
-					pSpellSprite.vPosition.z = pActors[v625].vPosition.z - (unsigned int)(signed __int64)((double)pActors[v625].uActorHeight * -0.8);
-					pSpellSprite.spell_target_pid = PID(OBJECT_Actor, _50BF30_actors_in_viewport_ids[a2]);
-					v627 = pSpellSprite.Create(0, 0, 0, 0);
-					v628 = a2;
-					DamageMonsterFromParty(PID(OBJECT_Item, v627), _50BF30_actors_in_viewport_ids[a2], &v707);
-					a2 = v628 + 1;
-				}
-				while ( v628 + 1 < _v733 );
-			}
-			v730 = 0;
-			v629 = 1;
-			do
-			{
-				v630 = pPlayers[v629];
-				if ( !v630->pConditions[2]
-				&& !v630->pConditions[12]
-				&& !v630->pConditions[13]
-				&& !v630->pConditions[14]
-				&& !v630->pConditions[15]
-								&& !v630->pConditions[16] )
-				{
-					v631 = v730++;
-					v681[v631] = v629;
-				}
-				++v629;
-			}
-			while ( v629 <= 4 );
-			v732 = (signed __int64)((double)(signed int)_v726 / (double)v730);
-			_v733 = 0;
-			if ( v730 > 0 )
-			{
-				do
-				{
-					//v632 = 4 * v681[HIDWORD(v733)] + 10965188;
-					v726 = pPlayers[v681[_v733]];
-					//v633 = pPlayers[v681[HIDWORD(v733)]];
-					v726->sHealth += v732;
-					//v726 = *(Player **)v632;
-					//v634 = v726->GetMaxHealth();
-					if ( v726->sHealth > v726->GetMaxHealth())
-						v726->sHealth = v726->GetMaxHealth();
-					v635 = _v733;
-
-					pGame->GetStru6()->SetPlayerBuffAnim(pCastSpell->uSpellID, WORD2(v733));
-					_v733 = v635 + 1;
-				}
-				while ( v635 + 1 < v730 );
-			}
-			pGame->GetStru6()->FadeScreen__like_Turn_Undead_and_mb_Armageddon(0, 0x40u);
-			LODWORD(v727) = 1;
-			break;
-		}
-		case SPELL_DARK_ARMAGEDDON:
-		{
-			if ( uCurrentlyLoadedLevelType == LEVEL_Indoor)
-			{
-				ShowStatusBarString(pGlobalTXT_LocalizationStrings[499], 2);  // Can't cast Armageddon indoors!
-				pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, 0, 0, -1, 0, 0, 0, 0);
-				pCastSpell->uSpellID = 0;
-				continue;
-			}
-			if ( skill_level == 4)
-				amount = 4;
-			else
-				amount = 3;
-			if ( pPlayer->uNumArmageddonCasts >= amount || pParty->armageddon_timer > 0 )
-			{
-				ShowStatusBarString(pGlobalTXT_LocalizationStrings[428], 2); // Spell failed
-				pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, 0, 0, -1, 0, 0, 0, 0);
-				pCastSpell->uSpellID = 0;
-				continue;
-			}
-			if ( !pPlayer->CanCastSpell(uRequiredMana) )
-				break;
-			pParty->armageddon_timer = 256;
-			pParty->armageddonDamage = spell_level;
-			++pPlayer->uNumArmageddonCasts;
-			if ( pParty->bTurnBasedModeOn == 1 )
-				++pTurnEngine->pending_actions;
-			int _v726 = 50;
-			do
-			{
-				v642 = rand() % 4096 - 2048;
-				v643 = rand();
-				v721 = v642 + pParty->vPosition.x;
-				y = (char *)(pParty->vPosition.y + v643 % 4096 - 2048);
-				v732 = GetTerrainHeightsAroundParty2(v642 + pParty->vPosition.x, (int)y, &v710, 0);
-				v644 = rand();
-				sub_42F7EB_DropItemAt(0xFE6u, v721, (int)y, v732 + 16, v644 % 500 + 500, 1, 0, 0, 0);
-				--_v726;
-			}
-			while ( _v726 != 0 );
-			LODWORD(v727) = 1;
-			break;
-		}
-
-		default:
-			break;
-	}
-	if ( pCastSpell->uFlags & 0x20 )
-	{
-		if ( v727 != 0.0 )
-			pAudioPlayer->PlaySound((SoundID)word_4EE088_sound_ids[pCastSpell->uSpellID], 0, 0, -1, 0, pCastSpell->sound_id, 0, 0);
-	}
-	else
-	{
-		if ( sRecoveryTime < 0 )
-			sRecoveryTime = 0;
-		if ( pParty->bTurnBasedModeOn )
-		{
-			v645 = sRecoveryTime;
-			pParty->pTurnBasedPlayerRecoveryTimes[pCastSpell->uPlayerID] = sRecoveryTime;
-			pPlayer->SetRecoveryTime(v645);
-			if ( !some_active_character )
-				pTurnEngine->ApplyPlayerAction();
-		}
-		else
-		{
-			pPlayer->SetRecoveryTime(
-				(signed __int64)(flt_6BE3A4_debug_recmod1 * (double)sRecoveryTime * 2.133333333333333));
-		}
-		if ( v727 != 0.0 )
-		{
-			pPlayer->PlaySound(SPEECH_49, 0);
-			if ( v727 != 0.0 )
-				pAudioPlayer->PlaySound((SoundID)word_4EE088_sound_ids[pCastSpell->uSpellID], 0, 0, -1, 0, pCastSpell->sound_id, 0,	0);
-		}
-	}
-	pCastSpell->uSpellID = 0;
-	spell_level = v723;
-	continue;
+          duration = 0;
+        else
+          duration = 3600 * spell_level;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          break;
+        ItemGen *item = &pParty->pPlayers[pCastSpell->uPlayerID_2].pInventoryItemList[a2];
+        item->UpdateTempBonus(pParty->uTimePlayed);
+        if ( item->uItemID >= 64 && item->uItemID <= 65//blasters
+            || LOBYTE(item->uAttributes) & 2
+            || item->uSpecEnchantmentType != 0
+            || item->uEnchantmentType != 0
+            || pItemsTable->pItems[item->uItemID].uEquipType != EQUIP_SINGLE_HANDED 
+            && pItemsTable->pItems[item->uItemID].uEquipType != EQUIP_TWO_HANDED
+            && pItemsTable->pItems[item->uItemID].uEquipType != EQUIP_BOW
+            || pItemsTable->IsMaterialNonCommon(item) )
+        {
+          _50C9D0_AfterEnchClickEventId = 113;
+          _50C9D4_AfterEnchClickEventSecondParam = 0;
+          _50C9D8_AfterEnchClickEventTimeout = 1;
+          ShowStatusBarString(pGlobalTXT_LocalizationStrings[428], 2); // Spell failed
+          pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, 0, 0, -1, 0, 0, 0, 0);
+          pCastSpell->uSpellID = 0;
+          continue;
+        }
+        item->uSpecEnchantmentType = 16;
+        if ( skill_level != 4 )
+        {
+          item->uExpireTime = pParty->uTimePlayed + (signed int)(signed __int64)((double)(signed int)((int)duration << 7) * 0.033333335);
+          item->uAttributes |= 8;
+        }
+        LOBYTE(item->uAttributes) |= 0x80;
+        _50C9A8_item_enchantment_timer = 256;
+        LODWORD(v727) = 1;
+        break;
+      }
+      case SPELL_DARK_SHARPMETAL://Шрапнель
+      {
+        switch (skill_level)
+        {
+          case 1: amount = 5; break;
+          case 2: amount = 5; break;
+          case 3: amount = 7; break;
+          case 4: amount = 9; break;
+          default:
+            assert(false);
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          break;
+        signed int _v726 = ((signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360);
+        pSpellSprite.stru_24.Reset();
+        pSpellSprite.spell_id = pCastSpell->uSpellID;
+        pSpellSprite.spell_level = spell_level;
+        pSpellSprite.spell_skill = skill_level;
+        pSpellSprite.uObjectDescID = pObjectList->ObjectIDByItemID(pSpellSprite.uType);
+        pSpellSprite.vPosition.x = pParty->vPosition.x;
+        pSpellSprite.vPosition.y = pParty->vPosition.y;
+        pSpellSprite.uAttributes = 0;
+        pSpellSprite.vPosition.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 2;
+        pSpellSprite.uSectorID = pIndoor->GetSector(pParty->vPosition.x, pParty->vPosition.y,
+                                               pParty->vPosition.z + (signed int)pParty->uPartyHeight / 2);
+        pSpellSprite.uSpriteFrameID = 0;
+        pSpellSprite.spell_caster_pid = PID(OBJECT_Player, pCastSpell->uPlayerID);
+        pSpellSprite.spell_target_pid = a2;
+        pSpellSprite.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
+        pSpellSprite.uSoundID = LOWORD(pCastSpell->sound_id);
+        if ( pParty->bTurnBasedModeOn == 1 )
+          LOBYTE(pSpellSprite.uAttributes) |= 4;
+        v188 = (signed int)_v726 / -2;
+        v189 = (signed int)_v726 / 2;
+        if ( v188 <= v189 )
+        {
+          do
+          {
+            pSpellSprite.uFacing = v188 + v715.uYawAngle;
+            if ( pSpellSprite.Create(pSpellSprite.uFacing, v715.uPitchAngle,
+                        pObjectList->pObjects[(signed __int16)pSpellSprite.uObjectDescID].uSpeed, pCastSpell->uPlayerID + 1) != -1
+                        && pParty->bTurnBasedModeOn == 1 )
+              ++pTurnEngine->pending_actions;
+            v188 += _v726 / (amount - 1);
+          }
+          while ( v188 <= v189 );
+        }
+        LODWORD(v727) = 1;
+        break;
+      }
+      case SPELL_DARK_CONTROL_UNDEAD://Глава нежити
+      {
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          break;
+        switch (skill_level)
+        {
+          case 1: duration = 180 * spell_level; break;
+          case 2: duration = 180 * spell_level; break;
+          case 3: duration = 300 * spell_level; break;
+          case 4: duration = 29030400; break;
+          default:
+            assert(false);
+        }
+        if (PID_TYPE(a2) == OBJECT_Actor)
+        {
+          mon_id = PID_ID(a2);
+          if ( !MonsterStats::BelongsToSupertype(pActors[mon_id].pMonsterInfo.uID, MONSTER_SUPERTYPE_UNDEAD) )
+            break;
+          if ( !stru_50C198.GetMagicalResistance(&pActors[mon_id], 10) )
+          {
+            ShowStatusBarString(pGlobalTXT_LocalizationStrings[428], 2); // Spell failed
+            pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, 0, 0, -1, 0, 0, 0, 0);
+            pCastSpell->uSpellID = 0;
+            continue;
+          }
+          pActors[mon_id].pActorBuffs[ACTOR_BUFF_BERSERK].Reset();
+          pActors[mon_id].pActorBuffs[ACTOR_BUFF_CHARM].Reset();
+          pActors[mon_id].pActorBuffs[ACTOR_BUFF_ENSLAVED].Apply(pParty->uTimePlayed + 
+                           (signed __int64)((double)(signed int)((int)duration << 7) * 0.033333335), skill_level, 0, 0, 0);
+          pSpellSprite.stru_24.Reset();
+          pSpellSprite.spell_id = pCastSpell->uSpellID;
+          pSpellSprite.spell_level = spell_level;
+          pSpellSprite.spell_skill = skill_level;
+          pSpellSprite.uObjectDescID = pObjectList->ObjectIDByItemID(pSpellSprite.uType);
+          pSpellSprite.vPosition.x = pActors[mon_id].vPosition.x;
+          pSpellSprite.vPosition.y = pActors[mon_id].vPosition.y;
+          pSpellSprite.vPosition.z = pActors[mon_id].vPosition.z + pActors[mon_id].uActorHeight;
+          pSpellSprite.uAttributes = 0;
+          pSpellSprite.uSectorID = pIndoor->GetSector(pActors[mon_id].vPosition.x, pActors[mon_id].vPosition.y, pSpellSprite.vPosition.z);
+          pSpellSprite.uSpriteFrameID = 0;
+          pSpellSprite.spell_caster_pid = PID(OBJECT_Player, pCastSpell->uPlayerID);
+          pSpellSprite.spell_target_pid = a2;
+          pSpellSprite.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
+          pSpellSprite.uFacing = LOWORD(v715.uYawAngle);
+          LOBYTE(pSpellSprite.uAttributes) |= 0x80;
+          pSpellSprite.uSoundID = LOWORD(pCastSpell->sound_id);
+          pSpellSprite.Create(0, 0, 0, pCastSpell->uPlayerID + 1);
+        }
+        LODWORD(v727) = 1;
+        break;
+      }
+      case SPELL_DARK_SACRIFICE://Жертва
+      {
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          break;
+        int _v733 = 0;
+        memset(&achieved_awards, 0, 4000);
+        //pNPCData = pParty->pHirelings.data();
+        for ( uint npc_id = 0; npc_id < 2; npc_id++ )
+        {
+          if ( pParty->pHirelings[npc_id].pName != 0)
+          {
+            //v606 = _v733++;
+            achieved_awards[_v733++] = (AwardType)(npc_id + 1);
+          }
+          //++i;
+          //++pNPCData;
+        }
+        //while ( pNPCData <= &pParty->pHirelings[1] );
+        
+        if ( (signed int)pNPCStats->uNumNewNPCs > 0)
+        {
+          //pNPCData = pNPCStats->pNewNPCData;
+          //__debugbreak(); // data offset
+          //AwardType *_v734 = &achieved_awards[_v733];
+          for ( int npc_id = 0; npc_id < pNPCStats->uNumNewNPCs; ++npc_id )
+          {
+            if ( pNPCStats->pNewNPCData[npc_id].uFlags & 0x80//hired(наёмный)
+              && (!pParty->pHirelings[0].pName
+              || strcmp(pNPCStats->pNewNPCData[npc_id].pName, pParty->pHirelings[0].pName))
+              && (!pParty->pHirelings[1].pName
+              || strcmp(pNPCStats->pNewNPCData[npc_id].pName, pParty->pHirelings[1].pName)) )
+            {
+              //v607 = _v734;
+              //++_v734;
+              achieved_awards[_v733++] = (AwardType)(npc_id + 3);
+            }
+            //++pNPCData;
+          }
+          //while (  );
+        }
+        //v608 = pCastSpell->uPlayerID_2;
+        //v609 = (signed int)*(&pFontCChar + pCastSpell->uPlayerID_2 + pParty->hirelingScrollPosition);
+        if ( pCastSpell->uPlayerID_2 != 4 && pCastSpell->uPlayerID_2 != 5
+           || achieved_awards[_v733 - 2] <= 0 || achieved_awards[_v733 - 2] >= 3 )
+        {
+          ShowStatusBarString(pGlobalTXT_LocalizationStrings[428], 2); // Spell failed
+          pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, 0, 0, -1, 0, 0, 0, 0);
+          pCastSpell->uSpellID = 0;
+          continue;
+        }
+        //v610 = 76 * achieved_awards[_v733];
+        //*((int *)&pParty->pPlayers[3].pInstalledBeacons[4].uBeaconTime + 19 * v609) = 0;
+        pParty->pHirelings[achieved_awards[_v733 - 2]].pName = 0;
+        //v611 = pIconsFrameTable->FindIcon("spell96");
+        //*(int *)((char *)&pParty->pPlayers[3].pInstalledBeacons[4].uBeaconTime + v610 + 4) = pIconsFrameTable->GetIconAnimLength(v611);
+        pParty->pHirelings[achieved_awards[_v733 - 2]].uPortraitID = pIconsFrameTable->GetIconAnimLength(pIconsFrameTable->FindIcon("spell96"));
+        //*(int *)((char *)&pParty->pPlayers[3].pInstalledBeacons[3].field_18 + v610) = 1;
+        //pParty->pHirelings[achieved_awards[_v733 - 2]].evt_A = 1;
+        for ( uint pl_id = 0; pl_id < 4; pl_id++ )
+        {
+          pParty->pPlayers[pl_id].sHealth = pParty->pPlayers[pl_id].GetMaxHealth();
+          pParty->pPlayers[pl_id].sMana = pParty->pPlayers[pl_id].GetMaxMana();
+        }
+        v613 = &pOutdoor->ddm;
+        if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor)
+          v613 = &pIndoor->dlv;
+        v613->uReputation += 15;
+        if ( v613->uReputation > 10000 )
+          v613->uReputation = 10000;
+        LODWORD(v727) = 1;
+        break;
+      }
+      case SPELL_DARK_PAIN_REFLECTION://Отражение боли
+      {
+        switch (skill_level)
+        {
+          case 1: duration = 300 * (spell_level + 12); break;
+          case 2: duration = 300 * (spell_level + 12); break;
+          case 3: duration = 300 * (spell_level + 12); break;
+          case 4: duration = 900 * (spell_level + 4); break;
+          default:
+            assert(false);
+        }
+        amount = spell_level + 5;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          break;
+        if ( skill_level != 3 && skill_level != 4 )
+        {
+          pGame->GetStru6()->SetPlayerBuffAnim(pCastSpell->uSpellID, pCastSpell->uPlayerID_2);
+          pParty->pPlayers[pCastSpell->uPlayerID_2].pPlayerBuffs[PLAYER_BUFF_PAIN_REFLECTION].Apply(pParty->uTimePlayed + 
+                               (signed int)(signed __int64)((double)(signed int)((int)duration << 7) * 0.033333335), skill_level, amount, 0, 0);
+          LODWORD(v727) = 1;
+          break;
+        }
+        for ( uint pl_id = 0; pl_id < 4; pl_id++ )
+        {
+          pGame->GetStru6()->SetPlayerBuffAnim(pCastSpell->uSpellID, pl_id);
+          pParty->pPlayers[pl_id].pPlayerBuffs[PLAYER_BUFF_PAIN_REFLECTION].Apply(pParty->uTimePlayed + 
+                            (signed int)(signed __int64)((double)(signed int)((int)duration << 7) * 0.033333335), skill_level, amount, 0, 0);
+        }
+        LODWORD(v727) = 1;
+        break;
+      }
+      case SPELL_DARK_SOULDRINKER://Испить душу
+      {
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          break;
+        pGame->GetIndoorCamera();
+        int mon_num = pRenderer->_46А6АС_GetActorsInViewport((signed __int64)pGame->pIndoorCameraD3D->GetPickDepth());
+        v707.x = 0;
+        v707.y = 0;
+        v707.z = 0;
+        pSpellSprite.stru_24.Reset();
+        pSpellSprite.spell_id = pCastSpell->uSpellID;
+        pSpellSprite.spell_level = spell_level;
+        pSpellSprite.spell_skill = skill_level;
+        pSpellSprite.uObjectDescID = pObjectList->ObjectIDByItemID(pSpellSprite.uType);
+        pSpellSprite.uAttributes = 0;
+        pSpellSprite.uSectorID = 0;
+        pSpellSprite.uSpriteFrameID = 0;
+        pSpellSprite.field_60_distance_related_prolly_lod = 0;
+        pSpellSprite.uFacing = 0;
+        pSpellSprite.spell_caster_pid = PID(OBJECT_Player, pCastSpell->uPlayerID);
+        pSpellSprite.uSoundID = LOWORD(pCastSpell->sound_id);
+        amount = 0;
+        if ( mon_num > 0 )
+        {
+          amount = (mon_num * (7 * spell_level + 25));
+          for ( uint mon_id = 0; mon_id < mon_num; mon_id++ )
+          {
+            pSpellSprite.vPosition.x = pActors[_50BF30_actors_in_viewport_ids[mon_id]].vPosition.x;
+            pSpellSprite.vPosition.y = pActors[_50BF30_actors_in_viewport_ids[mon_id]].vPosition.y;
+            pSpellSprite.vPosition.z = pActors[_50BF30_actors_in_viewport_ids[mon_id]].vPosition.z - 
+                       (unsigned int)(signed __int64)((double)pActors[_50BF30_actors_in_viewport_ids[mon_id]].uActorHeight * -0.8);
+            pSpellSprite.spell_target_pid = PID(OBJECT_Actor, _50BF30_actors_in_viewport_ids[mon_id]);
+            DamageMonsterFromParty(PID(OBJECT_Item, pSpellSprite.Create(0, 0, 0, 0)), _50BF30_actors_in_viewport_ids[mon_id], &v707);
+          }
+        }
+        int pl_num = 0;
+        int pl_array[4];
+        for ( uint pl_id = 1; pl_id <= 4; ++pl_id )
+        {
+          if ( !pPlayers[pl_id]->pConditions[Condition_Sleep] && !pPlayers[pl_id]->pConditions[Condition_Paralyzed]
+            && !pPlayers[pl_id]->pConditions[Condition_Unconcious] && !pPlayers[pl_id]->pConditions[Condition_Dead]
+            && !pPlayers[pl_id]->pConditions[Condition_Pertified] && !pPlayers[pl_id]->pConditions[Condition_Eradicated] )
+          {
+            pl_array[pl_num++] = pl_id;
+          }
+        }
+        for ( uint j = 0; j < pl_num; j++ )
+        {
+          pPlayers[pl_array[j]]->sHealth += (signed __int64)((double)(signed int)amount / (double)pl_num);
+          if ( pPlayers[pl_array[j]]->sHealth > pPlayers[pl_array[j]]->GetMaxHealth())
+            pPlayers[pl_array[j]]->sHealth = pPlayers[pl_array[j]]->GetMaxHealth();
+          pGame->GetStru6()->SetPlayerBuffAnim(pCastSpell->uSpellID, pl_array[j]);
+        }
+        pGame->GetStru6()->FadeScreen__like_Turn_Undead_and_mb_Armageddon(0, 64);
+        LODWORD(v727) = 1;
+        break;
+      }
+      case SPELL_DARK_ARMAGEDDON://Армагеддон
+      {
+        if ( uCurrentlyLoadedLevelType == LEVEL_Indoor)
+        {
+          ShowStatusBarString(pGlobalTXT_LocalizationStrings[499], 2);  // Can't cast Armageddon indoors!
+          pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, 0, 0, -1, 0, 0, 0, 0);
+          pCastSpell->uSpellID = 0;
+          continue;
+        }
+        if ( skill_level == 4)
+          amount = 4;
+        else
+          amount = 3;
+        if ( pPlayer->uNumArmageddonCasts >= amount || pParty->armageddon_timer > 0 )
+        {
+          ShowStatusBarString(pGlobalTXT_LocalizationStrings[428], 2); // Spell failed
+          pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, 0, 0, -1, 0, 0, 0, 0);
+          pCastSpell->uSpellID = 0;
+          continue;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          break;
+        pParty->armageddon_timer = 256;
+        pParty->armageddonDamage = spell_level;
+        ++pPlayer->uNumArmageddonCasts;
+        if ( pParty->bTurnBasedModeOn == 1 )
+          ++pTurnEngine->pending_actions;
+        for ( uint i = 0; i < 50; i++ )
+        {
+          v642 = rand() % 4096 - 2048;
+          v643 = rand();
+          v732 = GetTerrainHeightsAroundParty2(v642 + pParty->vPosition.x, pParty->vPosition.y + (v643 % 4096 - 2048), &v710, 0);
+          sub_42F7EB_DropItemAt(4070, v642 + pParty->vPosition.x, pParty->vPosition.y + (v643 % 4096 - 2048), v732 + 16, rand() % 500 + 500, 1, 0, 0, 0);
+        }
+        LODWORD(v727) = 1;
+        break;
+      }
+      default:
+        break;
+    }
+    if ( pCastSpell->uFlags & 0x20 )
+    {
+      if ( v727 != 0.0 )
+        pAudioPlayer->PlaySound((SoundID)word_4EE088_sound_ids[pCastSpell->uSpellID], 0, 0, -1, 0, pCastSpell->sound_id, 0, 0);
+    }
+    else
+    {
+      if ( sRecoveryTime < 0 )
+        sRecoveryTime = 0;
+      if ( pParty->bTurnBasedModeOn )
+      {
+        //v645 = sRecoveryTime;
+        pParty->pTurnBasedPlayerRecoveryTimes[pCastSpell->uPlayerID] = sRecoveryTime;
+        pPlayer->SetRecoveryTime(sRecoveryTime);
+        if ( !some_active_character )
+          pTurnEngine->ApplyPlayerAction();
+      }
+      else
+        pPlayer->SetRecoveryTime((signed __int64)(flt_6BE3A4_debug_recmod1 * (double)sRecoveryTime * 2.133333333333333));
+      if ( v727 != 0.0 )
+      {
+        pPlayer->PlaySound(SPEECH_49, 0);
+        if ( v727 != 0.0 )
+          pAudioPlayer->PlaySound((SoundID)word_4EE088_sound_ids[pCastSpell->uSpellID], 0, 0, -1, 0, pCastSpell->sound_id, 0,	0);
+      }
+    }
+    pCastSpell->uSpellID = 0;
+    spell_level = v723;
+    continue;
   }
   
 }
--- a/Party.cpp	Tue Jan 28 22:41:49 2014 +0600
+++ b/Party.cpp	Wed Jan 29 17:26:24 2014 +0600
@@ -757,7 +757,7 @@
     if ( pPlayer->classType == PLAYER_CLASS_LICH )
     {
       have_vessels_soul = false;
-      for ( uint i = 0; i < 138; i++ )
+      for ( uint i = 0; i < 126; i++ )
       {
         if ( pPlayer->pInventoryItemList[i].uItemID == ITEM_LICH_JAR_FULL && pPlayer->pInventoryItemList[i].uHolderPlayer == pPlayerID + 1 )
           have_vessels_soul = true;