14 #include "../Graphics/DecalBuilder.h"
15 #include "../Graphics/Level/Decoration.h"
16 #include "../Graphics/Outdoor.h"
17 #include "../Graphics/Overlays.h"
18 #include "../Graphics/PaletteManager.h"
19 #include "../Graphics/Sprites.h"
20 #include "../Graphics/Viewport.h"
21 #include "../Graphics/Vis.h"
23 #include "../OurMath.h"
25 #include "../Spells/CastSpellInfo.h"
26 #include "../Tables/FactionTable.h"
27 #include "../TurnEngine/TurnEngine.h"
28 #include "../stru298.h"
69 unsigned int bar_length;
85 unsigned int bar_filled_length = bar_length;
90 unsigned int uX =
window->uFrameX + (
signed int)(
window->uFrameWidth - bar_length) / 2;
92 render->SetUIClipRect(uX,
window->uFrameY + 32, uX + bar_length,
window->uFrameY + 52);
93 render->DrawTextureAlphaNew(uX / 640.0
f, (
window->uFrameY + 32) / 480.0f,
96 render->SetUIClipRect(uX,
window->uFrameY + 32, uX + bar_filled_length,
98 render->DrawTextureAlphaNew(uX / 640.0
f, (
window->uFrameY + 34) / 480.0f,
102 render->ResetUIClipRect();
103 render->DrawTextureAlphaNew((uX - 5) / 640.0f,
104 (
window->uFrameY + 32) / 480.0
f,
106 render->DrawTextureAlphaNew((uX + bar_length) / 640.0f,
107 (
window->uFrameY + 32) / 480.0
f,
113 if (uActorID >= 0 && uActorID <= (
signed int)(
uNumActors - 1)) {
115 pActors[uActorID].uAttributes |= uFlag;
117 if (uFlag == 0x10000) {
121 pActors[uActorID].uAttributes &= ~uFlag;
135 unsigned int bGive) {
136 if ((uActorID >= 0) &&
137 (
signed int)uActorID <= (
signed int)(
uNumActors - 1)) {
140 pActors[uActorID].uCarriedItemID = uItemID;
142 pActors[uActorID].ActorHasItems[0].uItemID = uItemID;
144 pActors[uActorID].ActorHasItems[1].uItemID = uItemID;
149 pActors[uActorID].ActorHasItems[0].Reset();
151 pActors[uActorID].ActorHasItems[1].Reset();
192 this->pMonsterInfo.uTreasureType,
193 &this->ActorHasItems[2]);
200 int uSpellID,
int a4,
unsigned int uSkillLevel) {
202 unsigned int realPoints;
203 unsigned int masteryLevel;
247 realPoints = uSkillLevel & 0x3F;
304 if (masteryLevel == 1 || masteryLevel == 2)
305 v39 = 60 * (realPoints + 60);
306 else if (masteryLevel == 3)
307 v39 = 2 * 60 * (realPoints + 20);
308 else if (masteryLevel == 4)
309 v39 = 3 * 60 * (realPoints + 15);
316 masteryLevel, 0, 0, 0);
327 if (masteryLevel == 2)
329 else if (masteryLevel == 3)
331 else if (masteryLevel == 4)
335 for (
int i = 0; i < v23; i++) {
337 spellnumc = v30 - 2500;
339 v119 = spellnumb * spellnumb;
340 if (sqrt((
float)(spellnumc * spellnumc + v119 + v120)) <= 1.0) {
344 v31 = (
signed __int64)sqrt((
float)(v119 + v120));
383 spellnumb = rand() % 1024 - 512;
384 v28 = rand() % 1024 - 512;
390 if (masteryLevel == 2)
392 else if (masteryLevel == 3)
394 else if (masteryLevel == 4)
421 v19 = spellnuma / -2;
423 if (spellnuma / -2 > spellnuma / 2) {
434 }
while (v19 <= a1a);
444 if (masteryLevel == 1 || masteryLevel == 2)
445 v8 = 5 * 60 * realPoints + 3840;
446 else if (masteryLevel == 3)
447 v8 = 15 * 60 * realPoints + 3840;
448 else if (masteryLevel == 4)
449 v8 = 60 * 60 * (realPoints + 64);
455 masteryLevel, 0, 0, 0);
459 if (masteryLevel == 1 || masteryLevel == 2)
460 v44 = 5 * 60 * realPoints + 3840;
461 else if (masteryLevel == 3)
462 v44 = 15 * 60 * realPoints + 3840;
463 else if (masteryLevel == 4)
464 v44 = 60 * 60 * (realPoints + 64);
470 masteryLevel, realPoints + 5, 0, 0);
477 if (masteryLevel == 1 || masteryLevel == 2)
478 v42 = 5 * 60 * realPoints + 3840;
479 else if (masteryLevel == 3)
480 v42 = 15 * 60 * realPoints + 3840;
481 else if (masteryLevel == 4)
482 v42 = 20 * 60 * realPoints + 3840;
488 masteryLevel, realPoints + 5, 0, 0);
497 if (masteryLevel == 1 || masteryLevel == 2)
498 v48 = 2 * realPoints + 40;
499 else if (masteryLevel == 3)
500 v48 = 3 * realPoints + 60;
501 else if (masteryLevel == 4)
502 v48 = 2 * (3 * realPoints + 60);
508 masteryLevel, v48, 0, 0);
516 if (masteryLevel == 1 || masteryLevel == 2)
517 v54 = 5 * 60 * realPoints + 3840;
518 else if (masteryLevel == 3)
519 v54 = 15 * 60 * realPoints + 3840;
520 else if (masteryLevel == 4)
521 v54 = 20 * 60 * realPoints + 3840;
527 masteryLevel, realPoints + 5, 0, 0);
535 if ((
signed int)masteryLevel <= 0 || (
signed int)masteryLevel > 4)
538 v51 = 60 * 60 * realPoints;
542 masteryLevel, realPoints, 0, 0);
561 for (
int i = 1; i <= 4; i++) {
562 v59 =
pPlayers[i]->GetParameterBonus(
564 v61 = (
pPlayers[i]->GetParameterBonus(
565 pPlayers[i]->GetActualIntelligence()) +
572 if (rand() % v63 < 30) {
573 for (
uint k = 0; k <
pPlayers[i]->pPlayerBuffs.size(); k++)
582 if (masteryLevel == 1 || masteryLevel == 2) {
583 v96 = 5 * 60 * realPoints + 128 * 30;
584 }
else if (masteryLevel == 3) {
585 HEXRAYS_LOWORD(realPoints) = 3 * realPoints;
586 v96 = 15 * 60 * (uSkillLevel & 0x3F) + 128 * 30;
587 }
else if (masteryLevel == 4) {
588 v96 = 20 * 60 * realPoints + 128 * 30;
589 HEXRAYS_LOWORD(realPoints) = 4 * realPoints;
591 HEXRAYS_LOWORD(realPoints) = uSkillLevel;
597 masteryLevel, realPoints, 0, 0);
605 if (masteryLevel == 1 || masteryLevel == 2)
606 v94 = 5 * 60 * realPoints + 30 * 128;
607 else if (masteryLevel == 3)
608 v94 = 15 * 60 * realPoints + 30 * 128;
609 else if (masteryLevel == 4)
610 v94 = 20 * 60 * realPoints + 30 * 128;
616 masteryLevel, realPoints + 5, 0, 0);
624 if (masteryLevel == 2)
626 else if (masteryLevel == 3)
628 else if (masteryLevel == 4)
655 a1c = spellnume / -2;
656 if (spellnume / -2 > spellnume / 2) {
657 v80 = spellnume / -2;
668 }
while (a1c <= spellnume / 2);
677 if (masteryLevel == 0)
679 else if (masteryLevel == 1 || (masteryLevel == 2) ||
681 v68 = 5 * 30 * realPoints + 30 * 128;
683 v68 = 15 * 30 * realPoints + 30 * 128;
687 masteryLevel, 0, 0, 0);
727 if (a2 == 1) victim->
uAttributes |= ACTOR_AGGRESSOR;
731 if (!actor->
CanAct() || i == uActorID)
continue;
740 if (a2 == 1) actor->
uAttributes |= ACTOR_AGGRESSOR;
797 Error(
"Item not found");
829 specAb =
pActors[uActorID].pMonsterInfo.uSpecialAbilityDamageDiceBonus;
834 if (specAb != 3)
return;
907 v4 = PID_ID(uObj1ID);
909 v5 = PID_ID(uObj2ID);
910 switch (PID_TYPE(uObj1ID)) {
918 outx =
pActors[v4].vPosition.x;
919 outy =
pActors[v4].vPosition.y;
920 outz =
pActors[v4].vPosition.z + (
pActors[v4].uActorHeight * 0.75);
937 Vec3_int_::Rotate(24, v18, 0, v37, &outx, &outy, &outz);
946 Vec3_int_::Rotate(8, v18, 0, v37, &outx, &outy, &outz);
955 Vec3_int_::Rotate(8, v18, 0, v37, &outx, &outy, &outz);
964 Vec3_int_::Rotate(24, v18, 0, v37, &outx, &outy, &outz);
996 switch (PID_TYPE(uObj2ID)) {
1005 outy2 = (
float)
pActors[v5].vPosition.y;
1006 a4 =
pActors[v5].vPosition.z + (
pActors[v5].uActorHeight * 0.75);
1044 v31 = (float)outx2 - (
float)outx;
1045 v32 = (float)outy2 - (
float)outy;
1046 a4a = (float)a4 - (
float)outz;
1049 v33 = sqrt(a4a * a4a + outy2 + outx2);
1077 if (rand() % 100 >= 5) {
1086 pActors[uActorID].uCurrentActionTime = 0;
1087 pActors[uActorID].vVelocity.z = 0;
1088 pActors[uActorID].vVelocity.y = 0;
1089 pActors[uActorID].vVelocity.x = 0;
1091 pActors[uActorID].uCurrentActionLength = 256;
1093 pActors[uActorID].UpdateAnimation();
1105 AI_Stand(uActorID, uObjID, uActionLength, a4);
1123 pActors[uActorID].uCurrentActionLength =
1126 pActors[uActorID].uCurrentActionLength = uActionLength;
1127 pActors[uActorID].uCurrentActionTime = 0;
1130 pActors[uActorID].vVelocity.z = 0;
1131 pActors[uActorID].vVelocity.y = 0;
1132 pActors[uActorID].vVelocity.x = 0;
1133 pActors[uActorID].UpdateAnimation();
1138 pActors[uActorID].uCurrentActionLength = rand() % 128 + 128;
1139 pActors[uActorID].uCurrentActionTime = 0;
1141 pActors[uActorID].vVelocity.z = 0;
1142 pActors[uActorID].vVelocity.y = 0;
1143 pActors[uActorID].vVelocity.x = 0;
1144 pActors[uActorID].UpdateAnimation();
1164 pActors[uActorID].pMonsterInfo.uAIType == 1) {
1170 v8 = PID_ID(sTargetPid);
1179 Error(
"Should not get here");
1183 v10.x =
pActors[uActorID].vPosition.x;
1184 v10.y =
pActors[uActorID].vPosition.y;
1188 if (
sub_407A1C((
int)v6, (
int)v7, v23, v10)) {
1189 if (arg0 !=
nullptr) {
1197 pActors[uActorID].uCurrentActionLength =
1202 pActors[uActorID].uCurrentActionTime = 0;
1211 pActors[uActorID].pMonsterInfo.uRecoveryTime = v25;
1213 pActors[uActorID].vVelocity.z = 0;
1214 pActors[uActorID].vVelocity.y = 0;
1215 pActors[uActorID].vVelocity.x = 0;
1216 pActors[uActorID].UpdateAnimation();
1235 pActors[uActorID].pMonsterInfo.uLevel +
1249 for (
int i = 1; i <= 4; i++) {
1319 unsigned __int16 v8;
1327 switch (dmgSource) {
1364 for (
int i = 0; i <
v3; i++) v11 += rand() % v4 + 1;
1365 return v11 + v5 +
v2;
1370 unsigned int InHostile_Id;
1372 InHostile_Id = this->
uAlly;
1374 return (
signed int)InHostile_Id >= 39 &&
1375 (
signed int)InHostile_Id <= 44
1376 || (
signed int)InHostile_Id >= 45 &&
1377 (
signed int)InHostile_Id <= 50
1378 || (
signed int)InHostile_Id >= 51 &&
1379 (
signed int)InHostile_Id <= 62
1380 || (
signed int)InHostile_Id >= 78 &&
1381 (
signed int)InHostile_Id <= 83;
1402 if (v8 < 30) v8 = 30;
1440 Error(
"Should not get here");
1443 v19 =
v3->uActorHeight;
1444 v7.z =
v3->vPosition.z + (v19 * 0.75);
1445 v7.y =
v3->vPosition.y;
1446 v7.x =
v3->vPosition.x;
1448 if (pDir ==
nullptr) {
1457 v3->uCurrentActionLength = 8 * v13;
1458 v3->uCurrentActionTime = 0;
1464 v3->pMonsterInfo.uRecoveryTime = pDira;
1468 v3->vVelocity.z = 0;
1469 v3->vVelocity.y = 0;
1470 v3->vVelocity.x = 0;
1472 v3->uCurrentActionLength = 64;
1473 v3->uCurrentActionTime = 0;
1475 v3->UpdateAnimation();
1478 v3->UpdateAnimation();
1504 v6 = PID_ID(sTargetPid);
1513 Error(
"Should not get here");
1516 v19 =
v3->uActorHeight;
1517 v7.z =
v3->vPosition.z + (v19 * 0.75);
1518 v7.y =
v3->vPosition.y;
1519 v7.x =
v3->vPosition.x;
1521 if (pDir ==
nullptr) {
1531 v3->uCurrentActionLength = 8 * v13;
1532 v3->uCurrentActionTime = 0;
1538 v3->pMonsterInfo.uRecoveryTime = pDira;
1542 v16 =
v3->pMonsterInfo.uSpell1ID;
1543 v3->vVelocity.z = 0;
1544 v3->vVelocity.y = 0;
1545 v3->vVelocity.x = 0;
1547 v3->uCurrentActionLength = 64;
1548 v3->uCurrentActionTime = 0;
1550 v3->UpdateAnimation();
1553 v3->UpdateAnimation();
1578 v6 = PID_ID(sTargetPid);
1587 Error(
"Should not get here");
1590 v18 =
v3->uActorHeight;
1591 v7.z =
v3->vPosition.z + (v18 * 0.75);
1592 v7.y =
v3->vPosition.y;
1593 v7.x =
v3->vPosition.x;
1595 if (pDir ==
nullptr) {
1605 v3->uCurrentActionLength = 8 * v13;
1606 v3->uCurrentActionTime = 0;
1614 v3->pMonsterInfo.uRecoveryTime = pDira;
1616 v3->vVelocity.z = 0;
1617 v3->vVelocity.y = 0;
1618 v3->vVelocity.x = 0;
1619 v3->UpdateAnimation();
1645 v6 = PID_ID(sTargetPid);
1659 v19 =
v3->uActorHeight;
1660 v7.z =
v3->vPosition.z + (v19 * 0.75);
1661 v7.y =
v3->vPosition.y;
1662 v7.x =
v3->vPosition.x;
1664 sub_407A1C(v7.x, v7.y, v7.z, Vec3_int_(v4, v5, v22))) {
1665 if (pDir ==
nullptr) {
1675 v3->uCurrentActionLength = 8 * v14;
1676 v3->uCurrentActionTime = 0;
1682 v3->pMonsterInfo.uRecoveryTime = pDira;
1686 v3->vVelocity.z = 0;
1687 v3->vVelocity.y = 0;
1688 v3->vVelocity.x = 0;
1689 v3->UpdateAnimation();
1697 int radius,
int uActionLength) {
1706 x =
pActors[uActor_id].vInitialPosition.x -
pActors[uActor_id].vPosition.x;
1707 y =
pActors[uActor_id].vInitialPosition.y -
pActors[uActor_id].vPosition.y;
1711 absx = absy + (absx / 2);
1713 absx = absx + absy / 2;
1716 if (!uActionLength) uActionLength = 256;
1718 &doNotInitializeBecauseShouldBeRandom);
1725 &doNotInitializeBecauseShouldBeRandom);
1728 absx += ((rand() & 0xF) * radius) / 16;
1730 if (rand() % 100 < 25) {
1734 v10 = v9 + rand() % 256 - 128;
1738 &doNotInitializeBecauseShouldBeRandom);
1741 pActors[uActor_id].uYawAngle = v10;
1743 pActors[uActor_id].uCurrentActionLength =
1744 32 * absx /
pActors[uActor_id].uMovementSpeed;
1746 pActors[uActor_id].uCurrentActionLength = 0;
1747 pActors[uActor_id].uCurrentActionTime = 0;
1750 pActors[uActor_id].UpdateAnimation();
1755 unsigned int uActorID,
signed int a2,
1816 int stunRegardlessOfState) {
1821 pActors[uActorID].uAttributes |= ACTOR_FLEEING;
1823 pActors[uActorID].uAttributes &= 0xFFFFFFFB;
1824 pActors[uActorID].pMonsterInfo.uHostilityType =
1831 if (stunRegardlessOfState ||
1844 pActors[uActorID].uCurrentActionTime = 0;
1846 pActors[uActorID].uCurrentActionLength = 8 * v7;
1848 pActors[uActorID].UpdateAnimation();
1921 for (
uint i = 0; i < 5; ++i)
1961 if (rand() % 100 < 20 && drop.
uItemID != 0) {
1965 rand() % 200 + 200, 1, 1, 0, &drop);
1977 if (sound_sample_id) {
2023 if (pDir ==
nullptr) {
2031 if (!uActionLength) uActionLength = 256;
2036 if (!uActionLength) uActionLength = 256;
2091 if (!uActionLength) uActionLength = 256;
2115 signed int uActionLength,
AIDirection *pDir,
int a5) {
2121 unsigned __int16 v14;
2142 if (!uActionLength) uActionLength = 256;
2147 if (!uActionLength) uActionLength = 256;
2151 if (uActionLength) {
2178 unsigned __int16 v16;
2198 if (!uActionLength) uActionLength = 256;
2202 if (!uActionLength) uActionLength = 256;
2205 if (uActionLength) {
2231 bool can_target_party) {
2240 signed int closestId;
2242 unsigned int lowestRadius;
2246 lowestRadius = UINT_MAX;
2263 if (v10 == 0)
continue;
2267 if (v10 == 0)
continue;
2281 if (v23 <= v11 && v27 <= v11 && v12 <= v11 &&
2284 v23 * v23 + v27 * v27 + v12 * v12 < lowestRadius) {
2285 lowestRadius = v23 * v23 + v27 * v27 + v12 * v12;
2290 if (lowestRadius != UINT_MAX) {
2310 if (v16 <= v15 && v28 <= v15 && v17 <= v15 &&
2311 (v16 * v16 + v28 * v28 + v17 * v17 < lowestRadius)) {
2320 unsigned int thisGroup;
2322 unsigned int thisAlly;
2323 unsigned int otherAlly;
2326 if (otherActPtr->
uGroup != 0 && this->uGroup != 0 &&
2327 otherActPtr->
uGroup == this->uGroup)
2332 thisAlly = this->
uAlly;
2335 else if (thisAlly > 0)
2336 thisGroup = thisAlly;
2342 otherAlly = otherActPtr->
uAlly;
2346 else if (otherAlly > 0)
2347 otherGroup = otherAlly;
2361 if (thisGroup >= 89 || otherGroup >= 89)
return 0;
2363 if (thisGroup == 0) {
2490 for (
uint i = 0; i < 8; ++i) {
2498 if (!(load_sounds_if_bit1_set & 1)) {
2508 unsigned int actor_id, Vec3_int_ *pVelocity,
2519 .field_60_distance_related_prolly_lod;
2520 attacker_id =
pSpriteObjects[PID_ID(attacker_id)].spell_caster_pid;
2524 pActors[actor_id].uLastCharacterIDToHit = attacker_id;
2526 pActors[actor_id].uAttributes |= ACTOR_FLEEING;
2529 dmgToRecv =
pActors[PID_ID(attacker_id)]._43B3E0_CalcDamage(a4);
2530 if (
pActors[PID_ID(attacker_id)]
2533 if (
pActors[PID_ID(attacker_id)]
2537 dmgToRecv /
pActors[PID_ID(attacker_id)]
2545 pActors[PID_ID(attacker_id)].pMonsterInfo.uAttack1Type;
2546 }
else if (a4 == 1) {
2548 pActors[PID_ID(attacker_id)].pMonsterInfo.uAttack2Type;
2552 dmgToRecv = dmgToRecv / 2;
2553 }
else if (a4 == 2) {
2557 }
else if (a4 == 3) {
2561 }
else if (a4 == 4) {
2562 v12 =
pActors[PID_ID(attacker_id)]
2563 .pMonsterInfo.field_3C_some_special_attack;
2567 finalDmg =
pActors[actor_id].CalcMagicalDamageToActor(
2569 pActors[actor_id].sCurrentHP -= finalDmg;
2577 20 * finalDmg /
pActors[actor_id].pMonsterInfo.uHP;
2578 if (pushDistance > 10) pushDistance = 10;
2588 pActors[actor_id].vVelocity.x =
2589 50 * (short)pVelocity->x;
2590 pActors[actor_id].vVelocity.y =
2591 50 * (
short)pVelocity->y;
2592 pActors[actor_id].vVelocity.z =
2593 50 * (short)pVelocity->z;
2607 unsigned __int8 extraSummonLevel;
2608 int summonMonsterBaseType;
2619 unsigned int monsterId;
2631 v19 = (
uint)(monsterId * 0.33333334);
2634 v13 = rand() % 2048;
2640 if (result != actorSector)
return;
2642 if (
result != -30000)
return;
2643 if (abs(
result - v27) > 1024)
return;
2648 if (extraSummonLevel) {
2649 if (extraSummonLevel >= 1 && extraSummonLevel <= 3)
2650 summonMonsterBaseType =
2651 summonMonsterBaseType + extraSummonLevel - 1;
2655 summonMonsterBaseType += 2;
2657 summonMonsterBaseType += 1;
2659 v7 = summonMonsterBaseType - 1;
2701 unsigned __int16
v3;
2715 v4 =
v2->uActorRadius;
2731 if (abs(v11) > v10 || v12 <= 0)
return false;
2737 if (v13 < 0) v13 = 0;
2761 unsigned __int8 v46;
2768 int target_pid_type;
2772 float radiusMultiplier;
2774 signed int target_pid;
2823 for (
int i = 1; i <= 4; i++) {
2854 for (
uint j = 0; j < 22; ++j) {
2922 target_pid_type = PID_TYPE(target_pid);
2925 radiusMultiplier = 0.5;
2927 radiusMultiplier = 1.0;
2937 for (
int i = 0; i < 22; i++) {
2987 radiusMultiplier * 307.2 < pDir->
uDistance ||
3026 [(
pActors[PID_ID(target_pid)].pMonsterInfo.uID - 1) /
3039 if (v37 >= 1 && v37 <= 4 && v36 < v38 || v37 == 1)
3046 if ((
signed int)v36 >= 10240)
3078 if (v43 > v42 && (
signed int)v36 < 10240) {
3087 v81 -=
pActors[PID_ID(target_pid)].uActorRadius;
3088 if (v81 < 0) v81 = 0;
3102 if (radiusMultiplier * 307.2 > (
double)v81)
3107 actor_id, v47, pDir);
3110 if ((
double)v81 >= radiusMultiplier * 307.2) {
3115 }
else if (v81 >= 1024) {
3119 v70 = (
signed int)(radiusMultiplier * 307.2);
3126 }
else if ((
signed int)
3135 }
else if (v45 == 2 || v45 == 3) {
3149 }
else if (radiusMultiplier * 307.2 > (
double)v81 ||
3158 if ((
double)v81 >= radiusMultiplier * 307.2) {
3163 }
else if (v81 >= 1024) {
3167 v70 = (
signed int)(radiusMultiplier * 307.2);
3171 }
else if ((
signed int)
3185 !target_pid || v81 >= 5120 || v45 != 1) {
3206 if ((
double)v81 >= radiusMultiplier * 307.2) {
3210 }
else if (v81 >= 1024) {
3213 v70 = (int)(radiusMultiplier * 307.2);
3222 if (radiusMultiplier * 307.2 > (
double)v81 ||
3241 unsigned int uNumAlive) {
3242 unsigned int uAliveActors;
3243 unsigned int uTotalActors;
3254 if (uType != 3)
return 0;
3263 return uAliveActors >= uNumAlive;
3265 return uTotalActors == uAliveActors;
3284 unsigned int uGroup) {
3335 bool bCelestia =
false;
3349 L
"%S %S %u", __FILE__, __FUNCTION__,
3368 if (!bCelestia || good)
3380 Vec3_int_ *pVelocity) {
3383 unsigned __int16 v16;
3386 int extraRecoveryTime;
3387 unsigned __int16 v43;
3388 unsigned __int16 v45;
3393 bool IsAdditionalDamagePossible;
3395 bool isLifeStealing;
3399 projectileSprite = 0;
3403 IsAdditionalDamagePossible =
false;
3412 assert(PID_ID(abs(a1)) < 4);
3414 pMonster = &
pActors[uActorID_Monster];
3419 bool hit_will_stun =
false, hit_will_paralyze =
false;
3420 if (!projectileSprite) {
3422 IsAdditionalDamagePossible =
true;
3424 uint main_hand_skill =
3426 uint main_hand_mastery =
3428 switch (main_hand_skill) {
3430 if (main_hand_mastery >= 3) {
3434 hit_will_stun =
true;
3439 if (main_hand_mastery >= 3) {
3443 hit_will_stun =
true;
3445 if (main_hand_mastery >= 4) {
3449 hit_will_paralyze =
true;
3469 if (v61 >= 5120 && !(pMonster->
uAttributes & ACTOR_ALIVE))
3471 else if (v61 >= 2560)
3477 switch (projectileSprite->
spell_id) {
3494 uDamageAmount >>= 1;
3495 IsAdditionalDamagePossible =
true;
3509 uDamageAmount >>= 1;
3510 IsAdditionalDamagePossible =
false;
3531 IsAdditionalDamagePossible =
true;
3545 IsAdditionalDamagePossible =
false;
3553 if (player->
IsWeak()) uDamageAmount /= 2;
3556 if (!projectileSprite && player->
IsUnarmed() &&
3562 uDamageAmount = v61;
3563 if (IsAdditionalDamagePossible) {
3564 if (projectileSprite) {
3567 &attackElement, &isLifeStealing);
3568 if (isLifeStealing && pMonster->
sCurrentHP > 0) {
3576 for (
int i = 0; i < 2; i++) {
3585 if (isLifeStealing && pMonster->
sCurrentHP > 0) {
3597 if (uDamageAmount == 0 && !hit_will_stun) {
3604 if (!
engine->config->NoShowDamage()) {
3606 if (projectileSprite)
3618 if (!
engine->config->NoBloodsplats()) {
3625 0.0, 0.0, (
float)v33, 0, 0);
3635 if (rand() % 100 < 20)
3638 if (!
engine->config->NoShowDamage()) {
3639 pMonsterName = (
char *)uDamageAmount;
3640 pPlayerName = player->
pName;
3643 175, player->
pName, uDamageAmount,
3651 int knockbackValue = 20 * v61 / (
signed int)pMonster->
pMonsterInfo.
uHP;
3655 extraRecoveryTime = 20;
3656 knockbackValue = 10;
3661 if (!
engine->config->NoShowDamage()) {
3662 pMonsterName = player->
pName;
3669 if (hit_will_paralyze && pMonster->
CanAct() &&
3675 if (!
engine->config->NoShowDamage()) {
3676 pMonsterName = player->
pName;
3679 636, player->
pName, pMonster);
3683 if (knockbackValue > 10) knockbackValue = 10;
3686 pVelocity->x =
fixpoint_mul(knockbackValue, pVelocity->x);
3687 pVelocity->y =
fixpoint_mul(knockbackValue, pVelocity->y);
3688 pVelocity->z =
fixpoint_mul(knockbackValue, pVelocity->z);
3689 pMonster->
vVelocity.x = 50 * (short)pVelocity->x;
3690 pMonster->
vVelocity.y = 50 * (
short)pVelocity->y;
3691 pMonster->
vVelocity.z = 50 * (short)pVelocity->z;
3758 int Victims_list[60];
3768 for (
uint i = 0; i < 16; i++) {
3819 for (
uint j = 0; j < 4; ++j) {
3821 if (for_class != -1 &&
3822 for_class ==
pPlayers[j + 1]->classType)
3824 if (for_sex != -1 && for_sex ==
pPlayers[j + 1]->uSex)
3826 if (for_race != -1 &&
3827 for_race ==
pPlayers[j + 1]->GetRace())
3840 Victims_list[
v2++] = j;
3845 if (
v2)
return Victims_list[rand() %
v2];
3847 for (
uint i = 0; i < 4; ++i) {
3853 Victims_list[
v2++] = i;
3856 return Victims_list[rand() %
v2];
3916 return (
unsigned __int16)v7;
4043 if ((
signed int)
uNumActors <= 0)
return false;
4055 pActors[i].GetActorsRelation(0)))
4153 (v7 = this->pMonsterInfo.uTreasureLevel) != 0) {
4187 if (!itemFound || rand() % 100 < 90)
4200 for (
int i = 0; i < 20; i++) {
4203 for (
int i = 1; i <= 4; i++) {
4204 for (
int j = 0; j < 22; j++) {
4205 if (
pPlayers[i]->pPlayerBuffs[j].Active())
return true;
4238 signed int okToCastSpell1;
4239 signed int okToCastSpell2;
4242 this->pMonsterInfo.uSpecialAbilityDamageDiceBonus < 3 &&
4309 v5 = rand() % v4 + 1;
4315 signed int incomingDmg) {
4369 for (
int i = 0; i < 4; i++) {
4370 if (rand() % v8 < 30)
break;
4427 unsigned int bToggle) {
4431 if (
pActors[i].uGroup == uGroupID) {
4432 pActors[i].uAttributes |= uFlag;
4433 if (uFlag == 0x10000) {
4441 if (
pActors[i].uGroup == uGroupID) {
4442 if (uFlag == 0x10000) {
4444 if (
pActors[i].uAIState != 4 &&
4449 HEXRAYS_LODWORD(
pActors[i].uAttributes) &= ~uFlag;
4536 for (
int j = 0; j < i; ++j) {
4594 pActors[i].uAttributes |= ACTOR_HOSTILE;
4609 for (
uint i = 1; i < v45; i++) {
4610 for (
uint j = 1; j < v45; ++j) {
4626 for (i = 0; i < v45; i++) {
4633 if (v19 >= 30)
break;
4642 pActors[i].uAttributes |= ACTOR_ACTIVE;
4648 pActors[i].uAttributes |= ACTOR_ACTIVE;
4657 for (j = 0; j < v45; ++j) {
4689 unsigned int uObj2ID) {
4708 __int16 next_sector;
4719 int sectors_visited;
4730 v2 = PID_ID(uObjID);
4731 switch (PID_TYPE(uObjID)) {
4741 v8 = (float)
pActors[
v2].uActorHeight * 0.69999999;
4744 obj1_z = (int)v8 +
pActors[
v2].vPosition.z;
4756 v12 = PID_ID(uObj2ID);
4757 switch (PID_TYPE(uObj2ID)) {
4773 obj2_y =
pActors[v12].vPosition.y;
4774 obj2_x =
pActors[v12].vPosition.x;
4775 v20 = (float)
pActors[v12].uActorHeight * 0.69999999;
4778 obj2_z = (int)v20 +
pActors[v12].vPosition.z;
4779 obj2_sector =
pActors[v12].uSectorID;
4790 dist_x = obj2_x - obj1_x;
4791 dist_z = obj2_z - obj1_z;
4792 dist_y = obj2_y - obj1_y;
4793 dist_3d =
integer_sqrt(dist_x * dist_x + dist_y * dist_y + dist_z * dist_z);
4795 if (dist_3d > 5120)
return 0;
4798 if (dist_3d) v25 = 65536 / dist_3d;
4802 if (obj1_x < obj2_x) {
4809 if (obj1_y < obj2_y) {
4816 if (obj1_z < obj2_z) {
4823 sectors_visited = 0;
4825 if (obj1_sector == obj2_sector)
return 1;
4827 current_sector = obj1_sector;
4828 for (
int current_portal = 0;
4838 if (current_sector != v29->
uSectorID) v31 = -v31;
4840 if (v31 >= 0 && v30->x != obj1_x && v30->y != obj1_y &&
4844 if (lower_x > v29->
pBounding.
x2 || higher_x < v29->pBounding.x1 ||
4845 lower_y > v29->
pBounding.
y2 || higher_y < v29->pBounding.y1 ||
4846 lower_z > v29->
pBounding.
z2 || higher_z < v29->pBounding.z1) {
4854 v59 = v32 + v33 + v34;
4875 if (abs(v38) >> 14 > abs(v59))
continue;
4879 if (v58 < 0)
continue;
4895 if (next_sector == current_sector)
break;
4898 current_sector = next_sector;
4901 if (next_sector == obj2_sector)
return 1;
4903 current_sector = next_sector;
4907 if (sectors_visited < 30 &&
4909 current_portal = -1;
4917 if (current_sector != obj2_sector)
return 0;
4935 memset(&actor, 0,
sizeof(
Actor));
4946 &pOut.x, &pOut.z, &pOut.y);
4962 pActors[v6].PrepareSprites(1);
4970 int duration_game_seconds) {
4973 const char *cMonsterName;
4974 unsigned int uFaceID;
4978 unsigned int uMonsterID;
4980 if (caster_skill_level == 4)
4981 cMonsterName =
"Elemental Light C";
4982 else if (caster_skill_level == 3)
4983 cMonsterName =
"Elemental Light B";
4985 cMonsterName =
"Elemental Light A";
4990 uint uActorIndex = 0;
4991 for (uActorIndex; uActorIndex <
uNumActors; uActorIndex++) {
5010 pActors[uActorIndex].word_000086_some_monster_id = uMonsterID + 1;
5013 pActors[uActorIndex].pMonsterInfo.uTreasureDiceRolls = 0;
5014 pActors[uActorIndex].pMonsterInfo.uTreasureType = 0;
5015 pActors[uActorIndex].pMonsterInfo.uExp = 0;
5016 pActors[uActorIndex].uMovementSpeed =
5018 v10 = rand() % 2048;
5019 pActors[uActorIndex].vInitialPosition.x =
5021 pActors[uActorIndex].vPosition.x =
pActors[uActorIndex].vInitialPosition.x;
5022 pActors[uActorIndex].vInitialPosition.y =
5024 pActors[uActorIndex].vPosition.y =
pActors[uActorIndex].vInitialPosition.y;
5026 pActors[uActorIndex].vPosition.z =
pActors[uActorIndex].vInitialPosition.z;
5027 pActors[uActorIndex].uTetherDistance = 256;
5028 pActors[uActorIndex].uSectorID = v21;
5029 pActors[uActorIndex].PrepareSprites(0);
5030 pActors[uActorIndex].pMonsterInfo.uHostilityType =
5032 pActors[uActorIndex].uAlly = 9999;
5033 pActors[uActorIndex].uGroup = 0;
5034 pActors[uActorIndex].uCurrentActionTime = 0;
5036 pActors[uActorIndex].uCurrentActionLength = 256;
5037 pActors[uActorIndex].UpdateAnimation();
5040 pActors[uActorIndex].vPosition.y,
5041 pActors[uActorIndex].vPosition.z);
5045 pActors[uActorIndex].vPosition.x,
pActors[uActorIndex].vPosition.y,
5056 caster_skill_level, spell_power, 0, 0);
5086 unsigned int uFaceID;
5116 switch (spawn->
uIndex - 1) {
5202 if (Source[0] ==
'0')
return;
5205 if (v57 > 4) v57 = 4;
5206 strcpy(Str2, Source);
5207 if (a4) NumToSpawn = a4;
5209 if (NumToSpawn <= 0)
return;
5210 if ((
signed int)(NumToSpawn +
uNumActors) >= 500)
return;
5223 for (
int i = v53; i < NumToSpawn; ++i) {
5243 }
else if (v24 == 2) {
5247 if (v24 != 3)
continue;
5252 sprintf(Str2, v44, pTexture);
5257 if ((
signed __int16)v50 == -1) {
5259 L
"Can't create random monster: '%S'! See MapStats.txt and "
5301 if (v37 == pSector) {
5304 if (v38 != -30000) {
5305 if (abs(v38 - a3) <= 1024) {
5321 int attacker_PID_type;
5322 signed int attacker_PID_id;
5323 unsigned int target_id;
5326 Vec3_int_ attacker_coord;
5351 attacker_PID_type = PID_TYPE(
pSpriteObjects[attacker_PID_id].spell_caster_pid);
5352 attacker_PID_id = PID_ID(
pSpriteObjects[attacker_PID_id].spell_caster_pid);
5359 if (target_type == 1) {
5364 if (a1 * a1 + v10 * v10 +
5393 pActors[target_id].CanAct()) {
5394 v15 =
pActors[target_id].vPosition.y -
5396 a1 =
pActors[target_id].vPosition.x -
5398 v44 =
pActors[target_id].vPosition.z;
5400 pActors[target_id].uActorRadius;
5402 if (a1 * a1 + v15 * v15 +
5403 (
pActors[target_id].vPosition.z +
5404 (
pActors[target_id].uActorHeight >> 1) -
5406 (
pActors[target_id].vPosition.z +
5407 (
pActors[target_id].uActorHeight >> 1) -
5409 (
unsigned int)(v19 * v19)) {
5414 pActors[target_id].vPosition.y,
5415 pActors[target_id].vPosition.z + 50,
5417 Vec3_int_::Normalize(&a1, &v48, &v44);
5435 if (a1 * a1 + v23 * v23 +
5446 for (
uint i = 0; i < 4; ++i) {
5464 for (
int actorID = 0;
5465 (
signed int)actorID < (
signed int)
uNumActors; ++actorID) {
5466 if (
pActors[actorID].CanAct()) {
5469 a1 =
pActors[actorID].vPosition.x -
5471 v31 =
pActors[actorID].vPosition.z;
5472 v48 =
pActors[actorID].vPosition.y -
5474 v44 =
pActors[actorID].vPosition.z;
5475 v32 = (
pActors[actorID].uActorHeight / 2) -
5477 v33 =
pActors[actorID].uActorRadius +
5479 if (a1 * a1 + v48 * v48 + (v31 + v32) * (v31 + v32) <
5480 (
unsigned int)(v33 * v33)) {
5486 pActors[actorID].vPosition.z + 50,
5488 Vec3_int_::Normalize(&a1, &v48, &v44);
5492 switch (attacker_PID_type) {
5500 if (sprite_obj_ptr &&
5501 pActors[attacker_PID_id].GetActorsRelation(
5535 for (
v2 = 0;
v2 < 5; ++
v2) {
5554 Vec3_int_ *pVelocity) {
5559 if (!
pActors[uActorID].IsNotAlive()) {
5566 pActors[uActorID].sCurrentHP);
5567 damage =
pActors[uActorID].CalcMagicalDamageToActor(
5569 pActors[uActorID].sCurrentHP -= damage;
5571 if (
pActors[uActorID].sCurrentHP > 0)
5576 (
signed int)
pActors[uActorID].pMonsterInfo.uHP;
5578 (
signed int)
pActors[uActorID].pMonsterInfo.uHP >
5582 pActors[uActorID].pMonsterInfo.uID,
5587 pActors[uActorID].vVelocity.x =
5588 50 * (short)pVelocity->x;
5589 pActors[uActorID].vVelocity.y =
5590 50 * (
short)pVelocity->y;
5591 pActors[uActorID].vVelocity.z =
5592 50 * (short)pVelocity->z;