View Single Post
  #13  
Old 06-05-2025, 04:23 AM
Torven
Sarnak
 
Join Date: Aug 2014
Posts: 76
Default

Code:
// CheckResistSpell() from March 21 2000 client. (a month before Kunark launch)  Decompiled with Ghidra
// Note that many of the subclass references and NULL checks were removed for readability
// Also note that the compiler reuses variables.  I have renamed some variables with multiple names for readability
// A return of 100 means full resist.  0 means full hit

uint __fastcall
FUN_0041a9a0(int param_1_00, undefined4 param_2_00, int spell_data, byte caster_level, int param_3, int caster, int spell_id)
{
  char cVar1;
  byte bVar2;
  undefined4 in_EAX;
  int iVar3;
  int iVar4;
  uint roll_result;
  uint charm_level_limit;
  byte bVarLevel;
  int iVar8;
  int iVar9;
  int iVar10;
  short sVar11;
  uint temp_resist;
  int local_10;
  int local_c;
  int level_diff;
  int local_4;
  
  level_diff = CONCAT22((short)((uint)in_EAX >> 0x10),GetLevel()) -
            (CONCAT31((int3)((uint)param_2_00 >> 8),caster_level) & 0xffff00ff);
  iVar10 = 0;
  iVar8 = -1;
  temp_resist = 0;
  local_c = 0xffffffff;
  local_4 = -1;
  if (spell_id == SPELL_982_CAZIC_TOUCH) {
    return 0;
  }
  if (spell_data == 0) {
    return 100;
  }
  if (*(int *)(param_1_00 + 0xa0) == 0) {
    return 100;
  }
  local_10 = param_1_00;
  bVarLevel = caster_level;
  if ((caster != 0) && (*(int *)(caster + 0xf0) == 27)) {		// probably body type.  27 is elementals
    caster_level = caster_level + 5;
    bVarLevel = caster_level;
  }
  do {
    if (((iVar8 != -1) ||
        ((iVar3 = FUN_0041a8d0(spell_data,iVar10), iVar9 = iVar10, iVar3 == 0 && (iVar9 = iVar8, false)
         ))) && (iVar4 = FUN_0041a8d0(spell_data,iVar10), iVar9 = iVar8, iVar3 = iVar10, iVar4 != 0))
    break;
    iVar10 = iVar10 + 1;
    iVar8 = iVar9;
    iVar3 = local_4;
  } while (iVar10 < 4);
  local_4 = iVar3;
  if (iVar9 == -1) {
    return 100;
  }
  local_c = iVar9;
  switch(*(undefined *)(spell_data + 0x1f9)) {
  case SPELL_RESIST_TYPE_1_MAGIC:
    iVar8 = FUN_004155e0(caster_level);
    if (((bVarLevel > 34) && (caster != 0)) && caster->GetClass() == WIZARD)) {
      if (*(char *)(spell_data + 0x1fa) == SPELL_EFFECT_TYPE_0_HP) goto LAB_0041ab3e;
      if (*(char *)(spell_data + 0x1fa) == SPELL_EFFECT_TYPE_79_INSTANTHP) {
        iVar8 = iVar8 + -10;
      }
    }
    break;
  case SPELL_RESIST_TYPE_2_FIRE:
    iVar8 = FUN_004156d0(caster_level);
    if (((bVarLevel > 34) && (caster != 0)) && caster->GetClass() == WIZARD)) {
      iVar8 = iVar8 + -10;
    }
    break;
  case SPELL_RESIST_TYPE_3_COLD:
    iVar8 = FUN_004157d0(caster_level);
    if (((bVarLevel > 34) && (caster != 0)) && caster->GetClass() == WIZARD)) {
LAB_0041ab3e:
      iVar8 = iVar8 + -10;
    }
    break;
  case SPELL_RESIST_TYPE_4_POISON:
    iVar8 = FUN_00415960(caster_level);
    break;
  case SPELL_RESIST_TYPE_5_DISEASE:
    iVar8 = FUN_004158a0(caster_level);
    break;
  default:
    goto LAB_LAND_SPELL;
  }
  cVar1 = *(char *)(iVar9 + 0x1fa + spell_data);
  if (cVar1 == SE_23_FEAR && IsNPC() && GetLevel() > 52)
  {
    return 100;
  }
  if (cVar1 == SE_22_CHARM && caster != 0 && !caster->IsNPC())
  {
    bVar2 = *(byte *)(spell_data + 0x204 + (uint)*(byte *)(caster + 0x95));		// level the caster gets this charm spell
    switch(GetRace()) {
    case RACE_44_FREEPORT_GUARD:
    case RACE_67_HIGHPASS_CITIZEN:
    case RACE_71_QEYNOS_CITIZEN:
    case RACE_77_NERIAK_CITIZEN:
    case RACE_78_ERUDITE_CITIZEN:
    case RACE_81_RIVERVALE_CITIZEN:
    case RACE_88_CLOCKWORK_GNOME:
    case RACE_90_HALAS_CITIIZEN:
    case RACE_92_GROB_CITIZEN:
    case RACE_93_OGGOK_CITIZEN:
    case RACE_94_KALADIM_CITIZEN:
    case RACE_106_FELGUARD:
    case RACE_112_FAYGUARD:
    case RACE_139_IKSAR_CITIZEN:
      goto LAB_RESIST_SPELL;			// guards are immune to charm casted by players
    case 0x2d:	// 45
    case 0x2e:
    case 0x2f:
    case 0x30:
    case 0x31:
    case 0x32:
    case 0x33:
    case 0x34:
    case 0x35:
    case 0x36:
    case 0x37:
    case 0x38:
    case 0x39:
    case 0x3a:
    case 0x3b:
    case 0x3c:
    case 0x3d:
    case 0x3e:
    case 0x3f:
    case 0x40:
    case 0x41:
    case 0x42:
    case 0x44:
    case 0x45:
    case 0x46:
    case 0x48:
    case 0x49:
    case 0x4a:
    case 0x4b:
    case 0x4c:
    case 0x4f:
    case 0x50:
    case 0x52:
    case 0x53:
    case 0x54:
    case 0x55:
    case 0x56:
    case 0x57:
    case 0x59:
    case 0x5b:
    case 0x5f:
    case 0x60:
    case 0x61:
    case 0x62:
    case 99:
    case 100:
    case 0x65:
    case 0x66:
    case 0x67:
    case 0x68:
    case 0x69:
    case 0x6b:
    case 0x6c:
    case 0x6d:
    case 0x6e:
    case 0x6f:
    case 0x71:
    case 0x72:
    case 0x73:
    case 0x74:
    case 0x75:
    case 0x76:
    case 0x77:
    case 0x78:
    case 0x79:
    case 0x7a:
    case 0x7b:
    case 0x7c:
    case 0x7d:
    case 0x7e:
    case 0x7f:
    case 0x80:
    case 0x81:
    case 0x82:
    case 0x83:
    case 0x84:
    case 0x85:
    case 0x86:
    case 0x87:
    case 0x88:
    case 0x89:
    case 0x8a:	// race 138 Yeti;  highest Kunark race is 167 though?
      bVarLevel = caster_level;		// this doesn't appear to do anything.  maybe vestigial
    }
    if (bVar2 > 50) {
      bVar2 = caster->GetLevel() / 2;
    }
    charm_level_limit = bVar2;
    if (caster->GetClass() != ENCHANTER) {
      bVar2 = *(byte *)(spell_data + 0x212);		// level enchanter gets the spell
      if (bVar2 != 0 && bVar2 < 51) {
        charm_level_limit = bVar2;
      }
    }
    charm_level_limit = (charm_level_limit * 15) / 10;
    if (charm_level_limit < 24) {
      charm_level_limit = 24;
    }
    if (spell_id < 183) {
      if (spell_id == SPELL_182_BEGUILE) {
LAB_0041acde:
        charm_level_limit = 37;
      }
      else if (spell_id == SPELL_141_BEGUILE_ANIMALS) {
        charm_level_limit = 43;
      }
      else if (spell_id == SPELL_142_ALLURE_OF_THE_WILD) {
        charm_level_limit = 51;
      }
    }
    else if (spell_id < 197) {
      if (spell_id == SPELL_196_DOMINATE_UNDEAD) {
        charm_level_limit = 32;
      }
      else {
        iVar10 = spell_id - 183;
LAB_0041acb4:
        if (iVar10 == 0) {				// Cajoling Whispers is spell ID 183;  Beguile Undead is 197
          charm_level_limit = 46;
        }
        else if (iVar10 == 1) {			// Allure is spell ID 184;  Cajole Undead is 198
          charm_level_limit = 51;
        }
      }
    }
    else if (spell_id < 261) {
      if (spell_id != SPELL_260_CHARM_ANIMALS) {
        iVar10 = spell_id - 197;
        goto LAB_0041acb4;
      }
      charm_level_limit = 33;
    }
    else if (spell_id < 1554) {
      if (spell_id == SPELL_1553_CALL_OF_KARANA) {
switchD_0041acf9_caseD_658:
        charm_level_limit = 51;
      }
      else if (spell_id == SPELL_725_SOLONS_SONG_OF_THE_SIRENS) goto LAB_0041acde;
    }
    else if (true) {
      switch(spell_id) {
      case SPELL_1556_TUNARES_REQUEST:
        charm_level_limit = 35;
        break;
      case SPELL_1624_THRALL_OF_BONES:
      case SPELL_1705_BOLTRANS_AGACERIE:
        goto switchD_0041acf9_caseD_658;
      case SPELL_1629_ENSLAVE_DEATH:
      case SPELL_1707_DICTATE:
        charm_level_limit = 52;
      }
    }
    if (charm_level_limit > 51) {
      charm_level_limit = 51;
    }
    iVar9 = local_c;
    if (charm_level_limit < GetLevel()) {
      if (*(int *)(caster + 0x74) != 0) {	// presumably some kind of IsClient() subclass check
        FUN_004ca2a0(*(int *)(caster + 0x74),s_Target_Too_High_level_for_your_c_005a8b14,0xd);
        return 100;
      }
      return 100;
    }
  }
  
  if (!IsNPC()) {
    if (iVar8 > 99) {
      iVar8 = 99;
    }
  }
  else if (iVar8 > 150) {
    return 100;
  }
  
  if (spell_id == SPELL_127_INVOKE_FEAR || spell_id == SPELL_59_PANIC_THE_DEAD || spell_id == SPELL_514_TERRORIZE_ANIMAL)
  {
    if (bVarLevel < GetLevel()) {
      iVar10 = -5;
    }
    else {
      iVar10 = -(uint)(caster_level >> 1);
    }
    iVar8 = iVar8 + iVar10;
    if (iVar8 < 5) {
      iVar8 = 5;
    }
  }
  
  if (spell_id == SPELL_1527_TREPIDATION || spell_id == SPELL_1550_REPULSE_ANIMAL || spell_id == SPELL_1532_DREAD_OF_NIGHT)
  {
    if (bVarLevel < GetLevel()) {
      iVar10 = -15;
    }
    else {
      iVar10 = -5 - caster_level / 2;
    }
    iVar8 = iVar8 + iVar10;
    if (iVar8 < 5) {
      iVar8 = 5;
    }
  }
  
  sVar11 = (short)iVar8;
  if (spell_id == SPELL_1544_ENFORCED_REVERENCE || spell_id == SPELL_1553_CALL_OF_KARANA || spell_id == SPELL_1624_THRALL_OF_BONES 
	|| spell_id == SPELL_1690_FASCINATION || spell_id == SPELL_1691_GLAMOUR_OF_KINTAZ || spell_id == SPELL_1705_BOLTRANS_AGACERIE)
  {
    sVar11 = sVar11 - 10;
  }
  
  iVar8 = IsUnresistableSpell(spell_data,spell_id);
  if (iVar8 == 0 && *(char *)(spell_data + 0x1fe) != 13) {		// spell type 13 (lifetap) will be false here and land
    temp_resist = temp_resist + (int)sVar11;
    if (true) {
      switch(*(undefined *)(iVar9 + 0x1fa + spell_data)) {
      case SE_0_CURRENTHP:
      case SE_79_CURRENT_HP_ONCE:
        if (IsNPC() && level_diff > 0 && GetLevel() > 16) {
          temp_resist = temp_resist + level_diff * 2;
        }
        break;
      case SE_22_CHARM:
        CharismaMod(&temp_resist,caster);
      case SE_3_MOVEMENTSPEED:
      case SE_20_BLIND:
      case SE_23_FEAR:
        if (param_3 == 0 && temp_resist < 5) {
          temp_resist = 5;
        }
        break;
      case SE_31_MEZ:
      case SE_34_CONFUSE:
      case SE_63_BLUR:
        CharismaMod(&temp_resist,caster);
        break;
      case SE_44_LYCANTHROPY:
        temp_resist = temp_resist + 0x1e;
      }
    }
    iVar8 = local_10;
    if (spell_id == SPELL_676_TASHAN || spell_id == SPELL_677_TASHANI || spell_id == SPELL_678_TASHANIA) {
      temp_resist = temp_resist * 2 / 3;
    }
	
	// resist floors
    if (IsNPC()) {
      if (level_diff > -11 && GetLevel() > 14 && (temp_resist < 10)) {
        temp_resist = 10;
      }
      if (level_diff < -20 || GetLevel() < 15) {
        if (temp_resist < 2) {
          temp_resist = 2;
        }
      }
      else if (temp_resist < 5) {
        temp_resist = 5;
      }
    }
    else if (temp_resist < 1) {
      temp_resist = 1;
    }
    if (temp_resist > 100) {
      temp_resist = 100;
    }
	
    iVar10 = IsLullSpell(spell_id);
    if (iVar10 != 0) {
      if (spell_id == SPELL_728_KELINS_LUGUBRIOUS_LAMENT) {
        temp_resist = temp_resist / 2;
        if (temp_resist < 5) {
          temp_resist = 5;
        }
        effective_resist = 5;			// note: the decompile code reuses the charm_level_limit variable for this
      }									// but I renamed it starting from here for readability
      else {
        bVarLevel = GetLevel();
        if (bVarLevel < 15) {
          effective_resist = 10;
        }
        else if (bVarLevel < 25) {
          effective_resist = 20;
        }
        else if (bVarLevel < 35) {
          effective_resist = 33;
        }
        else if (bVarLevel < 40) {
          effective_resist = 42;
        }
        else {
          effective_resist = (-(uint)(bVarLevel < 50) & 0xffffffd2) + 100;
        }
      }
      if (temp_resist < effective_resist) {
        temp_resist = effective_resist;
      }
    }
	
    if (caster != nullptr && caster->IsNPC()) &&
       (caster->GetClass() == ENCHANTER || caster->GetClass() == CLASS_30_ENCHANTER_GM) &&
       caster->GetLevel() > 24)
	{
      effective_resist = GetLevel();
      if (effective_resist < temp_resist) {
        temp_resist = effective_resist;
      }
      if (temp_resist > 40) {
        temp_resist = 40;
      }
    }
    effective_resist = temp_resist;
    roll_result = Roll0(0,100);
	
    if (roll_result < 99 && roll_result <= effective_resist)
	{
      if ((local_4 == -1 || // -1 means there is only one valid spell effect
          (((cVar1 = *(char *)(iVar9 + 0x1fa + spell_data), cVar1 != SE_0_CURRENTHP && (cVar1 != SE_79_CURRENT_HP_ONCE)) ||
           (*(byte *)(spell_data + 0x212) < 13)))) || (*(char *)(local_4 + 0x1fa + spell_data) == SE_27_CANCELMAGIC)
         )
	  {
        cVar1 = *(char *)(iVar9 + 0x1fa + spell_data);		// first spell effect
        if (cVar1 != SE_0_CURRENTHP && cVar1 != SE_79_CURRENT_HP_ONCE) {
          return 100;
        }
        effective_resist = (effective_resist * 100 + roll_result * -100) / effective_resist;
        if (IsNPC()) {
          if (level_diff > 0 && GetLevel() > 16) {
            effective_resist = effective_resist + 5;
          }
          bVarLevel = GetLevel();
          if (bVarLevel > 29) {
            effective_resist = (effective_resist - 25) + bVarLevel;
          }
          if (bVarLevel < 15) {
            effective_resist = effective_resist - 5;
          }
        }
        if (spell_id == SPELL_88_HARM_TOUCH) {
          effective_resist = effective_resist - 45;
        }
        if (effective_resist < 0) {
          effective_resist = 0;
        }
        if (effective_resist > 100) {
          return 100;
        }
        return effective_resist;
      }
LAB_RESIST_SPELL:
      return 100;
    }
  }
LAB_LAND_SPELL:
  return 0;
}
Reply With Quote