Добавлена система NPC, а также боевая система.
This commit is contained in:
@@ -127,13 +127,16 @@
|
|||||||
<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" />
|
||||||
|
<ClCompile Include="src\npc.cpp" />
|
||||||
<ClCompile Include="src\player.cpp" />
|
<ClCompile Include="src\player.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="include\game.h" />
|
<ClInclude Include="include\game.h" />
|
||||||
<ClInclude Include="include\inventory.h" />
|
<ClInclude Include="include\inventory.h" />
|
||||||
|
<ClInclude Include="include\npc.h" />
|
||||||
<ClInclude Include="include\player.h" />
|
<ClInclude Include="include\player.h" />
|
||||||
<ClInclude Include="include\location.h" />
|
<ClInclude Include="include\location.h" />
|
||||||
|
<ClInclude Include="include\point.h" />
|
||||||
<ClInclude Include="item.h" />
|
<ClInclude Include="item.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
|||||||
@@ -30,6 +30,9 @@
|
|||||||
<ClCompile Include="src\inventory.cpp">
|
<ClCompile Include="src\inventory.cpp">
|
||||||
<Filter>Исходные файлы</Filter>
|
<Filter>Исходные файлы</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\npc.cpp">
|
||||||
|
<Filter>Исходные файлы</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="include\location.h">
|
<ClInclude Include="include\location.h">
|
||||||
@@ -47,5 +50,11 @@
|
|||||||
<ClInclude Include="include\inventory.h">
|
<ClInclude Include="include\inventory.h">
|
||||||
<Filter>Файлы заголовков</Filter>
|
<Filter>Файлы заголовков</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\npc.h">
|
||||||
|
<Filter>Файлы заголовков</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\point.h">
|
||||||
|
<Filter>Файлы заголовков</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -14,7 +14,7 @@ RIDDLE_ANSWER=hole
|
|||||||
MAP_BEGIN
|
MAP_BEGIN
|
||||||
##########
|
##########
|
||||||
#@.......#
|
#@.......#
|
||||||
#....C...#
|
#..N.C...#
|
||||||
#........#
|
#........#
|
||||||
#......D.#
|
#......D.#
|
||||||
##########
|
##########
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ RIDDLE_ANSWER=magic
|
|||||||
MAP_BEGIN
|
MAP_BEGIN
|
||||||
##########
|
##########
|
||||||
#@.......#
|
#@.......#
|
||||||
#..E.....#
|
#..N..C..#
|
||||||
#........#
|
#........#
|
||||||
#......D.#
|
#......D.#
|
||||||
##########
|
##########
|
||||||
|
|||||||
@@ -16,6 +16,6 @@ MAP_BEGIN
|
|||||||
#@.......#
|
#@.......#
|
||||||
#....N...#
|
#....N...#
|
||||||
#........#
|
#........#
|
||||||
#......D.#
|
#...C..D.#
|
||||||
##########
|
##########
|
||||||
MAP_END
|
MAP_END
|
||||||
@@ -15,7 +15,7 @@ MAP_BEGIN
|
|||||||
##########
|
##########
|
||||||
#@.......#
|
#@.......#
|
||||||
#....C...#
|
#....C...#
|
||||||
#..E.....#
|
#..N.....#
|
||||||
#......D.#
|
#......D.#
|
||||||
##########
|
##########
|
||||||
MAP_END
|
MAP_END
|
||||||
@@ -14,7 +14,7 @@ RIDDLE_ANSWER=keyboard
|
|||||||
MAP_BEGIN
|
MAP_BEGIN
|
||||||
##########
|
##########
|
||||||
#@.......#
|
#@.......#
|
||||||
#....E...#
|
#....N...#
|
||||||
#....C...#
|
#....C...#
|
||||||
#......D.#
|
#......D.#
|
||||||
##########
|
##########
|
||||||
|
|||||||
23
data/npcs/npc_1.txt
Normal file
23
data/npcs/npc_1.txt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
ID=1
|
||||||
|
NAME=Old Guard
|
||||||
|
STATE=FRIENDLY
|
||||||
|
HP=60
|
||||||
|
DAMAGE=8
|
||||||
|
|
||||||
|
DIALOG_TEXT=The guard looks tired. He asks: "What do you seek here?"
|
||||||
|
OPTION_1=I seek knowledge.
|
||||||
|
RESULT_1=GIVE_ITEM
|
||||||
|
VALUE_1=101
|
||||||
|
MESSAGE_1=The guard gives you a small healing potion.
|
||||||
|
|
||||||
|
OPTION_2=Move away, old man.
|
||||||
|
RESULT_2=BECOME_HOSTILE
|
||||||
|
VALUE_2=0
|
||||||
|
MESSAGE_2=The guard becomes angry and attacks you.
|
||||||
|
|
||||||
|
OPTION_3=Can you open the next door?
|
||||||
|
RESULT_3=OPEN_LOCATION
|
||||||
|
VALUE_3=1
|
||||||
|
MESSAGE_3=The guard unlocks the next location.
|
||||||
|
|
||||||
|
END
|
||||||
13
data/npcs/npc_2.txt
Normal file
13
data/npcs/npc_2.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
ID=2
|
||||||
|
NAME=Dungeon Bandit
|
||||||
|
STATE=HOSTILE
|
||||||
|
HP=45
|
||||||
|
DAMAGE=12
|
||||||
|
|
||||||
|
DIALOG_TEXT=The bandit blocks your path.
|
||||||
|
OPTION_1=Fight.
|
||||||
|
RESULT_1=FIGHT
|
||||||
|
VALUE_1=0
|
||||||
|
MESSAGE_1=The fight begins.
|
||||||
|
|
||||||
|
END
|
||||||
23
data/npcs/npc_3.txt
Normal file
23
data/npcs/npc_3.txt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
ID=3
|
||||||
|
NAME=Archivist
|
||||||
|
STATE=FRIENDLY
|
||||||
|
HP=50
|
||||||
|
DAMAGE=6
|
||||||
|
|
||||||
|
DIALOG_TEXT=The archivist whispers: "Only those who understand patterns may pass."
|
||||||
|
OPTION_1=Ask about the sequence.
|
||||||
|
RESULT_1=OPEN_LOCATION
|
||||||
|
VALUE_1=3
|
||||||
|
MESSAGE_1=The archivist nods and unlocks the door.
|
||||||
|
|
||||||
|
OPTION_2=Demand his notes.
|
||||||
|
RESULT_2=BECOME_HOSTILE
|
||||||
|
VALUE_2=0
|
||||||
|
MESSAGE_2=The archivist becomes hostile.
|
||||||
|
|
||||||
|
OPTION_3=Ask for help.
|
||||||
|
RESULT_3=GIVE_ITEM
|
||||||
|
VALUE_3=102
|
||||||
|
MESSAGE_3=The archivist gives you a big healing potion.
|
||||||
|
|
||||||
|
END
|
||||||
23
data/npcs/npc_4.txt
Normal file
23
data/npcs/npc_4.txt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
ID=4
|
||||||
|
NAME=Library Keeper
|
||||||
|
STATE=FRIENDLY
|
||||||
|
HP=70
|
||||||
|
DAMAGE=10
|
||||||
|
|
||||||
|
DIALOG_TEXT=The keeper stands near the shelves. "Knowledge has a price."
|
||||||
|
OPTION_1=Respect the library.
|
||||||
|
RESULT_1=OPEN_LOCATION
|
||||||
|
VALUE_1=4
|
||||||
|
MESSAGE_1=The keeper allows you to pass.
|
||||||
|
|
||||||
|
OPTION_2=Steal a book.
|
||||||
|
RESULT_2=BECOME_HOSTILE
|
||||||
|
VALUE_2=0
|
||||||
|
MESSAGE_2=The keeper attacks you for stealing.
|
||||||
|
|
||||||
|
OPTION_3=Ask for supplies.
|
||||||
|
RESULT_3=GIVE_ITEM
|
||||||
|
VALUE_3=101
|
||||||
|
MESSAGE_3=The keeper gives you a small healing potion.
|
||||||
|
|
||||||
|
END
|
||||||
23
data/npcs/npc_5.txt
Normal file
23
data/npcs/npc_5.txt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
ID=5
|
||||||
|
NAME=Gate Warden
|
||||||
|
STATE=HOSTILE
|
||||||
|
HP=100
|
||||||
|
DAMAGE=16
|
||||||
|
|
||||||
|
DIALOG_TEXT=The warden blocks the final gate.
|
||||||
|
OPTION_1=Fight.
|
||||||
|
RESULT_1=FIGHT
|
||||||
|
VALUE_1=0
|
||||||
|
MESSAGE_1=The final battle begins.
|
||||||
|
|
||||||
|
OPTION_2=Try to negotiate.
|
||||||
|
RESULT_2=NOTHING
|
||||||
|
VALUE_2=0
|
||||||
|
MESSAGE_2=The warden ignores your words.
|
||||||
|
|
||||||
|
OPTION_3=Run away.
|
||||||
|
RESULT_3=NOTHING
|
||||||
|
VALUE_3=0
|
||||||
|
MESSAGE_3=You step back from the gate.
|
||||||
|
|
||||||
|
END
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "location.h"
|
#include "location.h"
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
|
#include "npc.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -15,6 +16,7 @@ private:
|
|||||||
Player player;
|
Player player;
|
||||||
std::vector<Location> locations;
|
std::vector<Location> locations;
|
||||||
std::vector<Item> itemDatabase;
|
std::vector<Item> itemDatabase;
|
||||||
|
std::vector<NPC> npcs;
|
||||||
|
|
||||||
void showMainMenu();
|
void showMainMenu();
|
||||||
|
|
||||||
@@ -25,6 +27,10 @@ private:
|
|||||||
|
|
||||||
Location* getCurrentLocation();
|
Location* getCurrentLocation();
|
||||||
|
|
||||||
|
void interactWithNPC(Location& location);
|
||||||
|
void startCombat(NPC& npc);
|
||||||
|
void applyDialogResult(NPC& npc, const DialogOption& option);
|
||||||
|
|
||||||
void render();
|
void render();
|
||||||
void processCommand();
|
void processCommand();
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct Point {
|
#include "Point.h"
|
||||||
int x = 0;
|
#include "NPC.h"
|
||||||
int y = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Chest {
|
struct Chest {
|
||||||
Point pos;
|
Point pos;
|
||||||
@@ -19,11 +17,6 @@ struct Enemy {
|
|||||||
int hp = 50;
|
int hp = 50;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NPC {
|
|
||||||
Point pos;
|
|
||||||
std::string name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Riddle {
|
struct Riddle {
|
||||||
int type = 0;
|
int type = 0;
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|||||||
48
include/npc.h
Normal file
48
include/npc.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "point.h"
|
||||||
|
|
||||||
|
enum class NPCState {
|
||||||
|
Friendly,
|
||||||
|
Hostile
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class DialogResultType {
|
||||||
|
GiveItem,
|
||||||
|
BecomeHostile,
|
||||||
|
OpenLocation,
|
||||||
|
Fight,
|
||||||
|
Nothing
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DialogOption {
|
||||||
|
std::string text;
|
||||||
|
DialogResultType result = DialogResultType::Nothing;
|
||||||
|
int value = 0;
|
||||||
|
std::string message;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NPC {
|
||||||
|
public:
|
||||||
|
int id = 0;
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
NPCState state = NPCState::Friendly;
|
||||||
|
|
||||||
|
int hp = 100;
|
||||||
|
int damage = 10;
|
||||||
|
|
||||||
|
Point position;
|
||||||
|
|
||||||
|
std::string dialogText;
|
||||||
|
std::vector<DialogOption> options;
|
||||||
|
|
||||||
|
bool defeated = false;
|
||||||
|
|
||||||
|
bool loadFromFile(const std::string& path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NPCState parseState(const std::string& value);
|
||||||
|
DialogResultType parseDialogResult(const std::string& value);
|
||||||
|
};
|
||||||
6
include/point.h
Normal file
6
include/point.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct Point {
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
};
|
||||||
126
src/game.cpp
126
src/game.cpp
@@ -182,7 +182,7 @@ void Game::handleTile(char tile) {
|
|||||||
std::cout << "Enemy encountered. Combat will be added later.\n";
|
std::cout << "Enemy encountered. Combat will be added later.\n";
|
||||||
}
|
}
|
||||||
else if (tile == 'N') {
|
else if (tile == 'N') {
|
||||||
std::cout << "NPC: Hello, traveler.\n";
|
interactWithNPC(*location);
|
||||||
}
|
}
|
||||||
else if (tile == 'D') {
|
else if (tile == 'D') {
|
||||||
if (!location->riddle.isSolved) {
|
if (!location->riddle.isSolved) {
|
||||||
@@ -315,3 +315,127 @@ void Game::openChest(Location& location) {
|
|||||||
|
|
||||||
std::cout << "Chest not found. Something went wrong.\n";
|
std::cout << "Chest not found. Something went wrong.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Game::applyDialogResult(NPC& npc, const DialogOption& option) {
|
||||||
|
if (option.result == DialogResultType::GiveItem) {
|
||||||
|
player.inventory.addItem(option.value);
|
||||||
|
std::cout << "Received item ID: " << option.value << "\n";
|
||||||
|
}
|
||||||
|
else if (option.result == DialogResultType::BecomeHostile) {
|
||||||
|
npc.state = NPCState::Hostile;
|
||||||
|
startCombat(npc);
|
||||||
|
}
|
||||||
|
else if (option.result == DialogResultType::OpenLocation) {
|
||||||
|
for (auto& location : locations) {
|
||||||
|
if (location.id == option.value) {
|
||||||
|
location.riddle.isSolved = true;
|
||||||
|
std::cout << "Location " << option.value << " has been unlocked.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Location " << option.value << " not found.\n";
|
||||||
|
}
|
||||||
|
else if (option.result == DialogResultType::Fight) {
|
||||||
|
startCombat(npc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cout << "Nothing happened.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::startCombat(NPC& npc) {
|
||||||
|
std::cout << "\nCombat started with " << npc.name << "!\n";
|
||||||
|
|
||||||
|
while (player.hp > 0 && npc.hp > 0) {
|
||||||
|
std::cout << "\nYour HP: " << player.hp << "\n";
|
||||||
|
std::cout << npc.name << " HP: " << npc.hp << "\n";
|
||||||
|
|
||||||
|
std::cout << "1. Attack\n";
|
||||||
|
std::cout << "2. Use small potion 101\n";
|
||||||
|
std::cout << "3. Run\n";
|
||||||
|
std::cout << "> ";
|
||||||
|
|
||||||
|
int choice;
|
||||||
|
std::cin >> choice;
|
||||||
|
|
||||||
|
if (choice == 1) {
|
||||||
|
int damage = player.getDamage(itemDatabase);
|
||||||
|
npc.hp -= damage;
|
||||||
|
|
||||||
|
std::cout << "You dealt " << damage << " damage.\n";
|
||||||
|
|
||||||
|
if (npc.hp <= 0) {
|
||||||
|
npc.defeated = true;
|
||||||
|
std::cout << "You defeated " << npc.name << ".\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (choice == 2) {
|
||||||
|
player.usePotion(101, itemDatabase);
|
||||||
|
}
|
||||||
|
else if (choice == 3) {
|
||||||
|
std::cout << "You ran away.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cout << "Invalid action.\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.hp -= npc.damage;
|
||||||
|
std::cout << npc.name << " dealt " << npc.damage << " damage.\n";
|
||||||
|
|
||||||
|
if (player.hp <= 0) {
|
||||||
|
std::cout << "You died.\n";
|
||||||
|
isRunning = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::interactWithNPC(Location& location) {
|
||||||
|
for (auto& npc : location.npcs) {
|
||||||
|
if (npc.position.x == player.position.x && npc.position.y == player.position.y) {
|
||||||
|
if (npc.defeated) {
|
||||||
|
std::cout << "There is nobody useful here anymore.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "\n=== " << npc.name << " ===\n";
|
||||||
|
|
||||||
|
if (npc.state == NPCState::Hostile) {
|
||||||
|
std::cout << npc.name << " is hostile.\n";
|
||||||
|
startCombat(npc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << npc.dialogText << "\n";
|
||||||
|
|
||||||
|
for (int i = 0; i < npc.options.size(); i++) {
|
||||||
|
std::cout << i + 1 << ". " << npc.options[i].text << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "> ";
|
||||||
|
|
||||||
|
int choice;
|
||||||
|
std::cin >> choice;
|
||||||
|
|
||||||
|
if (choice < 1 || choice > npc.options.size()) {
|
||||||
|
std::cout << "Invalid dialog option.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DialogOption& option = npc.options[choice - 1];
|
||||||
|
|
||||||
|
std::cout << option.message << "\n";
|
||||||
|
|
||||||
|
applyDialogResult(npc, option);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "NPC not found.\n";
|
||||||
|
}
|
||||||
@@ -64,7 +64,23 @@ 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.itemIds = { 101, 102 };
|
|
||||||
|
if (id == 1) {
|
||||||
|
chest.itemIds = { 101, 101 };
|
||||||
|
}
|
||||||
|
else if (id == 2) {
|
||||||
|
chest.itemIds = { 101, 201 };
|
||||||
|
}
|
||||||
|
else if (id == 3) {
|
||||||
|
chest.itemIds = { 102 };
|
||||||
|
}
|
||||||
|
else if (id == 4) {
|
||||||
|
chest.itemIds = { 102, 202 };
|
||||||
|
}
|
||||||
|
else if (id == 5) {
|
||||||
|
chest.itemIds = { 101, 102, 202 };
|
||||||
|
}
|
||||||
|
|
||||||
chests.push_back(chest);
|
chests.push_back(chest);
|
||||||
}
|
}
|
||||||
else if (tile == 'E') {
|
else if (tile == 'E') {
|
||||||
@@ -76,12 +92,29 @@ bool Location::loadFromFile(const std::string& path) {
|
|||||||
}
|
}
|
||||||
else if (tile == 'N') {
|
else if (tile == 'N') {
|
||||||
NPC npc;
|
NPC npc;
|
||||||
npc.pos = { x, y };
|
|
||||||
npc.name = "Stranger";
|
std::string npcPath;
|
||||||
|
|
||||||
|
if (id == 1) {
|
||||||
|
npcPath = "data/npcs/npc_1.txt";
|
||||||
|
}
|
||||||
|
else if (id == 2) {
|
||||||
|
npcPath = "data/npcs/npc_2.txt";
|
||||||
|
}
|
||||||
|
else if (id == 3) {
|
||||||
|
npcPath = "data/npcs/npc_3.txt";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
npcPath = "data/npcs/npc_1.txt";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (npc.loadFromFile(npcPath)) {
|
||||||
|
npc.position = { x, y };
|
||||||
npcs.push_back(npc);
|
npcs.push_back(npc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
81
src/npc.cpp
Normal file
81
src/npc.cpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#include "../include/NPC.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
NPCState NPC::parseState(const std::string& value) {
|
||||||
|
if (value == "FRIENDLY") return NPCState::Friendly;
|
||||||
|
if (value == "HOSTILE") return NPCState::Hostile;
|
||||||
|
|
||||||
|
return NPCState::Friendly;
|
||||||
|
}
|
||||||
|
|
||||||
|
DialogResultType NPC::parseDialogResult(const std::string& value) {
|
||||||
|
if (value == "GIVE_ITEM") return DialogResultType::GiveItem;
|
||||||
|
if (value == "BECOME_HOSTILE") return DialogResultType::BecomeHostile;
|
||||||
|
if (value == "OPEN_LOCATION") return DialogResultType::OpenLocation;
|
||||||
|
if (value == "FIGHT") return DialogResultType::Fight;
|
||||||
|
|
||||||
|
return DialogResultType::Nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NPC::loadFromFile(const std::string& path) {
|
||||||
|
std::ifstream file(path);
|
||||||
|
|
||||||
|
if (!file.is_open()) {
|
||||||
|
std::cout << "Cannot open NPC file: " << path << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
DialogOption option1;
|
||||||
|
DialogOption option2;
|
||||||
|
DialogOption option3;
|
||||||
|
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
if (line.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line == "END") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
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") id = std::stoi(value);
|
||||||
|
else if (key == "NAME") name = value;
|
||||||
|
else if (key == "STATE") state = parseState(value);
|
||||||
|
else if (key == "HP") hp = std::stoi(value);
|
||||||
|
else if (key == "DAMAGE") damage = std::stoi(value);
|
||||||
|
else if (key == "DIALOG_TEXT") dialogText = value;
|
||||||
|
|
||||||
|
else if (key == "OPTION_1") option1.text = value;
|
||||||
|
else if (key == "RESULT_1") option1.result = parseDialogResult(value);
|
||||||
|
else if (key == "VALUE_1") option1.value = std::stoi(value);
|
||||||
|
else if (key == "MESSAGE_1") option1.message = value;
|
||||||
|
|
||||||
|
else if (key == "OPTION_2") option2.text = value;
|
||||||
|
else if (key == "RESULT_2") option2.result = parseDialogResult(value);
|
||||||
|
else if (key == "VALUE_2") option2.value = std::stoi(value);
|
||||||
|
else if (key == "MESSAGE_2") option2.message = value;
|
||||||
|
|
||||||
|
else if (key == "OPTION_3") option3.text = value;
|
||||||
|
else if (key == "RESULT_3") option3.result = parseDialogResult(value);
|
||||||
|
else if (key == "VALUE_3") option3.value = std::stoi(value);
|
||||||
|
else if (key == "MESSAGE_3") option3.message = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!option1.text.empty()) options.push_back(option1);
|
||||||
|
if (!option2.text.empty()) options.push_back(option2);
|
||||||
|
if (!option3.text.empty()) options.push_back(option3);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user