#include "rpgmodule.h" #include #include #include #include #include "message.h" #include "user.h" QString RPGCharacter::toString() { QString str; str.append(pseudo).append(" "); str.append(password).append(" "); str.append(QString::number(level)).append(" "); str.append(QString::number(xp)).append(" "); str.append(QString::number(x)).append(" "); str.append(QString::number(y)); return str; } void RPGModule::initVillages() { Village v; Event eventBlacksmith; eventBlacksmith.name = "blacksmith"; eventBlacksmith.description = "you approach the strong bearded blacksmith, and asks him to show his goods."; eventBlacksmith.type = Event::TRADER; Trade t; t.goldPrice = 100; t.item = "rusty sword"; Trader *blacksmithTrader = new Trader(); blacksmithTrader->push_back(t); eventBlacksmith.trader = blacksmithTrader; Event eventInn; eventInn.name = "inn"; eventInn.description = "you enter the inn, there are plenty of townsfolk drinking and eating loudly."; eventInn.type = Event::TRADER; t.goldPrice = 20; t.item = "night of rest"; Trader *innkeeperTrader = new Trader(); innkeeperTrader->push_back(t); eventInn.trader = innkeeperTrader; v.x = 7; v.y = 4; v.name = "Dornwich"; v.events.push_back(eventInn); v.events.push_back(eventBlacksmith); villages.push_back(v); v.x = 1; v.y = 11; v.name = "Dawsbury"; v.events.push_back(eventInn); villages.push_back(v); v.x = 17; v.y = 8; v.name = "Willowdale"; v.events.push_back(eventInn); v.events.push_back(eventBlacksmith); villages.push_back(v); v.x = 19; v.y = 22; v.name = "Myrefall"; v.events.push_back(eventInn); villages.push_back(v); v.x = 12; v.y = 15; v.name = "Calmarnock"; v.events.push_back(eventInn); villages.push_back(v); v.x = 3; v.y = 18; v.name = "Waeldestone"; v.events.push_back(eventInn); v.events.push_back(eventBlacksmith); villages.push_back(v); } bool RPGCharacter::fromString(QString str) { QStringList list = str.split(QChar(' ')); if(list.size() == 6) { bool ok; pseudo = list[0]; password = list[1]; level = list[2].toInt(&ok); if(!ok) return false; xp = list[3].toInt(&ok); if(!ok) return false; x = list[4].toInt(&ok); if(!ok) return false; y = list[5].toInt(&ok); if(!ok) return false; return true; } else return false; } RPGModule::RPGModule() { initVillages(); QFile f("../../res/rpg.save"); if(!f.open(QFile::ReadOnly | QFile::Text)) { fprintf(stderr, "can't load save file.\n"); return; } QTextStream in(&f); QString line = "plop (line init)"; do { line = in.readLine(); RPGCharacter *c = new RPGCharacter(line); if(c->pseudo.compare("trash") != 0) charList.add(c); } while(!line.isNull()); f.close(); } void RPGModule::saveCharacters() { QFile f("../../res/rpg.save"); if(!f.open(QFile::WriteOnly | QFile::Text)) { fprintf(stderr, "can't load save file.\n"); return; } QTextStream out(&f); for(const std::string &name : charList.names) { if(name != "trash") out << charList.get(name)->toString() << "\n"; } f.close(); } void RPGModule::playerJoin(User *user, RPGCharacter *c) { c->user = user; charOnline[user] = c; } void RPGModule::playerLeave(User *user) { if(charOnline.count(user) > 0) { charOnline[user]->user = NULL; charOnline.erase(user); } } QString RPGModule::getTerrainName(int type) { switch(type) { case FOREST : return QString("the forest"); case MOUNTAINS : return QString("the mountains"); case PLAINS : return QString("the plains"); case ROAD : return QString("a road"); case VILLAGE : return QString("a village"); default : return QString("Hell"); } } Village* RPGModule::getVillage(RPGCharacter *c) { for(Village &v : villages) { if(v.x == c->x && v.y == c->y) return &v; } return NULL; } QString RPGModule::lookAt(RPGCharacter *c, QString target) { if(target.compare("around") == 0) { int terrain = WORLDMAP[c->x][c->y]; if(terrain == VILLAGE) { Village *v = getVillage(c); if(v == NULL) return QString("%1 is in an unknown village").arg(c->pseudo); QString str = QString("%1 is in %2").arg(c->pseudo).arg(v->name); QString evStr; bool first = true; for(Event &e : v->events) { if(first) first = false; else evStr += ", "; evStr += e.name; } if(!first) str += ", you can see " + evStr; return str; } else return QString("%1 is in %2").arg(c->pseudo).arg(getTerrainName(terrain)); } else if(target.compare("north") == 0 || target.compare("n") == 0) return QString("%1 looks north and sees %2").arg(c->pseudo).arg(getTerrainName(WORLDMAP[c->x-1][c->y])); else if(target.compare("south") == 0 || target.compare("s") == 0) return QString("%1 looks south and sees %2").arg(c->pseudo).arg(getTerrainName(WORLDMAP[c->x+1][c->y])); else if(target.compare("west") == 0 || target.compare("w") == 0) return QString("%1 looks west and sees %2").arg(c->pseudo).arg(getTerrainName(WORLDMAP[c->x][c->y-1])); else if(target.compare("east") == 0 || target.compare("e") == 0) return QString("%1 looks east and sees %2").arg(c->pseudo).arg(getTerrainName(WORLDMAP[c->x][c->y+1])); else return QString("%1 is not a valid target").arg(target); } QString RPGModule::eventInteract(RPGCharacter *c, QString target) { Village *v = getVillage(c); if(v != NULL) { for(Event &e : v->events) { if(e.name.compare(target) == 0) { return e.description; } } } return QString("%1 is not a valid target").arg(target); } QString RPGModule::playerTravel(RPGCharacter *c, QString dir, bool repeat) { char terrainType = WORLDMAP[c->x][c->y]; QString direction; QString currentArea = getTerrainName(terrainType); bool blocked = false; int dist = 0; do { if(dir.compare("north") == 0 || dir.compare("n") == 0) { bool isDiff = repeat && terrainType != WORLDMAP[c->x-1][c->y]; if(c->y == 0 || (isDiff && dist != 0)) blocked = true; else { if(isDiff) blocked = true; c->y -= 1; ++dist; } direction = "north"; } else if(dir.compare("south") == 0 || dir.compare("s") == 0) { bool isDiff = repeat && terrainType != WORLDMAP[c->x+1][c->y]; if(c->y == 24 || (isDiff && dist != 0)) blocked = true; else { if(isDiff) blocked = true; c->y += 1; ++dist; } direction = "south"; } else if(dir.compare("west") == 0 || dir.compare("w") == 0) { bool isDiff = repeat && terrainType != WORLDMAP[c->x][c->y-1]; if(c->x == 0 || (isDiff && dist != 0)) blocked = true; else { if(isDiff) blocked = true; c->x -= 1; ++dist; } direction = "west"; } else if(dir.compare("east") == 0 || dir.compare("e") == 0) { bool isDiff = repeat && terrainType != WORLDMAP[c->x][c->y+1]; if(c->x == 24 || (isDiff && dist != 0)) blocked = true; else { if(isDiff) blocked = true; c->x += 1; ++dist; } direction = "east"; } else return QString("%1 is not a valid direction, use : north, south, west, east").arg(dir); } while(!blocked && repeat); if(blocked) { if(repeat) { if(dist > 1) return QString("%1 travels %2 during %3 hours through %4") .arg(c->pseudo).arg(direction).arg(dist).arg(currentArea); else {} } else return QString("%1 cannot go %2, a hill is blocking his way").arg(c->pseudo).arg(direction); } char newTerrainType = WORLDMAP[c->x][c->y]; if(terrainType == newTerrainType) return QString("%1 is traveling %2 and is still in %3").arg(c->pseudo).arg(direction).arg(currentArea); else return QString("%1 is traveling %2, leaving %3 and entering %4") .arg(c->pseudo).arg(direction).arg(currentArea).arg(getTerrainName(WORLDMAP[c->x][c->y])); } bool RPGModule::messageHandler(Message msg) { User* src = getUsers()->getFromNick(msg.nick); if(msg.command.compare(QString("PRIVMSG"), Qt::CaseInsensitive) == 0) { if(msg.args.startsWith("!rpg register") && !msg.target.contains(getChan())) { QStringList paramList = msg.args.split(' '); if(paramList.size() != 4) answer = privateSay("usage : !rpg register [name of character] [password]", msg.nick); else { if(charList.get(paramList[2].toStdString()) != NULL) answer = privateSay(QString("ERROR : Character name \"%1\" already exists").arg(paramList[2]), msg.nick); else { answer = privateSay(QString("successfully created the character \"%1\"").arg(paramList[2]), msg.nick); charList.add(new RPGCharacter(paramList[2], paramList[3])); } } return true; } else if(msg.args.startsWith("!rpg join") && !msg.target.contains(getChan())) { QStringList paramList = msg.args.split(' '); if(paramList.size() != 4) answer = privateSay("usage : !rpg join [name of character] [password]", msg.nick); else { RPGCharacter *c = charList.get(paramList[2].toStdString()); if(c != NULL) { if(c->password.compare(paramList[3]) == 0) { playerJoin(getUsers()->getFromNick(msg.nick), c); answer = say(QString("%1 joins the RPG as %2").arg(msg.nick).arg(paramList[2])); } else answer = privateSay(QString("ERROR : Wrong password"), msg.nick); } else answer = privateSay(QString("ERROR : Character name \"%1\" does not exists").arg(paramList[2]), msg.nick); } return true; } else if(msg.args.startsWith("!rpg delete") && !msg.target.contains(getChan())) { QStringList paramList = msg.args.split(' '); if(paramList.size() != 4) answer = privateSay("usage : !rpg delete [name of character] [password]", msg.nick); else { RPGCharacter *c = charList.get(paramList[2].toStdString()); if(c != NULL) { if(c->password.compare(paramList[3]) == 0) { charOnline.erase(c->user); charList.erase(paramList[2].toStdString()); answer = say(QString("Character %2 has been deleted").arg(paramList[2])); } else answer = privateSay(QString("ERROR : Wrong password"), msg.nick); } else answer = privateSay(QString("ERROR : Character name \"%1\" does not exists").arg(paramList[2]), msg.nick); } return true; } else if(msg.args.compare("!rpg leave") == 0) { if(charOnline.count(src) > 0) { answer = say(QString("%1 (%2) left the RPG").arg(charOnline[src]->pseudo).arg(src->getNick())); playerLeave(src); return true; } } else if(msg.args.compare("!rpg list") == 0) { answer = QString(""); bool hasPeople = false; for(auto it : charOnline) { hasPeople = true; RPGCharacter *c = it.second; answer += say(QString("%1 [lvl %2] (%3)").arg(c->pseudo).arg(c->level).arg(c->user->getNick())); } return hasPeople; } else if(msg.args.compare("!rpg stats") == 0) { if(charOnline.count(src) > 0) { RPGCharacter *c = charOnline[src]; answer = say(QString("%1 is level %2 (%3 xp)").arg(c->pseudo).arg(c->level).arg(c->xp)); return true; } } else if(msg.args.compare("!rpg reset") == 0 && src->isOp()) { charList.data.clear(); charList.names.clear(); answer = say("cleared character database"); return true; } else if(msg.args.compare("!rpg save") == 0) { saveCharacters(); answer = say("saved RPG characters"); return true; } else if(msg.args.startsWith("go ")) { QStringList paramList = msg.args.split(' '); if(charOnline.count(src) > 0) { if(paramList.size() == 2) { answer = say(playerTravel(charOnline[src], paramList[1], false)); return true; } else if(paramList.size() == 3 && paramList[1].compare("to") == 0) { answer = say(eventInteract(charOnline[src], paramList[2])); return true; } } } else if(msg.args.startsWith("travel ")) { QStringList paramList = msg.args.split(' '); if(charOnline.count(src) > 0 && paramList.size() == 2) { answer = say(playerTravel(charOnline[src], paramList[1], true)); return true; } } else if(msg.args.startsWith("look ")) { QStringList paramList = msg.args.split(' '); if(charOnline.count(src) > 0 && paramList.size() == 2) { answer = say(lookAt(charOnline[src], paramList[1])); return true; } } else if(msg.args.compare("!rpg help") == 0) { answer = privateSay("Commands : register, join, delete, leave, save, stats, list", msg.nick); answer += privateSay("Create new character (works only in private message) : !rpg register [name of character] [password]", msg.nick); answer += privateSay("Join game with character (works only in private message) : !rpg join [name of character] [password]", msg.nick); answer += privateSay("Delete character (works only in private message) : !rpg delete [name of character] [password]", msg.nick); answer += privateSay("leave the game : !rpg leave", msg.nick); answer += privateSay("show your stats : !rpg stats", msg.nick); answer += privateSay("show all in-game players : !rpg list", msg.nick); return true; } } else if(msg.command.compare("QUIT", Qt::CaseInsensitive) == 0) playerLeave(src); else if(msg.command.compare("PART", Qt::CaseInsensitive) == 0) playerLeave(src); else if(msg.command.compare("KICK", Qt::CaseInsensitive) == 0) playerLeave(getUsers()->getFromNick(msg.target2)); return false; }