/*
* The ManaVerse Client
* Copyright (C) 2012-2019 The ManaPlus Developers
*
* This file is part of The ManaVerse 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 <http://www.gnu.org/licenses/>.
*/
#include "actions/commands.h"
#include "actormanager.h"
#include "configuration.h"
#include "game.h"
#include "party.h"
#include "actions/actiondef.h"
#include "being/flooritem.h"
#include "being/localplayer.h"
#include "being/playerrelations.h"
#include "being/homunculusinfo.h"
#include "being/playerinfo.h"
#include "const/resources/skill.h"
#include "gui/viewport.h"
#include "gui/popups/popupmenu.h"
#include "gui/shortcut/emoteshortcut.h"
#include "gui/shortcut/itemshortcut.h"
#include "gui/windows/mailwindow.h"
#include "gui/windows/chatwindow.h"
#include "gui/windows/inventorywindow.h"
#include "gui/windows/npcdialog.h"
#include "gui/windows/outfitwindow.h"
#include "gui/windows/shortcutwindow.h"
#include "gui/windows/skilldialog.h"
#include "gui/windows/socialwindow.h"
#include "gui/widgets/tabs/chat/whispertab.h"
#include "input/inputactionoperators.h"
#include "listeners/inputactionreplaylistener.h"
#include "net/adminhandler.h"
#include "net/chathandler.h"
#include "net/guildhandler.h"
#include "net/familyhandler.h"
#include "net/homunculushandler.h"
#include "net/mail2handler.h"
#include "net/mailhandler.h"
#include "net/net.h"
#include "net/npchandler.h"
#include "net/partyhandler.h"
#include "net/serverfeatures.h"
#include "resources/chatobject.h"
#include "resources/db/itemdb.h"
#include "resources/map/map.h"
#include "resources/skill/skillinfo.h"
#include "utils/booleanoptions.h"
#include "utils/chatutils.h"
#include "utils/copynpaste.h"
#include "utils/gmfunctions.h"
#include "utils/parameters.h"
#include "utils/process.h"
#ifdef HAVE_MALLOC_TRIM
#include <malloc.h>
#endif
#include "debug.h"
namespace Actions
{
static std::string getNick(const InputEvent &event)
{
std::string args = event.args;
if (args.empty())
{
if (event.tab == nullptr ||
event.tab->getType() != ChatTabType::WHISPER)
{
return std::string();
}
WhisperTab *const whisper = static_cast<WhisperTab *>(event.tab);
if (whisper->getNick().empty())
{
// TRANSLATORS: change relation
event.tab->chatLog(_("Please specify a name."),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
return std::string();
}
args = whisper->getNick();
}
return args;
}
static void reportRelation(const InputEvent &event,
const RelationT &rel,
const std::string &str1,
const std::string &str2)
{
if (event.tab != nullptr)
{
if (playerRelations.getRelation(event.args) == rel)
{
// TRANSLATORS: unignore command
event.tab->chatLog(str1,
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
}
else
{
// TRANSLATORS: unignore command
event.tab->chatLog(str2,
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
}
}
}
static void changeRelation(const InputEvent &event,
const RelationT relation,
const std::string &relationText)
{
std::string args = getNick(event);
if (args.empty())
return;
if (playerRelations.getRelation(args) == relation)
{
if (event.tab != nullptr)
{
// TRANSLATORS: change relation
event.tab->chatLog(strprintf(_("Player already %s!"),
relationText.c_str()),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
return;
}
}
else
{
playerRelations.setRelation(args, relation);
}
reportRelation(event,
relation,
// TRANSLATORS: change relation
strprintf(_("Player successfully %s!"), relationText.c_str()),
// TRANSLATORS: change relation
strprintf(_("Player could not be %s!"), relationText.c_str()));
}
impHandler(chatAnnounce)
{
if (adminHandler != nullptr)
{
adminHandler->announce(event.args);
return true;
}
return false;
}
impHandler(chatIgnore)
{
changeRelation(event, Relation::IGNORED, "ignored");
return true;
}
impHandler(chatUnignore)
{
std::string args = getNick(event);
if (args.empty())
return false;
const RelationT rel = playerRelations.getRelation(args);
if (rel != Relation::NEUTRAL && rel != Relation::FRIEND)
{
playerRelations.setRelation(args, Relation::NEUTRAL);
}
else
{
if (event.tab != nullptr)
{
// TRANSLATORS: unignore command
event.tab->chatLog(_("Player wasn't ignored!"),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
}
return true;
}
reportRelation(event,
Relation::NEUTRAL,
// TRANSLATORS: unignore command
_("Player no longer ignored!"),
// TRANSLATORS: unignore command
_("Player could not be unignored!"));
return true;
}
impHandler(chatErase)
{
std::string args = getNick(event);
if (args.empty())
return false;
if (playerRelations.getRelation(args) == Relation::ERASED)
{
if (event.tab != nullptr)
{
// TRANSLATORS: erase command
event.tab->chatLog(_("Player already erased!"),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
}
return true;
}
playerRelations.setRelation(args, Relation::ERASED);
reportRelation(event,
Relation::ERASED,
// TRANSLATORS: erase command
_("Player no longer erased!"),
// TRANSLATORS: erase command
_("Player could not be erased!"));
return true;
}
impHandler(chatFriend)
{
// TRANSLATORS: adding friend command
changeRelation(event, Relation::FRIEND, _("friend"));
return true;
}
impHandler(chatDisregard)
{
// TRANSLATORS: disregard command
changeRelation(event, Relation::DISREGARDED, _("disregarded"));
return true;
}
impHandler(chatNeutral)
{
// TRANSLATORS: neutral command
changeRelation(event, Relation::NEUTRAL, _("neutral"));
return true;
}
impHandler(chatBlackList)
{
// TRANSLATORS: blacklist command
changeRelation(event, Relation::BLACKLISTED, _("blacklisted"));
return true;
}
impHandler(chatEnemy)
{
// TRANSLATORS: enemy command
changeRelation(event, Relation::ENEMY2, _("enemy"));
return true;
}
impHandler(chatNuke)
{
if (actorManager == nullptr)
return false;
const std::string nick = getNick(event);
Being *const being = actorManager->findBeingByName(
nick, ActorType::Player);
if (being == nullptr)
return true;
actorManager->addBlock(being->getId());
actorManager->destroy(being);
return true;
}
impHandler(chatAdd)
{
if (chatWindow == nullptr)
return false;
if (event.args.empty())
return true;
STD_VECTOR<int> str;
splitToIntVector(str, event.args, ',');
if (str.empty())
return true;
int id = str[0];
if (id == 0)
return true;
if (ItemDB::exists(id))
{
const std::string names = ItemDB::getNamesStr(str);
if (!names.empty())
chatWindow->addItemText(names);
return true;
}
const FloorItem *const floorItem = actorManager->findItem(
fromInt(id, BeingId));
if (floorItem != nullptr)
{
str[0] = floorItem->getItemId();
const std::string names = ItemDB::getNamesStr(str);
chatWindow->addItemText(names);
}
return true;
}
impHandler0(present)
{
if (chatWindow != nullptr)
{
chatWindow->doPresent();
return true;
}
return false;
}
impHandler0(printAll)
{
if (actorManager != nullptr)
{
actorManager->printAllToChat();
return true;
}
return false;
}
impHandler(move)
{
int x = 0;
int y = 0;
if ((localPlayer != nullptr) && parse2Int(event.args, x, y))
{
localPlayer->setDestination(x, y);
return true;
}
return false;
}
impHandler(setTarget)
{
if ((actorManager == nullptr) || (localPlayer == nullptr))
return false;
Being *const target = actorManager->findNearestByName(event.args,
ActorType::Unknown);
if (target != nullptr)
localPlayer->setTarget(target);
return true;
}
impHandler(commandOutfit)
{
if (outfitWindow != nullptr)
{
if (!event.args.empty())
{
const std::string op = event.args.substr(0, 1);
if (op == "n")
{
outfitWindow->wearNextOutfit(true);
}
else if (op == "p")
{
outfitWindow->wearPreviousOutfit(true);
}
else
{
outfitWindow->wearOutfit(atoi(event.args.c_str()) - 1,
false, true);
}
}
else
{
outfitWindow->wearOutfit(atoi(event.args.c_str()) - 1,
false, true);
}
return true;
}
return false;
}
impHandler(commandEmote)
{
LocalPlayer::emote(CAST_U8(atoi(event.args.c_str())));
return true;
}
impHandler(awayMessage)
{
if (localPlayer != nullptr)
{
localPlayer->setAway(event.args);
return true;
}
return false;
}
impHandler(pseudoAway)
{
if (localPlayer != nullptr)
{
LocalPlayer::setPseudoAway(event.args);
localPlayer->updateStatus();
return true;
}
return false;
}
impHandler(follow)
{
if (localPlayer == nullptr)
return false;
if (!features.getBoolValue("allowFollow"))
return false;
if (!event.args.empty())
{
localPlayer->setFollow(event.args);
}
else if (event.tab != nullptr &&
event.tab->getType() == ChatTabType::WHISPER)
{
localPlayer->setFollow(static_cast<WhisperTab*>(event.tab)->getNick());
}
else
{
const Being *const being = localPlayer->getTarget();
if (being != nullptr)
localPlayer->setFollow(being->getName());
}
return true;
}
impHandler(navigate)
{
if ((localPlayer == nullptr) ||
!localPlayer->canMove())
{
return false;
}
int x = 0;
int y = 0;
if (parse2Int(event.args, x, y))
localPlayer->navigateTo(x, y);
else
localPlayer->navigateClean();
return true;
}
impHandler(navigateTo)
{
if ((localPlayer == nullptr) ||
!localPlayer->canMove())
{
return false;
}
const std::string args = event.args;
if (args.empty())
return true;
Being *const being = actorManager->findBeingByName(args,
ActorType::Unknown);
if (being != nullptr)
{
localPlayer->navigateTo(being->getTileX(), being->getTileY());
}
else if (localPlayer->isInParty())
{
const Party *const party = localPlayer->getParty();
if (party != nullptr)
{
const PartyMember *const m = party->getMember(args);
const PartyMember *const o = party->getMember(
localPlayer->getName());
if (m != nullptr &&
o != nullptr &&
m->getMap() == o->getMap())
{
localPlayer->navigateTo(m->getX(), m->getY());
}
}
}
return true;
}
impHandler(moveCamera)
{
int x = 0;
int y = 0;
if (viewport == nullptr)
return false;
if (parse2Int(event.args, x, y))
viewport->moveCameraToPosition(x * mapTileSize, y * mapTileSize);
return true;
}
impHandler0(restoreCamera)
{
if (viewport == nullptr)
return false;
viewport->returnCamera();
return true;
}
impHandler(imitation)
{
if (localPlayer == nullptr)
return false;
if (!event.args.empty())
{
localPlayer->setImitate(event.args);
}
else if (event.tab != nullptr &&
event.tab->getType() == ChatTabType::WHISPER)
{
localPlayer->setImitate(static_cast<WhisperTab*>(
event.tab)->getNick());
}
else
{
localPlayer->setImitate("");
}
return true;
}
impHandler(sendMail)
{
#ifdef TMWA_SUPPORT
const ServerTypeT type = Net::getNetworkType();
if (type == ServerType::EATHENA || type == ServerType::EVOL2)
#endif // TMWA_SUPPORT
{
std::string name;
std::string text;
if (parse2Str(event.args, name, text))
{
if (settings.enableNewMailSystem)
{
mail2Handler->queueCheckName(MailQueueType::SendMail,
name,
// TRANSLATORS: quick mail message caption
_("Quick message"),
text,
0);
}
else
{
// TRANSLATORS: quick mail message caption
mailHandler->send(name, _("Quick message"), text);
}
}
}
#ifdef TMWA_SUPPORT
else if (serverConfig.getBoolValue("enableManaMarketBot"))
{
chatHandler->privateMessage("ManaMarket", "!mail " + event.args);
return true;
}
#endif // TMWA_SUPPORT
return false;
}
impHandler(info)
{
if (event.tab == nullptr ||
localPlayer == nullptr ||
Net::getNetworkType() == ServerType::TMWATHENA)
{
return false;
}
if (guildHandler != nullptr &&
event.tab->getType() == ChatTabType::GUILD)
{
const Guild *const guild = localPlayer->getGuild();
if (guild != nullptr)
guildHandler->info();
}
return true;
}
impHandler(wait)
{
if (localPlayer != nullptr)
{
localPlayer->waitFor(event.args);
return true;
}
return false;
}
impHandler(addPriorityAttack)
{
if ((actorManager == nullptr) ||
actorManager->isInPriorityAttackList(event.args))
{
return false;
}
actorManager->removeAttackMob(event.args);
actorManager->addPriorityAttackMob(event.args);
if (socialWindow != nullptr)
socialWindow->updateAttackFilter();
return true;
}
impHandler(addAttack)
{
if (actorManager == nullptr)
return false;
actorManager->removeAttackMob(event.args);
actorManager->addAttackMob(event.args);
if (socialWindow != nullptr)
socialWindow->updateAttackFilter();
return true;
}
impHandler(removeAttack)
{
if (actorManager == nullptr)
return false;
if (event.args.empty())
{
if (actorManager->isInAttackList(event.args))
{
actorManager->removeAttackMob(event.args);
actorManager->addIgnoreAttackMob(event.args);
}
else
{
actorManager->removeAttackMob(event.args);
actorManager->addAttackMob(event.args);
}
}
else
{
actorManager->removeAttackMob(event.args);
}
if (socialWindow != nullptr)
socialWindow->updateAttackFilter();
return true;
}
impHandler(addIgnoreAttack)
{
if (actorManager == nullptr)
return false;
actorManager->removeAttackMob(event.args);
actorManager->addIgnoreAttackMob(event.args);
if (socialWindow != nullptr)
socialWindow->updateAttackFilter();
return true;
}
impHandler(setDrop)
{
GameModifiers::setQuickDropCounter(atoi(event.args.c_str()));
return true;
}
impHandler(url)
{
if (event.tab != nullptr)
{
std::string url1 = event.args;
if (!strStartWith(url1, "http") && !strStartWith(url1, "?"))
url1 = "http://" + url1;
std::string str(strprintf("[@@%s |%s@@]",
url1.c_str(), event.args.c_str()));
outStringNormal(event.tab, str, str);
return true;
}
return false;
}
impHandler(openUrl)
{
std::string url = event.args;
if (!strStartWith(url, "http"))
url = "http://" + url;
openBrowser(url);
return true;
}
impHandler(execute)
{
const size_t idx = event.args.find(' ');
std::string name;
std::string params;
if (idx == std::string::npos)
{
name = event.args;
}
else
{
name = event.args.substr(0, idx);
params = event.args.substr(idx + 1);
}
execFile(name, name, params, "");
return true;
}
impHandler(enableHighlight)
{
if (event.tab != nullptr)
{
event.tab->setAllowHighlight(true);
if (chatWindow != nullptr)
{
chatWindow->saveState();
return true;
}
}
return false;
}
impHandler(disableHighlight)
{
if (event.tab != nullptr)
{
event.tab->setAllowHighlight(false);
if (chatWindow != nullptr)
{
chatWindow->saveState();
return true;
}
}
return false;
}
impHandler(dontRemoveName)
{
if (event.tab != nullptr)
{
event.tab->setRemoveNames(false);
if (chatWindow != nullptr)
{
chatWindow->saveState();
return true;
}
}
return false;
}
impHandler(removeName)
{
if (event.tab != nullptr)
{
event.tab->setRemoveNames(true);
if (chatWindow != nullptr)
{
chatWindow->saveState();
return true;
}
}
return false;
}
impHandler(disableAway)
{
if (event.tab != nullptr)
{
event.tab->setNoAway(true);
if (chatWindow != nullptr)
{
chatWindow->saveState();
return true;
}
}
return false;
}
impHandler(enableAway)
{
if (event.tab != nullptr)
{
event.tab->setNoAway(false);
if (chatWindow != nullptr)
{
chatWindow->saveState();
return true;
}
}
return false;
}
impHandler(testParticle)
{
if (localPlayer != nullptr)
{
localPlayer->setTestParticle(event.args, true);
return true;
}
return false;
}
impHandler(talkRaw)
{
if (chatHandler != nullptr)
{
chatHandler->talkRaw(event.args);
return true;
}
return false;
}
impHandler(gm)
{
if (chatHandler != nullptr)
{
Gm::runCommand("wgm", event.args);
return true;
}
return false;
}
impHandler(hack)
{
if (chatHandler != nullptr)
{
chatHandler->sendRaw(event.args);
return true;
}
return false;
}
impHandler(debugSpawn)
{
if (localPlayer == nullptr)
return false;
int cnt = atoi(event.args.c_str());
if (cnt < 1)
cnt = 1;
const int half = cnt / 2;
const Map *const map = localPlayer->getMap();
int x1 = -half;
if (x1 < 0)
x1 = 0;
int y1 = x1;
int x2 = cnt - half;
if (x2 > map->getWidth())
x2 = map->getWidth();
int y2 = x2;
for (int x = x1; x < x2; x ++)
{
for (int y = y1; y < y2; y ++)
ActorManager::cloneBeing(localPlayer, x, y, cnt);
}
return true;
}
impHandler(serverIgnoreWhisper)
{
std::string args = getNick(event);
if (args.empty())
return false;
if (chatHandler != nullptr)
{
chatHandler->ignore(args);
return true;
}
return false;
}
impHandler(serverUnIgnoreWhisper)
{
std::string args = getNick(event);
if (args.empty())
return false;
if (chatHandler != nullptr)
{
chatHandler->unIgnore(args);
return true;
}
return false;
}
impHandler(setHomunculusName)
{
const std::string args = event.args;
if (args.empty())
{
const HomunculusInfo *const info = PlayerInfo::getHomunculus();
if (info != nullptr)
{
// TRANSLATORS: dialog header
inputActionReplayListener.openDialog(_("Rename your homun"),
info->name,
InputAction::HOMUNCULUS_SET_NAME);
}
return false;
}
if (homunculusHandler != nullptr)
{
homunculusHandler->setName(args);
return true;
}
return false;
}
impHandler0(fireHomunculus)
{
if (homunculusHandler != nullptr)
{
homunculusHandler->fire();
return true;
}
return false;
}
impHandler0(leaveParty)
{
if (partyHandler != nullptr)
{
partyHandler->leave();
return true;
}
return false;
}
impHandler0(leaveGuild)
{
if ((guildHandler != nullptr) && (localPlayer != nullptr))
{
const Guild *const guild = localPlayer->getGuild();
if (guild != nullptr)
guildHandler->leave(guild->getId());
return true;
}
return false;
}
impHandler(warp)
{
int x = 0;
int y = 0;
if ((adminHandler != nullptr) &&
(Game::instance() != nullptr) &&
parse2Int(event.args, x, y))
{
adminHandler->warp(Game::instance()->getCurrentMapName(),
x, y);
return true;
}
return false;
}
impHandler(homunTalk)
{
if ((serverFeatures == nullptr) || !serverFeatures->haveTalkPet())
return false;
std::string args = event.args;
if (findCutFirst(args, "/me "))
args = textToMe(args);
if (homunculusHandler != nullptr)
{
homunculusHandler->talk(args);
return true;
}
return false;
}
impHandler(homunEmote)
{
if ((serverFeatures == nullptr) || !serverFeatures->haveTalkPet())
return false;
if ((homunculusHandler != nullptr) &&
event.action >= InputAction::HOMUN_EMOTE_1 &&
event.action <= InputAction::HOMUN_EMOTE_48)
{
if (emoteShortcut != nullptr)
{
const int emotion = event.action - InputAction::HOMUN_EMOTE_1;
homunculusHandler->emote(emoteShortcut->getEmote(emotion));
}
if (Game::instance() != nullptr)
Game::instance()->setValidSpeed();
return true;
}
return false;
}
impHandler(commandHomunEmote)
{
if ((serverFeatures == nullptr) || !serverFeatures->haveTalkPet())
return false;
if (homunculusHandler != nullptr)
{
homunculusHandler->emote(CAST_U8(
atoi(event.args.c_str())));
return true;
}
return false;
}
impHandler(createPublicChatRoom)
{
if ((chatHandler == nullptr) || event.args.empty())
return false;
chatHandler->createChatRoom(event.args, "", 100, true);
return true;
}
impHandler(joinChatRoom)
{
if (chatHandler == nullptr)
return false;
const std::string args = event.args;
if (args.empty())
return false;
ChatObject *const chat = ChatObject::findByName(args);
if (chat == nullptr)
return false;
chatHandler->joinChat(chat, "");
return true;
}
impHandler0(leaveChatRoom)
{
if (chatHandler != nullptr)
{
chatHandler->leaveChatRoom();
return true;
}
return false;
}
impHandler(confSet)
{
std::string name;
std::string val;
if (parse2Str(event.args, name, val))
{
config.setValue(name, val);
return true;
}
return false;
}
impHandler(serverConfSet)
{
std::string name;
std::string val;
if (parse2Str(event.args, name, val))
{
serverConfig.setValue(name, val);
return true;
}
return false;
}
impHandler(confGet)
{
const std::string args = event.args;
if (args.empty())
return false;
// TRANSLATORS: result from command /confget
const std::string str = strprintf(_("Config value: %s"),
config.getStringValue(args).c_str());
outStringNormal(event.tab, str, str);
return true;
}
impHandler(serverConfGet)
{
const std::string args = event.args;
if (args.empty())
return false;
// TRANSLATORS: result from command /serverconfget
const std::string str = strprintf(_("Server config value: %s"),
serverConfig.getStringValue(args).c_str());
outStringNormal(event.tab, str, str);
return true;
}
impHandler(slide)
{
int x = 0;
int y = 0;
if ((adminHandler != nullptr) && parse2Int(event.args, x, y))
{
adminHandler->slide(x, y);
return true;
}
return false;
}
impHandler(selectSkillLevel)
{
int skill = 0;
int level = 0;
if ((skillDialog != nullptr) && parse2Int(event.args, skill, level))
{
skillDialog->selectSkillLevel(skill, level);
return true;
}
return false;
}
impHandler(skill)
{
StringVect vect;
splitToStringVector(vect, event.args, ' ');
const int sz = CAST_S32(vect.size());
if (sz < 1)
return true;
const int skillId = atoi(vect[0].c_str());
int level = 0;
std::string text;
if (sz > 1)
{
level = atoi(vect[1].c_str());
if (sz > 2)
text = vect[2];
}
// +++ add here also cast type and offsets
if (text.empty())
{
SkillDialog::useSkill(skillId,
AutoTarget_true,
level,
false,
"",
CastType::Default,
0,
0);
}
else
{
SkillDialog::useSkill(skillId,
AutoTarget_true,
level,
true,
text,
CastType::Default,
0,
0);
}
return true;
}
impHandler(craft)
{
const std::string args = event.args;
if (args.empty() || (inventoryWindow == nullptr))
return false;
inventoryWindow->moveItemToCraft(atoi(args.c_str()));
return true;
}
impHandler(npcClipboard)
{
if (npcHandler != nullptr)
{
int x = 0;
int y = 0;
NpcDialog *const dialog = npcHandler->getCurrentNpcDialog();
if ((dialog != nullptr) && parse2Int(event.args, x, y))
{
dialog->copyToClipboard(x, y);
return true;
}
}
return false;
}
impHandler(clipboardCopy)
{
const std::string args = event.args;
if (args.empty())
return false;
sendBuffer(args);
return true;
}
impHandler(addPickup)
{
if (actorManager != nullptr)
{
actorManager->removePickupItem(event.args);
actorManager->addPickupItem(event.args);
if (socialWindow != nullptr)
socialWindow->updatePickupFilter();
return true;
}
return false;
}
impHandler(removePickup)
{
if (actorManager != nullptr)
{
if (event.args.empty())
{ // default pickup manipulation
if (actorManager->checkDefaultPickup())
{
actorManager->removePickupItem(event.args);
actorManager->addIgnorePickupItem(event.args);
}
else
{
actorManager->removePickupItem(event.args);
actorManager->addPickupItem(event.args);
}
}
else
{ // any other pickups
actorManager->removePickupItem(event.args);
}
if (socialWindow != nullptr)
socialWindow->updatePickupFilter();
return true;
}
return false;
}
impHandler(ignorePickup)
{
if (actorManager != nullptr)
{
actorManager->removePickupItem(event.args);
actorManager->addIgnorePickupItem(event.args);
if (socialWindow != nullptr)
socialWindow->updatePickupFilter();
return true;
}
return false;
}
impHandler(monsterInfo)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->monsterInfo(args);
return true;
}
impHandler(itemInfo)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->itemInfo(args);
return true;
}
impHandler(whoDrops)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->whoDrops(args);
return true;
}
impHandler(mobSearch)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->mobSearch(args);
return true;
}
impHandler(mobSpawnSearch)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->mobSpawnSearch(args);
return true;
}
impHandler(playerGmCommands)
{
adminHandler->playerGmCommands(event.args);
return true;
}
impHandler(playerCharGmCommands)
{
adminHandler->playerCharGmCommands(event.args);
return true;
}
impHandler(commandShowLevel)
{
adminHandler->showLevel(event.args);
return true;
}
impHandler(commandShowStats)
{
adminHandler->showStats(event.args);
return true;
}
impHandler(commandShowStorage)
{
adminHandler->showStorageList(event.args);
return true;
}
impHandler(commandShowCart)
{
adminHandler->showCartList(event.args);
return true;
}
impHandler(commandShowInventory)
{
adminHandler->showInventoryList(event.args);
return true;
}
impHandler(locatePlayer)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->locatePlayer(args);
return true;
}
impHandler(commandShowAccountInfo)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->showAccountInfo(args);
return true;
}
impHandler(commandSpawn)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->spawn(args);
return true;
}
impHandler(commandSpawnSlave)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->spawnSlave(args);
return true;
}
impHandler(commandSpawnClone)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->spawnClone(args);
return true;
}
impHandler(commandSpawnSlaveClone)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->spawnSlaveClone(args);
return true;
}
impHandler(commandSpawnEvilClone)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->spawnEvilClone(args);
return true;
}
impHandler(commandSavePosition)
{
adminHandler->savePosition(event.args);
return true;
}
impHandler(commandLoadPosition)
{
adminHandler->loadPosition(event.args);
return true;
}
impHandler(commandRandomWarp)
{
adminHandler->randomWarp(event.args);
return true;
}
impHandler(commandGotoNpc)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->gotoNpc(args);
return true;
}
impHandler(commandGotoPc)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->gotoName(args);
return true;
}
impHandler(commandRecallPc)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->recallName(args);
return true;
}
impHandler(commandIpCheck)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->ipcheckName(args);
return true;
}
impHandler(commandKiller)
{
adminHandler->killer(event.args);
return true;
}
impHandler(commandKillable)
{
adminHandler->killable(event.args);
return true;
}
impHandler(commandHeal)
{
adminHandler->heal(event.args);
return true;
}
impHandler(commandAlive)
{
adminHandler->alive(event.args);
return true;
}
impHandler(commandDisguise)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->disguise(args);
return true;
}
impHandler(commandImmortal)
{
adminHandler->immortal(event.args);
return true;
}
impHandler(commandHide)
{
adminHandler->hide(event.args);
return true;
}
impHandler(commandNuke)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->nuke(args);
return true;
}
impHandler(commandKill)
{
adminHandler->kill(event.args);
return true;
}
impHandler(commandJail)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->jail(args);
return true;
}
impHandler(commandUnjail)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->unjail(args);
return true;
}
impHandler(commandNpcMove)
{
const std::string args = event.args;
if (args.empty())
return false;
StringVect pars;
if (!splitParameters(pars, args, " ,", '\"'))
return false;
if (pars.size() != 3)
return false;
adminHandler->npcMove(pars[0],
atoi(pars[1].c_str()),
atoi(pars[2].c_str()));
return true;
}
impHandler(commandNpcHide)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->hideNpc(args);
return true;
}
impHandler(commandNpcShow)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->showNpc(args);
return true;
}
impHandler(commandChangePartyLeader)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->changePartyLeader(args);
return true;
}
impHandler(commandPartyRecall)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->partyRecall(args);
return true;
}
impHandler(commandBreakGuild)
{
adminHandler->breakGuild(event.args);
return true;
}
impHandler(commandGuildRecall)
{
const std::string args = event.args;
if (args.empty())
return false;
adminHandler->guildRecall(args);
return true;
}
impHandler(mailTo)
{
if (mailWindow == nullptr)
return false;
const std::string args = event.args;
if (settings.enableNewMailSystem)
{
mail2Handler->queueCheckName(MailQueueType::EditMail,
args,
std::string(),
std::string(),
0);
}
else
{
MailWindow::createMail(args);
}
return true;
}
impHandler(adoptChild)
{
const std::string nick = getNick(event);
Being *const being = actorManager->findBeingByName(
nick, ActorType::Player);
if (being == nullptr)
return true;
familyHandler->askForChild(being);
return true;
}
impHandler(showSkillLevels)
{
const std::string args = event.args;
if (args.empty())
return false;
const SkillInfo *restrict const skill = skillDialog->getSkill(
atoi(args.c_str()));
if (skill == nullptr)
return false;
popupMenu->showSkillLevelPopup(skill);
return true;
}
impHandler(showSkillType)
{
const std::string args = event.args;
if (args.empty())
return false;
const SkillInfo *restrict const skill = skillDialog->getSkill(
atoi(args.c_str()));
if (skill == nullptr)
return false;
popupMenu->showSkillTypePopup(skill);
return true;
}
impHandler(selectSkillType)
{
int skill = 0;
int type = 0;
if ((skillDialog != nullptr) && parse2Int(event.args, skill, type))
{
skillDialog->selectSkillCastType(skill,
static_cast<CastTypeT>(type));
return true;
}
return false;
}
impHandler(showSkillOffsetX)
{
const std::string args = event.args;
if (args.empty())
return false;
const SkillInfo *restrict const skill = skillDialog->getSkill(
atoi(args.c_str()));
if (skill == nullptr)
return false;
popupMenu->showSkillOffsetPopup(skill, true);
return true;
}
impHandler(showSkillOffsetY)
{
const std::string args = event.args;
if (args.empty())
return false;
const SkillInfo *restrict const skill = skillDialog->getSkill(
atoi(args.c_str()));
if (skill == nullptr)
return false;
popupMenu->showSkillOffsetPopup(skill, false);
return true;
}
impHandler(setSkillOffsetX)
{
int skill = 0;
int offset = 0;
if ((skillDialog != nullptr) && parse2Int(event.args, skill, offset))
{
skillDialog->setSkillOffsetX(skill, offset);
return true;
}
return false;
}
impHandler(setSkillOffsetY)
{
int skill = 0;
int offset = 0;
if ((skillDialog != nullptr) && parse2Int(event.args, skill, offset))
{
skillDialog->setSkillOffsetY(skill, offset);
return true;
}
return false;
}
impHandler(partyItemShare)
{
if (localPlayer == nullptr)
return false;
if (localPlayer->isInParty() == false)
return true;
ChatTab *tab = event.tab;
if (tab == nullptr)
tab = localChatTab;
if (tab == nullptr)
return true;
const std::string args = event.args;
if (args.empty())
{
switch (partyHandler->getShareItems())
{
case PartyShare::YES:
// TRANSLATORS: chat message
tab->chatLog(_("Item sharing enabled."),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
return true;
case PartyShare::NO:
// TRANSLATORS: chat message
tab->chatLog(_("Item sharing disabled."),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
return true;
case PartyShare::NOT_POSSIBLE:
// TRANSLATORS: chat message
tab->chatLog(_("Item sharing not possible."),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
return true;
case PartyShare::UNKNOWN:
// TRANSLATORS: chat message
tab->chatLog(_("Item sharing unknown."),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
return true;
default:
break;
}
}
const signed char opt = parseBoolean(args);
switch (opt)
{
case 1:
partyHandler->setShareItems(
PartyShare::YES);
break;
case 0:
partyHandler->setShareItems(
PartyShare::NO);
break;
case -1:
tab->chatLog(strprintf(BOOLEAN_OPTIONS, "item"),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
break;
default:
break;
}
return true;
}
impHandler(partyExpShare)
{
if (localPlayer == nullptr)
return false;
if (localPlayer->isInParty() == false)
return true;
ChatTab *tab = event.tab;
if (tab == nullptr)
tab = localChatTab;
if (tab == nullptr)
return true;
const std::string args = event.args;
if (args.empty())
{
switch (partyHandler->getShareExperience())
{
case PartyShare::YES:
// TRANSLATORS: chat message
tab->chatLog(_("Experience sharing enabled."),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
return true;
case PartyShare::NO:
// TRANSLATORS: chat message
tab->chatLog(_("Experience sharing disabled."),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
return true;
case PartyShare::NOT_POSSIBLE:
// TRANSLATORS: chat message
tab->chatLog(_("Experience sharing not possible."),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
return true;
case PartyShare::UNKNOWN:
// TRANSLATORS: chat message
tab->chatLog(_("Experience sharing unknown."),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
return true;
default:
break;
}
}
const signed char opt = parseBoolean(args);
switch (opt)
{
case 1:
partyHandler->setShareExperience(
PartyShare::YES);
break;
case 0:
partyHandler->setShareExperience(
PartyShare::NO);
break;
case -1:
tab->chatLog(strprintf(BOOLEAN_OPTIONS, "exp"),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
break;
default:
break;
}
return true;
}
impHandler(partyAutoItemShare)
{
if (localPlayer == nullptr)
return false;
if (localPlayer->isInParty() == false)
return true;
ChatTab *tab = event.tab;
if (tab == nullptr)
tab = localChatTab;
if (tab == nullptr)
return true;
const std::string args = event.args;
if (args.empty())
{
switch (partyHandler->getShareAutoItems())
{
case PartyShare::YES:
// TRANSLATORS: chat message
tab->chatLog(_("Auto item sharing enabled."),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
return true;
case PartyShare::NO:
// TRANSLATORS: chat message
tab->chatLog(_("Auto item sharing disabled."),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
return true;
case PartyShare::NOT_POSSIBLE:
// TRANSLATORS: chat message
tab->chatLog(_("Auto item sharing not possible."),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
return true;
case PartyShare::UNKNOWN:
// TRANSLATORS: chat message
tab->chatLog(_("Auto item sharing unknown."),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
return true;
default:
break;
}
}
const signed char opt = parseBoolean(args);
switch (opt)
{
case 1:
partyHandler->setShareAutoItems(
PartyShare::YES);
break;
case 0:
partyHandler->setShareAutoItems(
PartyShare::NO);
break;
case -1:
tab->chatLog(strprintf(BOOLEAN_OPTIONS, "item"),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
break;
default:
break;
}
return true;
}
impHandler0(outfitToChat)
{
if ((outfitWindow == nullptr) || (chatWindow == nullptr))
return false;
const std::string str = outfitWindow->getOutfitString();
if (!str.empty())
chatWindow->addInputText(str, true);
return true;
}
impHandler0(outfitClear)
{
if (outfitWindow == nullptr)
return false;
outfitWindow->clearCurrentOutfit();
return true;
}
impHandler(moveAttackUp)
{
if (actorManager == nullptr)
return false;
const std::string args = event.args;
const int idx = actorManager->getAttackMobIndex(args);
if (idx > 0)
{
std::list<std::string> mobs
= actorManager->getAttackMobs();
std::list<std::string>::iterator it = mobs.begin();
std::list<std::string>::iterator it2 = it;
while (it != mobs.end())
{
if (*it == args)
{
-- it2;
mobs.splice(it2, mobs, it);
actorManager->setAttackMobs(mobs);
actorManager->rebuildAttackMobs();
break;
}
++ it;
++ it2;
}
if (socialWindow != nullptr)
socialWindow->updateAttackFilter();
return true;
}
return false;
}
impHandler(moveAttackDown)
{
if (actorManager == nullptr)
return false;
const std::string args = event.args;
const int idx = actorManager->getAttackMobIndex(args);
const int size = actorManager->getAttackMobsSize();
if (idx + 1 < size)
{
std::list<std::string> mobs
= actorManager->getAttackMobs();
std::list<std::string>::iterator it = mobs.begin();
std::list<std::string>::iterator it2 = it;
while (it != mobs.end())
{
if (*it == args)
{
++ it2;
if (it2 == mobs.end())
break;
mobs.splice(it, mobs, it2);
actorManager->setAttackMobs(mobs);
actorManager->rebuildAttackMobs();
break;
}
++ it;
++ it2;
}
if (socialWindow != nullptr)
socialWindow->updateAttackFilter();
return true;
}
return false;
}
impHandler(movePriorityAttackUp)
{
if (actorManager == nullptr)
return false;
const std::string args = event.args;
const int idx = actorManager->
getPriorityAttackMobIndex(args);
if (idx > 0)
{
std::list<std::string> mobs
= actorManager->getPriorityAttackMobs();
std::list<std::string>::iterator it = mobs.begin();
std::list<std::string>::iterator it2 = it;
while (it != mobs.end())
{
if (*it == args)
{
-- it2;
mobs.splice(it2, mobs, it);
actorManager->setPriorityAttackMobs(mobs);
actorManager->rebuildPriorityAttackMobs();
break;
}
++ it;
++ it2;
}
if (socialWindow != nullptr)
socialWindow->updateAttackFilter();
return true;
}
return false;
}
impHandler(movePriorityAttackDown)
{
if (actorManager == nullptr)
return false;
const std::string args = event.args;
const int idx = actorManager
->getPriorityAttackMobIndex(args);
const int size = actorManager->getPriorityAttackMobsSize();
if (idx + 1 < size)
{
std::list<std::string> mobs
= actorManager->getPriorityAttackMobs();
std::list<std::string>::iterator it = mobs.begin();
std::list<std::string>::iterator it2 = it;
while (it != mobs.end())
{
if (*it == args)
{
++ it2;
if (it2 == mobs.end())
break;
mobs.splice(it, mobs, it2);
actorManager->setPriorityAttackMobs(mobs);
actorManager->rebuildPriorityAttackMobs();
break;
}
++ it;
++ it2;
}
if (socialWindow != nullptr)
socialWindow->updateAttackFilter();
return true;
}
return false;
}
impHandler(addSkillShortcut)
{
const std::string args = event.args;
if (args.empty() ||
itemShortcutWindow == nullptr)
{
return false;
}
const SkillInfo *restrict const skill = skillDialog->getSkill(
atoi(args.c_str()));
if (skill == nullptr)
return false;
const int num = itemShortcutWindow->getTabIndex();
if (num < 0 ||
num >= CAST_S32(SHORTCUT_TABS) ||
num == CAST_S32(SHORTCUT_AUTO_TAB))
{
return false;
}
ItemShortcut *const selShortcut = itemShortcut[num];
const size_t index = selShortcut->getFreeIndex();
if (index == SHORTCUT_ITEMS)
return true;
selShortcut->setItem(index,
skill->id + SKILL_MIN_ID,
fromInt(skill->customSelectedLevel, ItemColor));
selShortcut->setItemData(index,
skill->toDataStr());
// popupMenu->showSkillLevelPopup(skill);
return true;
}
impHandler0(trimMemory)
{
#ifdef HAVE_MALLOC_TRIM
malloc_trim(0);
#else
// TRANSLATORS: chat error about trim command
localChatTab->chatLog(_("Trim memory not supported"),
ChatMsgType::BY_SERVER,
IgnoreRecord_false,
TryRemoveColors_true);
#endif
return true;
}
} // namespace Actions