From 601607488ae529b7dfd9bd55afd0e89e42762281 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Tue, 28 Oct 2014 19:19:02 +0300 Subject: Dehardcode default spells/commands. Read commands from defaultcommands.xml. Also improve a bit saving commands in spellmanager. --- data/perserver/default/CMakeLists.txt | 1 + data/perserver/default/Makefile.am | 1 + data/perserver/default/defaultcommands.xml | 158 +++++++++++++++++++++++++++++ src/CMakeLists.txt | 2 + src/Makefile.am | 2 + src/client.cpp | 4 + src/defaults.cpp | 3 + src/game.cpp | 4 - src/gui/windowmanager.cpp | 3 + src/resources/db/commandsdb.cpp | 144 ++++++++++++++++++++++++++ src/resources/db/commandsdb.h | 49 +++++++++ src/spellmanager.cpp | 101 +++++++----------- 12 files changed, 402 insertions(+), 70 deletions(-) create mode 100644 data/perserver/default/defaultcommands.xml create mode 100644 src/resources/db/commandsdb.cpp create mode 100644 src/resources/db/commandsdb.h diff --git a/data/perserver/default/CMakeLists.txt b/data/perserver/default/CMakeLists.txt index 19cf3686d..1c13e9a5b 100644 --- a/data/perserver/default/CMakeLists.txt +++ b/data/perserver/default/CMakeLists.txt @@ -2,6 +2,7 @@ SET (FILES charcreation.xml chatcommands.txt deadmessages.xml + defaultcommands.xml features.xml gmcommands.txt weapons.xml diff --git a/data/perserver/default/Makefile.am b/data/perserver/default/Makefile.am index 5b478d82d..cfbef29e7 100644 --- a/data/perserver/default/Makefile.am +++ b/data/perserver/default/Makefile.am @@ -4,6 +4,7 @@ default_DATA = \ charcreation.xml \ chatcommands.txt \ deadmessages.xml \ + defaultcommands.xml \ features.xml \ gmcommands.txt \ weapons.xml diff --git a/data/perserver/default/defaultcommands.xml b/data/perserver/default/defaultcommands.xml new file mode 100644 index 000000000..f7e564b94 --- /dev/null +++ b/data/perserver/default/defaultcommands.xml @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 83860b0a6..b4ede1dd9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -601,6 +601,8 @@ SET(SRCS resources/db/chardb.h resources/db/colordb.cpp resources/db/colordb.h + resources/db/commandsdb.cpp + resources/db/commandsdb.h resources/cursor.cpp resources/cursor.h resources/delayedmanager.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 7b948ac50..1631dda65 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -729,6 +729,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ resources/db/chardb.h \ resources/db/colordb.cpp \ resources/db/colordb.h \ + resources/db/commandsdb.cpp \ + resources/db/commandsdb.h \ resources/cursor.cpp \ resources/cursor.h \ resources/delayedmanager.cpp \ diff --git a/src/client.cpp b/src/client.cpp index 690c2b434..8a6f885c7 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -39,6 +39,7 @@ #include "party.h" #include "settings.h" #include "soundmanager.h" +#include "spellshortcut.h" #include "statuseffect.h" #include "units.h" #include "touchmanager.h" @@ -1243,6 +1244,9 @@ int Client::gameExec() TranslationManager::loadCurrentLang(); PlayerInfo::stateChange(mState); + spellManager = new SpellManager; + spellShortcut = new SpellShortcut; + // Load XML databases CharDB::load(); DeadDB::load(); diff --git a/src/defaults.cpp b/src/defaults.cpp index edfd8c45d..a383c02f6 100644 --- a/src/defaults.cpp +++ b/src/defaults.cpp @@ -570,6 +570,9 @@ DefaultsData* getPathsDefaults() AddDEF("deadMessagesFile", "deadmessages.xml"); AddDEF("deadMessagesPatchFile", "deadmessages_patch.xml"); AddDEF("deadMessagesPatchDir", "deadmessages.d"); + AddDEF("defaultCommandsFile", "defaultcommands.xml"); + AddDEF("defaultcommandsPatchFile", "defaultcommands_patch.xml"); + AddDEF("defaultcommandsPatchDir", "defaultcommands.d"); AddDEF("poisonEffectName", "poison"); return configData; diff --git a/src/game.cpp b/src/game.cpp index 4292d00cc..0451dd516 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -358,8 +358,6 @@ Game::Game() : mTime2(cur_time + 10) { touchManager.setInGame(true); - spellManager = new SpellManager; - spellShortcut = new SpellShortcut; // assert(!mInstance); if (mInstance) @@ -430,8 +428,6 @@ Game::~Game() delete2(particleEngine) delete2(viewport) delete2(mCurrentMap) - delete2(spellManager) - delete2(spellShortcut) delete2(guildManager) #ifdef USE_MUMBLE delete2(mumbleManager) diff --git a/src/gui/windowmanager.cpp b/src/gui/windowmanager.cpp index bd68f09bc..c786fa501 100644 --- a/src/gui/windowmanager.cpp +++ b/src/gui/windowmanager.cpp @@ -26,6 +26,7 @@ #include "configuration.h" #include "game.h" #include "settings.h" +#include "spellshortcut.h" #include "touchmanager.h" #include "gui/gui.h" @@ -124,6 +125,8 @@ void WindowManager::deleteWindows() delete2(helpWindow); delete2(setupWindow); delete2(userPalette); + delete2(spellManager) + delete2(spellShortcut) } void WindowManager::initTitle() diff --git a/src/resources/db/commandsdb.cpp b/src/resources/db/commandsdb.cpp new file mode 100644 index 000000000..c5c1d9e3c --- /dev/null +++ b/src/resources/db/commandsdb.cpp @@ -0,0 +1,144 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2014 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * 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 2 of the License, or + * 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 . + */ + +#include "resources/db/commandsdb.h" + +#include "configuration.h" +#include "logger.h" +#include "textcommand.h" + +#include "resources/beingcommon.h" + +#include "utils/dtor.h" +#include "utils/gettext.h" + +#include "debug.h" + +namespace +{ + CommandsMap mCommands; + bool mLoaded = false; +} + +void CommandsDB::load() +{ + if (mLoaded) + unload(); + loadXmlFile(paths.getStringValue("defaultCommandsFile")); + loadXmlFile(paths.getStringValue("defaultCommandsPatchFile")); + loadXmlDir("defaultCommandsPatchDir", loadXmlFile); + mLoaded = true; +} + +static SpellTarget parseTarget(const std::string &text) +{ + if (text == "allow target") + return ALLOWTARGET; + else if (text == "need target") + return NEEDTARGET; + else + return NOTARGET; +} + +void CommandsDB::loadXmlFile(const std::string &fileName) +{ + XML::Document doc(fileName); + const XmlNodePtrConst rootNode = doc.rootNode(); + + if (!rootNode || !xmlNameEqual(rootNode, "commands")) + { + logger->log("Commands Database: Error while loading %s!", + fileName.c_str()); + return; + } + + for_each_xml_child_node(commandNode, rootNode) + { + if (xmlNameEqual(commandNode, "include")) + { + const std::string name = XML::getProperty(commandNode, "name", ""); + if (!name.empty()) + loadXmlFile(name); + continue; + } + + if (!xmlNameEqual(commandNode, "command")) + continue; + + const int id = XML::getProperty(commandNode, "id", -1); + if (id == -1) + continue; + + CommandsMapIter it = mCommands.find(id); + if (it != mCommands.end()) + { + logger->log("Commands database: duplicate id: %d", id); + TextCommand *tempCmd = (*it).second; + mCommands.erase(it); + delete tempCmd; + } + const std::string name = XML::langProperty( + commandNode, "name", "?"); + const std::string command = XML::getProperty( + commandNode, "command", ""); + const std::string comment = XML::getProperty( + commandNode, "comment", ""); + const SpellTarget targetType = parseTarget(XML::getProperty( + commandNode, "target", "")); + const std::string icon = XML::getProperty( + commandNode, "icon", ""); + const int skill1 = XML::getIntProperty( + commandNode, "skill1", 0, 0, 1000000); + const int level1 = XML::getIntProperty( + commandNode, "level1", 0, 0, 1000); + const int skill2 = XML::getIntProperty( + commandNode, "skill2", 0, 0, 1000000); + const int level2 = XML::getIntProperty( + commandNode, "level2", 0, 0, 1000); + const int mana = XML::getIntProperty( + commandNode, "mana", 0, 0, 100000); + + TextCommand *cmd = nullptr; + if (skill1) + { + cmd = new TextCommand(id, name, command, comment, + targetType, icon, level1, static_cast(skill2), level2, mana); + } + else + { + cmd = new TextCommand(id, name, command, comment, + targetType, icon); + } + mCommands[id] = cmd; + } +} + +void CommandsDB::unload() +{ + mCommands.clear(); + mLoaded = false; +} + +std::map &CommandsDB::getAll() +{ + return mCommands; +} diff --git a/src/resources/db/commandsdb.h b/src/resources/db/commandsdb.h new file mode 100644 index 000000000..1725171d1 --- /dev/null +++ b/src/resources/db/commandsdb.h @@ -0,0 +1,49 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2014 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * 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 2 of the License, or + * 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 . + */ + +#ifndef RESOURCES_DB_COMMANDSDB_H +#define RESOURCES_DB_COMMANDSDB_H + +#include "resources/modinfo.h" + +#include +#include + +#include "localconsts.h" + +class TextCommand; + +typedef std::map CommandsMap; +typedef CommandsMap::iterator CommandsMapIter; + +namespace CommandsDB +{ + void load(); + + void unload(); + + void loadXmlFile(const std::string &fileName); + + CommandsMap &getAll(); +} // namespace CommandsDB + +#endif // RESOURCES_DB_COMMANDSDB_H diff --git a/src/spellmanager.cpp b/src/spellmanager.cpp index 6dfdd483d..9ad985a4a 100644 --- a/src/spellmanager.cpp +++ b/src/spellmanager.cpp @@ -32,6 +32,8 @@ #include "net/playerhandler.h" +#include "resources/db/commandsdb.h" + #include "utils/dtor.h" #include "debug.h" @@ -70,36 +72,20 @@ const TextCommand* SpellManager::getSpellByItem(const int itemId) const void SpellManager::fillSpells() { -// id, std::string name, std::string symbol, ST type, int basicLvl, -// MagicSchool school, int schoolLvl, int mana) - - addSpell(new TextCommand(0, "lum", "#lum", "heal with lifestones", - ALLOWTARGET, "", 1, SKILL_MAGIC_LIFE, 0, 6)); - addSpell(new TextCommand(1, "inm", "#inma", "heal", NEEDTARGET, - "", 2, SKILL_MAGIC_LIFE, 2, 10)); - addSpell(new TextCommand(2, "fla", "#flar", "", NOTARGET, - "", 1, SKILL_MAGIC_WAR, 0, 10)); - addSpell(new TextCommand(3, "chi", "#chiza", "", NOTARGET, - "", 1, SKILL_MAGIC_WAR, 0, 9)); - addSpell(new TextCommand(4, "ing", "#ingrav", "", NOTARGET, - "", 2, SKILL_MAGIC_WAR, 2, 20)); - addSpell(new TextCommand(5, "fri", "#frillyar", "", NOTARGET, - "", 2, SKILL_MAGIC_WAR, 2, 25)); - addSpell(new TextCommand(6, "upm", "#upmarmu", "", NOTARGET, - "", 2, SKILL_MAGIC_WAR, 2, 20)); - addSpell(new TextCommand(7, "ite", "#itenplz", "", NOTARGET, - "", 1, SKILL_MAGIC_NATURE, 0, 3)); - addSpell(new TextCommand(8, "bet", "#betsanc", "", ALLOWTARGET, - "", 2, SKILL_MAGIC_NATURE, 2, 14)); - addSpell(new TextCommand(9, "abi", "#abizit", "", NOTARGET, - "", 1, SKILL_MAGIC, 0, 1)); - addSpell(new TextCommand(10, "inw", "#inwilt", "", NOTARGET, - "", 2, SKILL_MAGIC, 2, 7)); - addSpell(new TextCommand(11, "hi", "hi", "", NOTARGET, "")); - addSpell(new TextCommand(12, "hea", "heal", "", NOTARGET, "")); - addSpell(new TextCommand(13, "@sp", "@spawn maggot 10", "", NOTARGET, "")); - for (unsigned f = 12; f < SPELL_SHORTCUT_ITEMS * SPELL_SHORTCUT_TABS; f++) - addSpell(new TextCommand(f)); + CommandsDB::load(); + + CommandsMap &commands = CommandsDB::getAll(); + FOR_EACH (CommandsMapIter, it, commands) + addSpell((*it).second); + + for (unsigned f = 0; f < SPELL_SHORTCUT_ITEMS * SPELL_SHORTCUT_TABS; f++) + { + const std::map::const_iterator + it = mSpells.find(f); + if (it == mSpells.end()) + addSpell(new TextCommand(f)); + } + CommandsDB::unload(); } bool SpellManager::addSpell(TextCommand *const spell) @@ -107,6 +93,12 @@ bool SpellManager::addSpell(TextCommand *const spell) if (!spell) return false; + const int id = spell->getId(); + if (id < 0 || id >= SPELL_SHORTCUT_ITEMS * SPELL_SHORTCUT_TABS) + { + delete spell; + return false; + } const std::map::const_iterator i = mSpells.find(spell->getId()); if (i == mSpells.end()) @@ -304,6 +296,13 @@ void SpellManager::load(const bool oldConfig) } } +#define setOrDel(str, method) \ + const std::string var##method = spell->method(); \ + if (var##method != "") \ + serverConfig.setValue(str + toString(i), var##method); \ + else \ + serverConfig.deleteKey(str + toString(i)); + void SpellManager::save() const { for (unsigned i = 0; i < SPELL_SHORTCUT_ITEMS * SPELL_SHORTCUT_TABS; i++) @@ -311,42 +310,10 @@ void SpellManager::save() const const TextCommand *const spell = mSpellsVector[i]; if (spell) { - if (spell->getCommand() != "") - { - serverConfig.setValue("commandShortcutCmd" + toString(i), - spell->getCommand()); - } - else - { - serverConfig.deleteKey("commandShortcutCmd" + toString(i)); - } - if (spell->getComment() != "") - { - serverConfig.setValue("commandShortcutComment" + toString(i), - spell->getComment()); - } - else - { - serverConfig.deleteKey("commandShortcutComment" + toString(i)); - } - if (spell->getSymbol() != "") - { - serverConfig.setValue("commandShortcutSymbol" + toString(i), - spell->getSymbol()); - } - else - { - serverConfig.deleteKey("commandShortcutSymbol" + toString(i)); - } - if (spell->getIcon() != "") - { - serverConfig.setValue("commandShortcutIcon" + toString(i), - spell->getIcon()); - } - else - { - serverConfig.deleteKey("commandShortcutIcon" + toString(i)); - } + setOrDel("commandShortcutCmd", getCommand); + setOrDel("commandShortcutComment", getComment); + setOrDel("commandShortcutSymbol", getSymbol); + setOrDel("commandShortcutIcon", getIcon); if (spell->getCommand() != "" && spell->getSymbol() != "") { serverConfig.setValue("commandShortcutFlags" + toString(i), @@ -365,6 +332,8 @@ void SpellManager::save() const } } +#undef setOrDel + std::string SpellManager::autoComplete(const std::string &partName) const { std::vector::const_iterator i = mSpellsVector.begin(); -- cgit v1.2.3-70-g09d2