Files
2026-02-02 04:50:13 +01:00

290 lines
7.1 KiB
C++

/* 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