///////////////////////////////////////////////////////////////////////////// // Name: pokemod/Dialog.cpp // Purpose: Define a dialog in a PokéMod // Author: Ben Boeckel // Modified by: Ben Boeckel // Created: Wed Feb 28 21:05:56 2007 // Copyright: ©2007 Ben Boeckel and Nerdy Productions // Licence: // 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 // (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, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ///////////////////////////////////////////////////////////////////////////// #include "Dialog.h" PokeGen::PokeMod::Dialog::Dialog(const Pokemod *par, const unsigned _id) : dialog("") { LogCtor("Dialog", _id); id = _id; pokemod = par; } PokeGen::PokeMod::Dialog::Dialog(const Pokemod *par, Ini &ini, const unsigned _id) { LogCtorIni("Dialog", _id); pokemod = par; ImportIni(ini, _id); if (id == UINT_MAX) LogIdError("Dialog"); } PokeGen::PokeMod::Dialog::~Dialog() { LogDtor("Dialog", id); } #ifdef PG_DEBUG_WINDOW void PokeGen::PokeMod::Dialog::Validate(const wxListBox &output) #else void PokeGen::PokeMod::Dialog::Validate() #endif { LogValidateStart("Dialog", id); if (dialog == "") { LogVarNotSet("Dialog", id, "dialog"); isValid = false; } if (dialog.Count('%') % 2) { Log(String("Dialog: Command delimiter mismatch in %u", id), PM_DEBUG_ERROR); isValid = false; } else { unsigned curCmd = DC_END; unsigned numArgs = 0; for (unsigned i = 0; i < dialog.length(); ++i) { switch (dialog[i]) { case '%': switch (curCmd) { case DC_FLIP_FLAG ... DC_EXIT: if (numArgs != DialogCommandNumArgs[curCmd]) { Log(String("Dialog: Invalid number of arguments (%u) for %s (%u wanted) in %u", numArgs, DialogCommandStr[curCmd], DialogCommandNumArgs[curCmd], id), PM_DEBUG_ERROR); isValid = false; } break; case DC_MENU: if (!(numArgs % 2)) { Log(String("Dialog: Argument mismatch for Menu in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case DC_END: String curCmdStr; for (; (dialog[i] != '%') && (dialog[i] != '#'); ++i) curCmdStr.append(1, dialog[i]); if (((curCmd = FindIn(DC_END, curCmdStr, DialogCommandAbbrStr)) == DC_END)) { if (curCmdStr != "") { Log(String("Dialog: Invalid command \"%s\" in %u", curCmdStr.c_str(), id), PM_DEBUG_ERROR); isValid = false; } curCmd = DC_END; } numArgs = 0; } case '#': if (curCmd != DC_END) { String arg; unsigned tempU; unsigned long tempUL; Map *map = NULL; for (; (dialog[i] != '%') && (dialog[i] != '#'); ++i) arg.append(1, dialog[i]); ++numArgs; // TODO (Ben#1#): Argument parsing checks switch (curCmd) { case DC_FLIP_FLAG: case DC_SET_FLAG: case DC_UNSET_FLAG: case DC_RANDOMIZE_FLAG: if (numArgs == 1) { if (!arg.Convert(tempUL)) { Log(String("Dialog: Bad flag in \"%s\" on %u", DialogCommandStr[curCmd], id), PM_DEBUG_ERROR); isValid = false; } } else { Log(String("Dialog: Too many arguments (%u) for \"%s\" in %u", numArgs, DialogCommandStr[curCmd], id), PM_DEBUG_ERROR); isValid = false; } break; case DC_TEST_FLAG: switch (numArgs) { case 1: if ((arg != "Call") || (arg != "Goto") || (arg != "0") || (arg != "1")) { Log(String("Dialog: Invalid argument #1 in \"Test Flag\" in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case 2: if ((arg != "Unset") || (arg != "Set") || (arg != "0") || (arg != "1")) { Log(String("Dialog: Invalid argument #2 in \"Test Flag\" in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case 3: if (!arg.Convert(tempUL)) { Log(String("Dialog: Bad flag in \"Test Flag\" in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case 4: case 5: if (!arg.Convert(tempU) || !pokemod->GetDialog(tempU)) { Log(String("Dialog: Invalid argument #%u in \"Test Flag\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; default: Log(String("Dialog: Too many arguments (%u) for \"Test Flag\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; case DC_DIALOG: switch (numArgs) { case 1: if ((arg != "Call") || (arg != "Goto") || (arg != "0") || (arg != "1")) { Log(String("Dialog: Invalid argument #1 in \"Dialog\" in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case 2: if (!arg.Convert(tempU) || !pokemod->GetDialog(tempU)) { Log(String("Dialog: Invalid argument #%u in \"Dialog\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; default: Log(String("Dialog: Too many arguments (%u) for \"Dialog\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; case DC_YES_NO: case DC_DELETE_MOVE: switch (numArgs) { case 1: if ((arg != "Call") || (arg != "Goto") || (arg != "0") || (arg != "1")) { Log(String("Dialog: Invalid argument #1 in \"%s\" in %u", DialogCommandStr[curCmd], id), PM_DEBUG_ERROR); isValid = false; } break; case 2: case 3: if (!arg.Convert(tempU) || !pokemod->GetDialog(tempU)) { Log(String("Dialog: Invalid argument #%u in \"%s\" in %u", numArgs, DialogCommandStr[curCmd], id), PM_DEBUG_ERROR); isValid = false; } break; default: Log(String("Dialog: Too many arguments (%u) for \"%s\" in %u", numArgs, DialogCommandStr[curCmd], id), PM_DEBUG_ERROR); isValid = false; } break; case DC_ITEM_SHOP: if (numArgs == 1) { if (!(arg.Convert(tempU) ? pokemod->GetStore(tempU) : pokemod->GetStore(arg))) { Log(String("Dialog: Invalid argument #1 in \"Test Flag\" in %u", id), PM_DEBUG_ERROR); isValid = false; } } else { Log(String("Dialog: Too many arguments (%u) for \"Test Flag\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; case DC_GIVE_ITEM: case DC_TAKE_ITEM: case DC_CHECK_ITEM: switch (numArgs) { case 1: if ((arg != "Call") || (arg != "Goto") || (arg != "0") || (arg != "1")) { Log(String("Dialog: Invalid argument #1 in \"%s\" in %u", DialogCommandStr[curCmd], id), PM_DEBUG_ERROR); isValid = false; } break; case 2: if (!(arg.Convert(tempU) ? pokemod->GetItem(tempU) : pokemod->GetItem(arg))) { Log(String("Dialog: Invalid argument #2 in \"%s\" in %u", DialogCommandStr[curCmd], id), PM_DEBUG_ERROR); isValid = false; } break; case 3: case 4: if (!arg.Convert(tempU) || !pokemod->GetDialog(tempU)) { Log(String("Dialog: Invalid argument #%u in \"%s\" in %u", numArgs, DialogCommandStr[curCmd], id), PM_DEBUG_ERROR); isValid = false; } break; default: Log(String("Dialog: Too many arguments (%u) for \"%s\" in %u", numArgs, DialogCommandStr[curCmd], id), PM_DEBUG_ERROR); isValid = false; } break; case DC_COIN_LIST: if (numArgs == 1) { if (!(arg.Convert(tempU) ? pokemod->GetCoinList(tempU) : pokemod->GetCoinList(arg))) { Log(String("Dialog: Invalid argument #1 in \"Coin List\" in %u", id), PM_DEBUG_ERROR); isValid = false; } } else { Log(String("Dialog: Too many arguments (%u) for \"Coin List\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; case DC_TEACH_MOVE: switch (numArgs) { case 1: if ((arg != "Call") || (arg != "Goto") || (arg != "0") || (arg != "1")) { Log(String("Dialog: Invalid argument #1 in \"Teach Move\" in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case 2: if (!(arg.Convert(tempU) ? pokemod->GetMove(tempU) : pokemod->GetMove(arg))) { Log(String("Dialog: Invalid argument #2 in \"Teach Move\" in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case 3: case 4: case 5: if (!arg.Convert(tempU) || !pokemod->GetDialog(tempU)) { Log(String("Dialog: Invalid argument #%u in \"Teach Move\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; default: Log(String("Dialog: Too many arguments (%u) for \"Teach Move\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; case DC_CHECK_MOVE: switch (numArgs) { case 1: if ((arg != "Call") || (arg != "Goto") || (arg != "0") || (arg != "1")) { Log(String("Dialog: Invalid argument #1 in \"Check Move\" in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case 2: if ((arg != "Lead") || (arg != "All") || (arg != "0") || (arg != "1")) { Log(String("Dialog: Invalid argument #2 in \"Check Move\" in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case 3: if (!(arg.Convert(tempU) ? pokemod->GetMove(tempU) : pokemod->GetMove(arg))) { Log(String("Dialog: Invalid argument #3 in \"Check Move\" in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case 4: case 5: if (!arg.Convert(tempU) || !pokemod->GetDialog(tempU)) { Log(String("Dialog: Invalid argument #%u in \"Check Move\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; default: Log(String("Dialog: Too many arguments (%u) for \"Check Move\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; case DC_GIVE_POKEMON: break; case DC_TAKE_POKEMON: break; case DC_SHOW_POKEMON: break; case DC_VIEW_POKEMON: break; case DC_GIVE_MONEY: if (numArgs == 1) { if (arg.Convert(tempUL)) { if (pokemod->GetMaxMoney() < tempUL) { Log(String("Dialog: More money given than can be held in \"Give Money\" in %u", id), PM_DEBUG_ERROR); isValid = false; } } else { Log(String("Dialog: Invalid argument #1 in \"Give Money\" in %u", id), PM_DEBUG_ERROR); isValid = false; } } else { Log(String("Dialog: Too many arguments (%u) for \"Give Money\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; case DC_TAKE_MONEY: switch (numArgs) { case 1: if ((arg != "Call") || (arg != "Goto") || (arg != "0") || (arg != "1")) { Log(String("Dialog: Invalid argument #1 in \"Take Money\" in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case 2: if (arg.Convert(tempUL)) { if (pokemod->GetMaxMoney() < tempUL) { Log(String("Dialog: More money taken than can be held in \"Take Money\" in %u", id), PM_DEBUG_ERROR); isValid = false; } } else { Log(String("Dialog: Invalid argument #2 in \"Take Money\" in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case 3: case 4: if (!arg.Convert(tempU) || !pokemod->GetDialog(tempU)) { Log(String("Dialog: Invalid argument #%u in \"Take Money\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; default: Log(String("Dialog: Too many arguments (%u) for \"Take Money\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; case DC_MOVE_EFFECT: break; case DC_TURN_EFFECT: break; case DC_CHECK_DIRECTION: break; case DC_CHECK_ROSTER: break; case DC_CHECK_LEVELS: break; case DC_CHECK_SPECIES: break; case DC_CHECK_HELD_ITEMS: break; case DC_CHECK_MONEY: switch (numArgs) { case 1: if ((arg != "Call") || (arg != "Goto") || (arg != "0") || (arg != "1")) { Log(String("Dialog: Invalid argument #1 in \"Check Money\" in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case 2: if ((arg != "<") || (arg != ">") || (arg != "=")) { Log(String("Dialog: Invalid argument #2 in \"Check Money\" in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case 3: if (arg.Convert(tempUL)) { if (pokemod->GetMaxMoney() < tempUL) { Log(String("Dialog: More money than can be held in \"Check Money\" in %u", id), PM_DEBUG_ERROR); isValid = false; } } else { Log(String("Dialog: Invalid argument #3 in \"Check Money\" in %u", id), PM_DEBUG_ERROR); isValid = false; } break; case 4: case 5: if (!arg.Convert(tempU) || !pokemod->GetDialog(tempU)) { Log(String("Dialog: Invalid argument #%u in \"Check Money\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; default: Log(String("Dialog: Too many arguments (%u) for \"Check Money\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; case DC_TRADE: break; case DC_DAYCARE: break; case DC_BATTLE: break; case DC_BADGE: break; case DC_WARP: if (numArgs == 1) { if (!(map = (arg.Convert(tempU) ? (Map *)pokemod->GetMap(tempU) : (Map *)pokemod->GetMap(arg))) { Log(String("Dialog: Invalid argument #1 in \"Warp\" in %u", id), PM_DEBUG_ERROR); isValid = false; } } else if (numArgs == 2) { if (map) { if (!(arg.Convert(tempU) ? map->GetWarp(tempU) : map->GetWarp(arg))) { Log(String("Dialog: Invalid argument #3 in \"Warp\" in %u", id), PM_DEBUG_ERROR); isValid = false; } } else Log(String("Dialog: Unable to validate argument #2 in \"Warp\" in %u", id), PM_DEBUG_ERROR); } else Log(String("Dialog: Too many arguments (%u) for \"Warp\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; break; case DC_NAME: if (numArgs == 1) { if (arg == "") { Log(String("Dialog: Invalid argument #1 in \"Name\" in %u", id), PM_DEBUG_ERROR); isValid = false; } } else { Log(String("Dialog: Too many arguments (%u) for \"Name\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } break; case DC_MUSIC: case DC_SOUND_EFFECT: if (numArgs == 1) { if (!Path(pokemod->GetPath() + "sound/" + arg).DoesExist()) { Log(String("Dialog: Invalid argument #1 in \"%s\" in %u", DialogCommandStr[curCmd], id), PM_DEBUG_ERROR); isValid = false; } } else { Log(String("Dialog: Too many arguments (%u) for \"%s\" in %u", numArgs, DialogCommandStr[curCmd], id), PM_DEBUG_ERROR); isValid = false; } break; case DC_TIMER: break; case DC_MAP_SIGN: break; case DC_WILD_SCOPE: break; case DC_SAFARI: break; case DC_HEAL_PARTY: case DC_REFRESH: case DC_CLEAR: case DC_PAUSE: case DC_NEW_LINE: case DC_EXIT: Log(String("Dialog: Too many arguments (%u) for \"%s\" in %u", numArgs, DialogCommandStr[curCmd], id), PM_DEBUG_ERROR); isValid = false; break; case DC_MENU: if (numArgs == 1) { if ((arg != "Call") || (arg != "Goto") || (arg != "0") || (arg != "1")) { Log(String("Dialog: Invalid argument #1 in \"Menu\" in %u", id), PM_DEBUG_ERROR); isValid = false; } } else if (numArgs % 2) { if (arg.Convert(tempU)) { if (!pokemod->GetDialog(tempU)) { Log(String("Dialog: Invalid argument #%u in \"Menu\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } } else { Log(String("Dialog: Invalid argument #%u in \"Menu\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } } else if (arg == "") { Log(String("Dialog: Invalid argument #%u in \"Menu\" in %u", numArgs, id), PM_DEBUG_ERROR); isValid = false; } } } } } } LogValidateOver("Dialog", id, isValid); } void PokeGen::PokeMod::Dialog::ImportIni(Ini &ini, const unsigned _id) { LogImportStart("Dialog"); if (_id == UINT_MAX) { ini.GetValue("id", id); if (id == UINT_MAX) LogIdNotFound("Dialog"); } else id = _id; ini.GetValue("dialog", dialog); LogImportOver("Dialog", id); } void PokeGen::PokeMod::Dialog::ExportIni(std::ofstream &fout) const { LogExportStart("Dialog", id); Ini exDialog("dialog"); exDialog.AddField("id", id); exDialog.AddField("dialog", dialog); exDialog.Export(fout); LogExportOver("Dialog", id); } void PokeGen::PokeMod::Dialog::SetDialog(const String &d) { LogSetVar("Dialog", id, "dialog", d); dialog = d; } PokeGen::PokeMod::String PokeGen::PokeMod::Dialog::GetDialog() const { LogFetchVar("Dialog", id, "dialog", dialog); return dialog; } void PokeGen::PokeMod::Dialog::InsertDialogCommand(const String &cmd, const unsigned pos) { Log(String("Dialog: Inserting dialog command %s into %u at %u", cmd.c_str(), id, pos), PM_DEBUG_INFO); if (dialog.length() < pos) { Log(String("Dialog: Position out-of-range in %u", id), PM_DEBUG_ERROR); return; } dialog.insert(pos, cmd); }