Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Development

Development::Development Forum for development topics and for those interested in EQEMu development. (Not a support forum)

Reply
 
Thread Tools Display Modes
  #1  
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
  #2  
Old 06-05-2025, 04:25 AM
Torven
Sarnak
 
Join Date: Aug 2014
Posts: 76
Default

Code:
// CheckResistSpell() from November 29 2000 client.  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 __thiscall CheckResistSpell(int this,int spell,byte caster_level,int no_resist_floor,int caster,int spell_id)
{
  byte *first_effect;
  char cVar2;
  ushort race;
  char *spell_slot;
  int iVar5;		// renamed to roll in some places
  int iVar6;
  uint roll;
  short sVar8;
  int iVar9;		// renamed to success_pct, slot and resist_pct depending on use
  bool bVar10;
  byte bVar11;		// renamed to this_level, charm_limit and spell_effect depending on use
  uint resist;
  int local_1c;
  int local_18;
  short level_diff;
  int temp_resist;
  uint final_resist;
  
  final_resist = 0;
  this_level = this->GetLevel();
  local_1c = -1;
  local_18 = -1;
  level_diff = this_level - caster_level;
  if (spell_id == 982) {	// Cazic Touch
    return 0;
  }
  if (spell == 0) {
    return 100;
  }
  if ((*(int *)(caster + 0xf4) == 27)) {	// we think this is body type but not 100% sure.  body type 27 is elementals, so this may be for pets
    caster_level = caster_level + 5;
  }
  
  // Guaranteed resist if spell is a fear and target has discipline 31 active.  This was added in the Nov 15 2000 client
  iVar9 = *(int *)(*(int *)(this + 0xa0) + 0x70);
  if (iVar9 != 0 && *(int *)(iVar9 + 0x2a4) == 31) {	// Fearless disc
    spell_slot = (char *)(spell + 0x1fa);
    do {
      if (*spell_slot != -2 && *spell_slot == SE_23_FEAR) {	// SE -2 seems to denote blank but SE_10_CHARISMA with value 0 is also used to denote blank
        return 100;
      }
      spell_slot = spell_slot + 1;
    } while ((int)(spell_slot + (-0x1fa - spell)) < 4);	// check 4 slots; return 100 if fear is one of the SEs
  }
  
  // Check for mez immunity.  This was moved here from HitBySpell() in the Nov 15 2000 client
  if (caster != NULL) {
    spell_slot = (char *)(spell + 0x1fa);	// first slot
    do {
      if (*spell_slot != -2 && *spell_slot == SE_31_MEZ) {		// -2 means blank
        if (caster->GetClass() == CLASS_8_BARD) {
          if (spell->type_number == 5) {						// single target
            if (spell_id == SPELL_1753_SONG_OF_TWILIGHT) {
              success_pct = 101;
            }
            else if (this_level < 25) {
              success_pct = 95;
            }
            else if (this_level < 30) {
              success_pct = 90;
            }
            else if (this_level < 40) {
              success_pct = 85;
            }
            else if (this_level < 45) {
              success_pct = 75;
            }
            else {
              success_pct = (-(uint)(this_level < 50) & 25) + 40;		// if level < 50 then value is 65, else value is 40
            }
          }
		  // AoE Mez
          else if (this_level < 25) {
            success_pct = 66;
          }
          else if (this_level < 30) {
            success_pct = 50;
          }
          else if (this_level < 40) {
            success_pct = 33;
          }
          else {
            success_pct = (-(uint)(this_level < 45) & 4) + 18;		// if level < 45 then value is 22, else value is 18
          }
          roll = Roll0(0,99);
          if (success_pct <= roll) {
            return 100;
          }
        }
		
		// HitBySpell() still does something like this, oddly, which would theoretically result in duplicate messages.  it does the StunMe() call
        DAT_005a82f4 = 0;
        if (spell_id == SPELL_1692_RAPTURE) {
          DAT_005a82f4 = 1;
        }
        else if (spell_id == SPELL_1691_GLAMOUR_OF_KINTAZ) {
          DAT_005a82f4 = 2;
        }
        iVar9 = IsStunImmune(this);
        if (iVar9 != 0 || (cVar2 = this->GetBodyType(), cVar2 == BODY_29_DRAGON2) || cVar2 == BODY_4_GIANT || cVar2 == BODY_26_DRAGON)
		{
          if (caster->IsNPC() == 0 && caster->IsClient()) {
            if (DAT_005a82f4 == 1) {
              spell_slot = "Your target cannot be mesmerized.";
            }
            else {
              spell_slot = "Your target cannot be mesmerized (with this spell)."
            }
            StringToClient(*(int *)(caster + 0x74),spell_slot,0x121);
          }
          DAT_005a82f4 = 0;
          return 100;
        }
        DAT_005a82f4 = 0;
        break;
      }
      spell_slot = spell_slot + 1;
    } while ((int)(spell_slot + (-0x1fa - spell)) < 4);
  }
  
  // Check for NPC fear immunity and resist all spells under Sancitification disc
  iVar9 = *(int *)(this + 0xa0);
  if (iVar9 != NULL) {
    if (this->IsNPC() == 1 && (*(char *)(this + 0x9eb) == 1)) {		// seems to be some kind of NPC fear immunity flag?
      spell_slot = (char *)(spell + 0x1fa);
      do {
        if (*spell_slot != -2 && *spell_slot == SE_23_FEAR) {
          return 100;
        }
        spell_slot = spell_slot + 1;
      } while ((int)(spell_slot + (-0x1fa - spell)) < 4);
    }
    if (iVar9 != NULL && *(int *)(iVar9 + 0x70) != NULL &&
       *(int *)(*(int *)(iVar9 + 0x70) + 0x2a4) == 23 &&		// Sanctification discipline
       spell->resist_type != 0 && spell->resist_type < 6)		// checking to make sure spell is MR FR CR PR DR
	{
      return 100;
    }
  }
  
  // check for valid spell effects in the first four spell slots (this era is probably limited to 4)
  slot = 0;
  do {
    if (local_1c == -1) {
      iVar5 = IsValidSpellSlot(spell,slot);
      if (iVar5 != 0) {
        local_1c = slot;
      }
    }
    else {
      iVar6 = IsValidSpellSlot(spell,slot);
      iVar5 = slot;
      if (iVar6 != 0) break;		// exit loop as soon as we have found two valid spell slots
    }
    slot = slot + 1;
    iVar5 = -1;				// I changed local_18 to -1 here for readability because local_18 is always -1 here
  } while (slot < 4);
  local_18 = iVar5;			// if iVar5 is -1 here that means the spell has only one effect in it
  if (local_1c == -1) {		// resist spell if no valid spell effects found
    return 100;
  }
  
  cVar2 = spell->resist_type;
  if (cVar2 == SPELL_TYPE_1_MAGIC) {
    temp_resist = GetMR(caster_level);
    if (34 < caster_level && caster->GetClass() == CLASS_12_WIZARD) {	// wizard class resist modifier; added January 20 2000
      if (*(char *)(spell + 0x1fa) != SE_0_HP) {
        bVar10 = *(char *)(spell + 0x1fa) == SE_79_INSTANTHP;		// these are checking the first slot for DD effects
        goto LAB_WIZ_CONTINUE;
      }
LAB_WIZ_DO_REDUCTION:
      temp_resist = temp_resist - 10;
    }
  }
  else {
    if (cVar2 == SPELL_TYPE_2_FIRE) {
      temp_resist = GetFR(caster_level);
    }
    else {
      if (cVar2 != SPELL_TYPE_3_COLD) {
        if (cVar2 == SPELL_TYPE_4_POISON) {
          temp_resist = GetPR(caster_level);
        }
        else {
          if (cVar2 != SPELL_TYPE_5_DISEASE) {
            return 0;							// if type is not 1-5 then spell just lands
          }
          temp_resist = GetDR(caster_level);
        }
        goto LAB_CHECK_LURE;
      }
      temp_resist = GetCR(caster_level);
    }
    if (34 < caster_level) {
      bVar10 = caster->GetClass() == CLASS_12_WIZARD;
LAB_WIZ_CONTINUE:
      if (bVar10) goto LAB_WIZ_DO_REDUCTION;
    }
  }

LAB_CHECK_LURE:
  iVar9 = IsStrongLureSpell(spell,spell_id);		// CHA -5 and -6
  if (iVar9 != 0) {
    if (temp_resist < 100) {
      return 0;
    }
    resist_pct = (temp_resist + -100) / 2 + 5;
    if (45 < resist_pct) {
      resist_pct = 45;
    }
LAB_DO_LURE_ROLL:
    roll = Roll0(1,100);
    return (resist_pct <= roll) - 1 & 100;		// if resist_pct >= roll then return 0 else 100
  }
  iVar9 = IsWeakerLureSpell(spell,spell_id);		// CHA -4
  if (iVar9 != 0) {
    if (temp_resist < 50) {
      return 0;
    }
    resist_pct = (temp_resist + -50) / 2 + 5;
    if (75 < resist_pct) {
      resist_pct = 75;
    }
    goto LAB_DO_LURE_ROLL;
  }
  iVar9 = IsWeakestLureSpell(spell,spell_id);		// CHA -3
  if (iVar9 != 0) {
    if (temp_resist < 25) {
      return 0;
    }
    resist_pct = (temp_resist + -25) / 2 + 5;
    if (85 < resist_pct) {
      resist_pct = 85;
    }
    goto LAB_DO_LURE_ROLL;
  }
  
  first_effect = (byte *)(local_1c + 0x1fa + spell);
  if (*first_effect == SE_23_FEAR && this->IsNPC() == true && this->GetLevel() > 52)
  {
    return 100;
  }
  
  if (*first_effect == SE_22_CHARM && caster->IsNPC() == false)
  {
    if (this->GetClass() == CLASS_15_MERCHANT) {		// 15 is beastlord in newer clients but back then was merchants
      return 100;
    }
    if (this->GetBodyType() == BODY_6_EXTRAPLANAR) {
      return 100;
    }
    race = *(ushort *)(this + 0x34);
    if (race < 89) {
      if (race == RACE_88_CLOCKWORK_GNOME) {
        return 100;
      }
      if (race == RACE_44_FREEPORT_GUARD) {
        return 100;
      }
      if (race == RACE_67_HIGHPASS_CITIZEN) {
        return 100;
      }
      if (race == RACE_71_QEYNOS_CITIZEN) {
        return 100;
      }
      if (76 < race) {
        if (race < 79) {
          return 100;
        }
        bVar10 = race == RACE_81_RIVERVALE_CITIZEN;
LAB_CHECK_RACE:
        if (bVar10) {
          return 100;
        }
      }
    }
    else {
      if (race == RACE_90_HALAS_CITIIZEN) {
        return 100;
      }
      if (91 < race) {
        if (race < 95) {
          return 100;
        }
        if (race == RACE_106_FELGUARD) {
          return 100;
        }
        if (race == RACE_112_FAYGUARD) {
          return 100;
        }
        bVar10 = race == RACE_139_IKSAR_CITIZEN;
        goto LAB_CHECK_RACE;
      }
    }
    if (spell_id < 726) {
      if (spell_id == SPELL_725_SOLONS_SONG_OF_THE_SIRENS) {
LAB_SET_CHARM_LIMIT_37:
        charm_limit = 37;
      }
      else {
        if (spell_id < SPELL_185_TEPID_DEEDS) {
          if (spell_id != SPELL_184_ALLURE) {
            if (spell_id == SPELL_141_BEGUILE_ANIMALS) {
              charm_limit = 43;
              goto LAB_CHECK_CHARM_LIMIT;
            }
            if (spell_id != SPELL_142_ALLURE_OF_THE_WILD) {
              if (spell_id != SPELL_182_BEGUILE) {
                if (spell_id != SPELL_183_CAJOLING_WHISPERS) goto LAB_SET_CHARM_LIMIT_25;
                goto LAB_SET_CHARM_LIMIT_46;
              }
              goto LAB_SET_CHARM_LIMIT_37;
            }
          }
          goto LAB_SET_CHARM_LIMIT_51;
        }
        if (spell_id == SPELL_196_DOMINATE_UNDEAD) {
          charm_limit = 32;
        }
        else if (spell_id == SPELL_197_BEGUILE_UNDEAD) {
LAB_SET_CHARM_LIMIT_46:
          charm_limit = 46;
        }
        else {
          if (spell_id == SPELL_198_CAJOLE_UNDEAD) goto LAB_SET_CHARM_LIMIT_51;
          if (spell_id != SPELL_260_CHARM_ANIMALS) goto LAB_SET_CHARM_LIMIT_25;
          charm_limit = 33;
        }
      }
    }
    else {
      if (spell_id < 1630) {
        if (spell_id == SPELL_1629_ENSLAVE_DEATH) {
LAB_SET_CHARM_LIMIT_52:
          charm_limit = 52;
          goto LAB_CHECK_CHARM_LIMIT;
        }
        if (spell_id != SPELL_750_SOLONS_BEWITCHING_BRAVURA && spell_id != SPELL_1553_CALL_OF_KARANA) {
          if (spell_id == SPELL_1556_TUNARES_REQUEST) goto LAB_SET_CHARM_LIMIT_35;
          if (spell_id != SPELL_1624_THRALL_OF_BONES) {
LAB_SET_CHARM_LIMIT_25:
            charm_limit = 25;
            goto LAB_CHECK_CHARM_LIMIT;
          }
        }
      }
      else if (spell_id != SPELL_1705_BOLTRANS_AGACERIE) {
        if (spell_id != SPELL_1707_DICTATE) {
          if (spell_id == SPELL_1817_ALLURING_WHISPERS) {
            charm_limit = 49;
            goto LAB_CHECK_CHARM_LIMIT;
          }
          if (spell_id != SPELL_1822_PERSUADE) goto LAB_SET_CHARM_LIMIT_25;
LAB_SET_CHARM_LIMIT_35:
          charm_limit = 35;
          goto LAB_CHECK_CHARM_LIMIT;
        }
        goto LAB_SET_CHARM_LIMIT_52;
      }
LAB_SET_CHARM_LIMIT_51:
      charm_limit = 51;
    }
LAB_CHECK_CHARM_LIMIT:
    if (caster->GetClass() == CLASS_8_BARD && caster->GetLevel() < this->GetLevel() && 37 < caster->GetLevel()) {
      return 100;							// bards prevented from charming yellows and reds
    }
    if (charm_limit < this->GetLevel()) {
      if (*(int *)(caster + 0x74) == 0) {	// checking if we're an NPC
        return 100;
      }
      StringToClient(*(int *)(caster + 0x74),s_Target_Too_High_level_for_your_c_0054f770,0x121);
      return 100;
    }
  }
  
  if (this->IsNPC() == 0) {
    if (temp_resist > 99) {
      temp_resist = 99;		// players/clients are capped at 99 here
    }
  }
  else if (temp_resist > 150) {
    return 100;				// an effective resist of 151+ will make everything resist, including lifetaps
  }
  
  if ( spell_id == SPELL_127_INVOKE_FEAR) || spell_id == SPELL_59_PANIC_THE_DEAD || spell_id == SPELL_514_TERRORIZE_ANIMAL )
  {
    if (caster_level < this->GetLevel()) {
      iVar9 = -5;
    }
    else {
      iVar9 = -(caster_level / 2);
    }
    temp_resist = temp_resist + iVar9;
    if (temp_resist < 5) {
      temp_resist = 5;
    }
  }
  if ( spell_id == SPELL_1527_TREPIDATION || spell_id == SPELL_1550_REPULSE_ANIMAL || spell_id == SPELL_1532_DREAD_OF_NIGHT )
  {
    if (caster_level < this->GetLevel()) {
      iVar9 = -15;
    }
    else {
      iVar9 = -5 - (caster_level / 2);
    }
    temp_resist = temp_resist + iVar9;
    if (temp_resist < 5) {
      temp_resist = 5;			// fear has a resist floor of 5 like charm
    }
  }
  
  sVar8 = temp_resist;
  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
  ) {
    sVar8 = sVar8 - 10;		// these spells get a resist bonus/reduction
  }
  iVar9 = IsUnresistableSpell(spell,spell_id);	// this returns true for Dictate, Rapture, Enslave Death
  if (iVar9 != 0) {
    return 0;
  }
  if (spell->type_number == 13) {	// type 13 is lifetap.  lifetaps land at this point.  they never did partial damage until Sept 4 2002
    return 0;
  }
  final_resist = final_resist + sVar8;
  spell_effect = *first_effect;
  if (spell_effect < 32) {
    if (spell_effect != SE_31_MEZ) {
      if (spell_effect == SE_0_HP) {
LAB_YELLOW_RED_DD_MOD:
        if (*(int *)(this + 0xa0) == NULL || this->IsNPC() != 1 || level_diff < 1 || this->GetLevel() < 17) goto LAB_TASH_SPELLS;
        resist = final_resist + level_diff * 2;		// this is adding +2 resist value for each level the target is above the player caster
      }
      else {
        if (spell_effect != SE_3_MOVEMENTSPEED && spell_effect != SE_20_BLIND) {
          if (spell_effect == SE_22_CHARM) {
            CharismaMod(&final_resist,caster);		// modify the resist value by the charisma bonus, which is -1 for every 8 CHA above 75
          }
          else if (spell_effect != SE_23_FEAR) goto LAB_TASH_SPELLS;
        }
        if (no_resist_floor != 0 || (resist = 5, 4 < final_resist)) goto LAB_TASH_SPELLS;
      }
      final_resist = resist;	// Charm, Root, Blind, Fear have a resist floor of 5 which is set here but the function has an override parameter
      goto LAB_TASH_SPELLS;
    }
  }
  else if (spell_effect != SE_34_CONFUSE) {
    if (spell_effect == SE_44_LYCANTHROPY) {
      final_resist = final_resist + 30;
      goto LAB_TASH_SPELLS;
    }
    if (spell_effect != SE_63_BLUR) {
      if (spell_effect != SE_79_CURRENT_HP_ONCE) goto LAB_TASH_SPELLS;
      goto LAB_YELLOW_RED_DD_MOD;
    }
  }
  CharismaMod(&final_resist,caster);		// Mez, Confuse and Blur spells call this.  They get the same CHA bonus charm does
  
LAB_TASH_SPELLS:
  if ( spell_id == SPELL_676_TASHAN || spell_id == SPELL_677_TASHANI || spell_id == SPELL_678_TASHANIA ) {
    final_resist = (final_resist * 2) / 3;	// this is weird since these spells are unresistable.  vestigial?
  }
  
  // Level based resist floor
  if (this->IsNPC() == 1) {
    if (level_diff > -11 && this->GetLevel() > 14 && final_resist < 10) {	// ten levels under the caster or higher unless it's a newbie mob
      final_resist = 10;
    }
    if (level_diff < -20 || this->GetLevel() < 15) {		// deep greens and newbie mobs
      resist = 2;
    }
    else {
      resist = 5;		// everything in between
    }
  }
  else {
    resist = 1;		// on players the floor is always 1
  }
  
  if (final_resist < resist) {
    final_resist = resist;
  }
  if (final_resist > 100) {		// this will cap players and NPCs but players were already capped at 99 before this
    final_resist = 100;
  }
  
  iVar9 = IsLullSpell(spell_id);
  if (iVar9 != 0) {
    if (spell_id == SPELL_728_KELINS_LUGUBRIOUS_LAMENT) {		// bard lull was good because it's only 3 ticks I guess
      resist = 5;
      final_resist = final_resist / 2;		// bard lull gets a big resist bonus here
      if (final_resist < 5) {
        final_resist = 5;
      }
    }
    else {					// lull/pacify resist floors; lull spells were bad apparently, except bard
      this_level = this->GetLevel();
      if (this_level < 15) {
        resist = 10;
      }
      else if (this_level < 25) {
        resist = 20;
      }
      else if (this_level < 35) {
        resist = 33;
      }
      else if (this_level < 40) {
        resist = 42;
      }
      else {
        resist = (-(uint)(this_level < 50) & 0xffffffd2) + 100;	// if level < 50 then value = 54 else value is 100.  50+ mobs were immune to non-bard lull
      }
    }
    if (final_resist < resist) {
      final_resist = resist;
    }
  }
  
  // our class list has necro GM as 30.  Sony's Kunark list had enchanter GM as 30
  if (caster->IsNPC() == 1 
    && (caster->GetClass() == CLASS_14_ENCHANTER || caster->GetClass() == CLASS_30_ENCHANTER_GM)
    && caster->GetLevel() > 24)
  {
    if (this->GetLevel() < final_resist) {
      final_resist = this->GetLevel();
    }
    if (final_resist > 40) {
      final_resist = 40;			// enchanter NPCs basically ignored your resists for the most part
    }
  }
  
  resist = final_resist;
  roll = Roll0(0,100);				// the 2nd number is really n - 1, so random range would be 0 to 99
  if (roll > 98 || resist < roll) {	// the attacker is doing the roll; a 99 and attacker auto-wins; roll a 0 or 1 and resist
    return 0;	// full hit
  }
  if (local_18 != -1									// two or more spell effects?
     && (*first_effect == 0 || *first_effect == 79) 			// first slot is DD effect
     && (12 < *(byte *)(spell + 0x212))					// enchanter minimum spell level > 12
     && ((cVar2 = *(char *)(local_18 + 0x1fa + spell), cVar2 != 27 && cVar2 != 92)))	// first effect is not SE 27 and not SE 92 (cancel magic, insta hate)
  {
    return 100;		// full resist
  }
  if (*first_effect == 0 || *first_effect == 79)
  {
    resist = (resist * 100 + roll * -100) / resist;
    if (this->IsNPC())
	{
      if (level_diff > 0 && 16 < this->GetLevel()) {
        resist = resist + 5;
      }
      this_level = this->GetLevel();
      if (this_level > 29) {
        resist = (resist - 25) + this_level;
      }
      if (this_level < 15) {
        resist = resist - 5;
      }
    }
    if (spell_id == 88) {		// Harm Touch
      resist = resist - 45;
    }
    if (resist < 0) {
      resist = 0;
    }
    if (resist < 101) {
      return resist;
    }
  }
  return 100;
}
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 01:56 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3