int16 CBattleEntity::GetRangedWeaponDelay(bool tp) { CItemWeapon* PRange = (CItemWeapon*)m_Weapons[SLOT_RANGED]; CItemWeapon* PAmmo = (CItemWeapon*)m_Weapons[SLOT_AMMO]; // base delay int delay = 240; if (PRange != nullptr && PRange->getDamage() != 0) { delay += ((PRange->getDelay() * 60) / 1000); } if (PAmmo != nullptr && PAmmo->isThrowing()) { // this is a throwing weapon delay += ((PAmmo->getDelay() * 60) / 1000); } delay = (((delay - getMod(MOD_RANGED_DELAY)) * 1000) / 110); //apply haste and delay reductions that don't affect tp if (!tp) { delay = delay * ((float)(100 + getMod(MOD_RANGED_DELAYP)) / 100); } else { if (PAmmo != nullptr && PAmmo->getDamage() != 0 && !PAmmo->isThrowing()) { delay += ((PAmmo->getDelay() * 60) / 1000); } } return delay; }
bool CRangeState::CanUseRangedAttack(CBattleEntity* PTarget) { if (!PTarget) { m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, m_PEntity, 0, 0, MSGBASIC_CANNOT_ATTACK_TARGET); return false; } CItemWeapon* PRanged = (CItemWeapon*)m_PEntity->getEquip(SLOT_RANGED); CItemWeapon* PAmmo = (CItemWeapon*)m_PEntity->getEquip(SLOT_AMMO); if (!(PRanged && PRanged->isType(ITEM_WEAPON) || PAmmo && PAmmo->isThrowing())) { m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, m_PEntity, 0, 0, MSGBASIC_NO_RANGED_WEAPON); return false; } auto SkillType = PRanged ? PRanged->getSkillType() : PAmmo->getSkillType(); switch (SkillType) { case SKILL_THR: { // remove barrage, doesn't work here m_PEntity->StatusEffectContainer->DelStatusEffect(EFFECT_BARRAGE); break; } case SKILL_ARC: case SKILL_MRK: { PRanged = (CItemWeapon*)m_PEntity->getEquip(SLOT_AMMO); if (PRanged != nullptr && PRanged->isType(ITEM_WEAPON)) { break; } } default: { m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, m_PEntity, 0, 0, MSGBASIC_NO_RANGED_WEAPON); return false; } } if (!isFaceing(m_PEntity->loc.p, PTarget->loc.p, 40)) { m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, PTarget, 0, 0, MSGBASIC_CANNOT_SEE); return false; } if (distance(m_PEntity->loc.p, PTarget->loc.p) > 25) { m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, PTarget, 0, 0, MSGBASIC_TOO_FAR_AWAY); return false; } if (!m_PEntity->PAI->TargetFind->canSee(&PTarget->loc.p)) { m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, PTarget, 0, 0, MSGBASIC_CANNOT_PERFORM_ACTION); return false; } return true; }