diff --git a/zone/attack.cpp b/zone/attack.cpp index 532a53686..85ee29e9d 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -928,231 +928,108 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate int banedmg = 0; int x = 0; - if(!against || against->GetInvul() || against->GetSpecialAbility(IMMUNE_MELEE)){ + if (!against || against->GetInvul() || against->GetSpecialAbility(IMMUNE_MELEE)) return 0; - } - //check for items being illegally attained - if(weapon_item){ - const Item_Struct *mWeaponItem = weapon_item->GetItem(); - if(mWeaponItem){ - if(mWeaponItem->ReqLevel > GetLevel()){ - return 0; - } - - if(!weapon_item->IsEquipable(GetBaseRace(), GetClass())){ - return 0; - } - } - else{ + // check for items being illegally attained + if (weapon_item) { + if (!weapon_item->GetItem()) + return 0; + + if (weapon_item->GetItemRequiredLevel(true) > GetLevel()) + return 0; + + if (!weapon_item->IsEquipable(GetBaseRace(), GetClass())) return 0; - } } - if(against->GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)){ - if(weapon_item){ + if (against->GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)) { + if (weapon_item) { // check to see if the weapon is magic - bool MagicWeapon = false; - if(weapon_item->GetItem() && weapon_item->GetItem()->Magic) - MagicWeapon = true; - else - if(spellbonuses.MagicWeapon || itembonuses.MagicWeapon) - MagicWeapon = true; + bool MagicWeapon = weapon_item->GetItemMagical(true) || spellbonuses.MagicWeapon || itembonuses.MagicWeapon; + if (MagicWeapon) { + auto rec_level = weapon_item->GetItemRecommendedLevel(true); + if (IsClient() && GetLevel() < rec_level) + dmg = CastToClient()->CalcRecommendedLevelBonus( + GetLevel(), rec_level, weapon_item->GetItemWeaponDamage(true)); else - // An augment on the weapon that is marked magic makes - // the item magical. - for(x = 0; MagicWeapon == false && x < EmuConstants::ITEM_COMMON_SIZE; x++) - { - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()) - { - if (weapon_item->GetAugment(x)->GetItem()->Magic) - MagicWeapon = true; - } - } - - if(MagicWeapon) { - - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - dmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->Damage); - } - else{ - dmg = weapon_item->GetItem()->Damage; - } - - for(int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - dmg += weapon_item->GetAugment(x)->GetItem()->Damage; - if (hate) *hate += weapon_item->GetAugment(x)->GetItem()->Damage + weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt; - } - } + dmg = weapon_item->GetItemWeaponDamage(true); dmg = dmg <= 0 ? 1 : dmg; - } - else + } else { return 0; - } - else{ - bool MagicGloves=false; + } + } else { + bool MagicGloves = false; if (IsClient()) { - ItemInst *gloves=CastToClient()->GetInv().GetItem(MainHands); - if (gloves != nullptr) { - MagicGloves = gloves->GetItem()->Magic; - } + const ItemInst *gloves = CastToClient()->GetInv().GetItem(MainHands); + if (gloves) + MagicGloves = gloves->GetItemMagical(true); } - if((GetClass() == MONK || GetClass() == BEASTLORD)) { - if(MagicGloves || GetLevel() >= 30){ + if (GetClass() == MONK || GetClass() == BEASTLORD) { + if (MagicGloves || GetLevel() >= 30) { dmg = GetHandToHandDamage(); - if (hate) *hate += dmg; + if (hate) + *hate += dmg; } - } - else if(GetOwner() && GetLevel() >= RuleI(Combat, PetAttackMagicLevel)){ //pets wouldn't actually use this but... - dmg = 1; //it gives us an idea if we can hit - } - else if(MagicGloves || GetSpecialAbility(SPECATK_MAGICAL)){ + } else if (GetOwner() && + GetLevel() >= + RuleI(Combat, PetAttackMagicLevel)) { // pets wouldn't actually use this but... + dmg = 1; // it gives us an idea if we can hit + } else if (MagicGloves || GetSpecialAbility(SPECATK_MAGICAL)) { dmg = 1; - } - else + } else return 0; } - } - else{ - if(weapon_item){ - if(weapon_item->GetItem()){ - - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - dmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->Damage); - } - else{ - dmg = weapon_item->GetItem()->Damage; + } else { + if (weapon_item) { + if (weapon_item->GetItem()) { + auto rec_level = weapon_item->GetItemRecommendedLevel(true); + if (IsClient() && GetLevel() < rec_level) { + dmg = CastToClient()->CalcRecommendedLevelBonus( + GetLevel(), rec_level, weapon_item->GetItemWeaponDamage(true)); + } else { + dmg = weapon_item->GetItemWeaponDamage(true); } - for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - dmg += weapon_item->GetAugment(x)->GetItem()->Damage; - if (hate) *hate += weapon_item->GetAugment(x)->GetItem()->Damage + weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt; - } - } dmg = dmg <= 0 ? 1 : dmg; } - } - else{ + } else { dmg = GetHandToHandDamage(); - if (hate) *hate += dmg; + if (hate) + *hate += dmg; } } int eledmg = 0; - if(!against->GetSpecialAbility(IMMUNE_MAGIC)){ - if(weapon_item && weapon_item->GetItem() && weapon_item->GetItem()->ElemDmgAmt){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - eledmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->ElemDmgAmt); - } - else{ - eledmg = weapon_item->GetItem()->ElemDmgAmt; - } - - if(eledmg) - { - eledmg = (eledmg * against->ResistSpell(weapon_item->GetItem()->ElemDmgType, 0, this) / 100); - } - } - - if(weapon_item){ - for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - if(weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt) - eledmg += (weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt * against->ResistSpell(weapon_item->GetAugment(x)->GetItem()->ElemDmgType, 0, this) / 100); - } - } - } + if (!against->GetSpecialAbility(IMMUNE_MAGIC)) { + if (weapon_item && weapon_item->GetItem() && weapon_item->GetItemElementalFlag(true)) + // the client actually has the way this is done, it does not appear to check req! + eledmg = against->ResistElementalWeaponDmg(weapon_item); } - if(against->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)){ - if(weapon_item && weapon_item->GetItem()){ - if(weapon_item->GetItem()->BaneDmgBody == against->GetBodyType()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgAmt; - } - } + if (weapon_item && weapon_item->GetItem() && + (weapon_item->GetItemBaneDamageBody(true) || weapon_item->GetItemBaneDamageRace(true))) + banedmg = against->CheckBaneDamage(weapon_item); - if(weapon_item->GetItem()->BaneDmgRace == against->GetRace()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgRaceAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgRaceAmt; - } - } - - for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgBody == against->GetBodyType()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgAmt; - } - - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgRace == against->GetRace()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgRaceAmt; - } - } - } - } - - if(!eledmg && !banedmg) - { - if(!GetSpecialAbility(SPECATK_BANE)) + if (against->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)) { + if (!eledmg && !banedmg) { + if (!GetSpecialAbility(SPECATK_BANE)) return 0; else return 1; - } - else { + } else { dmg += (banedmg + eledmg); - if (hate) *hate += banedmg; - } - } - else{ - if(weapon_item && weapon_item->GetItem()){ - if(weapon_item->GetItem()->BaneDmgBody == against->GetBodyType()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgAmt; - } - } - - if(weapon_item->GetItem()->BaneDmgRace == against->GetRace()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgRaceAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgRaceAmt; - } - } - - for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgBody == against->GetBodyType()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgAmt; - } - - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgRace == against->GetRace()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgRaceAmt; - } - } - } + if (hate) + *hate += banedmg; } + } else { dmg += (banedmg + eledmg); - if (hate) *hate += banedmg; + if (hate) + *hate += banedmg; } - if(dmg <= 0){ - return 0; - } - else - return dmg; + return std::max(0, dmg); } //note: throughout this method, setting `damage` to a negative is a way to diff --git a/zone/mob.cpp b/zone/mob.cpp index e28ccefcc..2ac1c7f5e 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -5689,4 +5689,170 @@ int32 Mob::GetMeleeMitigation() { mitigation += itembonuses.MeleeMitigationEffect; mitigation += aabonuses.MeleeMitigationEffect; return mitigation; -} \ No newline at end of file +} + +/* this is the mob being attacked. + * Pass in the weapon's ItemInst + */ +int Mob::ResistElementalWeaponDmg(const ItemInst *item) +{ + if (!item) + return 0; + int magic = 0, fire = 0, cold = 0, poison = 0, disease = 0, chromatic = 0, prismatic = 0, physical = 0, + corruption = 0; + int resist = 0; + int roll = 0; + /* this is how the client does the resist rolls for these. + * Given the difficulty of parsing out these resists, I'll trust the client + */ + if (item->GetItemElementalDamage(magic, fire, cold, poison, disease, chromatic, prismatic, physical, corruption, true)) { + if (magic) { + resist = GetMR(); + if (resist >= 201) { + magic = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + magic = 0; + else if (roll < 100) + magic = magic * roll / 100; + } + } + + if (fire) { + resist = GetFR(); + if (resist >= 201) { + fire = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + fire = 0; + else if (roll < 100) + fire = fire * roll / 100; + } + } + + if (cold) { + resist = GetCR(); + if (resist >= 201) { + cold = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + cold = 0; + else if (roll < 100) + cold = cold * roll / 100; + } + } + + if (poison) { + resist = GetPR(); + if (resist >= 201) { + poison = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + poison = 0; + else if (roll < 100) + poison = poison * roll / 100; + } + } + + if (disease) { + resist = GetDR(); + if (resist >= 201) { + disease = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + disease = 0; + else if (roll < 100) + disease = disease * roll / 100; + } + } + + if (corruption) { + resist = GetCorrup(); + if (resist >= 201) { + corruption = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + corruption = 0; + else if (roll < 100) + corruption = corruption * roll / 100; + } + } + + if (chromatic) { + resist = GetFR(); + int temp = GetCR(); + if (temp < resist) + resist = temp; + + temp = GetMR(); + if (temp < resist) + resist = temp; + + temp = GetDR(); + if (temp < resist) + resist = temp; + + temp = GetPR(); + if (temp < resist) + resist = temp; + + if (resist >= 201) { + chromatic = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + chromatic = 0; + else if (roll < 100) + chromatic = chromatic * roll / 100; + } + } + + if (prismatic) { + resist = (GetFR() + GetCR() + GetMR() + GetDR() + GetPR()) / 5; + if (resist >= 201) { + prismatic = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + prismatic = 0; + else if (roll < 100) + prismatic = prismatic * roll / 100; + } + } + + if (physical) { + resist = GetPhR(); + if (resist >= 201) { + physical = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + physical = 0; + else if (roll < 100) + physical = physical * roll / 100; + } + } + } + + return magic + fire + cold + poison + disease + chromatic + prismatic + physical + corruption; +} + +/* this is the mob being attacked. + * Pass in the weapon's ItemInst + */ +int Mob::CheckBaneDamage(const ItemInst *item) +{ + if (!item) + return 0; + + int damage = item->GetItemBaneDamageBody(GetBodyType(), true); + damage += item->GetItemBaneDamageRace(GetRace(), true); + + return damage; +} diff --git a/zone/mob.h b/zone/mob.h index 334c81e51..516bdfe8b 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -231,6 +231,8 @@ public: int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false, int level_override = -1); int ResistPhysical(int level_diff, uint8 caster_level); + int ResistElementalWeaponDmg(const ItemInst *item); + int CheckBaneDamage(const ItemInst *item); uint16 GetSpecializeSkillValue(uint16 spell_id) const; void SendSpellBarDisable(); void SendSpellBarEnable(uint16 spellid);