Esempio n. 1
0
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);
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}