bool WeaponMelee::useWeapon(Player* player, Item* item, Creature* target) const { int32_t damageModifier = playerWeaponCheck(player, target); if (damageModifier == 0) { return false; } return internalUseWeapon(player, item, target, damageModifier); }
bool Weapon::useWeapon(Player* player, Item* item, Creature* target) const { int32_t damageModifier = playerWeaponCheck(player, target, item->getShootRange()); if (damageModifier == 0) { return false; } internalUseWeapon(player, item, target, damageModifier); return true; }
bool WeaponMelee::useWeapon(Player* player, Item* item, Creature* target) const { int32_t damageModifier = playerWeaponCheck(player, target); if(damageModifier == 0) return false; if(elementDamage != 0) { int32_t damage = getElementDamage(player, item); CombatParams eParams; eParams.combatType = elementType; eParams.isAggressive = true; eParams.useCharges = true; Combat::doCombatHealth(player, target, damage, damage, eParams); } return internalUseWeapon(player, item, target, damageModifier); }
bool WeaponDistance::useWeapon(Player* player, Item* item, Creature* target) const { int32_t damageModifier = playerWeaponCheck(player, target); if (damageModifier == 0) { return false; } int32_t chance; if (hitChance == 0) { //hit chance is based on distance to target and distance skill uint32_t skill = player->getSkillLevel(SKILL_DISTANCE); const Position& playerPos = player->getPosition(); const Position& targetPos = target->getPosition(); uint32_t distance = std::max<uint32_t>(Position::getDistanceX(playerPos, targetPos), Position::getDistanceY(playerPos, targetPos)); if (maxHitChance == 75) { //chance for one-handed weapons switch (distance) { case 1: case 5: chance = std::min<uint32_t>(skill, 74) + 1; break; case 2: chance = static_cast<uint32_t>(std::min<uint32_t>(skill, 28) * 2.40f) + 8; break; case 3: chance = static_cast<uint32_t>(std::min<uint32_t>(skill, 45) * 1.55f) + 6; break; case 4: chance = static_cast<uint32_t>(std::min<uint32_t>(skill, 58) * 1.25f) + 3; break; case 6: chance = static_cast<uint32_t>(std::min<uint32_t>(skill, 90) * 0.80f) + 3; break; case 7: chance = static_cast<uint32_t>(std::min<uint32_t>(skill, 104) * 0.70f) + 2; break; default: chance = hitChance; break; } } else if (maxHitChance == 90) { //formula for two-handed weapons switch (distance) { case 1: case 5: chance = static_cast<uint32_t>(std::min<uint32_t>(skill, 74) * 1.20f) + 1; break; case 2: chance = static_cast<uint32_t>(std::min<uint32_t>(skill, 28) * 3.20f); break; case 3: chance = std::min<uint32_t>(skill, 45) * 2; break; case 4: chance = static_cast<uint32_t>(std::min<uint32_t>(skill, 58) * 1.55f); break; case 6: case 7: chance = std::min<uint32_t>(skill, 90); break; default: chance = hitChance; break; } } else if (maxHitChance == 100) { switch (distance) { case 1: case 5: chance = static_cast<uint32_t>(std::min<uint32_t>(skill, 73) * 1.35f) + 1; break; case 2: chance = static_cast<uint32_t>(std::min<uint32_t>(skill, 30) * 3.20f) + 4; break; case 3: chance = static_cast<uint32_t>(std::min<uint32_t>(skill, 48) * 2.05f) + 2; break; case 4: chance = static_cast<uint32_t>(std::min<uint32_t>(skill, 65) * 1.50f) + 2; break; case 6: chance = static_cast<uint32_t>(std::min<uint32_t>(skill, 87) * 1.20f) - 4; break; case 7: chance = static_cast<uint32_t>(std::min<uint32_t>(skill, 90) * 1.10f) + 1; break; default: chance = hitChance; break; } } else { chance = maxHitChance; } } else { chance = hitChance; } if (item->getWeaponType() == WEAPON_AMMO) { Item* bow = player->getWeapon(true); if (bow && bow->getHitChance() != 0) { chance += bow->getHitChance(); } } if (chance >= uniform_random(1, 100)) { Weapon::internalUseWeapon(player, item, target, damageModifier); } else { //miss target Tile* destTile = target->getTile(); if (!Position::areInRange<1, 1, 0>(player->getPosition(), target->getPosition())) { static std::vector<std::pair<int32_t, int32_t>> destList { {-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {0, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1} }; std::shuffle(destList.begin(), destList.end(), getRandomGenerator()); Position destPos = target->getPosition(); for (const auto& dir : destList) { Tile* tmpTile = g_game.map.getTile(destPos.x + dir.first, destPos.y + dir.second, destPos.z); // Blocking tiles or tiles without ground ain't valid targets for spears if (tmpTile && !tmpTile->hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID) && tmpTile->ground != nullptr) { destTile = tmpTile; break; } } } Weapon::internalUseWeapon(player, item, destTile); } return true; }
bool WeaponDistance::useWeapon(Player* player, Item* item, Creature* target) const { int32_t damageModifier = playerWeaponCheck(player, target); if (damageModifier == 0) { return false; } int32_t chance; if (hitChance == 0) { //hit chance is based on distance to target and distance skill uint32_t skill = player->getSkill(SKILL_DIST, SKILL_LEVEL); const Position& playerPos = player->getPosition(); const Position& targetPos = target->getPosition(); uint32_t distance = std::max<uint32_t>(Position::getDistanceX(playerPos, targetPos), Position::getDistanceY(playerPos, targetPos)); if (maxHitChance == 75) { //chance for one-handed weapons switch (distance) { case 1: chance = std::min<uint32_t>(skill, 74) + 1; break; case 2: chance = (uint32_t)((float)2.4 * std::min<uint32_t>(skill, 28)) + 8; break; case 3: chance = (uint32_t)((float)1.55 * std::min<uint32_t>(skill, 45)) + 6; break; case 4: chance = (uint32_t)((float)1.25 * std::min<uint32_t>(skill, 58)) + 3; break; case 5: chance = (uint32_t)((float)std::min<uint32_t>(skill, 74)) + 1; break; case 6: chance = (uint32_t)((float)0.8 * std::min<uint32_t>(skill, 90)) + 3; break; case 7: chance = (uint32_t)((float)0.7 * std::min<uint32_t>(skill, 104)) + 2; break; default: chance = hitChance; break; } } else if (maxHitChance == 90) { //formula for two-handed weapons switch (distance) { case 1: chance = (uint32_t)((float)1.2 * std::min<uint32_t>(skill, 74)) + 1; break; case 2: chance = (uint32_t)((float)3.2 * std::min<uint32_t>(skill, 28)); break; case 3: chance = (uint32_t)((float)2.0 * std::min<uint32_t>(skill, 45)); break; case 4: chance = (uint32_t)((float)1.55 * std::min<uint32_t>(skill, 58)); break; case 5: chance = (uint32_t)((float)1.2 * std::min<uint32_t>(skill, 74)) + 1; break; case 6: chance = (uint32_t)((float)1.0 * std::min<uint32_t>(skill, 90)); break; case 7: chance = (uint32_t)((float)1.0 * std::min<uint32_t>(skill, 90)); break; default: chance = hitChance; break; } } else if (maxHitChance == 100) { switch (distance) { case 1: chance = (uint32_t)((float)1.35 * std::min<uint32_t>(skill, 73)) + 1; break; case 2: chance = (uint32_t)((float)3.2 * std::min<uint32_t>(skill, 30)) + 4; break; case 3: chance = (uint32_t)((float)2.05 * std::min<uint32_t>(skill, 48)) + 2; break; case 4: chance = (uint32_t)((float)1.5 * std::min<uint32_t>(skill, 65)) + 2; break; case 5: chance = (uint32_t)((float)1.35 * std::min<uint32_t>(skill, 73)) + 1; break; case 6: chance = (uint32_t)((float)1.2 * std::min<uint32_t>(skill, 87)) - 4; break; case 7: chance = (uint32_t)((float)1.1 * std::min<uint32_t>(skill, 90)) + 1; break; default: chance = hitChance; break; } } else { chance = maxHitChance; } } else { chance = hitChance; } if (item->getWeaponType() == WEAPON_AMMO) { Item* bow = player->getWeapon(true); if (bow && bow->getHitChance() != 0) { chance += bow->getHitChance(); } } if (chance >= random_range(1, 100)) { if (elementDamage != 0) { int32_t damage = getElementDamage(player, target, item); CombatParams eParams; eParams.combatType = elementType; eParams.isAggressive = true; eParams.useCharges = true; Combat::doCombatHealth(player, target, damage, damage, eParams); } Weapon::internalUseWeapon(player, item, target, damageModifier); } else { //miss target Tile* destTile = target->getTile(); if (!Position::areInRange<1, 1, 0>(player->getPosition(), target->getPosition())) { std::vector<std::pair<int32_t, int32_t>> destList; destList.push_back(std::make_pair(-1, -1)); destList.push_back(std::make_pair(-1, 0)); destList.push_back(std::make_pair(-1, 1)); destList.push_back(std::make_pair(0, -1)); destList.push_back(std::make_pair(0, 0)); destList.push_back(std::make_pair(0, 1)); destList.push_back(std::make_pair(1, -1)); destList.push_back(std::make_pair(1, 0)); destList.push_back(std::make_pair(1, 1)); std::random_shuffle(destList.begin(), destList.end()); Position destPos = target->getPosition(); for (const auto& dir : destList) { Tile* tmpTile = g_game.getTile(destPos.x + dir.first, destPos.y + dir.second, destPos.z); // Blocking tiles or tiles without ground ain't valid targets for spears if (tmpTile && !tmpTile->hasProperty(IMMOVABLEBLOCKSOLID) && tmpTile->ground != NULL) { destTile = tmpTile; break; } } } Weapon::internalUseWeapon(player, item, destTile); } return true; }