13 constexpr
unsigned int EndNode = 9999999;
15 void shiftDownJumps(std::vector<Conversation::Node>& nodes,
unsigned int i) {
16 const auto updateJump = [&nodes, i](std::uint32_t& jump) {
17 const auto isSimpleNext = [&nodes](
unsigned int i) {
18 if (i >= nodes.size())
return false;
19 switch (nodes[i].getType()) {
33 if (isSimpleNext(jump)) {
34 const std::uint32_t j = nodes[jump].next();
35 jump = j > i ? j - 1 : j;
37 else { jump = EndNode; }
43 for (
unsigned int j = 0; j < nodes.size(); ++j) {
44 Conversation::Node& node = nodes[j];
47 updateJump(node.nextOnPass());
48 updateJump(node.nextOnReject());
52 for (
auto& pair : node.choices()) {
54 updateJump(pair.second);
62 return ConversationManager::initializeExisting(file, *
this);
66 return bl::serial::json::Serializer<Conversation>::deserializeStream(input, *
this);
70 return bl::serial::binary::Serializer<Conversation>::deserialize(input, *
this);
74 std::ofstream output(file.c_str());
75 return bl::serial::json::Serializer<Conversation>::serializeStream(output, *
this, 4, 0);
79 bl::resource::bundle::FileHandlerContext&)
const {
80 return bl::serial::binary::Serializer<Conversation>::serialize(output, *
this);
86 if (i < cnodes.size()) {
87 shiftDownJumps(cnodes, i);
88 cnodes.erase(cnodes.begin() + i);
90 else { BL_LOG_WARN <<
"Tried to delete out of range node: " << i; }
96 if (i < cnodes.size()) { cnodes[i] = node; }
97 else { BL_LOG_WARN <<
"Out of range node assign: " << i; }
107 next() = nextOnPass() = nextOnReject() = 999999;
112 data.emplace<
Item>();
117 data.emplace<std::uint32_t>(0);
121 data.emplace<std::vector<std::pair<std::string, std::uint32_t>>>();
125 data.emplace<
bool>(
false);
142 static bool null =
false;
143 bool* r = std::get_if<bool>(&data);
145 BL_LOG_ERROR <<
"Bad Node access (concurrent). Type=" <<
static_cast<int>(type);
150 const bool* r = std::get_if<bool>(&data);
152 BL_LOG_ERROR <<
"Bad Node access (concurrent). Type=" <<
static_cast<int>(type);
157 static std::vector<std::pair<std::string, std::uint32_t>>
null;
158 auto* d = std::get_if<std::vector<std::pair<std::string, std::uint32_t>>>(&data);
159 if (d) {
return *d; }
160 BL_LOG_ERROR <<
"Bad Node access (choices). Type=" <<
static_cast<int>(type);
165 static std::uint32_t
null;
166 std::uint32_t* m = std::get_if<std::uint32_t>(&data);
168 BL_LOG_ERROR <<
"Bad node access (money). Type=" <<
static_cast<int>(type);
174 Item* i = std::get_if<Item>(&data);
176 BL_LOG_ERROR <<
"Bad node access (item). Type=" <<
static_cast<int>(type);
193 static std::vector<std::pair<std::string, std::uint32_t>>
null;
194 const auto* d = std::get_if<std::vector<std::pair<std::string, std::uint32_t>>>(&data);
195 if (d) {
return *d; }
196 BL_LOG_ERROR <<
"Bad Node access (choices). Type=" << type;
201 static unsigned int null;
202 const unsigned int* m = std::get_if<unsigned int>(&data);
204 BL_LOG_ERROR <<
"Bad node access (money). Type=" <<
static_cast<int>(type);
209 static const Item null;
210 const Item* i = std::get_if<Item>(&data);
212 BL_LOG_ERROR <<
"Bad node access (item). Type=" <<
static_cast<int>(type);
224 #ifdef PEOPLEMON_DEBUG
227 node.
message() =
"WARNING: Failed to load conversation: " + f;
238 case Node::Type::Talk:
240 case Node::Type::Prompt:
242 case Node::Type::GiveItem:
244 case Node::Type::TakeItem:
246 case Node::Type::GiveMoney:
248 case Node::Type::TakeMoney:
250 case Node::Type::RunScript:
252 case Node::Type::CheckSaveFlag:
254 case Node::Type::SetSaveFlag:
256 case Node::Type::CheckInteracted:
257 return "Check Talked";
273 next.push_back(node.
next());
275 case T::CheckInteracted:
276 case T::CheckSaveFlag:
283 for (
const auto& c : node.
choices()) { next.push_back(c.second); }
286 BL_LOG_ERROR <<
"Unknown node type: " << node.
getType();
Core classes and functionality for both the editor and game.
Stores a conversation that an NPC or trainer can have with the player.
bool saveBundle(bl::serial::binary::OutputStream &output, bl::resource::bundle::FileHandlerContext &ctx) const
Saves the data from this object to the given bundle and registers depency files if any.
static void getNextJumps(const Node &node, std::vector< unsigned int > &jumps)
Populates the jumps vector with the indices reachable from the given node.
bool load(const std::string &file)
Loads the conversation from the given file.
void deleteNode(unsigned int i)
Deletes the node at the given index. Jump indexes for other nodes are updated if affected....
void setNode(unsigned int i, const Node &node)
Updates the value of the node at the given index.
bool loadProd(bl::serial::binary::InputStream &input)
Loads the conversation from its binary format.
const std::vector< Node > & nodes() const
Returns the list of nodes in the conversation.
bool loadDev(std::istream &input)
Loads the conversation from its json format.
bool save(const std::string &file) const
Saves the conversation to the given file.
static Conversation makeLoadError(const std::string &filename)
Helper function to create a conversation that reports an error if in debug mode.
void appendNode(const Node &node)
Appends the given node to the list of nodes.
Building block of conversations. A conversation is a tree of nodes and each node is an action that ha...
std::string & script()
Returns the script file of this node.
static std::string typeToString(Type type)
Converts a node type to a human readable string.
std::string & message()
Returns the message or prompt for this node.
std::uint32_t & nextOnPass()
Returns the next node if a check passes (ie take item or money)
std::uint32_t & nextOnReject()
Returns the next node if a check is rejected (ie not taking money or item)
void setType(Type type)
Clears node data and updates to a new type.
std::uint32_t & money()
Returns the money requested or given, undefined behavior if not a money node.
Type getType() const
Returns the type of this node.
bool & runConcurrently()
Returns whether or not the launched script should be executed concurrently.
std::string & saveFlag()
Returns the save flag of this node.
Item & item()
Returns the item to give or take. Undefined behavior if not an item node.
std::uint32_t & next()
Returns the index of the next node in the case of a Talk, Give, and Script nodes.
std::vector< std::pair< std::string, std::uint32_t > > & choices()
Returns the choices if this is a prompt node. Undefined behavior if not.
Node()
Creates an empty talk node.
Type
Represents the different effects that nodes can have.
@ RunScript
This will run a script. Must be a file.
@ Prompt
This will output a message then prompt the player for a choice.
@ Talk
This just outputs a message.
@ GiveItem
This unconditionally gives the player an item.
@ SetSaveFlag
This will check if a flag exists and jump to the next node accordingly.
@ GiveMoney
This will unconditionally give money to the player.