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;
}