Добавлен инвентарь, в сундуках могут содержаться предметы.
This commit is contained in:
@@ -123,6 +123,7 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\inventory.cpp" />
|
||||||
<ClCompile Include="src\location.cpp" />
|
<ClCompile Include="src\location.cpp" />
|
||||||
<ClCompile Include="src\game.cpp" />
|
<ClCompile Include="src\game.cpp" />
|
||||||
<ClCompile Include="src\main.cpp" />
|
<ClCompile Include="src\main.cpp" />
|
||||||
@@ -130,8 +131,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="include\game.h" />
|
<ClInclude Include="include\game.h" />
|
||||||
|
<ClInclude Include="include\inventory.h" />
|
||||||
<ClInclude Include="include\player.h" />
|
<ClInclude Include="include\player.h" />
|
||||||
<ClInclude Include="include\location.h" />
|
<ClInclude Include="include\location.h" />
|
||||||
|
<ClInclude Include="item.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|||||||
@@ -27,6 +27,9 @@
|
|||||||
<ClCompile Include="src\location.cpp">
|
<ClCompile Include="src\location.cpp">
|
||||||
<Filter>Исходные файлы</Filter>
|
<Filter>Исходные файлы</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\inventory.cpp">
|
||||||
|
<Filter>Исходные файлы</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="include\location.h">
|
<ClInclude Include="include\location.h">
|
||||||
@@ -38,5 +41,11 @@
|
|||||||
<ClInclude Include="include\player.h">
|
<ClInclude Include="include\player.h">
|
||||||
<Filter>Файлы заголовков</Filter>
|
<Filter>Файлы заголовков</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="item.h">
|
||||||
|
<Filter>Файлы заголовков</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\inventory.h">
|
||||||
|
<Filter>Файлы заголовков</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
31
data/items.txt
Normal file
31
data/items.txt
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
ID=101
|
||||||
|
NAME=Small Healing Potion
|
||||||
|
DESCRIPTION=Restores 25 HP.
|
||||||
|
TYPE=POTION
|
||||||
|
HEAL=25
|
||||||
|
DAMAGE=0
|
||||||
|
END
|
||||||
|
|
||||||
|
ID=102
|
||||||
|
NAME=Big Healing Potion
|
||||||
|
DESCRIPTION=Restores 50 HP.
|
||||||
|
TYPE=POTION
|
||||||
|
HEAL=50
|
||||||
|
DAMAGE=0
|
||||||
|
END
|
||||||
|
|
||||||
|
ID=201
|
||||||
|
NAME=Rusty Sword
|
||||||
|
DESCRIPTION=Old sword. Better than fists.
|
||||||
|
TYPE=WEAPON
|
||||||
|
HEAL=0
|
||||||
|
DAMAGE=10
|
||||||
|
END
|
||||||
|
|
||||||
|
ID=202
|
||||||
|
NAME=Iron Axe
|
||||||
|
DESCRIPTION=Heavy axe with good damage.
|
||||||
|
TYPE=WEAPON
|
||||||
|
HEAL=0
|
||||||
|
DAMAGE=18
|
||||||
|
END
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "location.h"
|
#include "location.h"
|
||||||
|
#include "item.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class Game {
|
class Game {
|
||||||
public:
|
public:
|
||||||
@@ -12,10 +14,15 @@ private:
|
|||||||
|
|
||||||
Player player;
|
Player player;
|
||||||
std::vector<Location> locations;
|
std::vector<Location> locations;
|
||||||
|
std::vector<Item> itemDatabase;
|
||||||
|
|
||||||
void showMainMenu();
|
void showMainMenu();
|
||||||
|
|
||||||
|
void loadItems();
|
||||||
void loadLocations();
|
void loadLocations();
|
||||||
|
|
||||||
|
ItemType parseItemType(const std::string& type);
|
||||||
|
|
||||||
Location* getCurrentLocation();
|
Location* getCurrentLocation();
|
||||||
|
|
||||||
void render();
|
void render();
|
||||||
@@ -24,5 +31,7 @@ private:
|
|||||||
void movePlayer(int dx, int dy);
|
void movePlayer(int dx, int dy);
|
||||||
void handleTile(char tile);
|
void handleTile(char tile);
|
||||||
|
|
||||||
|
void openChest(Location& location);
|
||||||
|
|
||||||
bool solveRiddle(Location& location);
|
bool solveRiddle(Location& location);
|
||||||
};
|
};
|
||||||
21
include/inventory.h
Normal file
21
include/inventory.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
#include "Item.h"
|
||||||
|
|
||||||
|
struct InventorySlot {
|
||||||
|
int itemId = 0;
|
||||||
|
int count = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Inventory {
|
||||||
|
public:
|
||||||
|
void addItem(int itemId, int count = 1);
|
||||||
|
bool removeItem(int itemId, int count = 1);
|
||||||
|
|
||||||
|
void show(const std::vector<Item>& itemDatabase) const;
|
||||||
|
|
||||||
|
bool hasItem(int itemId) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<InventorySlot> items;
|
||||||
|
};
|
||||||
18
include/item.h
Normal file
18
include/item.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
enum class ItemType {
|
||||||
|
Potion,
|
||||||
|
Weapon,
|
||||||
|
Unknown
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Item {
|
||||||
|
int id = 0;
|
||||||
|
std::string name;
|
||||||
|
std::string description;
|
||||||
|
ItemType type = ItemType::Unknown;
|
||||||
|
|
||||||
|
int heal = 0;
|
||||||
|
int damage = 0;
|
||||||
|
};
|
||||||
@@ -9,8 +9,8 @@ struct Point {
|
|||||||
|
|
||||||
struct Chest {
|
struct Chest {
|
||||||
Point pos;
|
Point pos;
|
||||||
int gold = 0;
|
|
||||||
bool opened = false;
|
bool opened = false;
|
||||||
|
std::vector<int> itemIds;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Enemy {
|
struct Enemy {
|
||||||
|
|||||||
@@ -2,23 +2,27 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "location.h"
|
#include "location.h"
|
||||||
|
#include "inventory.h"
|
||||||
|
#include "item.h"
|
||||||
|
|
||||||
class Player {
|
class Player {
|
||||||
public:
|
public:
|
||||||
std::string name = "Character Name";
|
std::string name = "Character Name";
|
||||||
|
|
||||||
int hp = 100;
|
int hp = 100;
|
||||||
|
int maxHp = 100;
|
||||||
int atk = 10;
|
int atk = 10;
|
||||||
int gold = 0;
|
int gold = 0;
|
||||||
|
|
||||||
int currentLocation = 1;
|
int currentLocation = 1;
|
||||||
Point position;
|
Point position;
|
||||||
|
Inventory inventory;
|
||||||
int weaponId = 101;
|
int equippedWeaponId = 0;
|
||||||
std::vector<int> items;
|
|
||||||
|
|
||||||
Player() = default;
|
Player() = default;
|
||||||
Player(std::string name);
|
Player(std::string name);
|
||||||
|
|
||||||
|
int getDamage(const std::vector<Item>& itemDatabase) const;
|
||||||
|
void usePotion(int itemId, const std::vector<Item>& itemDatabase);
|
||||||
|
void equipWeapon(int itemId, const std::vector<Item>& itemDatabase);
|
||||||
void showStats() const;
|
void showStats() const;
|
||||||
};
|
};
|
||||||
95
src/game.cpp
95
src/game.cpp
@@ -1,8 +1,10 @@
|
|||||||
#include "../include/game.h"
|
#include "../include/game.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
void Game::run() {
|
void Game::run() {
|
||||||
|
loadItems();
|
||||||
loadLocations();
|
loadLocations();
|
||||||
showMainMenu();
|
showMainMenu();
|
||||||
|
|
||||||
@@ -96,6 +98,9 @@ void Game::render() {
|
|||||||
std::cout << "WASD - move\n";
|
std::cout << "WASD - move\n";
|
||||||
std::cout << "stats - show stats\n";
|
std::cout << "stats - show stats\n";
|
||||||
std::cout << "exit - exit game\n";
|
std::cout << "exit - exit game\n";
|
||||||
|
std::cout << "inventory - show inventory\n";
|
||||||
|
std::cout << "use <id> - use potion\n";
|
||||||
|
std::cout << "equip <id> - equip weapon\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::processCommand() {
|
void Game::processCommand() {
|
||||||
@@ -122,6 +127,19 @@ void Game::processCommand() {
|
|||||||
else if (command == "d" || command == "D") {
|
else if (command == "d" || command == "D") {
|
||||||
movePlayer(1, 0);
|
movePlayer(1, 0);
|
||||||
}
|
}
|
||||||
|
else if (command == "inventory") {
|
||||||
|
player.inventory.show(itemDatabase);
|
||||||
|
}
|
||||||
|
else if (command == "use") {
|
||||||
|
int itemId;
|
||||||
|
std::cin >> itemId;
|
||||||
|
player.usePotion(itemId, itemDatabase);
|
||||||
|
}
|
||||||
|
else if (command == "equip") {
|
||||||
|
int itemId;
|
||||||
|
std::cin >> itemId;
|
||||||
|
player.equipWeapon(itemId, itemDatabase);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
std::cout << "Unknown command.\n";
|
std::cout << "Unknown command.\n";
|
||||||
}
|
}
|
||||||
@@ -158,8 +176,7 @@ void Game::handleTile(char tile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tile == 'C') {
|
if (tile == 'C') {
|
||||||
std::cout << "You found a chest. For now it gives you 25 gold.\n";
|
openChest(*location);
|
||||||
player.gold += 25;
|
|
||||||
}
|
}
|
||||||
else if (tile == 'E') {
|
else if (tile == 'E') {
|
||||||
std::cout << "Enemy encountered. Combat will be added later.\n";
|
std::cout << "Enemy encountered. Combat will be added later.\n";
|
||||||
@@ -223,4 +240,78 @@ bool Game::solveRiddle(Location& location) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemType Game::parseItemType(const std::string& type) {
|
||||||
|
if (type == "POTION") return ItemType::Potion;
|
||||||
|
if (type == "WEAPON") return ItemType::Weapon;
|
||||||
|
|
||||||
|
return ItemType::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::loadItems() {
|
||||||
|
itemDatabase.clear();
|
||||||
|
|
||||||
|
std::ifstream file("data/items.txt");
|
||||||
|
|
||||||
|
if (!file.is_open()) {
|
||||||
|
std::cout << "Cannot open items file: data/items.txt\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Item item;
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
if (line.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line == "END") {
|
||||||
|
itemDatabase.push_back(item);
|
||||||
|
item = Item();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t pos = line.find('=');
|
||||||
|
|
||||||
|
if (pos == std::string::npos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string key = line.substr(0, pos);
|
||||||
|
std::string value = line.substr(pos + 1);
|
||||||
|
|
||||||
|
if (key == "ID") item.id = std::stoi(value);
|
||||||
|
else if (key == "NAME") item.name = value;
|
||||||
|
else if (key == "DESCRIPTION") item.description = value;
|
||||||
|
else if (key == "TYPE") item.type = parseItemType(value);
|
||||||
|
else if (key == "HEAL") item.heal = std::stoi(value);
|
||||||
|
else if (key == "DAMAGE") item.damage = std::stoi(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Loaded items: " << itemDatabase.size() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::openChest(Location& location) {
|
||||||
|
for (auto& chest : location.chests) {
|
||||||
|
if (chest.pos.x == player.position.x && chest.pos.y == player.position.y) {
|
||||||
|
if (chest.opened) {
|
||||||
|
std::cout << "Chest is already opened.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "You opened the chest.\n";
|
||||||
|
|
||||||
|
for (int itemId : chest.itemIds) {
|
||||||
|
player.inventory.addItem(itemId);
|
||||||
|
std::cout << "Received item ID: " << itemId << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
chest.opened = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Chest not found. Something went wrong.\n";
|
||||||
}
|
}
|
||||||
63
src/inventory.cpp
Normal file
63
src/inventory.cpp
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#include "../include/inventory.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
void Inventory::addItem(int itemId, int count) {
|
||||||
|
for (auto& slot : items) {
|
||||||
|
if (slot.itemId == itemId) {
|
||||||
|
slot.count += count;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
items.push_back({ itemId, count });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Inventory::removeItem(int itemId, int count) {
|
||||||
|
for (auto it = items.begin(); it != items.end(); ++it) {
|
||||||
|
if (it->itemId == itemId) {
|
||||||
|
if (it->count < count) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
it->count -= count;
|
||||||
|
|
||||||
|
if (it->count <= 0) {
|
||||||
|
items.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Inventory::hasItem(int itemId) const {
|
||||||
|
for (const auto& slot : items) {
|
||||||
|
if (slot.itemId == itemId) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inventory::show(const std::vector<Item>& itemDatabase) const {
|
||||||
|
std::cout << "\n=== INVENTORY ===\n";
|
||||||
|
|
||||||
|
if (items.empty()) {
|
||||||
|
std::cout << "Inventory is empty.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& slot : items) {
|
||||||
|
for (const auto& item : itemDatabase) {
|
||||||
|
if (item.id == slot.itemId) {
|
||||||
|
std::cout << item.id << " | "
|
||||||
|
<< item.name << " x" << slot.count
|
||||||
|
<< " | " << item.description << "\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -64,7 +64,7 @@ bool Location::loadFromFile(const std::string& path) {
|
|||||||
if (tile == 'C') {
|
if (tile == 'C') {
|
||||||
Chest chest;
|
Chest chest;
|
||||||
chest.pos = { x, y };
|
chest.pos = { x, y };
|
||||||
chest.gold = 25;
|
chest.itemIds = { 101, 102 };
|
||||||
chests.push_back(chest);
|
chests.push_back(chest);
|
||||||
}
|
}
|
||||||
else if (tile == 'E') {
|
else if (tile == 'E') {
|
||||||
|
|||||||
@@ -16,4 +16,59 @@ void Player::showStats() const {
|
|||||||
std::cout << "\nGOLD: " << gold;
|
std::cout << "\nGOLD: " << gold;
|
||||||
std::cout << "\nLOCATION: " << currentLocation;
|
std::cout << "\nLOCATION: " << currentLocation;
|
||||||
std::cout << "\nPOSITION: " << position.x << ", " << position.y << "\n";
|
std::cout << "\nPOSITION: " << position.x << ", " << position.y << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int Player::getDamage(const std::vector<Item>& itemDatabase) const {
|
||||||
|
int damage = atk;
|
||||||
|
|
||||||
|
for (const auto& item : itemDatabase) {
|
||||||
|
if (item.id == equippedWeaponId && item.type == ItemType::Weapon) {
|
||||||
|
damage += item.damage;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::usePotion(int itemId, const std::vector<Item>& itemDatabase) {
|
||||||
|
for (const auto& item : itemDatabase) {
|
||||||
|
if (item.id == itemId && item.type == ItemType::Potion) {
|
||||||
|
if (!inventory.hasItem(itemId)) {
|
||||||
|
std::cout << "You don't have this potion.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hp += item.heal;
|
||||||
|
|
||||||
|
if (hp > maxHp) {
|
||||||
|
hp = maxHp;
|
||||||
|
}
|
||||||
|
|
||||||
|
inventory.removeItem(itemId, 1);
|
||||||
|
|
||||||
|
std::cout << "You used " << item.name << ". HP: " << hp << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "This item is not a potion.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::equipWeapon(int itemId, const std::vector<Item>& itemDatabase) {
|
||||||
|
for (const auto& item : itemDatabase) {
|
||||||
|
if (item.id == itemId && item.type == ItemType::Weapon) {
|
||||||
|
if (!inventory.hasItem(itemId)) {
|
||||||
|
std::cout << "You don't have this weapon.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
equippedWeaponId = itemId;
|
||||||
|
|
||||||
|
std::cout << "Equipped weapon: " << item.name << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "This item is not a weapon.\n";
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user