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)

 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
  #12  
Old 06-05-2025, 04:20 AM
Torven
Sarnak
 
Join Date: Aug 2014
Posts: 76
Default

I will paste my translations of several resist function decompiles here for convenience. These and more are found on my public Google Drive.

Code:
// CheckResistSpell() from February 16 1999 client. (original launch CD)  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

// param_1 = spell_data
// param_2 = caster level
// param_3 = no_resist_floor
// param_4 = caster_object
// param_5 = spell ID
// this + 0x38 = level
// uVar5 = roll
// uVar6 = final_resist
// sVar7 = level_diff
// 0x94 = IsNPC()
// iVar10 = start_resist


uint __thiscall
FUN_00416fd0(int this, int spell_data, byte caster_level, int no_resist_floor, undefined4 caster_object, int spell_id)
{
  char cVar1;
  byte level;
  int iVar3;
  int iVar4;
  uint roll;
  uint final_resist;
  short level_diff;
  int iVar8;
  int iVar9;
  int start_resist;
  int local_4;
  
  level = caster_level;
  start_resist = 0;
  level_diff = this->GetLevel() - caster_level;
  temp_resist = 0;
  local_4 = -1;
  if (spell_data == nullptr) {
    return 100;
  }
  iVar8 = -1;
  if (*(int *)(this + 0xa0) == nullptr) {
    return 100;
  }
  do {
    if (((iVar8 != -1) ||
        ((iVar3 = FUN_00416f50(spell_data,start_resist), iVar9 = start_resist, iVar3 == 0 && (iVar9 = iVar8, false)
         ))) && (iVar4 = FUN_00416f50(spell_data,start_resist), iVar9 = iVar8, iVar3 = start_resist, iVar4 != 0))
    break;
    start_resist = start_resist + 1;		// compiler optimizer reusing variables; this is basically 'i' for this loop
    iVar8 = iVar9;
    iVar3 = local_4;				// -1
  } while (start_resist < 4);		// only 4 spell slots max in this era
  local_4 = iVar3;
  if (iVar9 == -1) {
    return 100;			// no valid spell slots
  }
  switch(*(undefined *)(spell_data + 0x1f9)) {		// spell resist type
  case SPELL_RESIST_TYPE_1_MAGIC:
    start_resist = GetMR(level);	// attacker's level; needed to modify resist by level difference
    break;
  case SPELL_RESIST_TYPE_2_FIRE:
    start_resist = GetFR(level);
    break;
  case SPELL_RESIST_TYPE_3_COLD:
    start_resist = GetCR(level);
    break;
  case SPELL_RESIST_TYPE_4_POISON:
    start_resist = GetPR(level);
    break;
  case SPELL_RESIST_TYPE_5_DISEASE:
    start_resist = GetDR(level);
    break;
  default:
    goto LAB_LAND_SPELL;
  }
  iVar8 = *(int *)(this + 0xa0);	// used in IsNPC() lines that I removed for readability
  if (!IsNPC()) {
    if (start_resist > 99) {
      start_resist = 99;		// players capped at 99
    }
  }
  else if (start_resist > 150) {
    return 100; // guaranteed full resist if resist > 150
  }
  temp_resist = temp_resist + start_resist;
  if (true) {
    switch(*(undefined *)(iVar9 + 0x1fa + spell_data)) {		// first spell slot effect
    case SE_0_CURRENTHP:
    case SE_79_CURRENT_HP_ONCE:
      if (IsNPC() && level_diff > 0 && this->GetLevel() > 16) {
        temp_resist = temp_resist + level_diff * 2;
      }
      break;
    case SE_22_CHARM:
      ModResistCHA(&temp_resist,caster_object);
    case SE_3_MOVEMENTSPEED:
    case SE_20_BLIND:
    case SE_23_FEAR:
      if (no_resist_floor == 0 && temp_resist < 5) {
        temp_resist = 5;
      }
      break;
    case SE_31_MEZ:
    case SE_34_CONFUSE:
    case SE_63_BLUR:
      ModResistCHA(&temp_resist,caster_object);
      break;
    case SE_44_LYCANTHROPY:
      temp_resist = temp_resist + 30;
    }
  }
  
  // NPC target resist floors
  if (IsNPC()) {
    if (level_diff > -11 && this->GetLevel() > 14 && temp_resist < 10) {
      temp_resist = 10;
    }
    if ((level_diff < -20) || this->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;				// player targets floor at 1
  }
  if (temp_resist > 100) {
    temp_resist = 100;				// resist capped at 100 here for everything
  }
  final_resist = temp_resist;
  roll = RandNum(0,100);			// roll a number from 0 to 99 inclusive
  if (roll < 99 && roll <= final_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))
	{
      return 100;	// if there are multiple effects in the spell, and the first effect is damage, then full resist
    }
    cVar1 = *(char *)(iVar9 + 0x1fa + spell_data);						// get first spell effect
    if (cVar1 == SE_0_CURRENTHP || cVar1 == SE_79_CURRENT_HP_ONCE)		// only pure DD spells may partial hit
	{
	  // calculate possible partial damage; still may full resist.  Only single effect spells with SE 0 or 79 end up here
	
      final_resist = (final_resist * 100 + roll * -100) / final_resist;
      if (IsNPC())
	  {
        if (level_diff > 0 && this->GetLevel() > 16) {
          final_resist = final_resist + 5;				// yellows and reds resist more
        }
        level = this->GetLevel();		// target's level
        if (level > 29) {
          final_resist = (final_resist - 25) + level;	// level 30+ mobs resist more; the higher the level the more it resists
        }
        if (level < 15) {
          final_resist = final_resist - 5;				// newbie mobs resist less
        }
      }
      if (spell_id == SPELL_88_HARM_TOUCH) {
        final_resist = final_resist - 15;
      }
      if (final_resist < 0) {
        final_resist = 0;
      }
      if (final_resist < 101) {
        return final_resist;
      }
    }
    return 100;		// 100 means zero damage/full resist
  }
LAB_LAND_SPELL:
  return 0;		// 0 means full damage
}
Reply With Quote
 


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 02:10 AM.


 

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