Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#include "crab/event/EventSeqGroup.h"
namespace Crab {
using namespace pyrodactyl::event;
void EventSeqGroup::endSeq(const uint &id) {
_seq.erase(id);
_end.push_back(id);
}
void EventSeqGroup::addSeq(const uint &id, const Common::Path &path) {
_seq[id].load(path);
}
bool EventSeqGroup::eventInProgress(const uint &id) {
return _seq.contains(id) && _seq[id].eventInProgress();
}
GameEvent *EventSeqGroup::curEvent(const uint &id) {
return _seq[id].currentEvent();
}
void EventSeqGroup::nextEvent(const uint &id, Info &info, const Common::String &playerId,
Common::Array<EventResult> &result, Common::Array<EventSeqInfo> &endSeq, const int choice) {
return _seq[id].nextEvent(info, playerId, result, endSeq, choice);
}
void EventSeqGroup::internalEvents(Info &info) {
for (auto &it : _seq)
it._value.internalEvents(info);
}
bool EventSeqGroup::activeSeq(uint &activeSeq) {
for (auto &i : _seq) {
if (i._value.eventInProgress()) {
activeSeq = i._key;
return true;
}
}
activeSeq = UINT_MAX;
return false;
}
void EventSeqGroup::saveState(rapidxml::xml_document<> &doc, rapidxml::xml_node<char> *root) {
for (const auto &i : _end) {
rapidxml::xml_node<char> *child = doc.allocate_node(rapidxml::node_element, "end");
child->value(g_engine->_stringPool->get(i));
root->append_node(child);
}
for (auto &i : _seq)
i._value.saveState(doc, root, g_engine->_stringPool->get(i._key));
}
void EventSeqGroup::loadState(rapidxml::xml_node<char> *node) {
for (rapidxml::xml_node<char> *i = node->first_node("end"); i != nullptr; i = i->next_sibling("end"))
endSeq(stringToNumber<uint>(i->value()));
for (auto n = node->first_node("set"); n != nullptr; n = n->next_sibling("set"))
if (n->first_attribute("name") != nullptr) {
uint id = stringToNumber<uint>(n->first_attribute("name")->value());
if (_seq.contains(id))
_seq[id].loadState(n);
}
}
} // End of namespace Crab

View File

@@ -0,0 +1,72 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#ifndef CRAB_EVENTSEQGROUP_H
#define CRAB_EVENTSEQGROUP_H
#include "crab/event/EventSequence.h"
namespace Crab {
namespace pyrodactyl {
namespace event {
class EventSeqGroup {
typedef Common::HashMap<uint, EventSequence> SeqMap;
// The event sequences in this group
SeqMap _seq;
// The sequences that have ended in this group
Common::Array<uint> _end;
public:
EventSeqGroup() {}
~EventSeqGroup() {}
void addSeq(const uint &id, const Common::Path &path);
void endSeq(const uint &id);
bool eventInProgress(const uint &id);
bool activeSeq(uint &activeSeq);
GameEvent *curEvent(const uint &id);
void nextEvent(const uint &id, Info &info, const Common::String &playerId, Common::Array<EventResult> &result,
Common::Array<EventSeqInfo> &endSeq, const int choice = -1);
void internalEvents(Info &info);
void saveState(rapidxml::xml_document<> &doc, rapidxml::xml_node<char> *root);
void loadState(rapidxml::xml_node<char> *node);
};
} // End of namespace event
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_EVENTSEQGROUP_H

View File

@@ -0,0 +1,148 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#include "crab/XMLDoc.h"
#include "crab/event/EventSequence.h"
namespace Crab {
using namespace pyrodactyl::event;
//------------------------------------------------------------------------
// Purpose: Load
//------------------------------------------------------------------------
void EventSequence::load(const Common::Path &filename) {
XMLDoc conf(filename);
if (conf.ready()) {
rapidxml::xml_node<char> *node = conf.doc()->first_node("events");
for (auto n = node->first_node("event"); n != nullptr; n = n->next_sibling("event")) {
GameEvent e(n);
_events.push_back(e);
}
}
}
//------------------------------------------------------------------------
// Purpose: Check for events happening
//------------------------------------------------------------------------
void EventSequence::internalEvents(pyrodactyl::event::Info &info) {
for (const auto &nxe : _next) {
if (nxe < _events.size()) {
if (_events[nxe]._trig.evaluate(info)) {
_eventInProgress = true;
_cur = nxe;
break;
}
}
}
}
//------------------------------------------------------------------------
// Purpose: Go to next event
//------------------------------------------------------------------------
void EventSequence::nextEvent(pyrodactyl::event::Info &info, const Common::String &player_id, Common::Array<EventResult> &result,
Common::Array<EventSeqInfo> &end_seq, int NextEventChoice) {
bool sync = false;
_eventInProgress = false;
// Execute all effects associated with the event
for (auto &i : _events[_cur]._effect)
if (i.execute(info, player_id, result, end_seq))
sync = true;
// Play a notification sound
using namespace pyrodactyl::music;
if (info._sound._repDec)
g_engine->_musicManager->playEffect(g_engine->_musicManager->_repDec, 0);
else if (info._sound._repInc)
g_engine->_musicManager->playEffect(g_engine->_musicManager->_repInc, 0);
else if (info._sound._notify)
g_engine->_musicManager->playEffect(g_engine->_musicManager->_notify, 0);
info._sound._notify = false;
info._sound._repDec = false;
info._sound._repInc = false;
if (!result.empty() || sync) {
EventResult r;
r._type = ER_SYNC;
result.push_back(r);
}
// Clear the next event list
_next.clear();
// Add the next event to the event list
if (NextEventChoice != -1)
_next.push_back(NextEventChoice);
else {
for (const auto &i : _events[_cur]._next)
_next.push_back(i);
}
}
//------------------------------------------------------------------------
// Purpose: Save the state of the object
//------------------------------------------------------------------------
void EventSequence::saveState(rapidxml::xml_document<char> &doc, rapidxml::xml_node<char> *root, const char *name) {
rapidxml::xml_node<char> *seqnode = doc.allocate_node(rapidxml::node_element, "set");
// Write current event id and name to node
seqnode->append_attribute(doc.allocate_attribute("name", name));
seqnode->append_attribute(doc.allocate_attribute("current", g_engine->_stringPool->get(_cur)));
// Prepare strings of next events and write them
for (uint i = 0; i < _next.size(); i++) {
rapidxml::xml_node<char> *child = doc.allocate_node(rapidxml::node_element, "next");
child->value(g_engine->_stringPool->get(_next[i]));
seqnode->append_node(child);
}
root->append_node(seqnode);
}
//------------------------------------------------------------------------
// Purpose: Load the state of the object
//------------------------------------------------------------------------
void EventSequence::loadState(rapidxml::xml_node<char> *node) {
rapidxml::xml_attribute<char> *curid = node->first_attribute("current");
if (curid != nullptr)
_cur = stringToNumber<uint>(curid->value());
_next.clear();
for (auto n = node->first_node("next"); n != nullptr; n = n->next_sibling("next"))
_next.push_back(stringToNumber<uint>(n->value()));
if (_next.empty())
_next.push_back(0);
}
} // End of namespace Crab

View File

@@ -0,0 +1,89 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#ifndef CRAB_EVENTSEQUENCE_H
#define CRAB_EVENTSEQUENCE_H
#include "crab/event/gameevent.h"
namespace Crab {
namespace pyrodactyl {
namespace event {
class EventSequence {
Common::Array<GameEvent> _events;
bool _eventInProgress;
// The event currently in execution - updated only when all trigger conditions are met in InternalEvents
uint _cur;
// The events that can happen next - these are updated when the cur event is over
// This means cur and next operate in an alternating way
// scan next until find event, make it cur, end cur and update next, repeat
Common::Array<uint> _next;
public:
EventSequence() {
_eventInProgress = false;
_next.push_back(0);
_cur = 0;
}
~EventSequence() {}
GameEvent *currentEvent() {
return &_events[_cur];
}
// See if we should trigger any event
void internalEvents(pyrodactyl::event::Info &info);
void nextEvent(Info &info, const Common::String &playerId, Common::Array<EventResult> &result,
Common::Array<EventSeqInfo> &endSeq, int nextEventChoice = -1);
bool eventInProgress() {
return _eventInProgress;
}
void eventInProgress(bool val) {
_eventInProgress = val;
}
// Load and save
void load(const Common::Path &filename);
void saveState(rapidxml::xml_document<char> &doc, rapidxml::xml_node<char> *root, const char *name);
void loadState(rapidxml::xml_node<char> *node);
};
} // End of namespace event
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_EVENTSEQUENCE_H

View File

@@ -0,0 +1,398 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#include "crab/XMLDoc.h"
#include "crab/event/eventstore.h"
#include "crab/event/GameEventInfo.h"
namespace Crab {
namespace pyrodactyl {
namespace event {
bool isChar(char c) {
if (c >= '0' && c <= '9')
return false;
return true;
}
} // End of namespace event
} // End of namespace pyrodactyl
using namespace pyrodactyl::people;
using namespace pyrodactyl::event;
//------------------------------------------------------------------------
// Purpose: Load from xml
//------------------------------------------------------------------------
void Info::load(rapidxml::xml_node<char> *node) {
if (nodeValid("people", node)) {
rapidxml::xml_node<char> *pnode = node->first_node("people");
_stem.load(pnode->first_attribute("templates")->value());
XMLDoc conf(pnode->first_attribute("list")->value());
if (conf.ready()) {
rapidxml::xml_node<char> *cnode = conf.doc()->first_node("characters");
if (nodeValid(cnode)) {
loadNum(OPINION_MIN, "op_min", cnode);
loadNum(OPINION_MAX, "op_max", cnode);
for (auto n = cnode->first_node("group"); n != nullptr; n = n->next_sibling("group"))
loadPeople(n->value());
}
}
}
if (nodeValid("objective", node))
_journal.load(node->first_node("objective")->first_attribute("layout")->value());
if (nodeValid("inventory", node)) {
rapidxml::xml_node<char> *inode = node->first_node("inventory");
_inv.load(inode->first_attribute("layout")->value());
}
curLocID(node->first_node("level")->first_attribute("start")->value());
_inv.itemFile(node->first_node("item")->first_attribute("list")->value());
}
void Info::loadPeople(const Common::Path &filename) {
XMLDoc conf(filename);
if (conf.ready()) {
rapidxml::xml_node<char> *node = conf.doc()->first_node("people");
if (nodeValid(node)) {
for (auto n = node->first_node(); n != nullptr; n = n->next_sibling()) {
Common::String str;
loadStr(str, "id", n);
_people[str].load(n, _stem);
}
}
}
}
//------------------------------------------------------------------------
// Purpose: Get/Set information about object type
//------------------------------------------------------------------------
void Info::type(const Common::String &id, const PersonType &val) {
if (_people.contains(id))
_people[id]._type = val;
}
PersonType Info::type(const Common::String &id) {
if (_people.contains(id))
return _people[id]._type;
return PE_NEUTRAL;
}
//------------------------------------------------------------------------
// Purpose: Get/Set information about object state
//------------------------------------------------------------------------
void Info::state(const Common::String &id, const PersonState &val) {
if (_people.contains(id))
_people[id]._state = val;
}
PersonState Info::state(const Common::String &id) {
if (_people.contains(id))
return _people[id]._state;
return PST_NORMAL;
}
//------------------------------------------------------------------------
// Purpose: Get/Set information about variables
//------------------------------------------------------------------------
bool Info::varGet(const Common::String &name, int &val) {
if (!_var.contains(name))
return false;
else
val = _var[name];
return true;
}
void Info::varSet(const Common::String &name, const Common::String &val) {
int varVal = 0;
bool assignToVar = Common::find_if(val.begin(), val.end(), isChar) != val.end();
if (assignToVar)
varGet(val, varVal);
else
varVal = stringToNumber<int>(val);
_var[name] = varVal;
}
void Info::varAdd(const Common::String &name, const int &val) {
if (!_var.contains(name))
varSet(name, 0);
_var[name] += val;
}
void Info::varSub(const Common::String &name, const int &val) {
if (!_var.contains(name))
varSet(name, 0);
_var[name] -= val;
}
void Info::varMul(const Common::String &name, const int &val) {
if (!_var.contains(name))
varSet(name, 0);
_var[name] *= val;
}
void Info::varDiv(const Common::String &name, const int &val) {
if (!_var.contains(name))
varSet(name, 0);
_var[name] /= val;
}
void Info::varDel(const Common::String &name) {
_var.erase(name);
}
//------------------------------------------------------------------------
// Purpose: Get/Set person traits
//------------------------------------------------------------------------
void Info::traitAdd(const Common::String &perId, const int &traitId) {
if (personValid(perId)) { // Valid person id
if (traitId >= 0 && (uint)traitId < g_engine->_eventStore->_trait.size()) { // Valid trait id
// Check for duplicate traits, DONT award anything if duplicate found
Person *p = &personGet(perId);
for (const auto &i : p->_trait)
if (i._id == traitId)
return;
p->_trait.push_back(g_engine->_eventStore->_trait[traitId]);
g_engine->_eventStore->setAchievement(g_engine->_eventStore->_trait[traitId]._id);
}
}
}
void Info::traitDel(const Common::String &perId, const int &traitId) {
if (personValid(perId)) { // Valid person id
if (traitId > 0 && (uint)traitId < g_engine->_eventStore->_trait.size()) { // Valid trait id
Person *p = &personGet(perId);
for (auto j = p->_trait.begin(); j != p->_trait.end(); ++j) {
if (j->_id == traitId) {
p->_trait.erase(j);
break;
}
}
}
}
}
//------------------------------------------------------------------------
// Purpose: Get/Set information about object opinion
//------------------------------------------------------------------------
bool Info::opinionGet(const Common::String &name, const pyrodactyl::people::OpinionType &type, int &val) {
if (!_people.contains(name))
return false;
val = _people[name]._opinion._val[type];
return true;
}
void Info::opinionChange(const Common::String &name, const pyrodactyl::people::OpinionType &type, int val) {
if (_people.contains(name))
_people[name]._opinion.change(type, val);
}
void Info::opinionSet(const Common::String &name, const pyrodactyl::people::OpinionType &type, int val) {
if (_people.contains(name))
_people[name]._opinion.set(type, val);
}
//------------------------------------------------------------------------
// Purpose: Get/Set information about object stats
//------------------------------------------------------------------------
bool Info::statGet(const Common::String &name, const pyrodactyl::stat::StatType &type, int &num) {
if (!_people.contains(name))
return false;
num = _people[name]._stat._val[type]._cur;
return true;
}
void Info::statSet(const Common::String &name, const pyrodactyl::stat::StatType &type, const int &num) {
if (_people.contains(name))
_people[name]._stat.set(type, num);
}
void Info::statChange(const Common::String &name, const pyrodactyl::stat::StatType &type, const int &num) {
if (_people.contains(name))
_people[name]._stat.change(type, num);
}
//------------------------------------------------------------------------
// Purpose: Get person object
//------------------------------------------------------------------------
bool Info::personGet(const Common::String &id, pyrodactyl::people::Person &p) {
if (!_people.contains(id))
return false;
p = _people[id];
return true;
}
bool Info::personValid(const Common::String &id) {
return _people.contains(id);
}
pyrodactyl::people::Person &Info::personGet(const Common::String &id) {
// Make sure to check PersonValid before doing this!
// Only use this to change parts of an object
return _people[id];
}
bool Info::collideWithTrigger(const Common::String &id, int rectIndex) {
if (_people.contains(id)) {
for (const auto &i : _people[id]._trig)
if (i == rectIndex)
return true;
}
return false;
}
//------------------------------------------------------------------------
// Purpose: Replace all #values with their appropriate names in a string
//------------------------------------------------------------------------
void Info::insertName(Common::String &msg) {
// We scan the dialog for #id values, which we convert to actual NPC names
for (uint i = 0; i < msg.size(); ++i) {
// The # symbol indicates that the next string until an end character needs to be replaced by the name
if (msg[i] == '#') {
// The position we want to start from, and the length of the substring
uint start = i, end = i + 1, len = 0;
// First make sure # wasn't the end of the string
for (; end < msg.size(); ++end, ++len)
if (msg[end] == ',' || msg[end] == '.' || msg[end] == '!' || msg[end] == ' ' ||
msg[end] == '?' || msg[end] == '-' || msg[end] == '\'' || msg[end] == '\"')
break;
if (end < msg.size()) {
// We use start+1 here because # isn't part of the id
Common::String s = msg.substr(start + 1, len);
// We use length+1 here because otherwise it lets the last character stay in dialog
if (personValid(s))
msg.replace(start, len + 1, personGet(s)._name);
}
}
}
}
Common::String Info::getName(const Common::String &id) {
if (personValid(id))
return personGet(id)._name;
return id;
}
//------------------------------------------------------------------------
// Purpose: Save and load object state
//------------------------------------------------------------------------
void Info::saveState(rapidxml::xml_document<> &doc, rapidxml::xml_node<char> *root) {
for (const auto &v : _var) {
rapidxml::xml_node<char> *child = doc.allocate_node(rapidxml::node_element, "var");
child->append_attribute(doc.allocate_attribute("id", v._key.c_str()));
child->append_attribute(doc.allocate_attribute("val", g_engine->_stringPool->get(v._value)));
root->append_node(child);
}
for (auto &p : _people)
p._value.saveState(doc, root);
rapidxml::xml_node<char> *childUnr = doc.allocate_node(rapidxml::node_element, "unread");
saveBool(_unread._inventory, "inventory", doc, childUnr);
saveBool(_unread._journal, "journal", doc, childUnr);
saveBool(_unread._trait, "trait", doc, childUnr);
saveBool(_unread._map, "map", doc, childUnr);
root->append_node(childUnr);
rapidxml::xml_node<char> *child_img = doc.allocate_node(rapidxml::node_element, "img");
child_img->append_attribute(doc.allocate_attribute("index", g_engine->_stringPool->get(_playerImg)));
root->append_node(child_img);
rapidxml::xml_node<char> *child_money = doc.allocate_node(rapidxml::node_element, "money");
child_money->append_attribute(doc.allocate_attribute("var", _moneyVar.c_str()));
root->append_node(child_money);
_journal.saveState(doc, root);
_inv.saveState(doc, root);
}
void Info::loadState(rapidxml::xml_node<char> *node) {
for (rapidxml::xml_node<char> *v = node->first_node("var"); v != nullptr; v = v->next_sibling("var"))
_var[v->first_attribute("id")->value()] = stringToNumber<int>(v->first_attribute("val")->value());
for (rapidxml::xml_node<char> *p = node->first_node("object"); p != nullptr; p = p->next_sibling("object")) {
Common::String id;
loadStr(id, "id", p);
_people[id].loadState(p);
}
if (nodeValid("unread", node)) {
rapidxml::xml_node<char> *unrnode = node->first_node("unread");
loadBool(_unread._inventory, "inventory", unrnode);
loadBool(_unread._journal, "journal", unrnode);
loadBool(_unread._trait, "trait", unrnode);
loadBool(_unread._map, "map", unrnode);
}
if (nodeValid("img", node))
loadNum(_playerImg, "index", node->first_node("img"));
if (nodeValid("money", node))
loadStr(_moneyVar, "var", node->first_node("money"));
_journal.loadState(node);
_inv.loadState(node);
}
//------------------------------------------------------------------------
// Purpose: Calculate UI positions after change in screen size
//------------------------------------------------------------------------
void Info::setUI() {
_journal.setUI();
_inv.setUI();
}
} // End of namespace Crab

View File

@@ -0,0 +1,243 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#ifndef CRAB_GAMEEVENTINFO_H
#define CRAB_GAMEEVENTINFO_H
#include "crab/stat/StatTemplate.h"
#include "crab/ui/Inventory.h"
#include "crab/ui/journal.h"
namespace Crab {
namespace pyrodactyl {
namespace event {
bool isChar(char c);
class Info {
// The characters in the game
pyrodactyl::people::PersonMap _people;
// The stat templates used in declaring person objects
pyrodactyl::stat::StatTemplates _stem;
// The variables set by the events so far
typedef Common::HashMap<Common::String, int> VarMap;
VarMap _var;
// The last object player interacted with
Common::String _lastobj;
// Is the game Iron Man or not?
// Iron man means only one save - no reloading
bool _ironman;
// The player's current location
struct PlayerLoc {
// id of the player's current location
Common::String _id;
// The name of the player's current location
Common::String _name;
PlayerLoc() {}
} _loc;
// This image changes to reflect the playable character
int _playerImg;
void loadPeople(const Common::Path &filename);
public:
// The player's one stop shop for objectives and lore
pyrodactyl::ui::Journal _journal;
// The current player inventory
pyrodactyl::ui::Inventory _inv;
// This structure keeps track of unread indicators
struct UnreadData {
bool _inventory, _journal, _trait, _map;
UnreadData() {
_inventory = false;
_journal = false;
_trait = true;
_map = false;
}
} _unread;
// This is the variable corresponding to money that is drawn
Common::String _moneyVar;
// Has the player pressed the talk key
bool _talkKeyDown;
// Used so we only play one sound per event
struct NotifySounds {
bool _notify, _repInc, _repDec;
NotifySounds() {
_notify = false;
_repInc = false;
_repDec = false;
}
} _sound;
Info() {
Init();
}
~Info() {}
void Init() {
_lastobj = "";
_ironman = false;
_playerImg = 0;
_talkKeyDown = false;
}
void load(rapidxml::xml_node<char> *node);
// Person related stuff
void type(const Common::String &id, const pyrodactyl::people::PersonType &val);
pyrodactyl::people::PersonType type(const Common::String &id);
void state(const Common::String &id, const pyrodactyl::people::PersonState &val);
pyrodactyl::people::PersonState state(const Common::String &id);
// Opinion
bool opinionGet(const Common::String &name, const pyrodactyl::people::OpinionType &type, int &val);
void opinionSet(const Common::String &name, const pyrodactyl::people::OpinionType &type, int val);
void opinionChange(const Common::String &name, const pyrodactyl::people::OpinionType &type, int val);
// Stats
bool statGet(const Common::String &name, const pyrodactyl::stat::StatType &type, int &num);
void statSet(const Common::String &name, const pyrodactyl::stat::StatType &type, const int &num);
void statChange(const Common::String &name, const pyrodactyl::stat::StatType &type, const int &num);
// Variables
bool varGet(const Common::String &name, int &val);
void varSet(const Common::String &name, const Common::String &val);
void varAdd(const Common::String &name, const int &val);
void varSub(const Common::String &name, const int &val);
void varMul(const Common::String &name, const int &val);
void varDiv(const Common::String &name, const int &val);
void varDel(const Common::String &name);
// The trait functions
void traitAdd(const Common::String &perId, const int &traitId);
void traitDel(const Common::String &perId, const int &traitId);
// Player character button
void playerImg(const int &val) {
_playerImg = val;
}
int playerImg() {
return _playerImg;
}
Common::String curLocID() {
return _loc._id;
}
void curLocID(const Common::String &id) {
_loc._id = id;
}
Common::String curLocName() {
return _loc._name;
}
void curLocName(const Common::String &name) {
_loc._name = name;
}
// Player stuff
Common::String lastPerson() {
return _lastobj;
}
void lastPerson(const Common::String &name) {
_lastobj = name;
}
// Return the variable map for stuff like visibility checks
VarMap &mapGet() {
return _var;
}
bool personGet(const Common::String &id, pyrodactyl::people::Person &p);
bool personValid(const Common::String &id);
pyrodactyl::people::Person &personGet(const Common::String &id);
// Is an object colliding with a trigger area
bool collideWithTrigger(const Common::String &id, int rectIndex);
// Replace all #values with their appropriate names in a string
void insertName(Common::String &msg);
Common::String getName(const Common::String &id);
// Draw the inventory
void invDraw(const Common::String &id) {
if (_var.contains(_moneyVar))
_inv.draw(_people[id], _var[_moneyVar]);
else
_inv.draw(_people[id], 0);
}
// Get whether game is iron man or not
bool ironMan() {
return _ironman;
}
void ironMan(const bool &val) {
_ironman = val;
}
void loadIronMan(rapidxml::xml_node<char> *node) {
Common::String str;
loadStr(str, "diff", node);
_ironman = (str == "Iron Man");
}
void saveState(rapidxml::xml_document<> &doc, rapidxml::xml_node<char> *root);
void loadState(rapidxml::xml_node<char> *node);
void setUI();
};
} // End of namespace event
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_GAMEEVENTINFO_H

View File

@@ -0,0 +1,73 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#ifndef CRAB_CHANGEVAL_H
#define CRAB_CHANGEVAL_H
#include "common/str.h"
#include "crab/loaders.h"
#include "crab/people/opinion.h"
namespace Crab {
using namespace pyrodactyl::people;
namespace pyrodactyl {
namespace event {
struct ChangeVal {
// The person whose opinion is changed
Common::String _id;
// How much does opinion change?
int _val[pyrodactyl::people::OPI_TOTAL];
ChangeVal() {
_val[OPI_LIKE] = 0;
_val[OPI_RESPECT] = 0;
_val[OPI_FEAR] = 0;
}
ChangeVal(rapidxml::xml_node<char> *node) : ChangeVal() {
load(node);
}
void load(rapidxml::xml_node<char> *node) {
loadStr(_id, "id", node);
loadNum(_val[OPI_LIKE], "like", node);
loadNum(_val[OPI_RESPECT], "respect", node);
loadNum(_val[OPI_FEAR], "fear", node);
}
};
} // End of namespace event
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_CHANGEVAL_H

View File

@@ -0,0 +1,55 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#include "crab/event/conversationdata.h"
namespace Crab {
using namespace pyrodactyl::event;
void ReplyChoice::load(rapidxml::xml_node<char> *node) {
loadStr(_text, "text", node);
loadNum(_tone, "tone", node);
loadNum(_nextid, "next", node);
if (nodeValid("unlock", node, false))
_unlock.load(node->first_node("unlock"));
if (nodeValid("change", node, false))
for (auto n = node->first_node("change"); n != nullptr; n = n->next_sibling("change"))
_change.push_back(n);
}
void ConversationData::load(rapidxml::xml_node<char> *node) {
for (auto n = node->first_node("reply"); n != nullptr; n = n->next_sibling("reply"))
_reply.push_back(n);
}
} // End of namespace Crab

View File

@@ -0,0 +1,83 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#ifndef CRAB_CONVERSATIONDATA_H
#define CRAB_CONVERSATIONDATA_H
#include "crab/event/changeval.h"
#include "crab/event/triggerset.h"
namespace Crab {
namespace pyrodactyl {
namespace event {
struct ReplyChoice {
// The text for the reply
Common::String _text;
// The tone of the response
uint _tone;
// The next event id
uint _nextid;
// The conditions to unlock this choice
TriggerSet _unlock;
// The changes to opinion that are possible for this reply
// All NPCs affected by this conversation
Common::Array<ChangeVal> _change;
ReplyChoice() {
_tone = 0;
_nextid = 0;
}
ReplyChoice(rapidxml::xml_node<char> *node) : ReplyChoice() {
load(node);
}
void load(rapidxml::xml_node<char> *node);
};
struct ConversationData {
// The set of replies
Common::Array<ReplyChoice> _reply;
ConversationData() {}
void load(rapidxml::xml_node<char> *node);
};
} // End of namespace event
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_CONVERSATIONDATA_H

View File

@@ -0,0 +1,289 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#include "crab/crab.h"
#include "crab/event/effect.h"
namespace Crab {
using namespace pyrodactyl::event;
using namespace pyrodactyl::music;
void Effect::load(rapidxml::xml_node<char> *node) {
Common::String ty;
loadStr(ty, "type", node);
// Should we throw a warning about missing fields? Depends on the type of effect
bool echoOp = true, echoSub = true, echoVal = true;
if (ty == "var")
_type = EFF_VAR;
else if (ty == "journal")
_type = EFF_JOURNAL;
else if (ty == "person")
_type = EFF_OBJ;
else if (ty == "item")
_type = EFF_ITEM;
else if (ty == "like")
_type = EFF_LIKE;
else if (ty == "fear")
_type = EFF_FEAR;
else if (ty == "respect")
_type = EFF_RESPECT;
else if (ty == STATNAME_HEALTH)
_type = EFF_HEALTH;
else if (ty == "sound")
_type = EFF_SOUND;
else if (ty == "money")
_type = EFF_MONEY;
else if (ty == "end") {
_type = EFF_END;
echoSub = false;
echoVal = false;
} else if (ty == "map")
_type = EFF_MAP;
else if (ty == "dest")
_type = EFF_DEST;
else if (ty == "img") {
_type = EFF_IMG;
echoOp = false;
echoSub = false;
} else if (ty == "trait") {
_type = EFF_TRAIT;
echoOp = false;
} else if (ty == "move") {
_type = EFF_MOVE;
echoOp = false;
} else if (ty == "level")
_type = EFF_LEVEL;
else if (ty == "player") {
_type = EFF_PLAYER;
echoOp = false;
echoSub = false;
} else if (ty == "save") {
_type = EFF_SAVE;
echoOp = false;
echoSub = false;
echoVal = false;
} else if (ty == "quit") {
_type = EFF_QUIT;
echoOp = false;
echoSub = false;
echoVal = false;
} else
_type = EFF_VAR;
loadStr(_subject, "subject", node, echoSub);
loadStr(_operation, "operation", node, echoOp);
loadStr(_val, "val", node, echoVal);
}
void Effect::changeOpinion(pyrodactyl::event::Info &info, pyrodactyl::people::OpinionType opType) {
int oldOp = 0;
// Only bother if the person exists and has a valid opinion
if (info.opinionGet(_subject, opType, oldOp)) {
if (_operation == "=")
info.opinionSet(_subject, opType, stringToNumber<int>(_val));
else if (_operation == "+")
info.opinionChange(_subject, opType, stringToNumber<int>(_val));
else if (_operation == "-")
info.opinionChange(_subject, opType, -1 * stringToNumber<int>(_val));
int newOp = 0;
info.opinionGet(_subject, opType, newOp);
if (newOp > oldOp)
info._sound._repInc = true;
else if (newOp < oldOp)
info._sound._repDec = true;
}
}
bool Effect::execute(pyrodactyl::event::Info &info, const Common::String &playerId,
Common::Array<EventResult> &result, Common::Array<EventSeqInfo> &endSeq) {
if (_type < EFF_MOVE) {
switch (_type) {
case EFF_VAR:
if (_operation == "=")
info.varSet(_subject, _val);
else if (_operation == "del")
info.varDel(_subject);
else if (_operation == "+")
info.varAdd(_subject, stringToNumber<int>(_val));
else if (_operation == "-")
info.varSub(_subject, stringToNumber<int>(_val));
else if (_operation == "*")
info.varMul(_subject, stringToNumber<int>(_val));
else if (_operation == "/")
info.varDiv(_subject, stringToNumber<int>(_val));
break;
case EFF_JOURNAL:
if (_subject == "finish")
info._journal.move(playerId, _operation, true);
else if (_subject == "start")
info._journal.move(playerId, _operation, false);
else
info._journal.add(playerId, _subject, _operation, _val);
// Update unread status of journal
info._unread._journal = true;
// used so we only play one notify sound per event
info._sound._notify = true;
break;
case EFF_OBJ:
if (_operation == "type")
info.type(_subject, pyrodactyl::people::stringToPersonType(_val));
else if (_operation == "state")
info.state(_subject, pyrodactyl::people::stringToPersonState(_val));
break;
case EFF_ITEM:
if (_operation == "del")
info._inv.delItem(_subject, _val);
else
info._inv.loadItem(_subject, _val);
// Update unread status of inventory
info._unread._inventory = true;
// used so we only play one notify sound per event
info._sound._notify = true;
break;
case EFF_LIKE:
changeOpinion(info, pyrodactyl::people::OPI_LIKE);
break;
case EFF_FEAR:
changeOpinion(info, pyrodactyl::people::OPI_FEAR);
break;
case EFF_RESPECT:
changeOpinion(info, pyrodactyl::people::OPI_RESPECT);
break;
case EFF_HEALTH: {
using namespace pyrodactyl::stat;
int num = stringToNumber<int>(_val);
if (_operation == "=")
info.statSet(_subject, STAT_HEALTH, num);
else if (_operation == "+")
info.statChange(_subject, STAT_HEALTH, num);
else if (_operation == "-")
info.statChange(_subject, STAT_HEALTH, -1 * num);
} break;
case EFF_SOUND:
if (_subject == "music") {
if (_operation == "play") {
MusicKey m = stringToNumber<MusicKey>(_val);
g_engine->_musicManager->playMusic(m);
} else if (_operation == "stop")
g_engine->_musicManager->stop();
else if (_operation == "pause")
g_engine->_musicManager->pause();
else if (_operation == "resume")
g_engine->_musicManager->resume();
} else
g_engine->_musicManager->playEffect(stringToNumber<ChunkKey>(_val), 0);
break;
case EFF_MONEY:
info._moneyVar = _val;
break;
case EFF_END:
if (_operation == "cur")
endSeq.push_back(true);
else {
EventSeqInfo seqinfo;
seqinfo._loc = _subject;
seqinfo._val = _val;
endSeq.push_back(seqinfo);
}
break;
default:
break;
}
return true;
} else {
EventResult r;
r._val = _subject;
r._x = stringToNumber<int>(_operation);
r._y = stringToNumber<int>(_val);
switch (_type) {
case EFF_MOVE:
r._type = ER_MOVE;
break;
case EFF_MAP:
r._type = ER_MAP;
break;
case EFF_DEST:
r._type = ER_DEST;
break;
case EFF_IMG:
r._type = ER_IMG;
info.playerImg(stringToNumber<int>(_val));
break;
case EFF_TRAIT:
r._type = ER_TRAIT;
info._unread._trait = true;
info._sound._notify = true;
break;
case EFF_LEVEL:
r._type = ER_LEVEL;
break;
case EFF_PLAYER:
r._type = ER_PLAYER;
break;
case EFF_SAVE:
r._type = ER_SAVE;
break;
case EFF_QUIT:
r._type = ER_QUIT;
break;
default:
break;
}
result.push_back(r);
}
return false;
}
} // End of namespace Crab

127
engines/crab/event/effect.h Normal file
View File

@@ -0,0 +1,127 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#ifndef CRAB_EFFECT_H
#define CRAB_EFFECT_H
#include "crab/loaders.h"
#include "crab/event/GameEventInfo.h"
#include "crab/people/person.h"
#include "crab/rapidxml/rapidxml.hpp"
namespace Crab {
namespace pyrodactyl {
namespace event {
enum EventResultType {
ER_NONE, // Do nothing
ER_MAP, // Change the map visible to player
ER_DEST, // Add or remove a destination on world map
ER_IMG, // Change the character button image
ER_TRAIT, // Add or remove a trait from a character
ER_LEVEL, // Change level
ER_MOVE, // Move sprite
ER_PLAYER, // Switch the player sprite
ER_SAVE, // Save game
ER_SYNC, // Sync the level
ER_QUIT // Quit to main menu
};
struct EventResult {
EventResultType _type;
Common::String _val;
int _x, _y;
EventResult() {
_type = ER_NONE;
_x = -1;
_y = -1;
}
};
struct EventSeqInfo {
bool _cur;
Common::String _loc, _val;
EventSeqInfo() {
_cur = false;
}
EventSeqInfo(const bool &cur) {
_cur = cur;
}
};
enum EffectType {
EFF_VAR, // variable operations like adding, removing etc
EFF_JOURNAL, // Add an objective to the player quest book
EFF_OBJ, // Change status (hostile, coward etc), state (stand, fight, flee, KO etc) of a character
EFF_ITEM, // Add/remove an item in the player's inventory
EFF_LIKE, // Change opinion of a character (charm)
EFF_FEAR, // Change opinion of a character (intimidate)
EFF_RESPECT, // Change opinion of a character (respect)
EFF_HEALTH, // Change health of a character
EFF_SOUND, // Manipulate the game music
EFF_MONEY, // Set the money variable (not its value, just that which variable is the current money variable)
EFF_END, // End of the event sequence, remove it from active sequences
// EFFECT DIVISION HERE
EFF_MOVE, // Make a character move
EFF_MAP, // Change the world map
EFF_DEST, // Add a destination to the world map
EFF_IMG, // Change the player button image
EFF_TRAIT, // Add or remove a trait from a character
EFF_LEVEL, // Load a new level
EFF_PLAYER, // Swap the player sprite
EFF_SAVE, // Auto save the game
EFF_QUIT // Quit to main menu
};
struct Effect {
EffectType _type;
Common::String _subject, _operation, _val;
Effect() {
_type = EFF_VAR;
}
~Effect() {}
void load(rapidxml::xml_node<char> *node);
bool execute(pyrodactyl::event::Info &info, const Common::String &playerId,
Common::Array<EventResult> &result, Common::Array<EventSeqInfo> &endSeq);
void changeOpinion(pyrodactyl::event::Info &info, pyrodactyl::people::OpinionType type);
};
} // End of namespace event
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_EFFECT_H

View File

@@ -0,0 +1,102 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#include "crab/XMLDoc.h"
#include "crab/event/eventstore.h"
namespace Crab {
using namespace pyrodactyl::event;
void GameEventStore::addConv(rapidxml::xml_node<char> *node, uint &index) {
ConversationData c;
if (nodeValid("talk", node))
c.load(node->first_node("talk"));
index = _con.size();
_con.push_back(c);
}
void GameEventStore::load(const Common::Path &filename) {
// Request current user stats from Steam
// m_pSteamUserStats = SteamUserStats();
// if (m_pSteamUserStats != nullptr)
// m_pSteamUserStats->RequestCurrentStats();
XMLDoc conf(filename);
if (conf.ready()) {
rapidxml::xml_node<char> *node = conf.doc()->first_node("store");
if (nodeValid("animations", node)) {
rapidxml::xml_node<char> *animnode = node->first_node("animations");
for (auto n = animnode->first_node("anim"); n != nullptr; n = n->next_sibling("anim"))
_anim.push_back(n);
}
if (nodeValid("tones", node)) {
rapidxml::xml_node<char> *tonenode = node->first_node("tones");
for (auto n = tonenode->first_node("tone"); n != nullptr; n = n->next_sibling("tone")) {
ToneData dat;
loadStr(dat._text, "text", n);
_tone.push_back(dat);
}
}
if (nodeValid("images", node)) {
rapidxml::xml_node<char> *imgnode = node->first_node("images");
for (auto n = imgnode->first_node("img"); n != nullptr; n = n->next_sibling("img"))
_img.push_back(n);
}
if (nodeValid("traits", node)) {
rapidxml::xml_node<char> *traitnode = node->first_node("traits");
for (auto n = traitnode->first_node("trait"); n != nullptr; n = n->next_sibling("trait"))
_trait.push_back(n);
}
}
}
void GameEventStore::setAchievement(const int &id) {
/*
if (m_pSteamUserStats != nullptr)
{
if (id == 0)
m_pSteamUserStats->SetAchievement("a0");
else
m_pSteamUserStats->SetAchievement(trait[id].id_str.c_str());
m_pSteamUserStats->StoreStats();
}
*/
}
} // End of namespace Crab

View File

@@ -0,0 +1,91 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#ifndef CRAB_EVENTSTORE_H
#define CRAB_EVENTSTORE_H
#include "crab/animation/animation.h"
#include "crab/event/conversationdata.h"
#include "crab/ui/StateButton.h"
namespace Crab {
namespace pyrodactyl {
namespace event {
// This structure is responsible for storing the special data structures for events like replies, conversations
struct GameEventStore {
// Data related to conversation events
Common::Array<ConversationData> _con;
// Data related to animations
Common::Array<pyrodactyl::anim::Animation> _anim;
// Data related to the tones of a character
struct ToneData {
Common::String _text;
};
// This sets the text the player sees as "tone" during the reply menu
Common::Array<ToneData> _tone;
// We need to change player character images when switching between characters
Common::Array<pyrodactyl::ui::StateButtonImage> _img;
// The set of traits for various characters
Common::Array<pyrodactyl::people::Trait> _trait;
// Steam UserStats interface
// ISteamUserStats *m_pSteamUserStats;
GameEventStore() {
// Huge number to prevent lots of resizing and stuff
_con.reserve(9999);
_trait.reserve(120);
_tone.reserve(120);
}
void clear() {
_con.clear();
_anim.clear();
}
void load(const Common::Path &filename);
void addConv(rapidxml::xml_node<char> *node, uint &index);
void setAchievement(const int &id);
};
} // End of namespace event
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_EVENTSTORE_H

View File

@@ -0,0 +1,91 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#include "crab/event/gameevent.h"
namespace Crab {
using namespace pyrodactyl::event;
using namespace pyrodactyl::people;
GameEvent::GameEvent() {
_id = 0;
_type = EVENT_DIALOG;
_special = 0;
_state = PST_NORMAL;
}
void GameEvent::load(rapidxml::xml_node<char> *node) {
if (!LoadEventID(_id, "id", node))
_id = 0;
loadStr(_title, "title", node);
loadStr(_dialog, "dialog", node);
loadEnum(_state, "state", node, false);
Common::String type;
loadStr(type, "type", node);
if (type == "dlg") {
_type = EVENT_DIALOG;
_special = 0;
} else if (type == "reply") {
_type = EVENT_REPLY;
g_engine->_eventStore->addConv(node, _special);
} else if (type == "animation") {
_type = EVENT_ANIM;
loadNum(_special, "anim", node);
} else if (type == "silent") {
_type = EVENT_SILENT;
_special = 0;
} else if (type == "text") {
_type = EVENT_TEXT;
_special = 0;
} else {
_type = EVENT_SPLASH;
_special = 0;
}
_trig.load(node);
_next.clear();
for (rapidxml::xml_node<char> *i = node->first_node("next"); i != nullptr; i = i->next_sibling("next"))
if (i->first_attribute("id") != nullptr)
_next.push_back(stringToNumber<EventID>(i->first_attribute("id")->value()));
_effect.clear();
for (rapidxml::xml_node<char> *it = node->first_node("effect"); it != nullptr; it = it->next_sibling("effect")) {
Effect e;
e.load(it);
_effect.push_back(e);
}
}
} // End of namespace Crab

View File

@@ -0,0 +1,99 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#ifndef CRAB_GAMEEVENT_H
#define CRAB_GAMEEVENT_H
#include "crab/event/effect.h"
#include "crab/event/eventstore.h"
#include "crab/people/person.h"
#include "crab/event/triggerset.h"
namespace Crab {
// An uinteger is our event id format
typedef uint EventID;
// Just map loading function to number load
#define LoadEventID loadNum
namespace pyrodactyl {
namespace event {
enum EventType {
EVENT_DIALOG,
EVENT_REPLY,
EVENT_TEXT,
EVENT_ANIM,
EVENT_SILENT,
EVENT_SPLASH
};
struct GameEvent {
// The event identifier
EventID _id;
// The heading for the dialog spoken
Common::String _title;
// The dialog spoken in the event
Common::String _dialog;
// The state decides which animation is drawn in the dialog box
pyrodactyl::people::PersonState _state;
// Event type and related data index
EventType _type;
uint _special;
// The variables changed/added in the event
Common::Array<Effect> _effect;
// The triggers for the event
TriggerSet _trig;
// The id of the next event
Common::Array<EventID> _next;
GameEvent();
GameEvent(rapidxml::xml_node<char> *node) : GameEvent() {
load(node);
}
~GameEvent() {}
void load(rapidxml::xml_node<char> *node);
};
} // End of namespace event
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_GAMEEVENT_H

View File

@@ -0,0 +1,371 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#include "crab/event/gameeventmanager.h"
namespace Crab {
using namespace pyrodactyl::people;
using namespace pyrodactyl::event;
using namespace pyrodactyl::level;
using namespace pyrodactyl::image;
using namespace pyrodactyl::ui;
void Manager::init() {
_eventMap.clear();
_activeSeq = UINT_MAX;
_curSp = nullptr;
_player = false;
_curEvent = nullptr;
_drawGame = true;
}
//------------------------------------------------------------------------
// Purpose: Load this
//------------------------------------------------------------------------
void Manager::load(rapidxml::xml_node<char> *node, ParagraphData &popup) {
if (nodeValid(node)) {
XMLDoc conf(node->first_attribute("list")->value());
if (conf.ready()) {
rapidxml::xml_node<char> *lnode = conf.doc()->first_node("event_list");
for (rapidxml::xml_node<char> *loc = lnode->first_node("loc"); loc != nullptr; loc = loc->next_sibling("loc")) {
Common::String locName;
loadStr(locName, "name", loc);
for (auto n = loc->first_node("file"); n != nullptr; n = n->next_sibling("file")) {
uint id;
Common::Path path;
loadNum(id, "name", n);
loadPath(path, "path", n);
_eventMap[locName].addSeq(id, path);
}
}
}
_activeSeq = UINT_MAX;
conf.load(node->first_attribute("layout")->value());
if (conf.ready()) {
rapidxml::xml_node<char> *layout = conf.doc()->first_node("layout");
if (nodeValid(layout)) {
if (nodeValid("character", layout))
_oh.load(layout->first_node("character"));
if (nodeValid("popup", layout))
popup.load(layout->first_node("popup"));
if (nodeValid("intro", layout))
_intro.load(layout->first_node("intro"));
}
}
_reply.load(node->first_attribute("conversation")->value());
_per.load(node->first_attribute("char")->value());
}
}
//------------------------------------------------------------------------
// Purpose: Handle events
//------------------------------------------------------------------------
void Manager::handleEvents(Info &info, const Common::String &playerId, Common::Event &event, HUD &hud, Level &level, Common::Array<EventResult> &result) {
// If an event is already being performed
if (_eventMap.contains(info.curLocID()) && _eventMap[info.curLocID()].eventInProgress(_activeSeq)) {
switch (_curEvent->_type) {
case EVENT_DIALOG:
if (_oh._showJournal) {
info._journal.handleEvents(playerId, event);
if (hud._back.handleEvents(event) == BUAC_LCLICK || hud._pausekey.handleEvents(event))
_oh._showJournal = false;
} else {
// If journal button is select from within an event, go to the entry corresponding to that person's name
if (_oh.handleCommonEvents(event)) {
if (info.personValid(_curEvent->_title)) {
Person &p = info.personGet(_curEvent->_title);
if (p._altJournalName)
info._journal.open(playerId, JE_PEOPLE, p._journalName);
else
info._journal.open(playerId, JE_PEOPLE, p._name);
}
}
if (_oh.handleDlboxEvents(event)) {
_oh.onExit();
_eventMap[info.curLocID()].nextEvent(_activeSeq, info, playerId, result, _endSeq);
_oh._showJournal = false;
}
}
break;
case EVENT_ANIM:
// Skip animation if key pressed or mouse pressed
if (event.type == Common::EVENT_LBUTTONUP || event.type == Common::EVENT_RBUTTONUP)
_eventMap[info.curLocID()].nextEvent(_activeSeq, info, playerId, result, _endSeq);
break;
case EVENT_REPLY:
if (_oh._showJournal) {
info._journal.handleEvents(playerId, event);
if (hud._back.handleEvents(event) == BUAC_LCLICK || hud._pausekey.handleEvents(event))
_oh._showJournal = false;
} else {
// If journal button is select from within an event, go to the entry corresponding to that person's name
if (_oh.handleCommonEvents(event))
if (info.personValid(_curEvent->_title))
info._journal.open(playerId, JE_PEOPLE, info.personGet(_curEvent->_title)._name);
unsigned int option = static_cast<unsigned int>(_reply.hoverIndex());
const auto &replyChoice = g_engine->_eventStore->_con[_curEvent->_special]._reply;
if (option < replyChoice.size()) {
_intro.onEntry(replyChoice[option]._text);
}
int choice = _reply.handleEvents(info, g_engine->_eventStore->_con[_curEvent->_special], _curEvent->_title, _oh, event);
if (choice >= 0) {
_reply.onExit();
_eventMap[info.curLocID()].nextEvent(_activeSeq, info, playerId, result, _endSeq, choice);
_oh._showJournal = false;
}
}
break;
case EVENT_TEXT:
// If journal button is select from within an event, go to the entry corresponding to that person's name
if (_oh.handleCommonEvents(event))
if (info.personValid(_curEvent->_title))
info._journal.open(playerId, JE_PEOPLE, info.personGet(_curEvent->_title)._name);
if (_textin.handleEvents(event))
_eventMap[info.curLocID()].nextEvent(_activeSeq, info, playerId, result, _endSeq);
break;
case EVENT_SPLASH:
if (_intro._showTraits) {
_per.handleEvents(info, _curEvent->_title, event);
if (hud._back.handleEvents(event) == BUAC_LCLICK || hud._pausekey.handleEvents(event))
_intro._showTraits = false;
} else {
if (_intro.handleEvents(event)) {
_intro.onExit();
_eventMap[info.curLocID()].nextEvent(_activeSeq, info, playerId, result, _endSeq);
}
if (_intro._showTraits)
_per.Cache(info, level.playerId(), level);
}
break;
default:
break;
}
endSequence(info.curLocID());
}
}
//------------------------------------------------------------------------
// Purpose: Internal Events
//------------------------------------------------------------------------
void Manager::internalEvents(Info &info, Level &level, Common::Array<EventResult> &result) {
if (_eventMap.contains(info.curLocID())) {
if (_eventMap[info.curLocID()].eventInProgress(_activeSeq)) {
switch (_curEvent->_type) {
case EVENT_DIALOG:
// fallthrough intended
case EVENT_REPLY:
// fallthrough intended
case EVENT_SPLASH:
updateDialogBox(info, level);
break;
case EVENT_ANIM: {
using namespace pyrodactyl::anim;
DrawType drawVal = DRAW_SAME;
if (g_engine->_eventStore->_anim[_curEvent->_special].internalEvents(drawVal))
_eventMap[info.curLocID()].nextEvent(_activeSeq, info, level.playerId(), result, _endSeq);
if (drawVal == DRAW_STOP)
_drawGame = false;
else if (drawVal == DRAW_START)
_drawGame = true;
} break;
case EVENT_SILENT:
_eventMap[info.curLocID()].nextEvent(_activeSeq, info, level.playerId(), result, _endSeq);
break;
default:
break;
}
endSequence(info.curLocID());
} else {
_eventMap[info.curLocID()].internalEvents(info);
calcActiveSeq(info, level, level.camera());
}
}
}
void Manager::updateDialogBox(Info &info, pyrodactyl::level::Level &level) {
_oh.internalEvents(_curEvent->_state, _curSp);
}
//------------------------------------------------------------------------
// Purpose: Draw
//------------------------------------------------------------------------
void Manager::draw(Info &info, HUD &hud, Level &level) {
if (_eventMap.contains(info.curLocID()) && _eventMap[info.curLocID()].eventInProgress(_activeSeq)) {
switch (_curEvent->_type) {
case EVENT_ANIM:
g_engine->_eventStore->_anim[_curEvent->_special].draw();
break;
case EVENT_DIALOG:
g_engine->_imageManager->dimScreen();
if (_oh._showJournal) {
info._journal.draw(level.playerId());
hud._back.draw();
} else
_oh.draw(info, _curEvent, _curEvent->_title, _player, _curSp);
break;
case EVENT_REPLY:
g_engine->_imageManager->dimScreen();
if (_oh._showJournal) {
info._journal.draw(level.playerId());
hud._back.draw();
} else {
_oh.draw(info, _curEvent, _curEvent->_title, _player, _curSp);
_reply.draw();
}
break;
case EVENT_TEXT:
_oh.draw(info, _curEvent, _curEvent->_title, _player, _curSp);
_textin.draw();
break;
case EVENT_SPLASH:
g_engine->_imageManager->dimScreen();
if (_intro._showTraits) {
_per.draw(info, _curEvent->_title);
hud._back.draw();
} else
_intro.draw(info, _curEvent->_dialog, _curSp, _curEvent->_state);
break;
default:
break;
}
}
}
//------------------------------------------------------------------------
// Purpose: Calculate the current sequence in progress
//------------------------------------------------------------------------
void Manager::calcActiveSeq(Info &info, pyrodactyl::level::Level &level, const Rect &camera) {
if (_eventMap[info.curLocID()].activeSeq(_activeSeq)) {
// Set all the pointers to the new values
_curEvent = _eventMap[info.curLocID()].curEvent(_activeSeq);
_oh.reset(_curEvent->_title);
_curSp = level.getSprite(_curEvent->_title);
// The player character's dialog is drawn a bit differently compared to others
_player = (_curEvent->_title == level.playerId());
switch (_curEvent->_type) {
case EVENT_DIALOG:
_oh.onEntry(_curEvent->_dialog);
break;
case EVENT_ANIM:
g_engine->_eventStore->_anim[_curEvent->_special].start();
break;
case EVENT_REPLY:
_reply.onEntry(_curEvent->_dialog);
_reply.cache(info, g_engine->_eventStore->_con[_curEvent->_special]);
break;
case EVENT_SPLASH:
_intro.onEntry(_curEvent->_dialog);
break;
default:
break;
}
}
}
//------------------------------------------------------------------------
// Purpose: Get/set info
//------------------------------------------------------------------------
void Manager::endSequence(const Common::String &curloc) {
if (_endSeq.empty())
return;
for (const auto &i : _endSeq)
if (i._cur)
_eventMap[curloc].endSeq(_activeSeq);
else if (_eventMap.contains(i._loc))
_eventMap[i._loc].endSeq(stringToNumber<uint>(i._val));
_activeSeq = UINT_MAX;
_endSeq.clear();
}
bool Manager::eventInProgress() {
if (_activeSeq == UINT_MAX)
return false;
return true;
}
//------------------------------------------------------------------------
// Purpose: Save the state of the object
//------------------------------------------------------------------------
void Manager::saveState(rapidxml::xml_document<> &doc, rapidxml::xml_node<char> *root) {
for (auto &i : _eventMap) {
rapidxml::xml_node<char> *child = doc.allocate_node(rapidxml::node_element, "loc");
child->append_attribute(doc.allocate_attribute("name", i._key.c_str()));
i._value.saveState(doc, child);
root->append_node(child);
}
}
//------------------------------------------------------------------------
// Purpose: Load the state of the object
//------------------------------------------------------------------------
void Manager::loadState(rapidxml::xml_node<char> *node) {
for (auto n = node->first_node("loc"); n != nullptr; n = n->next_sibling("loc")) {
if (n->first_attribute("name") != nullptr) {
Common::String name = n->first_attribute("name")->value();
if (_eventMap.contains(name))
_eventMap[name].loadState(n);
}
}
}
//------------------------------------------------------------------------
// Purpose: Function called when window size is changed to adjust UI
//------------------------------------------------------------------------
void Manager::setUI() {
_oh.setUI();
_reply.setUI();
_textin.setUI();
_per.setUI();
}
} // End of namespace Crab

View File

@@ -0,0 +1,117 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#ifndef CRAB_GAMEEVENTMANAGER_H
#define CRAB_GAMEEVENTMANAGER_H
#include "crab/event/EventSeqGroup.h"
#include "crab/ui/ChapterIntro.h"
#include "crab/ui/hud.h"
#include "crab/ui/journal.h"
#include "crab/ui/PersonHandler.h"
#include "crab/ui/PersonScreen.h"
#include "crab/ui/ReplyMenu.h"
#include "crab/ui/textarea.h"
namespace Crab {
namespace pyrodactyl {
namespace event {
class Manager {
protected:
// All the events in the game
Common::HashMap<Common::String, EventSeqGroup> _eventMap;
// The currently happening or active sequence
uint _activeSeq;
// THIS IS NOT THE DEFINITIVE LIST OF ENDED SEQUENCES
// JUST A TEMPORARY LIST OF EVENT SEQUENCES TO PASS AROUND
Common::Array<EventSeqInfo> _endSeq;
// The objects used to draw the dialog box and opinion bars
pyrodactyl::ui::PersonHandler _oh;
// The _reply menu and the colors and font of the text
pyrodactyl::ui::ReplyMenu _reply;
// The field for text input
pyrodactyl::ui::TextArea _textin;
// The info for intro events
pyrodactyl::ui::ChapterIntro _intro;
// Store the current event data temporarily
GameEvent *_curEvent;
bool _player;
pyrodactyl::anim::Sprite *_curSp;
void updateDialogBox(Info &info, pyrodactyl::level::Level &level);
public:
// The object used to draw the character screen
pyrodactyl::ui::PersonScreen _per;
// A flag used to stop drawing the game for a better fade in/fade out experience
bool _drawGame;
Manager() {
init();
}
~Manager() {}
void init();
void load(rapidxml::xml_node<char> *node, pyrodactyl::ui::ParagraphData &popup);
void draw(Info &info, pyrodactyl::ui::HUD &hud, pyrodactyl::level::Level &level);
// cur_per is also updated here
void internalEvents(Info &info, pyrodactyl::level::Level &level, Common::Array<EventResult> &result);
void handleEvents(Info &info, const Common::String &playerId, Common::Event &event,
pyrodactyl::ui::HUD &hud, pyrodactyl::level::Level &level, Common::Array<EventResult> &result);
void calcActiveSeq(Info &info, pyrodactyl::level::Level &level, const Rect &camera);
void endSequence(const Common::String &curloc);
bool eventInProgress();
void saveState(rapidxml::xml_document<> &doc, rapidxml::xml_node<char> *root);
void loadState(rapidxml::xml_node<char> *node);
void setUI();
};
} // End of namespace event
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_GAMEEVENTMANAGER_H

View File

@@ -0,0 +1,68 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#include "crab/event/quest.h"
namespace Crab {
using namespace pyrodactyl::event;
Quest::Quest(const Common::String &title, const Common::String &text, const bool &unread, const bool &marker) : _title(title) {
_text.insert_at(0, text);
_unread = unread;
_marker = marker;
}
void Quest::loadState(rapidxml::xml_node<char> *node) {
loadStr(_title, "title", node);
loadBool(_unread, "unread", node);
loadBool(_marker, "marker", node);
for (rapidxml::xml_node<char> *n = node->first_node("info"); n != nullptr; n = n->next_sibling("info"))
_text.push_back(n->value());
}
void Quest::saveState(rapidxml::xml_document<> &doc, rapidxml::xml_node<char> *root) {
rapidxml::xml_node<char> *child = doc.allocate_node(rapidxml::node_element, "quest");
child->append_attribute(doc.allocate_attribute("title", _title.c_str()));
saveBool(_unread, "unread", doc, child);
saveBool(_marker, "marker", doc, child);
for (const auto &i : _text) {
rapidxml::xml_node<char> *grandchild = doc.allocate_node(rapidxml::node_element, "info");
grandchild->value(i.c_str());
child->append_node(grandchild);
}
root->append_node(child);
}
} // End of namespace Crab

View File

@@ -0,0 +1,69 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#ifndef CRAB_QUEST_H
#define CRAB_QUEST_H
#include "common/array.h"
#include "crab/loaders.h"
namespace Crab {
namespace pyrodactyl {
namespace event {
struct Quest {
// The title of the quest
Common::String _title;
// The objective text, the last one being the current objective
Common::Array<Common::String> _text;
// Keep track of which quests the player has read
bool _unread;
// Does this quest have an associated destination marker
bool _marker;
Quest() {
_unread = true;
_marker = false;
}
Quest(const Common::String &title, const Common::String &text, const bool &unread, const bool &marker);
void loadState(rapidxml::xml_node<char> *node);
void saveState(rapidxml::xml_document<char> &doc, rapidxml::xml_node<char> *root);
};
} // End of namespace event
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_QUEST_H

View File

@@ -0,0 +1,204 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#include "crab/event/trigger.h"
namespace Crab {
using namespace pyrodactyl::event;
void Trigger::load(rapidxml::xml_node<char> *node) {
Common::String ty;
loadStr(ty, "type", node);
// Should we throw a warning about missing fields? Depends on the type of trigger
bool echoOp = true, echoTar = false, echoSub = true;
if (ty == "obj")
_type = TRIG_OBJ;
else if (ty == "opinion") {
_type = TRIG_OPINION;
echoTar = true;
} else if (ty == "loc") {
_type = TRIG_LOC;
echoOp = false;
} else if (ty == "item") {
_type = TRIG_ITEM;
echoOp = false;
} else if (ty == "rect") {
_type = TRIG_RECT;
echoOp = false;
} else if (ty == "stat") {
_type = TRIG_STAT;
echoTar = true;
} else if (ty == "diff") {
_type = TRIG_DIFF;
echoSub = false;
} else if (ty == "trait") {
_type = TRIG_TRAIT;
} else
_type = TRIG_VAR;
loadStr(_target, "target", node, echoTar);
loadStr(_subject, "subject", node, echoSub);
loadStr(_operation, "operation", node, echoOp);
loadStr(_val, "val", node);
Common::String str;
loadStr(str, "rel", node, false);
if (str == "or")
_rel = OP_OR;
else
_rel = OP_AND;
loadStr(str, "prefix", node, false);
if (str == "!")
_negate = true;
else
_negate = false;
}
bool Trigger::evaluate(int lhs, int rhs) {
if (_operation == ">" && lhs > rhs)
return true;
else if (_operation == "=" && lhs == rhs)
return true;
else if (_operation == "<" && lhs < rhs)
return true;
else if (_operation == "!=" && lhs != rhs)
return true;
else if (_operation == "<=" && lhs <= rhs)
return true;
else if (_operation == ">=" && lhs >= rhs)
return true;
return false;
}
bool Trigger::evaluate(pyrodactyl::event::Info &info) {
using namespace pyrodactyl::people;
using namespace pyrodactyl::stat;
switch (_type) {
case TRIG_OBJ:
if (_operation == "p") {
if (info._talkKeyDown && info.lastPerson() == _val)
return true;
else
return false;
} else if (_operation == "status") {
PersonType ty = stringToPersonType(_val);
if (info.type(_subject) == ty)
return true;
else
return false;
} else if (_operation == "state") {
PersonState st = stringToPersonState(_val);
if (info.state(_subject) == st)
return true;
else
return false;
}
break;
case TRIG_OPINION: {
Person p;
if (info.personGet(_subject, p)) {
if (_target == "like")
return evaluate(p._opinion._val[OPI_LIKE], stringToNumber<int>(_val));
else if (_target == "fear")
return evaluate(p._opinion._val[OPI_FEAR], stringToNumber<int>(_val));
else if (_target == "respect")
return evaluate(p._opinion._val[OPI_RESPECT], stringToNumber<int>(_val));
}
}
break;
case TRIG_LOC:
return (info.curLocID() == _val);
break;
case TRIG_ITEM:
return info._inv.hasItem(_target, _subject, _val);
break;
case TRIG_RECT:
return info.collideWithTrigger(_subject, stringToNumber<int>(_val));
case TRIG_STAT: {
StatType ty = stringToStatType(_target);
int sub = 0, value = 0;
bool compareToVar = Common::find_if(_val.begin(), _val.end(), isChar) != _val.end();
info.statGet(_subject, ty, sub);
if (compareToVar)
info.statGet(_val, ty, value);
else
value = stringToNumber<int>(_val);
return evaluate(sub, value);
}
break;
case TRIG_DIFF:
return evaluate(info.ironMan(), stringToNumber<int>(_val));
case TRIG_TRAIT:
if (info.personValid(_target)) {
Person *p = &info.personGet(_target);
for (auto &i : p->_trait)
if (i._name == _val)
return true;
}
break;
case TRIG_VAR: {
int varSub = 0, varVal = 0;
bool compareToVar = Common::find_if(_val.begin(), _val.end(), isChar) != _val.end();
info.varGet(_subject, varSub);
if (compareToVar)
info.varGet(_val, varVal);
else
varVal = stringToNumber<int>(_val);
return evaluate(varSub, varVal);
}
break;
default:
break;
}
return false;
}
} // End of namespace Crab

View File

@@ -0,0 +1,87 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#ifndef CRAB_TRIGGER_H
#define CRAB_TRIGGER_H
#include "crab/event/GameEventInfo.h"
namespace Crab {
namespace pyrodactyl {
namespace event {
enum RelOp {
OP_AND,
OP_OR
};
enum TriggerType {
TRIG_OBJ, // Interacting with an object, status of character (hostile, coward etc), state (stand, fight, flee, KO)
TRIG_OPINION, // Check opinion of a character (charm / intimidate / respect)
TRIG_LOC, // Being in a place on the map
TRIG_ITEM, // An item is present or not
TRIG_RECT, // A sprite is colliding with a rectangle
TRIG_STAT, // Check any stat of an object (health, attack, defense etc)
TRIG_DIFF, // Check the game's difficulty
TRIG_TRAIT, // See if a character has a certain trait
TRIG_VAR // A variable is present or not, or if it's a certain value
};
struct Trigger {
TriggerType _type;
Common::String _target, _subject, _operation, _val;
// Relation to the next trigger
RelOp _rel;
// Represents the Boolean ! operator
bool _negate;
Trigger() {
_type = TRIG_VAR;
_rel = OP_AND;
_negate = false;
}
Trigger(rapidxml::xml_node<char> *node) {
load(node);
}
void load(rapidxml::xml_node<char> *node);
bool evaluate(pyrodactyl::event::Info &info);
bool evaluate(int lhs, int rhs);
};
} // End of namespace event
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_TRIGGER_H

View File

@@ -0,0 +1,73 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#include "crab/event/triggerset.h"
namespace Crab {
using namespace pyrodactyl::event;
void TriggerSet::load(rapidxml::xml_node<char> *node) {
for (rapidxml::xml_node<char> *n = node->first_node("trigger"); n != nullptr; n = n->next_sibling("trigger")) {
Trigger t(n);
_statement.push_back(t);
}
}
void TriggerSet::add(const Trigger &t) {
_statement.push_back(t);
}
bool TriggerSet::evaluate(pyrodactyl::event::Info &info) {
_result = true;
if (_statement.empty() == false) {
RelOp nextOp = OP_AND;
bool curResult = false;
for (auto &i : _statement) {
if (i._negate)
curResult = !i.evaluate(info);
else
curResult = i.evaluate(info);
if (nextOp == OP_AND)
_result = curResult && _result;
else
_result = curResult || _result;
nextOp = i._rel;
}
}
return _result;
}
} // End of namespace Crab

View File

@@ -0,0 +1,79 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This code is based on the CRAB engine
*
* Copyright (c) Arvind Raja Yadav
*
* Licensed under MIT
*
*/
#ifndef CRAB_TRIGGERSET_H
#define CRAB_TRIGGERSET_H
#include "crab/event/trigger.h"
namespace Crab {
namespace pyrodactyl {
namespace event {
class TriggerSet {
// The conditions needed to unlock whatever we want
// Places where this is used - events, levels, fighting moves
Common::Array<Trigger> _statement;
// Is the thing unlocked or not?
bool _result;
public:
TriggerSet() {
_result = true;
}
void load(rapidxml::xml_node<char> *node);
bool evaluate(pyrodactyl::event::Info &info);
void add(const Trigger &t);
bool result() {
return _result;
}
void result(bool val) {
_result = val;
}
void clear(const bool &val = true) {
_statement.clear();
_result = val;
}
bool empty() {
return _statement.empty();
}
};
} // End of namespace event
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_TRIGGERSET_H