Загрузка данных


#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>

using namespace std;

class Weapon {
protected:
	string name;
	int maxAmmo;
	int damage;
	int currentAmmo;

public:
	Weapon(string name, int damage, int maxAmmo)
		: name(name), damage(damage), maxAmmo(maxAmmo), currentAmmo(maxAmmo) {

	}

	void reload() {
		currentAmmo = maxAmmo;
		cout << "\nПерезарядка. Текущий боезапас " << currentAmmo << '/' << maxAmmo;
	}

	virtual void shooting() {
		if (currentAmmo > 0) {
			currentAmmo--;
			cout << "\nВыстрел. Текущий боезапас " << currentAmmo << '/' << maxAmmo << ". Урон " << damage;
		}
		else
			cout << "\nНет патронов. Требуется перезарядка";
	}

	void hitChance() {
		int hit = rand() % 91 + 5;
		if (hit >= 5 && hit <= 45)
			cout << "\nПромах";
		else if (hit >= 46 && hit <= 65)
			cout << "\nПопадание по касательной. Нанесено " << damage / 2 << " урона";
		else if (hit >= 66 && hit <= 95)
			cout << "\nПопадание. Нанесено " << damage << " урона";
	}

	virtual void critFail() {
		int hitFail = rand() % 101;
		if (hitFail >= 0 && hitFail <= 4)
			cout << "\nКритическая неудача";
		else
			hitChance();
	}

	virtual ~Weapon() {}
};

class Knife : public Weapon {
public:
	Knife(string name, int damage, int maxAmmo)
		: Weapon(name, damage, maxAmmo) {

	}

	void shooting() override {
		if (currentAmmo > 0) {
			currentAmmo -= 10;
			if (currentAmmo < 0) currentAmmo = 0;
			cout << "\nНанесен удар ножом. Прочность ножа " << currentAmmo << '/' << maxAmmo;
			critFail();
		}
		else
			cout << "\nТребуется заточить нож";
	}

	void critFail() override {
		int hitFail = rand() % 101;
		if (hitFail >= 0 && hitFail <= 4)
			cout << "\nКритический промах! Получен урон " << damage;
		else
			hitChance();
	}
};

class Rifle : public Weapon {
public:
	Rifle(string name, int damage, int maxAmmo)
		: Weapon(name, damage, maxAmmo) {

	}

	void shooting() override {
		if (currentAmmo > 0) {
			int n;
			bool ex = false;
			cout << "\nКакой режим стрельбы? \n1 - Одиночный выстрел \n2 - Очередь (x3) \n3 - Автоматический огонь (все оставшиеся патроны)\n";
			while (!ex) {
				if (!(cin >> n)) {
					cin.clear();
					cin.ignore(10000, '\n');
					n = 1;
				}
				switch (n) {
					case 1:
						currentAmmo--;
						cout << "\nСделан одиночный выстрел. Текущий боезапас " << currentAmmo << '/' << maxAmmo;
						critFail();
						ex = true;
						break;
					case 2:
						for (int i = 3; i > 0 && currentAmmo > 0; i--) {
							currentAmmo--;
							critFail();
						}
						cout << "\nСделана очередь. Текущий боезапас " << currentAmmo << '/' << maxAmmo;
						ex = true;
						break;
					case 3:
						for (int i = currentAmmo; i > 0; i--) {
							currentAmmo--;
							critFail();
						}
						cout << "\nАвтоматический огонь. Текущий боезапас " << currentAmmo << '/' << maxAmmo;
						ex = true;
						break;
					default:
						cout << "\nОшибка. Какой режим стрельбы? \n1 - Одиночный выстрел \n2 - Очередь (x3) \n3 - Автоматический огонь (все оставшиеся патроны)\n";
				}
			}
		}
		else
			cout << "\nТребуется перезарядка";
	}

	void critFail() override {
		int hitFail = rand() % 101;
		if (hitFail >= 0 && hitFail <= 4) {
			int selfDamage = damage / 2 + (maxAmmo - currentAmmo);
			cout << "\nВыстрел себе в ногу! Получено " << selfDamage << " урона";
		}
		else
			hitChance();
	}
};

class Grenade : public Weapon {
public:
	Grenade(string name, int damage, int maxAmmo)
		: Weapon(name, damage, maxAmmo) {

	}

	void shooting() override {
		if (currentAmmo > 0) {
			currentAmmo--;
			cout << "\nВыстрел из гранатомета. Урон по площади: " << damage
				 << ". Текущий боезапас " << currentAmmo << '/' << maxAmmo;
			critFail();
		}
		else
			cout << "\nТребуется перезарядка";
	}

	void critFail() override {
		int hitFail = rand() % 101;
		if (hitFail >= 0 && hitFail <= 4)
			cout << "\nГраната взорвалась рядом! Вас разнесло в фарш. Получено " << damage * 2 << " урона";
		else
			hitChance();
	}
};

class Enemy {
protected:
	string name;
	int hp;
	int armor;
	Weapon* weapon;

public:
	Enemy(string name, int hp, int armor, Weapon* weapon)
		: name(name), hp(hp), armor(armor), weapon(weapon) {

	}

	void takeDamage(int dmg) {
		int realDamage = dmg - armor;
		if (realDamage < 0) realDamage = 0;
		hp -= realDamage;
		if (hp < 0) hp = 0;
		cout << "\n" << name << " получает " << realDamage << " урона. Осталось HP: " << hp;
		fleeIfLowHp();
	}

	void attack() {
		cout << "\n" << name << " атакует:";
		if (weapon != nullptr)
			weapon->shooting();
		else
			cout << "\nУ " << name << " нет оружия!";
	}

	void fleeIfLowHp() {
		if (hp > 0 && hp <= 20)
			cout << "\n" << name << " паникует и убегает с низким HP (" << hp << ")!";
	}

	bool isAlive() const {
		return hp > 0;
	}

	string getName() const {
		return name;
	}
};

int main() {
	setlocale(0, "ru");
	srand(static_cast<unsigned>(time(0)));

	Knife butterfly("Нож-бабочка", 20, 50);
	Knife cerambit("Керамбит", 25, 40);
	butterfly.reload();
	butterfly.shooting();
	butterfly.shooting();

	Rifle m4a1("M4A1", 30, 20);
	Rifle ak47("АК-47", 25, 30);
	m4a1.reload();
	m4a1.shooting();

	Grenade rpg("РПГ-7", 80, 4);
	rpg.reload();
	rpg.shooting();

	Enemy enemy1("Солдат", 100, 5, &ak47);
	enemy1.attack();
	enemy1.takeDamage(90);

	cout << endl;
	return 0;
}