1. void __cdecl Spell_C_GetMinMaxRange(CGUnit_C *sourceUnit, SpellRec *spellInfo, float *minRange, float *maxRange, int friendly, CGObject_C *targetObject, int difficultyID)
  2. {
  3. CGUnit_C *targetUnit; // edi@1
  4. SpellMiscRec *v8; // eax@6
  5. int v9; // eax@7
  6. SpellRangeRec_C *spellRange; // eax@9 MAPDST
  7. int v13; // eax@12
  8. CGUnitData *targetUnitFields; // eax@15 MAPDST
  9. float v17; // xmm0_4@23
  10. float v19; // xmm0_4@29
  11. float v21; // xmm0_4@32
  12. CGItem_C *v23; // eax@46
  13. CGObjectData *v24; // esi@47
  14. CGObjectData *v25; // eax@47
  15. int v26; // eax@47
  16. SmartGuid v27; // [sp+8h] [bp-14h]@14
  17. float rangeModifier; // [sp+18h] [bp-4h]@6 MAPDST
  18. targetUnit = (CGUnit_C *)targetObject;
  19. if ( !targetObject || !(((unsigned int)LOWORD(targetObject->Fields->OBJECT_FIELD_TYPE) >> 3) & 1) )
  20. targetUnit = 0;
  21. if ( CheckSpellAttribute(spellInfo, 0, 0x404) )// SPELL_ATTR0_ON_NEXT_SWING | SPELL_ATTR0_ON_NEXT_SWING_2
  22. {
  23. *(_DWORD *)maxRange = 1120403456; // 100.000000 - this means you can activate the spell from any range, not that it will go off from there (Heroic Strike)
  24. return;
  25. }
  26. rangeModifier = 0.0;
  27. v8 = (SpellMiscRec *)GetSpellMisc(difficultyID);
  28. if ( v8 )
  29. v9 = v8->RangeIndex;
  30. else
  31. v9 = 1;
  32. spellRange = (SpellRangeRec_C *)sub_674744((int)&g_spellRangeDB, v9, g_guidNull, 0, 0, 0);// LookupEntry
  33. if ( spellRange )
  34. {
  35. if ( !sourceUnit )
  36. {
  37. *minRange = spellRange->MinRange[friendly];
  38. *maxRange = spellRange->MaxRange[friendly];
  39. return;
  40. }
  41. v13 = spellRange->Flags;
  42. if ( v13 & 1 )
  43. {
  44. *(_DWORD *)minRange = 0;
  45. if ( targetUnit
  46. || (v27.Data[0] = sourceUnit->dwordED8.Data[0],
  47. v27.Data[1] = sourceUnit->dwordED8.Data[1],
  48. v27.Data[2] = sourceUnit->dwordED8.Data[2],
  49. v27.Data[3] = sourceUnit->dwordED8.Data[3],
  50. (targetUnit = (CGUnit_C *)ClntObjMgrObjectPtr(&v27, 8)) != 0) )
  51. {
  52. targetUnitFields = targetUnit->Fields;
  53. }
  54. else
  55. {
  56. targetUnitFields = sourceUnit->Fields;
  57. }
  58. rangeModifier = (float)(*(float *)&sourceUnit->Fields->UNIT_FIELD_COMBATREACH + 1.3333334) + *(float *)&targetUnitFields->UNIT_FIELD_COMBATREACH;
  59. if ( rangeModifier <= 5.0 )
  60. rangeModifier = 5.0;
  61. }
  62. else
  63. {
  64. if ( v13 & 2 )
  65. {
  66. if ( targetUnit )
  67. targetUnitFields = targetUnit->Fields;
  68. else
  69. targetUnitFields = sourceUnit->Fields;
  70. v17 = (float)(*(float *)&sourceUnit->Fields->UNIT_FIELD_COMBATREACH + 1.3333334) + *(float *)&targetUnitFields->UNIT_FIELD_COMBATREACH;
  71. *minRange = v17;
  72. if ( v17 <= 5.0 )
  73. v17 = 5.0;
  74. *minRange = v17;
  75. *minRange = spellRange->MinRange[friendly] + v17;
  76. }
  77. else
  78. {
  79. *minRange = spellRange->MinRange[friendly];
  80. }
  81. *maxRange = spellRange->MaxRange[friendly];
  82. if ( targetObject && targetObject->Fields->OBJECT_FIELD_TYPE & 0x88 )// player or creature or corpse
  83. {
  84. v19 = *(float *)&sourceUnit->Fields->UNIT_FIELD_COMBATREACH;
  85. rangeModifier = targetUnit ? *(float *)&targetUnit->Fields->UNIT_FIELD_COMBATREACH + v19 : v19 + v19;
  86. v21 = *minRange;
  87. __asm { lahf }
  88. if ( __SETP__(_AH & 0x44, 0) ) // !isnan(v21) && !isZero(v21)
  89. {
  90. if ( !(spellRange->Flags & 2) )
  91. *minRange = v21 + rangeModifier;
  92. }
  93. }
  94. }
  95. if ( targetUnit
  96. && *(_DWORD *)(sourceUnit->dword12C + 64) & 0x80D// MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT | MOVEMENTFLAG_FALLING; in other words, IsMoving()
  97. && *(_DWORD *)(targetUnit->dword12C + 64) & 0x80D// MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT | MOVEMENTFLAG_FALLING; in other words, IsMoving()
  98. && !CGUnit_C::IsWalking(sourceUnit)
  99. && !CGUnit_C::IsWalking(targetUnit)
  100. && (spellRange->Flags & 1 || ((unsigned int)LOWORD(targetUnit->Object.Fields->OBJECT_FIELD_TYPE) >> 4) & 1) )
  101. {
  102. rangeModifier = rangeModifier + 2.6666667;
  103. }
  104. }
  105. if ( CheckSpellAttribute(spellInfo, 0, 2) ) // SPELL_ATTR0_REQ_AMMO - bow range (not relevant for 6.x)
  106. {
  107. if ( sourceUnit )
  108. {
  109. if ( ((unsigned int)LOWORD(sourceUnit->Object.Fields->OBJECT_FIELD_TYPE) >> 4) & 1 )
  110. {
  111. v23 = (CGItem_C *)CGBag_C::GetRangedItemPointer((int)&sourceUnit[2].dwordE48);
  112. if ( v23 )
  113. {
  114. v24 = sourceUnit->Object.Fields;
  115. v25 = v23->Object.Fields;
  116. v27.Data[0] = v24->OBJECT_FIELD_GUID.Data[0];
  117. v24 = (CGObjectData *)((char *)v24 + 4);
  118. v27.Data[1] = v24->OBJECT_FIELD_GUID.Data[0];
  119. v24 = (CGObjectData *)((char *)v24 + 4);
  120. v27.Data[2] = v24->OBJECT_FIELD_GUID.Data[0];
  121. v27.Data[3] = v24->OBJECT_FIELD_GUID.Data[1];
  122. v26 = WowClientDB2<ItemRecSparse_C>::GetRecord((int)&g_itemSparseDB, v25->OBJECT_FIELD_ENTRY, &v27, 0, 0, 0);
  123. if ( v26 )
  124. *maxRange = (float)(*(float *)(v26 + 272) * 0.0099999998) * *maxRange;// 0.0099999998 is just the closest representable value to 0.01, use that when writing code instead (or / 100)
  125. }
  126. }
  127. }
  128. }
  129. ApplyModifiers(spellInfo, maxRange, 5); // SPELLMOD_RANGE
  130. *maxRange = *maxRange + rangeModifier;
  131. }