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

06-05-2025, 04:23 AM
|
Sarnak
|
|
Join Date: Aug 2014
Posts: 76
|
|
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;
}
|
 |
|
 |
 |
|
 |

06-05-2025, 04:25 AM
|
Sarnak
|
|
Join Date: Aug 2014
Posts: 76
|
|
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;
}
|
 |
|
 |
Thread Tools |
|
Display Modes |
Hybrid Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -4. The time now is 01:56 PM.
|
|
 |
|
 |
|
|
|
 |
|
 |
|
 |