void CMagicProcess::CheckExpiredType6Skills(Unit * pTarget) { if (!pTarget->isPlayer() || !TO_USER(pTarget)->isTransformed() || (UNIXTIME - TO_USER(pTarget)->m_tTransformationStartTime) < TO_USER(pTarget)->m_sTransformationDuration) return; MagicInstance instance; instance.pSkillCaster = pTarget; instance.Type6Cancel(); }
/** * @brief Changes an NPC's hitpoints. * * @param amount The amount to adjust the HP by. * @param pAttacker The attacker. * @param bSendToAI true to update the AI server. */ void CNpc::HpChange(int amount, Unit *pAttacker /*= nullptr*/, bool bSendToAI /*= true*/) { uint16 tid = (pAttacker != nullptr ? pAttacker->GetID() : -1); // Implement damage/HP cap. if (amount < -MAX_DAMAGE) amount = -MAX_DAMAGE; else if (amount > MAX_DAMAGE) amount = MAX_DAMAGE; // Glorious copypasta. if (amount < 0 && -amount > m_iHP) m_iHP = 0; else if (amount >= 0 && m_iHP + amount > m_iMaxHP) m_iHP = m_iMaxHP; else m_iHP += amount; // NOTE: This will handle the death notification/looting. if (bSendToAI) SendHpChangeToAI(tid, amount); if (pAttacker != nullptr && pAttacker->isPlayer()) TO_USER(pAttacker)->SendTargetHP(0, GetID(), amount); }
short Unit::GetACDamage(int damage, Unit *pTarget) { // This isn't applicable to NPCs. if (isNPC() || pTarget->isNPC()) return damage; #ifdef EBENEZER if (pTarget->isDead()) return 0; CUser * pUser = TO_USER(this); uint8 weaponSlots[] = { RIGHTHAND, LEFTHAND }; foreach_array (slot, weaponSlots) { _ITEM_TABLE * pWeapon = pUser->GetItemPrototype(slot); if (pWeapon == nullptr) continue; if (pWeapon->isDagger()) damage -= damage * pTarget->m_sDaggerR / 200; else if (pWeapon->isSword()) damage -= damage * pTarget->m_sSwordR / 200; else if (pWeapon->isAxe()) damage -= damage * pTarget->m_sAxeR / 200; else if (pWeapon->isMace()) damage -= damage * pTarget->m_sMaceR / 200; else if (pWeapon->isSpear()) damage -= damage * pTarget->m_sSpearR / 200; else if (pWeapon->isBow()) damage -= damage * pTarget->m_sBowR / 200; }
/** * @brief Executes the death process. * * @param pKiller The killer. */ void CNpc::OnDeathProcess(Unit *pKiller) { CUser * pUser = TO_USER(pKiller); if (TO_NPC(this) != nullptr && pUser != nullptr) { if (pUser->isPlayer()) { if (!m_bMonster) { switch (m_tNpcType) { case NPC_BIFROST_MONUMENT: pUser->BifrostProcess(pUser); break; case NPC_PVP_MONUMENT: PVPMonumentProcess(pUser); break; case NPC_BATTLE_MONUMENT: BattleMonumentProcess(pUser); break; case NPC_HUMAN_MONUMENT: NationMonumentProcess(pUser); break; case NPC_KARUS_MONUMENT: NationMonumentProcess(pUser); break; case NPC_CHAOS_STONE: { if (pUser == nullptr) return ; if (pUser->isInPKZone()) ChaosStoneProcess(pUser,5); } break; } } } else if (m_bMonster) { if (m_sSid == 700 || m_sSid == 750) { if (pUser->CheckExistEvent(STARTER_SEED_QUEST, 1)) pUser->SaveEvent(STARTER_SEED_QUEST, 2); } else if (g_pMain->m_MonsterRespawnListArray.GetData(m_sSid) != nullptr) { if (pUser->isInPKZone() || GetZoneID() == ZONE_JURAD_MOUNTAIN) g_pMain->SpawnEventNpc(g_pMain->m_MonsterRespawnListArray.GetData(m_sSid)->sSid, true, GetZoneID(), GetX(), GetY(), GetZ(), g_pMain->m_MonsterRespawnListArray.GetData(m_sSid)->sCount); } else if (m_tNpcType == NPC_CHAOS_STONE && pUser->isInPKZone()) { ChaosStoneProcess(pUser,5); } } DateTime time; g_pMain->WriteDeathUserLogFile(string_format("[ %s - %d:%d:%d ] Killer=%s,SID=%d,Target=%s,Zone=%d,X=%d,Z=%d\n",m_bMonster ? "MONSTER" : "NPC",time.GetHour(),time.GetMinute(),time.GetSecond(),pKiller->GetName().c_str(),m_sSid,GetName().c_str(),GetZoneID(),uint16(GetX()),uint16(GetZ()))); } }
void CMagicProcess::MagicPacket(Packet & pkt, Unit * pCaster /*= nullptr*/) { MagicInstance instance; pkt >> instance.bOpcode >> instance.nSkillID; instance.pSkill = g_pMain->m_MagictableArray.GetData(instance.nSkillID); if (instance.pSkill == nullptr) { if (pCaster != nullptr) TRACE("[%s] Used skill %d but it does not exist.\n", pCaster->GetName().c_str(), instance.nSkillID); return; } pkt >> instance.sCasterID >> instance.sTargetID >> instance.sData[0] >> instance.sData[1] >> instance.sData[2] >> instance.sData[3] >> instance.sData[4] >> instance.sData[5] >> instance.sData[6]; // Prevent users from faking other players or NPCs. if (pCaster != nullptr // if it's nullptr, it's from AI. && (instance.sCasterID >= NPC_BAND || instance.sCasterID != pCaster->GetID())) return; if (instance.bSendSkillFailed) instance.bSendSkillFailed = false; CUser * pUser = TO_USER(pCaster); if (pUser != nullptr) { if (pUser->isPlayer()) { if (instance.nSkillID < 400000) { if (pUser->m_LastSkillID != instance.nSkillID) { if (instance.pSkill->bType[0] == pUser->m_LastSkillType || instance.pSkill->bType[1] == pUser->m_LastSkillType) { if ((UNIXTIME - pUser->m_LastSkillUseTime) <= PLAYER_SKILL_REQUEST_INTERVAL) { instance.bSendSkillFailed = true; } } } else if (pUser->m_LastSkillID == instance.nSkillID) { if (instance.pSkill->sReCastTime != 0) { if ((UNIXTIME - pUser->m_LastSkillUseTime) * 1000 <= (instance.pSkill->sReCastTime * 100)) { instance.bSendSkillFailed = true; } } } } } } instance.bIsRecastingSavedMagic = false; instance.Run(); }
/** * @brief Executes the death process. * * @param pKiller The killer. */ void CNpc::OnDeathProcess(Unit *pKiller) { CUser * pUser = TO_USER(pKiller); if (TO_NPC(this) != nullptr && pUser != nullptr) { if (pUser->isPlayer()) { if (!m_bMonster) { switch (m_tNpcType) { case NPC_BIFROST_MONUMENT: pUser->BifrostProcess(pUser); break; case NPC_PVP_MONUMENT: PVPMonumentProcess(pUser); break; case NPC_BATTLE_MONUMENT: BattleMonumentProcess(pUser); break; case NPC_HUMAN_MONUMENT: NationMonumentProcess(pUser); break; case NPC_KARUS_MONUMENT: NationMonumentProcess(pUser); break; } } else if (m_bMonster) { if (m_sSid == 700 || m_sSid == 750) { if (pUser->CheckExistEvent(STARTER_SEED_QUEST, 1)) pUser->SaveEvent(STARTER_SEED_QUEST, 2); } else if (g_pMain->m_MonsterRespawnListArray.GetData(m_sSid) != nullptr) { if (pUser->isInPKZone() || GetZoneID() == ZONE_JURAD_MOUNTAIN) g_pMain->SpawnEventNpc(g_pMain->m_MonsterRespawnListArray.GetData(m_sSid)->sSid, true, GetZoneID(), GetX(), GetY(), GetZ(), g_pMain->m_MonsterRespawnListArray.GetData(m_sSid)->sCount); } else if (m_tNpcType == NPC_CHAOS_STONE && pUser->isInPKZone()) { ChaosStoneProcess(pUser,5); } } } } }
/** * @brief Changes an NPC's hitpoints. * * @param amount The amount to adjust the HP by. * @param pAttacker The attacker. * @param bSendToAI true to update the AI server. */ void CNpc::HpChange(int amount, Unit *pAttacker /*= nullptr*/, bool bSendToAI /*= true*/) { // Glorious copypasta. if (amount < 0 && -amount > m_iHP) m_iHP = 0; else if (amount >= 0 && m_iHP + amount > m_iMaxHP) m_iHP = m_iMaxHP; else m_iHP += amount; if (bSendToAI) { // NOTE: This will handle the death notification/looting. Packet result(AG_NPC_HP_CHANGE); result << GetID() << pAttacker->GetID() << m_iHP << amount; Send_AIServer(&result); } if (pAttacker != nullptr && pAttacker->isPlayer()) TO_USER(pAttacker)->SendTargetHP(0, GetID(), amount); }
void CMagicProcess::MagicPacket(Packet & pkt, Unit * pCaster /*= nullptr*/) { if (g_pMain->m_IsMagicTableInUpdateProcess) return; MagicInstance instance; pkt >> instance.bOpcode >> instance.nSkillID; instance.pSkill = g_pMain->m_MagictableArray.GetData(instance.nSkillID); if (instance.pSkill == nullptr) { if (pCaster != nullptr) TRACE("[%s] Used skill %d but it does not exist.\n", pCaster->GetName().c_str(), instance.nSkillID); if (pCaster->isPlayer() && instance.nSkillID < 0) { DateTime time; g_pMain->SendFormattedNotice("%s is currently disconnect for skill hack.",Nation::ALL, pCaster->GetName().c_str()); g_pMain->WriteCheatLogFile(string_format("[ SkillHack - %d:%d:%d ] %s Disconnected for SkillHack.\n", time.GetHour(),time.GetMinute(),time.GetSecond(), pCaster->GetName().c_str())); TO_USER(pCaster)->Disconnect(); } return; } pkt >> instance.sCasterID >> instance.sTargetID >> instance.sData[0] >> instance.sData[1] >> instance.sData[2] >> instance.sData[3] >> instance.sData[4] >> instance.sData[5] >> instance.sData[6]; // Prevent users from faking other players or NPCs. if (pCaster != nullptr // if it's nullptr, it's from AI. && (instance.sCasterID >= NPC_BAND || instance.sCasterID != pCaster->GetID())) return; instance.bIsRecastingSavedMagic = false; instance.Run(); }
/** * @brief Executes the death action. * * @param pKiller The killer. */ void CNpc::OnDeath(Unit *pKiller) { if (m_NpcState == NPC_DEAD) return; ASSERT(GetMap() != nullptr); ASSERT(GetRegion() != nullptr); m_NpcState = NPC_DEAD; if (m_byObjectType == SPECIAL_OBJECT) { _OBJECT_EVENT *pEvent = GetMap()->GetObjectEvent(GetProtoID()); if (pEvent != nullptr) pEvent->byLife = 0; } Unit::OnDeath(pKiller); CNpc * pNpc = TO_NPC(this); CUser * pUser = TO_USER(pKiller); if (pNpc != nullptr && pUser != nullptr) { if (pNpc->isMonster() && pUser->isPlayer()) { if (pNpc->m_sSid == 700 || pNpc->m_sSid == 750) { if (pUser->CheckExistEvent(STARTER_SEED_QUEST, 0) || pUser->CheckExistEvent(STARTER_SEED_QUEST, 1)) pUser->SaveEvent(STARTER_SEED_QUEST, 2); } } } GetRegion()->Remove(TO_NPC(this)); SetRegion(); }
void CMagicProcess::MagicPacket(Packet & pkt, Unit * pCaster /*= nullptr*/) { bool bSkillTestMode = false; if (bSkillTestMode) { if (pCaster->isPlayer()) if (!TO_USER(pCaster)->isGM()) return; } MagicInstance instance; pkt >> instance.bOpcode >> instance.nSkillID; instance.pSkill = g_pMain->m_MagictableArray.GetData(instance.nSkillID); if (instance.pSkill == nullptr) { if (pCaster != nullptr) TRACE("[%s] Used skill %d but it does not exist.\n", pCaster->GetName().c_str(), instance.nSkillID); return; } pkt >> instance.sCasterID >> instance.sTargetID >> instance.sData[0] >> instance.sData[1] >> instance.sData[2] >> instance.sData[3] >> instance.sData[4] >> instance.sData[5] >> instance.sData[6]; // Prevent users from faking other players or NPCs. if (pCaster != nullptr // if it's nullptr, it's from AI. && (instance.sCasterID >= NPC_BAND || instance.sCasterID != pCaster->GetID())) return; instance.bIsRecastingSavedMagic = false; instance.Run(); }
bool CMagicProcess::RemoveType4Buff(uint8 byBuffType, Unit *pTarget) { // Buff must be added at this point. If it doesn't exist, we can't remove it twice. FastGuard lock(pTarget->m_buffLock); auto itr = pTarget->m_buffMap.find(byBuffType); if (itr == pTarget->m_buffMap.end()) return false; _MAGIC_TABLE * pSkill = g_pMain->m_MagictableArray.GetData(itr->second.m_nSkillID); if (pSkill == nullptr) return false; _MAGIC_TYPE4 * pType = g_pMain->m_Magictype4Array.GetData(pSkill->iNum); if (pType == nullptr) return false; // If this buff persists across logout, it should be removed here too. if (pTarget->isPlayer() && pTarget->HasSavedMagic(pSkill->iNum)) TO_USER(pTarget)->RemoveSavedMagic(pSkill->iNum); if (itr->second.isBuff()) pTarget->m_buffCount--; pTarget->m_buffMap.erase(itr); switch (byBuffType) { case BUFF_TYPE_HP_MP: pTarget->m_sMaxHPAmount = 0; pTarget->m_sMaxMPAmount = 0; break; case BUFF_TYPE_AC: case BUFF_TYPE_WEAPON_AC: if (pType->sAC == 0 && pType->sACPct > 0) pTarget->m_sACPercent -= (pType->sACPct - 100); else pTarget->m_sACAmount -= pType->sAC; break; case BUFF_TYPE_SIZE: pTarget->StateChangeServerDirect(3, ABNORMAL_NORMAL); break; case BUFF_TYPE_DAMAGE: pTarget->m_bAttackAmount = 100; break; case BUFF_TYPE_ATTACK_SPEED: pTarget->m_sAttackSpeedAmount -= (pType->bAttackSpeed - 100); break; case BUFF_TYPE_SPEED: pTarget->m_bSpeedAmount = 100; break; case BUFF_TYPE_STATS: if (pTarget->isPlayer()) { TO_USER(pTarget)->SetStatBuff(STAT_STR, 0); TO_USER(pTarget)->SetStatBuff(STAT_STA, 0); TO_USER(pTarget)->SetStatBuff(STAT_DEX, 0); TO_USER(pTarget)->SetStatBuff(STAT_INT, 0); TO_USER(pTarget)->SetStatBuff(STAT_CHA, 0); } break; case BUFF_TYPE_RESISTANCES: pTarget->m_bFireRAmount = 0; pTarget->m_bColdRAmount = 0; pTarget->m_bLightningRAmount = 0; pTarget->m_bMagicRAmount = 0; pTarget->m_bDiseaseRAmount = 0; pTarget->m_bPoisonRAmount = 0; break; case BUFF_TYPE_ACCURACY: pTarget->m_bHitRateAmount = 100; pTarget->m_sAvoidRateAmount = 100; break; case BUFF_TYPE_MAGIC_POWER: pTarget->m_sMagicAttackAmount = 0; break; case BUFF_TYPE_EXPERIENCE: if (pTarget->isPlayer()) TO_USER(pTarget)->m_sExpGainAmount = 100; break; case BUFF_TYPE_WEIGHT: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bMaxWeightAmount = 100; break; case BUFF_TYPE_WEAPON_DAMAGE: // uses pType->Attack break; case BUFF_TYPE_LOYALTY: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bNPGainAmount = 100; break; case BUFF_TYPE_NOAH_BONUS: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bNoahGainAmount = 100; break; case BUFF_TYPE_PREMIUM_MERCHANT: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bPremiumMerchant = false; break; case BUFF_TYPE_ATTACK_SPEED_ARMOR: // NOTE: This officially uses the Attack field (usually used for AP), but the skill is designed to adjust attack speed. pTarget->m_sACAmount -= pType->sAC; pTarget->m_sAttackSpeedAmount -= (pType->bAttack - 100); break; case BUFF_TYPE_DAMAGE_DOUBLE: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bPlayerAttackAmount = 100; break; case BUFF_TYPE_DISABLE_TARGETING: pTarget->m_bIsBlinded = false; break; case BUFF_TYPE_BLIND: // Only players can be blinded (at least by the only skill - "Blinding Strafe" - that uses this type). if (pTarget->isPlayer()) { pTarget->m_bIsBlinded = false; TO_USER(pTarget)->SendUserStatusUpdate(USER_STATUS_POISON, USER_STATUS_CURE); } break; case BUFF_TYPE_FREEZE: // Proportional to the target user's current HP. pTarget->m_bSpeedAmount = 100; break; case BUFF_TYPE_INSTANT_MAGIC: pTarget->m_bInstantCast = false; break; case BUFF_TYPE_DECREASE_RESIST: pTarget->m_bFireRAmount = 0; pTarget->m_bColdRAmount = 0; pTarget->m_bLightningRAmount = 0; pTarget->m_bMagicRAmount = 0; pTarget->m_bDiseaseRAmount = 0; pTarget->m_bPoisonRAmount = 0; break; case BUFF_TYPE_MAGE_ARMOR: pTarget->m_bReflectArmorType = 0; break; case BUFF_TYPE_PROHIBIT_INVIS: pTarget->m_bCanStealth = false; break; case BUFF_TYPE_RESIS_AND_MAGIC_DMG: // Elysian Web pTarget->m_bMagicDamageReduction = 100; break; case BUFF_TYPE_TRIPLEAC_HALFSPEED: // Wall of Iron pTarget->m_sACPercent -= 300; // 300%, or 3x pTarget->m_bSpeedAmount = 100; break; case BUFF_TYPE_BLOCK_CURSE: // Counter Curse pTarget->m_bBlockCurses = false; break; case BUFF_TYPE_BLOCK_CURSE_REFLECT: // Curse Refraction pTarget->m_bReflectCurses = false; break; case BUFF_TYPE_MANA_ABSORB: // Outrage / Frenzy / Mana Shield pTarget->m_bManaAbsorb = 0; break; case BUFF_TYPE_IGNORE_WEAPON: // Weapon cancellation // Disarms the opponent. (rendering them unable to attack) break; case BUFF_TYPE_VARIOUS_EFFECTS: //... whatever the event item grants. // what is tweaked in the database: AC, Attack, MaxHP, resistances break; case BUFF_TYPE_PASSION_OF_SOUL: // Passion of the Soul // Increase pet's HP by 120 break; case BUFF_TYPE_FIRM_DETERMINATION: // Firm Determination // Increase pet's AC by 20 break; case BUFF_TYPE_SPEED2: // Cold Wave pTarget->m_bSpeedAmount = 100; break; case BUFF_TYPE_UNK_EXPERIENCE: // unknown buff type, used for something relating to XP. break; case BUFF_TYPE_ATTACK_RANGE_ARMOR: // Inevitable Murderous pTarget->m_sACAmount -= 100; pTarget->m_bRadiusAmount = 0; break; case BUFF_TYPE_MIRROR_DAMAGE_PARTY: // Minak's Thorn pTarget->m_bMirrorDamage = false; pTarget->m_byMirrorAmount = 0; break; case BUFF_TYPE_DAGGER_BOW_DEFENSE: // Eskrima // Inflicts attacks as well as a bleeding curse on the enemy. Decreases 10% Dagger and Bow Defense of the enemy under the bleeding curse buff. pTarget->m_byDaggerRAmount = pTarget->m_byBowRAmount = 100; // note: overwrite the percentage for now (nothing else uses it) break; case BUFF_TYPE_LOYALTY_AMOUNT: // Santa's Present (gives an extra +2NP per kill, unlike BUFF_TYPE_LOYALTY which uses an percent). if (pTarget->isPlayer()) TO_USER(pTarget)->m_bSkillNPBonus -= 2; break; case BUFF_TYPE_NO_RECALL: // prevents teleportation. pTarget->m_bCanTeleport = true; break; case BUFF_TYPE_REDUCE_TARGET: // "Reduction" (reduces target's stats, but enlarges their character to make them easier to attack) // NOTE: Skill description says "Enlarge enemy, but decrease attack and defense rate by 5%" // There's nothing else set in the client to give those stats, and AC's reduced by 15% according to the data... // Just working with the TBL data for now (i.e. just the 15% AC reduction). if (pTarget->isPlayer()) { pTarget->StateChangeServerDirect(3, ABNORMAL_NORMAL); pTarget->m_sACPercent -= (pType->sACPct - 100); } break; case BUFF_TYPE_SILENCE_TARGET: // Silences the target to prevent them from using any skills (or potions) pTarget->m_bCanUseSkills = true; break; case BUFF_TYPE_NO_POTIONS: // "No Potion" prevents target from using potions. pTarget->m_bCanUsePotions = true; break; case BUFF_TYPE_KAUL_TRANSFORMATION: // Transforms the target into a Kaul (a pig thing), preventing you from /town'ing or attacking, but increases defense. if (pTarget->isPlayer()) { pTarget->m_bIsKaul = false; pTarget->m_sACAmount -= 500; pTarget->StateChangeServerDirect(3, TO_USER(pTarget)->m_nOldAbnormalType); } break; case BUFF_TYPE_UNDEAD: // User becomes undead, increasing defense but preventing the use of potions and converting all health received into damage. pTarget->m_bIsUndead = false; pTarget->m_sACPercent -= (pType->sACPct - 100); break; case BUFF_TYPE_UNSIGHT: // Blocks the caster's sight (not the target's). pTarget->m_bIsBlinded = false; break; case BUFF_TYPE_BLOCK_PHYSICAL_DAMAGE: // Blocks all physical damage. pTarget->m_bBlockPhysical = false; break; case BUFF_TYPE_BLOCK_MAGICAL_DAMAGE: // Blocks all magical/skill damage. pTarget->m_bBlockMagic = false; break; case BUFF_TYPE_UNK_POTION: // unknown potion, "Return of the Warrior", "Comeback potion", perhaps some sort of revive? break; case BUFF_TYPE_SLEEP: // Zantman(Sandman), puts enemies to sleep. break; case BUFF_TYPE_INVISIBILITY_POTION: // "Unidentified potion" break; case BUFF_TYPE_GODS_BLESSING: // Increases your defense/max HP break; case BUFF_TYPE_HELP_COMPENSATION: // Compensation for using the help system (to help, ask for help, both?) break; default: return false; } if (pTarget->isPlayer()) { if (pSkill->bMoral >= MORAL_ENEMY) { if (byBuffType == BUFF_TYPE_SPEED || byBuffType == BUFF_TYPE_SPEED2) TO_USER(pTarget)->SendUserStatusUpdate(USER_STATUS_SPEED, USER_STATUS_CURE); } TO_USER(pTarget)->SetUserAbility(); Packet result(WIZ_MAGIC_PROCESS, uint8(MAGIC_TYPE4_END)); result << byBuffType; TO_USER(pTarget)->Send(&result); } return true; }
// TO-DO: Clean this up (even using unit code...) bool CMagicProcess::UserRegionCheck(Unit * pSkillCaster, Unit * pSkillTarget, _MAGIC_TABLE * pSkill, int radius, short mousex /*= 0*/, short mousez /*= 0*/) { if (pSkillCaster->isDead() || pSkillTarget == nullptr) return false; switch (pSkill->bMoral) { case MORAL_PARTY_ALL: // Check that it's your party. // NPCs cannot be in parties. if (pSkillCaster->isNPC() || pSkillTarget->isNPC()) return false; if (!TO_USER(pSkillTarget)->isInParty()) return (pSkillTarget == pSkillCaster); if (TO_USER(pSkillTarget)->GetPartyID() == TO_USER(pSkillCaster)->GetPartyID() && pSkill->bType[0] != 8) goto final_test; else if (TO_USER(pSkillTarget)->GetPartyID() == TO_USER(pSkillCaster)->GetPartyID() && pSkill->bType[0] == 8) { if (pSkillTarget->GetMap()->isWarZone() && (UNIXTIME - TO_USER(pSkillTarget)->m_tLastRegeneTime < CLAN_SUMMON_TIME)) return false; goto final_test; } break; // Nation alone cannot dictate whether a unit can attack another. // As such, we must check behaviour specific to these entities. // For example: same nation players attacking each other in an arena. case MORAL_SELF_AREA: case MORAL_AREA_ENEMY: if (pSkillCaster->CanAttack(pSkillTarget)) goto final_test; break; case MORAL_AREA_FRIEND: if (pSkillTarget->GetNation() == pSkillCaster->GetNation()) goto final_test; break; case MORAL_CLAN_ALL: // NPCs cannot be in clans. if (pSkillCaster->isNPC() || pSkillTarget->isNPC()) return false; if (!TO_USER(pSkillTarget)->isInClan()) return (pSkillTarget == pSkillCaster); if (TO_USER(pSkillTarget)->GetClanID() == TO_USER(pSkillCaster)->GetClanID() && pSkill->bType[0] != 8) goto final_test; else if (TO_USER(pSkillTarget)->GetClanID() == TO_USER(pSkillCaster)->GetClanID() && pSkill->bType[0] == 8) { if (pSkillTarget->GetMap()->isWarZone() && (UNIXTIME - TO_USER(pSkillTarget)->m_tLastRegeneTime < CLAN_SUMMON_TIME)) return false; goto final_test; } break; } return false; final_test: return (radius == 0 || pSkillTarget->isInRangeSlow(mousex, mousez, (float) radius)); }
bool CMagicProcess::GrantType4Buff(_MAGIC_TABLE * pSkill, _MAGIC_TYPE4 *pType, Unit * pCaster, Unit *pTarget, bool bIsRecastingSavedMagic /*= false*/) { // Buff mustn't already be added at this point. FastGuard lock(pTarget->m_buffLock); if (!bIsRecastingSavedMagic && pTarget->m_buffMap.find(pType->bBuffType) != pTarget->m_buffMap.end()) return false; switch (pType->bBuffType) { case BUFF_TYPE_HP_MP: if (pType->sMaxHP == 0 && pType->sMaxHPPct > 0) pTarget->m_sMaxHPAmount = (pType->sMaxHPPct - 100) * (pTarget->GetMaxHealth() - pTarget->m_sMaxHPAmount) / 100; else pTarget->m_sMaxHPAmount = pType->sMaxHP; if (pType->sMaxMP == 0 && pType->sMaxMPPct > 0) pTarget->m_sMaxMPAmount = (pType->sMaxMPPct - 100) * (pTarget->GetMaxMana() - pTarget->m_sMaxMPAmount) / 100; else pTarget->m_sMaxMPAmount = pType->sMaxMP; break; case BUFF_TYPE_AC: case BUFF_TYPE_WEAPON_AC: if (pType->sAC == 0 && pType->sACPct > 0) pTarget->m_sACPercent += (pType->sACPct - 100); else pTarget->m_sACAmount += pType->sAC; break; case BUFF_TYPE_SIZE: if (pCaster->isPlayer()) { // Unfortunately there's no way to differentiate which does what. // Officially it also resorts to checking the skill ID. uint8 bEffect = ABNORMAL_NORMAL; switch (pSkill->iNum) { case 490034: // Bezoar case 490401: // Maximize Scroll bEffect = ABNORMAL_GIANT; break; case 490035: // Rice cake case 490100: // unknown, possibly intended to be "Minimize Scroll" bEffect = ABNORMAL_DWARF; break; } if (bEffect != ABNORMAL_NORMAL) pTarget->StateChangeServerDirect(3, bEffect); } break; case BUFF_TYPE_DAMAGE: pTarget->m_bAttackAmount = pType->bAttack; break; case BUFF_TYPE_ATTACK_SPEED: pTarget->m_sAttackSpeedAmount += (pType->bAttackSpeed - 100); break; case BUFF_TYPE_SPEED: pTarget->m_bSpeedAmount = pType->bSpeed; break; case BUFF_TYPE_STATS: if (pTarget->isPlayer()) { TO_USER(pTarget)->SetStatBuff(STAT_STR, pType->bStr); TO_USER(pTarget)->SetStatBuff(STAT_STA, pType->bSta); TO_USER(pTarget)->SetStatBuff(STAT_DEX, pType->bDex); TO_USER(pTarget)->SetStatBuff(STAT_INT, pType->bIntel); TO_USER(pTarget)->SetStatBuff(STAT_CHA, pType->bCha); } break; case BUFF_TYPE_RESISTANCES: pTarget->m_bFireRAmount = pType->bFireR; pTarget->m_bColdRAmount = pType->bColdR; pTarget->m_bLightningRAmount = pType->bLightningR; pTarget->m_bMagicRAmount = pType->bMagicR; pTarget->m_bDiseaseRAmount = pType->bDiseaseR; pTarget->m_bPoisonRAmount = pType->bPoisonR; break; case BUFF_TYPE_ACCURACY: pTarget->m_bHitRateAmount = pType->bHitRate; pTarget->m_sAvoidRateAmount = pType->sAvoidRate; break; case BUFF_TYPE_MAGIC_POWER: if (pTarget->isPlayer()) pTarget->m_sMagicAttackAmount = (pType->bMagicAttack - 100) * TO_USER(pTarget)->GetStat(STAT_CHA) / 100; break; case BUFF_TYPE_EXPERIENCE: if (pTarget->isPlayer()) TO_USER(pTarget)->m_sExpGainAmount = (uint8) pType->sExpPct; break; case BUFF_TYPE_WEIGHT: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bMaxWeightAmount = (uint8) pType->sExpPct; break; case BUFF_TYPE_WEAPON_DAMAGE: // uses pType->Attack break; case BUFF_TYPE_LOYALTY: if(pTarget->isPlayer()) TO_USER(pTarget)->m_bNPGainAmount = (uint8) pType->sExpPct; break; case BUFF_TYPE_NOAH_BONUS: if(pTarget->isPlayer()) TO_USER(pTarget)->m_bNoahGainAmount = (uint8) pType->sExpPct; break; case BUFF_TYPE_PREMIUM_MERCHANT: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bPremiumMerchant = true; break; case BUFF_TYPE_ATTACK_SPEED_ARMOR: // NOTE: This officially uses the Attack field (usually used for AP), but the skill is designed to adjust attack speed. pTarget->m_sACAmount += pType->sAC; pTarget->m_sAttackSpeedAmount += (pType->bAttack - 100); break; case BUFF_TYPE_DAMAGE_DOUBLE: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bPlayerAttackAmount = pType->bAttack; break; case BUFF_TYPE_DISABLE_TARGETING: pTarget->m_bIsBlinded = true; break; case BUFF_TYPE_BLIND: // The only skill that uses this buff type is "Blinding Strafe", which states: // Description: Shoots an arrow that inflicts 400% damage and blinds the enemy. Does not apply to monsters. // As such, we should not blind monsters. if (pTarget->isPlayer()) pTarget->m_bIsBlinded = true; break; case BUFF_TYPE_FREEZE: // Proportional to the target user's current HP. pTarget->m_bSpeedAmount = pType->bSpeed; break; case BUFF_TYPE_INSTANT_MAGIC: pTarget->m_bInstantCast = true; break; case BUFF_TYPE_DECREASE_RESIST: pTarget->m_bFireRAmount = -(pType->bFireR / 100) * (pTarget->m_sFireR - pTarget->m_bFireRAmount); pTarget->m_bColdRAmount = -(pType->bColdR / 100) * (pTarget->m_sColdR - pTarget->m_bColdRAmount); pTarget->m_bLightningRAmount = -(pType->bLightningR / 100) * (pTarget->m_sLightningR - pTarget->m_bLightningRAmount); pTarget->m_bMagicRAmount = -(pType->bMagicR / 100) * (pTarget->m_sMagicR - pTarget->m_bMagicRAmount); pTarget->m_bDiseaseRAmount = -(pType->bDiseaseR / 100) * (pTarget->m_sDiseaseR - pTarget->m_bDiseaseRAmount); pTarget->m_bPoisonRAmount = -(pType->bPoisonR / 100) * (pTarget->m_sPoisonR - pTarget->m_bPoisonRAmount); break; case BUFF_TYPE_MAGE_ARMOR: pTarget->m_bReflectArmorType = (pSkill->sSkill % 100); break; case BUFF_TYPE_PROHIBIT_INVIS: pTarget->m_bCanStealth = true; break; case BUFF_TYPE_RESIS_AND_MAGIC_DMG: // Elysian Web pTarget->m_bMagicDamageReduction = (uint8) pType->sExpPct; break; case BUFF_TYPE_TRIPLEAC_HALFSPEED: // Wall of Iron pTarget->m_sACPercent += 300; // 300%, or 3x pTarget->m_bSpeedAmount = pTarget->m_bSpeedAmount / 2; if (pTarget->m_bSpeedAmount == 0) pTarget->m_bSpeedAmount = 1; break; case BUFF_TYPE_BLOCK_CURSE: // Counter Curse pTarget->m_bBlockCurses = true; break; case BUFF_TYPE_BLOCK_CURSE_REFLECT: // Curse Refraction pTarget->m_bReflectCurses = true; break; case BUFF_TYPE_MANA_ABSORB: // Outrage / Frenzy / Mana Shield pTarget->m_bManaAbsorb = (uint8) pType->sExpPct; break; case BUFF_TYPE_VARIOUS_EFFECTS: //... whatever the event item grants. // what is tweaked in the database: AC, Attack, MaxHP, resistances break; case BUFF_TYPE_IGNORE_WEAPON: // Weapon cancellation // Disarms the opponent. (rendering them unable to attack) break; case BUFF_TYPE_PASSION_OF_SOUL: // Passion of the Soul // Increase pet's HP by 120 break; case BUFF_TYPE_FIRM_DETERMINATION: // Firm Determination // Increase pet's AC by 20 break; case BUFF_TYPE_SPEED2: // Cold Wave pTarget->m_bSpeedAmount = (pTarget->m_bSpeedAmount / 100 * 65); break; case BUFF_TYPE_UNK_EXPERIENCE: // unknown buff type, used for something relating to XP. break; case BUFF_TYPE_ATTACK_RANGE_ARMOR: // Inevitable Murderous pTarget->m_sACAmount += 100; pTarget->m_bRadiusAmount = pType->bRadius; break; case BUFF_TYPE_MIRROR_DAMAGE_PARTY: // Minak's Thorn pTarget->m_bMirrorDamage = true; pTarget->m_byMirrorAmount = (uint8) pType->sSpecialAmount; break; case BUFF_TYPE_DAGGER_BOW_DEFENSE: // Eskrima // Inflicts attacks as well as a bleeding curse on the enemy. Decreases 10% Dagger and Bow Defense of the enemy under the bleeding curse buff. // NOTE: overwrite the percentage for now (nothing else uses it) // Also: the amount is 20 in the database. Could be that it's divided by 2 (i.e. splitting it between dagger/bow), the skill description's inaccurate // or the description roughly reflects the final damage after player damage reduction. For now, we'll just assume it's the latter. pTarget->m_byDaggerRAmount = pTarget->m_byBowRAmount = 100 - (uint8) pType->sSpecialAmount; break; case BUFF_TYPE_LOYALTY_AMOUNT: // Santa's Present (gives an extra +2NP per kill, unlike BUFF_TYPE_LOYALTY which uses an percent). if (pTarget->isPlayer()) TO_USER(pTarget)->m_bSkillNPBonus += 2; break; case BUFF_TYPE_NO_RECALL: // prevents teleportation. pTarget->m_bCanTeleport = false; break; case BUFF_TYPE_REDUCE_TARGET: // "Reduction" (reduces target's stats, but enlarges their character to make them easier to attack) // NOTE: Skill description says "Enlarge enemy, but decrease attack and defense rate by 5%" // There's nothing else set in the client to give those stats, and AC's reduced by 15% according to the data... // Just working with the TBL data for now (i.e. just the 15% AC reduction). if (pTarget->isPlayer()) { pTarget->StateChangeServerDirect(3, ABNORMAL_GIANT); pTarget->m_sACPercent += (pType->sACPct - 100); } break; case BUFF_TYPE_SILENCE_TARGET: // Silences the target to prevent them from using any skills (or potions) pTarget->m_bCanUseSkills = false; break; case BUFF_TYPE_NO_POTIONS: // "No Potion" prevents target from using potions. pTarget->m_bCanUsePotions = false; break; case BUFF_TYPE_KAUL_TRANSFORMATION: // Transforms the target into a Kaul (a pig thing), preventing you from /town'ing or attacking, but increases defense. if (pTarget->isPlayer()) { pTarget->m_bIsKaul = true; pTarget->m_sACAmount += 500; pTarget->StateChangeServerDirect(3, pType->iNum); } break; case BUFF_TYPE_UNDEAD: // User becomes undead, increasing defense but preventing the use of potions and converting all health received into damage. pTarget->m_bIsUndead = true; pTarget->m_sACPercent += (pType->sACPct - 100); break; case BUFF_TYPE_UNSIGHT: // Blocks the caster's sight (not the target's). pTarget->m_bIsBlinded = true; break; case BUFF_TYPE_BLOCK_PHYSICAL_DAMAGE: // Blocks all physical damage. pTarget->m_bBlockPhysical = true; break; case BUFF_TYPE_BLOCK_MAGICAL_DAMAGE: // Blocks all magical/skill damage. pTarget->m_bBlockMagic = true; break; case BUFF_TYPE_UNK_POTION: // unknown potion, "Return of the Warrior", "Comeback potion", perhaps some sort of revive? break; case BUFF_TYPE_SLEEP: // Zantman(Sandman), puts enemies to sleep. break; case BUFF_TYPE_INVISIBILITY_POTION: // "Unidentified potion" break; case BUFF_TYPE_GODS_BLESSING: // Increases your defense/max HP break; case BUFF_TYPE_HELP_COMPENSATION: // Compensation for using the help system (to help, ask for help, both?) break; default: return false; } return true; }
bool CMagicProcess::GrantType4Buff(_MAGIC_TABLE * pSkill, _MAGIC_TYPE4 *pType, Unit * pCaster, Unit *pTarget, bool bIsRecastingSavedMagic /*= false*/) { // Buff mustn't already be added at this point. FastGuard lock(pTarget->m_buffLock); if (!bIsRecastingSavedMagic && pTarget->m_buffMap.find(pType->bBuffType) != pTarget->m_buffMap.end()) return false; switch (pType->bBuffType) { case BUFF_TYPE_HP_MP: if (pType->sMaxHP == 0 && pType->sMaxHPPct > 0) pTarget->m_sMaxHPAmount = (pType->sMaxHPPct - 100) * (pTarget->GetMaxHealth() - pTarget->m_sMaxHPAmount) / 100; else pTarget->m_sMaxHPAmount = pType->sMaxHP; if (pType->sMaxMP == 0 && pType->sMaxMPPct > 0) pTarget->m_sMaxMPAmount = (pType->sMaxMPPct - 100) * (pTarget->GetMaxMana() - pTarget->m_sMaxMPAmount) / 100; else pTarget->m_sMaxMPAmount = pType->sMaxMP; break; case BUFF_TYPE_AC: if (pType->sAC == 0 && pType->sACPct > 0) pTarget->m_sACAmount = pTarget->m_sTotalAc * (pType->sACPct - 100) / 100; else pTarget->m_sACAmount = pType->sAC; break; case BUFF_TYPE_SIZE: if (pCaster->isPlayer()) { // Unfortunately there's no way to differentiate which does what. // Officially it also resorts to checking the skill ID. uint8 bEffect = ABNORMAL_NORMAL; switch (pSkill->iNum) { case 490034: // Bezoar case 490401: // Maximize Scroll bEffect = ABNORMAL_GIANT; break; case 490035: // Rice cake case 490100: // unknown, possibly intended to be "Minimize Scroll" bEffect = ABNORMAL_DWARF; break; } if (bEffect != ABNORMAL_NORMAL) TO_USER(pTarget)->StateChangeServerDirect(3, bEffect); } break; case BUFF_TYPE_DAMAGE: pTarget->m_bAttackAmount = pType->bAttack; break; case BUFF_TYPE_ATTACK_SPEED: pTarget->m_bAttackSpeedAmount = pType->bAttackSpeed; break; case BUFF_TYPE_SPEED: pTarget->m_bSpeedAmount = pType->bSpeed; break; case BUFF_TYPE_STATS: if (pTarget->isPlayer()) { TO_USER(pTarget)->SetStatBuff(STAT_STR, pType->bStr); TO_USER(pTarget)->SetStatBuff(STAT_STA, pType->bSta); TO_USER(pTarget)->SetStatBuff(STAT_DEX, pType->bDex); TO_USER(pTarget)->SetStatBuff(STAT_INT, pType->bIntel); TO_USER(pTarget)->SetStatBuff(STAT_CHA, pType->bCha); } break; case BUFF_TYPE_RESISTANCES: pTarget->m_bFireRAmount = pType->bFireR; pTarget->m_bColdRAmount = pType->bColdR; pTarget->m_bLightningRAmount = pType->bLightningR; pTarget->m_bMagicRAmount = pType->bMagicR; pTarget->m_bDiseaseRAmount = pType->bDiseaseR; pTarget->m_bPoisonRAmount = pType->bPoisonR; break; case BUFF_TYPE_ACCURACY: pTarget->m_bHitRateAmount = pType->bHitRate; pTarget->m_sAvoidRateAmount = pType->sAvoidRate; break; case BUFF_TYPE_MAGIC_POWER: if (pTarget->isPlayer()) pTarget->m_sMagicAttackAmount = (pType->bMagicAttack - 100) * TO_USER(pTarget)->GetStat(STAT_CHA) / 100; break; case BUFF_TYPE_EXPERIENCE: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bExpGainAmount = pType->bExpPct; break; case BUFF_TYPE_WEIGHT: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bMaxWeightAmount = pType->bExpPct; break; case BUFF_TYPE_WEAPON_DAMAGE: // uses pType->Attack break; case BUFF_TYPE_WEAPON_AC: if (pType->sAC == 0 && pType->sACPct > 0) pTarget->m_sACAmount = pTarget->m_sTotalAc * (pType->sACPct - 100) / 100; else pTarget->m_sACAmount = pType->sAC; break; case BUFF_TYPE_LOYALTY: if(pTarget->isPlayer()) TO_USER(pTarget)->m_bNPGainAmount = pType->bExpPct; break; case BUFF_TYPE_NOAH_BONUS: if(pTarget->isPlayer()) TO_USER(pTarget)->m_bNoahGainAmount = pType->bExpPct; break; case BUFF_TYPE_PREMIUM_MERCHANT: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bPremiumMerchant = true; break; case BUFF_TYPE_ATTACK_SPEED_ARMOR: pTarget->m_sACAmount += pType->sAC; // Prevent total defense from ever going below 0 if ((pTarget->m_sACAmount + pTarget->m_sTotalAc) < 0) pTarget->m_sACAmount = -(pTarget->m_sTotalAc); pTarget->m_bAttackAmount = pType->bAttack; break; case BUFF_TYPE_DAMAGE_DOUBLE: pTarget->m_bAttackAmount = pType->bAttack; break; case BUFF_TYPE_DISABLE_TARGETING: pTarget->m_bIsBlinded = true; break; case BUFF_TYPE_BLIND: // The only skill that uses this buff type is "Blinding Strafe", which states: // Description: Shoots an arrow that inflicts 400% damage and blinds the enemy. Does not apply to monsters. // As such, we should not blind monsters. if (pTarget->isPlayer()) pTarget->m_bIsBlinded = true; break; case BUFF_TYPE_FREEZE: // Proportional to the target user's current HP. pTarget->m_bSpeedAmount = pType->bSpeed; break; case BUFF_TYPE_INSTANT_MAGIC: pTarget->m_bInstantCast = true; break; case BUFF_TYPE_DECREASE_RESIST: pTarget->m_bFireRAmount = -(pType->bFireR / 100) * (pTarget->m_sFireR - pTarget->m_bFireRAmount); pTarget->m_bColdRAmount = -(pType->bColdR / 100) * (pTarget->m_sColdR - pTarget->m_bColdRAmount); pTarget->m_bLightningRAmount = -(pType->bLightningR / 100) * (pTarget->m_sLightningR - pTarget->m_bLightningRAmount); pTarget->m_bMagicRAmount = -(pType->bMagicR / 100) * (pTarget->m_sMagicR - pTarget->m_bMagicRAmount); pTarget->m_bDiseaseRAmount = -(pType->bDiseaseR / 100) * (pTarget->m_sDiseaseR - pTarget->m_bDiseaseRAmount); pTarget->m_bPoisonRAmount = -(pType->bPoisonR / 100) * (pTarget->m_sPoisonR - pTarget->m_bPoisonRAmount); break; case BUFF_TYPE_MAGE_ARMOR: pTarget->m_bReflectArmorType = (pSkill->sSkill % 100); break; case BUFF_TYPE_PROHIBIT_INVIS: pTarget->m_bCanStealth = true; break; case BUFF_TYPE_RESIS_AND_MAGIC_DMG: // Elysian Web pTarget->m_bMagicDamageReduction = pType->bExpPct; break; case BUFF_TYPE_TRIPLEAC_HALFSPEED: // Wall of Iron pTarget->m_sACAmount += pTarget->m_sTotalAc * 2; // TO-DO: Store this value independently for restoration pTarget->m_bSpeedAmount = pTarget->m_bSpeedAmount / 2; if (pTarget->m_bSpeedAmount = 0) pTarget->m_bSpeedAmount = 1; break; case BUFF_TYPE_BLOCK_CURSE: // Counter Curse // Blocks all curses. pTarget->m_bBlockCurse = true; break; case BUFF_TYPE_BLOCK_CURSE_REFLECT: // Curse Refraction // Blocks all curses and has a chance to reflect the curse back upon the caster. break; case BUFF_TYPE_MANA_ABSORB: // Outrage / Frenzy / Mana Shield // Uses mana to receive damage (for mana shield its multiplied by 4, 100 damage = 400 mana used) break; case BUFF_TYPE_VARIOUS_EFFECTS: //... whatever the event item grants. // what is tweaked in the database: AC, Attack, MaxHP, resistances break; case BUFF_TYPE_IGNORE_WEAPON: // Weapon cancellation // Disarms the opponent. (rendering them unable to attack) break; case BUFF_TYPE_PASSION_OF_SOUL: // Passion of the Soul // Increase pet's HP by 120 break; case BUFF_TYPE_FIRM_DETERMINATION: // Firm Determination // Increase pet's AC by 20 break; case BUFF_TYPE_SPEED2: // Cold Wave pTarget->m_bSpeedAmount = (pTarget->m_bSpeedAmount / 100 * 65); break; case BUFF_TYPE_UNK_EXPERIENCE: // unknown buff type, used for something relating to XP. break; case BUFF_TYPE_ATTACK_RANGE_ARMOR: // Inevitable Murderous pTarget->m_sACAmount += 100; // Increase attack range by 1 meter. break; case BUFF_TYPE_MIRROR_DAMAGE_PARTY: // Minak's Thorn // Spreads damage received across party members and mirror's part of the damage. break; case BUFF_TYPE_DAGGER_BOW_DEFENSE: // Eskrima // Inflicts attacks as well as a bleeding curse on the enemy. Decreases 10% Dagger and Bow Defense of the enemy under the bleeding curse buff. break; case BUFF_TYPE_LOYALTY_AMOUNT: // Santa's Present (gives an extra +2NP per kill, unlike BUFF_TYPE_LOYALTY which uses an percent). break; case BUFF_TYPE_NO_RECALL: // prevents teleportation. break; case BUFF_TYPE_REDUCE_TARGET: // "Reduction" (reduces target's stats, but enlarges their character to make them easier to attack) break; case BUFF_TYPE_SILENCE_TARGET: // Silences the target to prevent them from using any skills (or potions) break; case BUFF_TYPE_NO_POTIONS: // "No Potion" prevents target from using potions. break; case BUFF_TYPE_KAUL_TRANSFORMATION: // Transforms the target into a Kaul (a pig thing), preventing you from /town'ing or attacking, but increases defense. break; case BUFF_TYPE_UNDEAD: // User becomes undead, increasing defense but preventing the use of potions and converting all health received into damage. break; case BUFF_TYPE_UNSIGHT: // Unsure how this is different to "Blind", but skill description simply reads "Blocks your[the target's] sight." break; case BUFF_TYPE_BLOCK_PHYSICAL_DAMAGE: // Blocks all physical damage. break; case BUFF_TYPE_BLOCK_MAGICAL_DAMAGE: // Blocks all magical/skill damage. break; case BUFF_TYPE_UNK_POTION: // unknown potion, "Return of the Warrior", "Comeback potion", perhaps some sort of revive? break; case BUFF_TYPE_SLEEP: // Zantman(Sandman), puts enemies to sleep. break; case BUFF_TYPE_INVISIBILITY_POTION: // "Unidentified potion" break; case BUFF_TYPE_GODS_BLESSING: // Increases your defense/max HP break; case BUFF_TYPE_HELP_COMPENSATION: // Compensation for using the help system (to help, ask for help, both?) break; default: return false; } return true; }
void CUser::Attack(Packet & pkt) { int16 sid = -1, tid = -1, damage, delaytime, distance; uint8 bType, bResult = 0; Unit * pTarget = nullptr; pkt >> bType >> bResult >> tid >> delaytime >> distance; // delaytime = delaytime / 100.0f; // distance = distance / 10.0f; if (isIncapacitated()) return; if (isInSafetyArea()) return; if (m_bInvisibilityType != INVIS_NONE) { CMagicProcess::RemoveStealth(this, INVIS_DISPEL_ON_MOVE); CMagicProcess::RemoveStealth(this, INVIS_DISPEL_ON_ATTACK); } // If you're holding a weapon, do a client-based (ugh, do not trust!) delay check. _ITEM_TABLE *pTable = GetItemPrototype(RIGHTHAND); if (pTable != nullptr) { if (delaytime < (pTable->m_sDelay + 10) // client adds 0.1 onto the interval (0.1 of 100 is 10) || distance > pTable->m_sRange) return; } // Empty handed. else if (delaytime < 100) return; pTarget = g_pMain->GetUnitPtr(tid); bResult = ATTACK_FAIL; if (pTarget != nullptr && isInAttackRange(pTarget) && CanAttack(pTarget)) { if (isAttackable(pTarget) && CanCastRHit(GetSocketID())) { if (isInTempleEventZone()) if (GetUserGroup() != -1 && !isSameUserGroup(pTarget)) return; CUser *pUser = g_pMain->GetUserPtr(GetSocketID()); if (pUser != nullptr) pUser->m_RHitRepeatList.insert(std::make_pair(GetSocketID(), UNIXTIME)); damage = GetDamage(pTarget); // Can't use R attacks in the Snow War. if (GetZoneID() == ZONE_SNOW_BATTLE && g_pMain->m_byBattleOpen == SNOW_BATTLE) damage = 0; if (damage > 0) { pTarget->HpChange(-damage, this); if (pTarget->isDead()) bResult = ATTACK_TARGET_DEAD; else bResult = ATTACK_SUCCESS; // Every attack takes a little of your weapon's durability. ItemWoreOut(ATTACK, damage); // Every hit takes a little of the defender's armour durability. if (pTarget->isPlayer()) TO_USER(pTarget)->ItemWoreOut(DEFENCE, damage); } } } Packet result(WIZ_ATTACK, bType); result << bResult << GetSocketID() << tid; SendToRegion(&result); }
// TO-DO: Clean this up (even using unit code...) bool CMagicProcess::UserRegionCheck(Unit * pSkillCaster, Unit * pSkillTarget, _MAGIC_TABLE * pSkill, int radius, short mousex /*= 0*/, short mousez /*= 0*/) { if (pSkillCaster->isDead() || pSkillTarget == NULL) return false; switch (pSkill->bMoral) { case MORAL_PARTY_ALL: // Check that it's your party. // NPCs cannot be in parties. if (pSkillCaster->isNPC() || pSkillTarget->isNPC()) return false; if (!TO_USER(pSkillTarget)->isInParty()) return (pSkillTarget == pSkillCaster); if (TO_USER(pSkillTarget)->m_sPartyIndex == TO_USER(pSkillCaster)->m_sPartyIndex && pSkill->bType[0] != 8) goto final_test; else if (TO_USER(pSkillTarget)->m_sPartyIndex == TO_USER(pSkillCaster)->m_sPartyIndex && pSkill->bType[0] == 8) { if (pSkillTarget->GetZoneID() == ZONE_BATTLE && (UNIXTIME - TO_USER(pSkillTarget)->m_tLastRegeneTime < CLAN_SUMMON_TIME)) return false; goto final_test; } break; case MORAL_SELF_AREA: case MORAL_AREA_ENEMY: if (pSkillTarget->GetNation() != pSkillCaster->GetNation()) goto final_test; break; case MORAL_AREA_FRIEND: if (pSkillTarget->GetNation() == pSkillCaster->GetNation()) goto final_test; break; case MORAL_CLAN_ALL: // NPCs cannot be in clans. if (pSkillCaster->isNPC() || pSkillTarget->isNPC()) return false; if (!TO_USER(pSkillTarget)->isInClan()) return (pSkillTarget == pSkillCaster); if (TO_USER(pSkillTarget)->GetClanID() == TO_USER(pSkillCaster)->GetClanID() && pSkill->bType[0] != 8) goto final_test; else if (TO_USER(pSkillTarget)->GetClanID() == TO_USER(pSkillCaster)->GetClanID() && pSkill->bType[0] == 8) { if (pSkillTarget->GetZoneID() == ZONE_BATTLE && (UNIXTIME - TO_USER(pSkillTarget)->m_tLastRegeneTime < CLAN_SUMMON_TIME)) return false; goto final_test; } break; } return false; final_test: if (pSkillTarget->GetRegion() != pSkillCaster->GetRegion()) return false; if (radius != 0) { float temp_x = pSkillTarget->GetX() - mousex; float temp_z = pSkillTarget->GetZ() - mousez; float distance = pow(temp_x, 2.0f) + pow(temp_z, 2.0f); if (distance > pow((float)radius, 2.0f)) return false; } return true; // Target is in the area. }
bool CMagicProcess::RemoveType4Buff(uint8 byBuffType, CUser *pTarget) { switch (byBuffType) { case BUFF_TYPE_HP_MP: pTarget->m_sMaxHPAmount = 0; pTarget->m_sMaxMPAmount = 0; break; case BUFF_TYPE_AC: pTarget->m_sACAmount = 0; break; case BUFF_TYPE_SIZE: pTarget->StateChangeServerDirect(3, ABNORMAL_NORMAL); break; case BUFF_TYPE_DAMAGE: pTarget->m_bAttackAmount = 100; break; case BUFF_TYPE_ATTACK_SPEED: pTarget->m_bAttackSpeedAmount = 100; break; case BUFF_TYPE_SPEED: pTarget->m_bSpeedAmount = 100; break; case BUFF_TYPE_STATS: TO_USER(pTarget)->setStatBuff(STAT_STR, 0); TO_USER(pTarget)->setStatBuff(STAT_STA, 0); TO_USER(pTarget)->setStatBuff(STAT_DEX, 0); TO_USER(pTarget)->setStatBuff(STAT_INT, 0); TO_USER(pTarget)->setStatBuff(STAT_CHA, 0); break; case BUFF_TYPE_RESISTANCES: pTarget->m_bFireRAmount = 0; pTarget->m_bColdRAmount = 0; pTarget->m_bLightningRAmount = 0; pTarget->m_bMagicRAmount = 0; pTarget->m_bDiseaseRAmount = 0; pTarget->m_bPoisonRAmount = 0; break; case BUFF_TYPE_ACCURACY: pTarget->m_bHitRateAmount = 100; pTarget->m_sAvoidRateAmount = 100; break; case BUFF_TYPE_MAGIC_POWER: pTarget->m_sMagicAttackAmount = 0; break; case BUFF_TYPE_EXPERIENCE: pTarget->m_bExpGainAmount = 100; break; case BUFF_TYPE_WEIGHT: pTarget->m_bMaxWeightAmount = 100; break; case BUFF_TYPE_WEAPON_DAMAGE: // uses pType->Attack break; case BUFF_TYPE_WEAPON_AC: pTarget->m_sACAmount = 0; break; case BUFF_TYPE_LOYALTY: // uses pType->ExpPct break; case BUFF_TYPE_NOAH_BONUS: break; case BUFF_TYPE_PREMIUM_MERCHANT: TO_USER(pTarget)->m_bPremiumMerchant = false; break; case BUFF_TYPE_ATTACK_SPEED_ARMOR: // should this revert a specific amount? if so, we need to store it so that we know how much. // most likely though, it's just recalculated. pTarget->m_sACAmount = 0; pTarget->m_bAttackAmount = 100; break; case BUFF_TYPE_DAMAGE_DOUBLE: pTarget->m_bAttackAmount = 100; break; case BUFF_TYPE_DISABLE_TARGETING: pTarget->m_bIsBlinded = false; break; case BUFF_TYPE_BLIND: pTarget->m_bIsBlinded = false; if (pTarget->isPlayer()) TO_USER(pTarget)->SendUserStatusUpdate(USER_STATUS_BLIND, USER_STATUS_CURE); break; case BUFF_TYPE_FREEZE: // Proportional to the target user's current HP. pTarget->m_bSpeedAmount = 100; break; case BUFF_TYPE_INSTANT_MAGIC: pTarget->m_bInstantCast = false; break; case BUFF_TYPE_DECREASE_RESIST: pTarget->m_bFireRAmount = 0; pTarget->m_bColdRAmount = 0; pTarget->m_bLightningRAmount = 0; pTarget->m_bMagicRAmount = 0; pTarget->m_bDiseaseRAmount = 0; pTarget->m_bPoisonRAmount = 0; break; case BUFF_TYPE_MAGE_ARMOR: pTarget->m_bReflectArmorType = 0; break; case BUFF_TYPE_PROHIBIT_INVIS: pTarget->m_bCanStealth = false; break; case BUFF_TYPE_RESIS_AND_MAGIC_DMG: // Elysian Web // Increases your magic resistance to block an additional 30% magic damage. break; case BUFF_TYPE_TRIPLEAC_HALFSPEED: // Wall of Iron pTarget->m_sACAmount -= (pTarget->m_sTotalAc / 3 * 2); pTarget->m_bSpeedAmount = 100; if (pTarget->m_bSpeedAmount = 0) pTarget->m_bSpeedAmount = 1; break; case BUFF_TYPE_BLOCK_CURSE: // Counter Curse // Blocks all curses. break; case BUFF_TYPE_BLOCK_CURSE_REFLECT: // Curse Refraction // Blocks all curses and has a chance to reflect the curse back upon the caster. break; case BUFF_TYPE_MANA_ABSORB: // Outrage / Frenzy / Mana Shield // Uses mana to receive damage (for mana shield its multiplied by 4, 100 damage = 400 mana used) break; case BUFF_TYPE_IGNORE_WEAPON: // Weapon cancellation // Disarms the opponent. (rendering them unable to attack) break; case BUFF_TYPE_PASSION_OF_SOUL: // Passion of the Soul // Increase pet's HP by 120 break; case BUFF_TYPE_FIRM_DETERMINATION: // Firm Determination // Increase pet's AC by 20 break; case BUFF_TYPE_SPEED2: // Cold Wave pTarget->m_bSpeedAmount = 100; break; case BUFF_TYPE_ATTACK_RANGE_ARMOR: // Inevitable Murderous pTarget->m_sACAmount -= 100; // Buff type increases attack range by 1 meter. break; case BUFF_TYPE_MIRROR_DAMAGE_PARTY: // Minak's Thorn // Spreads damage received across party members and mirror's part of the damage. break; default: return false; } pTarget->SetSlotItemValue(); pTarget->SetUserAbility(); pTarget->SendItemMove(2); pTarget->Send2AI_UserUpdateInfo(); pTarget->m_sDuration[byBuffType - 1] = 0; pTarget->m_tStartTime[byBuffType - 1] = 0; pTarget->m_bType4Buff[byBuffType - 1] = 0; Packet result(WIZ_MAGIC_PROCESS, uint8(MAGIC_TYPE4_END)); result << byBuffType; pTarget->Send(&result); return true; }
bool CMagicProcess::GrantType4Buff(_MAGIC_TABLE * pSkill, _MAGIC_TYPE4 *pType, Unit * pCaster, CUser *pTarget) { switch (pType->bBuffType) { case BUFF_TYPE_HP_MP: if (pType->sMaxHP == 0 && pType->sMaxHPPct > 0) pTarget->m_sMaxHPAmount = (pType->sMaxHPPct - 100) * (pTarget->GetMaxHealth() - pTarget->m_sMaxHPAmount) / 100; else pTarget->m_sMaxHPAmount = pType->sMaxHP; if (pType->sMaxMP == 0 && pType->sMaxMPPct > 0) pTarget->m_sMaxMPAmount = (pType->sMaxMPPct - 100) * (pTarget->m_iMaxMp - pTarget->m_sMaxMPAmount) / 100; else pTarget->m_sMaxMPAmount = pType->sMaxMP; break; case BUFF_TYPE_AC: if (pType->sAC == 0 && pType->sACPct > 0) pTarget->m_sACAmount = pTarget->m_sTotalAc * (pType->sACPct - 100) / 100; else pTarget->m_sACAmount = pType->sAC; break; case BUFF_TYPE_SIZE: if (pCaster->isPlayer()) TO_USER(pCaster)->StateChangeServerDirect(3, ABNORMAL_NORMAL); break; case BUFF_TYPE_DAMAGE: pTarget->m_bAttackAmount = pType->bAttack; break; case BUFF_TYPE_ATTACK_SPEED: pTarget->m_bAttackSpeedAmount = pType->bAttackSpeed; break; case BUFF_TYPE_SPEED: pTarget->m_bSpeedAmount = pType->bSpeed; break; case BUFF_TYPE_STATS: if (pCaster->isPlayer()) { TO_USER(pTarget)->setStatBuff(STAT_STR, pType->bStr); TO_USER(pTarget)->setStatBuff(STAT_STA, pType->bSta); TO_USER(pTarget)->setStatBuff(STAT_DEX, pType->bDex); TO_USER(pTarget)->setStatBuff(STAT_INT, pType->bIntel); TO_USER(pTarget)->setStatBuff(STAT_CHA, pType->bCha); } break; case BUFF_TYPE_RESISTANCES: pTarget->m_bFireRAmount = pType->bFireR; pTarget->m_bColdRAmount = pType->bColdR; pTarget->m_bLightningRAmount = pType->bLightningR; pTarget->m_bMagicRAmount = pType->bMagicR; pTarget->m_bDiseaseRAmount = pType->bDiseaseR; pTarget->m_bPoisonRAmount = pType->bPoisonR; break; case BUFF_TYPE_ACCURACY: pTarget->m_bHitRateAmount = pType->bHitRate; pTarget->m_sAvoidRateAmount = pType->sAvoidRate; break; case BUFF_TYPE_MAGIC_POWER: pTarget->m_sMagicAttackAmount = (pType->bMagicAttack - 100) * TO_USER(pTarget)->getStat(STAT_CHA) / 100; break; case BUFF_TYPE_EXPERIENCE: pTarget->m_bExpGainAmount = pType->bExpPct; break; case BUFF_TYPE_WEIGHT: pTarget->m_bMaxWeightAmount = pType->bExpPct; break; case BUFF_TYPE_WEAPON_DAMAGE: // uses pType->Attack break; case BUFF_TYPE_WEAPON_AC: if (pType->sAC == 0 && pType->sACPct > 0) pTarget->m_sACAmount = pTarget->m_sTotalAc * (pType->sACPct - 100) / 100; else pTarget->m_sACAmount = pType->sAC; break; case BUFF_TYPE_LOYALTY: // uses pType->ExpPct break; case BUFF_TYPE_NOAH_BONUS: break; case BUFF_TYPE_PREMIUM_MERCHANT: TO_USER(pTarget)->m_bPremiumMerchant = true; break; case BUFF_TYPE_ATTACK_SPEED_ARMOR: pTarget->m_sACAmount -= pType->sAC; pTarget->m_bAttackAmount = pType->bAttack; break; case BUFF_TYPE_DAMAGE_DOUBLE: pTarget->m_bAttackAmount = pType->bAttack; break; case BUFF_TYPE_DISABLE_TARGETING: pTarget->m_bIsBlinded = true; break; case BUFF_TYPE_BLIND: pTarget->m_bIsBlinded = true; if (pTarget->isPlayer()) TO_USER(pTarget)->SendUserStatusUpdate(USER_STATUS_BLIND, USER_STATUS_INFLICT); break; case BUFF_TYPE_FREEZE: // Proportional to the target user's current HP. pTarget->m_bSpeedAmount = pType->bSpeed; break; case BUFF_TYPE_INSTANT_MAGIC: pTarget->m_bInstantCast = true; break; case BUFF_TYPE_DECREASE_RESIST: pTarget->m_bFireRAmount = -(pType->bFireR / 100) * (pTarget->m_bFireR - pTarget->m_bFireRAmount); pTarget->m_bColdRAmount = -(pType->bColdR / 100) * (pTarget->m_bColdR - pTarget->m_bColdRAmount); pTarget->m_bLightningRAmount = -(pType->bLightningR / 100) * (pTarget->m_bLightningR - pTarget->m_bLightningRAmount); pTarget->m_bMagicRAmount = -(pType->bMagicR / 100) * (pTarget->m_bMagicR - pTarget->m_bMagicRAmount); pTarget->m_bDiseaseRAmount = -(pType->bDiseaseR / 100) * (pTarget->m_bDiseaseR - pTarget->m_bDiseaseRAmount); pTarget->m_bPoisonRAmount = -(pType->bPoisonR / 100) * (pTarget->m_bPoisonR - pTarget->m_bPoisonRAmount); break; case BUFF_TYPE_MAGE_ARMOR: pTarget->m_bReflectArmorType = (pSkill->sSkill % 100); break; case BUFF_TYPE_PROHIBIT_INVIS: pTarget->m_bCanStealth = true; break; case BUFF_TYPE_RESIS_AND_MAGIC_DMG: // Elysian Web // Increases your magic resistance to block an additional 30% magic damage. break; case BUFF_TYPE_TRIPLEAC_HALFSPEED: // Wall of Iron pTarget->m_sACAmount += pTarget->m_sTotalAc * 2; pTarget->m_bSpeedAmount = pTarget->m_bSpeedAmount / 2; if (pTarget->m_bSpeedAmount = 0) pTarget->m_bSpeedAmount = 1; break; case BUFF_TYPE_BLOCK_CURSE: // Counter Curse // Blocks all curses. break; case BUFF_TYPE_BLOCK_CURSE_REFLECT: // Curse Refraction // Blocks all curses and has a chance to reflect the curse back upon the caster. break; case BUFF_TYPE_MANA_ABSORB: // Outrage / Frenzy / Mana Shield // Uses mana to receive damage (for mana shield its multiplied by 4, 100 damage = 400 mana used) break; case BUFF_TYPE_IGNORE_WEAPON: // Weapon cancellation // Disarms the opponent. (rendering them unable to attack) break; case BUFF_TYPE_PASSION_OF_SOUL: // Passion of the Soul // Increase pet's HP by 120 break; case BUFF_TYPE_FIRM_DETERMINATION: // Firm Determination // Increase pet's AC by 20 break; case BUFF_TYPE_SPEED2: // Cold Wave pTarget->m_bSpeedAmount = (pTarget->m_bSpeedAmount / 100 * 65); break; case BUFF_TYPE_ATTACK_RANGE_ARMOR: // Inevitable Murderous pTarget->m_sACAmount += 100; // Increase attack range by 1 meter. break; case BUFF_TYPE_MIRROR_DAMAGE_PARTY: // Minak's Thorn // Spreads damage received across party members and mirror's part of the damage. break; default: return false; } return true; }
bool CMagicProcess::RemoveType4Buff(uint8 byBuffType, Unit *pTarget) { // Buff must be added at this point. If it doesn't exist, we can't remove it twice. FastGuard lock(pTarget->m_buffLock); auto itr = pTarget->m_buffMap.find(byBuffType); if (itr == pTarget->m_buffMap.end()) return false; _MAGIC_TABLE * pSkill = g_pMain->m_MagictableArray.GetData(itr->second.m_nSkillID); if (pSkill == nullptr) return false; // If this buff persists across logout, it should be removed here too. if (pTarget->isPlayer() && pTarget->HasSavedMagic(pSkill->iNum)) TO_USER(pTarget)->RemoveSavedMagic(pSkill->iNum); pTarget->m_buffMap.erase(itr); switch (byBuffType) { case BUFF_TYPE_HP_MP: pTarget->m_sMaxHPAmount = 0; pTarget->m_sMaxMPAmount = 0; break; case BUFF_TYPE_AC: pTarget->m_sACAmount = 0; break; case BUFF_TYPE_SIZE: pTarget->StateChangeServerDirect(3, ABNORMAL_NORMAL); break; case BUFF_TYPE_DAMAGE: pTarget->m_bAttackAmount = 100; break; case BUFF_TYPE_ATTACK_SPEED: pTarget->m_bAttackSpeedAmount = 100; break; case BUFF_TYPE_SPEED: pTarget->m_bSpeedAmount = 100; break; case BUFF_TYPE_STATS: if (pTarget->isPlayer()) { TO_USER(pTarget)->SetStatBuff(STAT_STR, 0); TO_USER(pTarget)->SetStatBuff(STAT_STA, 0); TO_USER(pTarget)->SetStatBuff(STAT_DEX, 0); TO_USER(pTarget)->SetStatBuff(STAT_INT, 0); TO_USER(pTarget)->SetStatBuff(STAT_CHA, 0); } break; case BUFF_TYPE_RESISTANCES: pTarget->m_bFireRAmount = 0; pTarget->m_bColdRAmount = 0; pTarget->m_bLightningRAmount = 0; pTarget->m_bMagicRAmount = 0; pTarget->m_bDiseaseRAmount = 0; pTarget->m_bPoisonRAmount = 0; break; case BUFF_TYPE_ACCURACY: pTarget->m_bHitRateAmount = 100; pTarget->m_sAvoidRateAmount = 100; break; case BUFF_TYPE_MAGIC_POWER: pTarget->m_sMagicAttackAmount = 0; break; case BUFF_TYPE_EXPERIENCE: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bExpGainAmount = 100; break; case BUFF_TYPE_WEIGHT: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bMaxWeightAmount = 100; break; case BUFF_TYPE_WEAPON_DAMAGE: // uses pType->Attack break; case BUFF_TYPE_WEAPON_AC: pTarget->m_sACAmount = 0; break; case BUFF_TYPE_LOYALTY: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bNPGainAmount = 100; break; case BUFF_TYPE_NOAH_BONUS: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bNoahGainAmount = 100; break; case BUFF_TYPE_PREMIUM_MERCHANT: if (pTarget->isPlayer()) TO_USER(pTarget)->m_bPremiumMerchant = false; break; case BUFF_TYPE_ATTACK_SPEED_ARMOR: // should this revert a specific amount? if so, we need to store it so that we know how much. // most likely though, it's just recalculated. pTarget->m_sACAmount = 0; pTarget->m_bAttackAmount = 100; break; case BUFF_TYPE_DAMAGE_DOUBLE: pTarget->m_bAttackAmount = 100; break; case BUFF_TYPE_DISABLE_TARGETING: pTarget->m_bIsBlinded = false; break; case BUFF_TYPE_BLIND: // Only players can be blinded (at least by the only skill - "Blinding Strafe" - that uses this type). if (pTarget->isPlayer()) { pTarget->m_bIsBlinded = false; TO_USER(pTarget)->SendUserStatusUpdate(USER_STATUS_POISON, USER_STATUS_CURE); } break; case BUFF_TYPE_FREEZE: // Proportional to the target user's current HP. pTarget->m_bSpeedAmount = 100; break; case BUFF_TYPE_INSTANT_MAGIC: pTarget->m_bInstantCast = false; break; case BUFF_TYPE_DECREASE_RESIST: pTarget->m_bFireRAmount = 0; pTarget->m_bColdRAmount = 0; pTarget->m_bLightningRAmount = 0; pTarget->m_bMagicRAmount = 0; pTarget->m_bDiseaseRAmount = 0; pTarget->m_bPoisonRAmount = 0; break; case BUFF_TYPE_MAGE_ARMOR: pTarget->m_bReflectArmorType = 0; break; case BUFF_TYPE_PROHIBIT_INVIS: pTarget->m_bCanStealth = false; break; case BUFF_TYPE_RESIS_AND_MAGIC_DMG: // Elysian Web pTarget->m_bMagicDamageReduction = 100; break; case BUFF_TYPE_TRIPLEAC_HALFSPEED: // Wall of Iron pTarget->m_sACAmount -= pTarget->m_sTotalAc * 2; // TO-DO: Store this value independently for restoration pTarget->m_bSpeedAmount = 100; if (pTarget->m_bSpeedAmount = 0) pTarget->m_bSpeedAmount = 1; break; case BUFF_TYPE_BLOCK_CURSE: // Counter Curse // Blocks all curses. pTarget->m_bBlockCurse = false; break; case BUFF_TYPE_BLOCK_CURSE_REFLECT: // Curse Refraction // Blocks all curses and has a chance to reflect the curse back upon the caster. break; case BUFF_TYPE_MANA_ABSORB: // Outrage / Frenzy / Mana Shield // Uses mana to receive damage (for mana shield its multiplied by 4, 100 damage = 400 mana used) break; case BUFF_TYPE_IGNORE_WEAPON: // Weapon cancellation // Disarms the opponent. (rendering them unable to attack) break; case BUFF_TYPE_VARIOUS_EFFECTS: //... whatever the event item grants. // what is tweaked in the database: AC, Attack, MaxHP, resistances break; case BUFF_TYPE_PASSION_OF_SOUL: // Passion of the Soul // Increase pet's HP by 120 break; case BUFF_TYPE_FIRM_DETERMINATION: // Firm Determination // Increase pet's AC by 20 break; case BUFF_TYPE_SPEED2: // Cold Wave pTarget->m_bSpeedAmount = 100; break; case BUFF_TYPE_UNK_EXPERIENCE: // unknown buff type, used for something relating to XP. break; case BUFF_TYPE_ATTACK_RANGE_ARMOR: // Inevitable Murderous pTarget->m_sACAmount -= 100; // Buff type increases attack range by 1 meter. break; case BUFF_TYPE_MIRROR_DAMAGE_PARTY: // Minak's Thorn // Spreads damage received across party members and mirror's part of the damage. break; case BUFF_TYPE_DAGGER_BOW_DEFENSE: // Eskrima // Inflicts attacks as well as a bleeding curse on the enemy. Decreases 10% Dagger and Bow Defense of the enemy under the bleeding curse buff. break; case BUFF_TYPE_LOYALTY_AMOUNT: // Santa's Present (gives an extra +2NP per kill, unlike BUFF_TYPE_LOYALTY which uses an percent). break; case BUFF_TYPE_NO_RECALL: // prevents teleportation. break; case BUFF_TYPE_REDUCE_TARGET: // "Reduction" (reduces target's stats, but enlarges their character to make them easier to attack) break; case BUFF_TYPE_SILENCE_TARGET: // Silences the target to prevent them from using any skills (or potions) break; case BUFF_TYPE_NO_POTIONS: // "No Potion" prevents target from using potions. break; case BUFF_TYPE_KAUL_TRANSFORMATION: // Transforms the target into a Kaul (a pig thing), preventing you from /town'ing or attacking, but increases defense. break; case BUFF_TYPE_UNDEAD: // User becomes undead, increasing defense but preventing the use of potions and converting all health received into damage. break; case BUFF_TYPE_UNSIGHT: // Unsure how this is different to "Blind", but skill description simply reads "Blocks your[the target's] sight." break; case BUFF_TYPE_BLOCK_PHYSICAL_DAMAGE: // Blocks all physical damage. break; case BUFF_TYPE_BLOCK_MAGICAL_DAMAGE: // Blocks all magical/skill damage. break; case BUFF_TYPE_UNK_POTION: // unknown potion, "Return of the Warrior", "Comeback potion", perhaps some sort of revive? break; case BUFF_TYPE_SLEEP: // Zantman(Sandman), puts enemies to sleep. break; case BUFF_TYPE_INVISIBILITY_POTION: // "Unidentified potion" break; case BUFF_TYPE_GODS_BLESSING: // Increases your defense/max HP break; case BUFF_TYPE_HELP_COMPENSATION: // Compensation for using the help system (to help, ask for help, both?) break; default: return false; } if (pTarget->isPlayer()) { if (pSkill->bMoral >= MORAL_ENEMY) { if (byBuffType == BUFF_TYPE_SPEED || byBuffType == BUFF_TYPE_SPEED2) TO_USER(pTarget)->SendUserStatusUpdate(USER_STATUS_SPEED, USER_STATUS_CURE); } TO_USER(pTarget)->SetSlotItemValue(); TO_USER(pTarget)->SetUserAbility(); Packet result(WIZ_MAGIC_PROCESS, uint8(MAGIC_TYPE4_END)); result << byBuffType; TO_USER(pTarget)->Send(&result); } return true; }