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 Weapon::internalUseWeapon(Player* player, Item* item, Creature* target, int32_t damageModifier) const { if (m_scripted) { LuaVariant var; var.type = VARIANT_NUMBER; var.number = target->getID(); executeUseWeapon(player, var); } else { CombatDamage damage; damage.primary.type = params.combatType; damage.primary.value = (getWeaponDamage(player, target, item) * damageModifier) / 100; damage.secondary.type = getElementType(); damage.secondary.value = getElementDamage(player, target, item); Combat::doCombatHealth(player, target, damage, params); } onUsedAmmo(player, item, target->getTile()); onUsedWeapon(player, item, target->getTile()); return true; }
void Weapon::internalUseWeapon(Player* player, Item* item, Creature* target, int32_t damageModifier) const { if (m_scripted) { LuaVariant var; var.type = VARIANT_NUMBER; var.number = target->getID(); executeUseWeapon(player, var); } else { CombatDamage damage; WeaponType_t weaponType = item->getWeaponType(); if (weaponType == WEAPON_AMMO || weaponType == WEAPON_DISTANCE) { damage.origin = ORIGIN_RANGED; } else { damage.origin = ORIGIN_MELEE; } damage.primary.type = params.combatType; damage.primary.value = (getWeaponDamage(player, target, item) * damageModifier) / 100; damage.secondary.type = getElementType(); damage.secondary.value = getElementDamage(player, target, item); Combat::doCombatHealth(player, target, damage, params); } onUsedWeapon(player, item, target->getTile()); }
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; }