mirror of
https://bitbucket.org/theswgsource/src-1.2.git
synced 2026-10-12 02:13:43 -04:00
676 lines
24 KiB
C++
Executable File
676 lines
24 KiB
C++
Executable File
// ======================================================================
|
|
//
|
|
// ConsoleCommandParserAi.cpp
|
|
// Copyright (c) 2004 Sony Online Entertainment
|
|
//
|
|
// ======================================================================
|
|
|
|
#include "serverGame/FirstServerGame.h"
|
|
#include "serverGame/ConsoleCommandParserAi.h"
|
|
|
|
#include "serverGame/AiCreatureController.h"
|
|
#include "serverGame/AiShipController.h"
|
|
#include "serverGame/Chat.h"
|
|
#include "serverGame/CreatureObject.h"
|
|
#include "serverGame/HateList.h"
|
|
#include "serverGame/ServerWorld.h"
|
|
#include "serverGame/WeaponObject.h"
|
|
#include "serverUtility/ServerClock.h"
|
|
#include "sharedFile/FileNameUtils.h"
|
|
#include "sharedFoundation/FormattedString.h"
|
|
#include "sharedFoundation/NetworkId.h"
|
|
#include "sharedGame/AiDebugString.h"
|
|
#include "sharedNetworkMessages/GenericValueTypeMessage.h"
|
|
#include "sharedObject/CellProperty.h"
|
|
#include "sharedObject/NetworkIdManager.h"
|
|
#include "sharedUtility/DataTable.h"
|
|
#include "sharedUtility/DataTableManager.h"
|
|
#include "UnicodeUtils.h"
|
|
|
|
// ======================================================================
|
|
|
|
static const CommandParser::CmdInfo cmds[] =
|
|
{
|
|
{"info", 0, "[oid]", "Displays information about the specified AI. Assumes target if no oid specified."},
|
|
{"hatelist", 0, "[oid]", "Displays the specified object's hate list. Assumes target if no oid specified."},
|
|
{"kill", 0, "[oid]", "Kills the specified AI. Assumes target if no oid specified."},
|
|
{"log", 0, "[oid]", "Toggles log file data for the specified AI. Assumes target if no oid specified."},
|
|
{"retreat", 0, "[oid]", "Toggles whether the specified AI can auto retreat due to a player running away without attacking. Assumes target if no oid specified."},
|
|
{"walkspeed", 1, "<speed | oid speed>", "Displays the current walk speed or sets the walk speed for the specified AI. Assumes target if no oid specified."},
|
|
{"runspeed", 1, "<speed | oid speed>", "Displays the current run speed or sets the run speed for the specified AI. Assumes target if no oid specified."},
|
|
#ifdef _DEBUG
|
|
{"killall", 0, "", "Kills all the AI on the server."},
|
|
{"debug", 0, "", "Toggles client AI debugging."},
|
|
{"debugText", 0, "", "Toggles the client AI debugging text."},
|
|
#endif // _DEBUG
|
|
{"", 0, "", ""} // this must be last
|
|
};
|
|
|
|
// ======================================================================
|
|
//
|
|
// ConsoleCommandParserAiNamespace
|
|
//
|
|
// ======================================================================
|
|
|
|
namespace ConsoleCommandParserAiNamespace
|
|
{
|
|
CreatureObject * const getAiCreatureObject(CreatureObject const & user, std::vector<Unicode::String> const & argv);
|
|
}
|
|
|
|
//-----------------------------------------------------------------
|
|
|
|
CreatureObject * const ConsoleCommandParserAiNamespace::getAiCreatureObject(CreatureObject const & user, std::vector<Unicode::String> const & argv)
|
|
{
|
|
NetworkId aiNetworkId;
|
|
|
|
if (argv.size() > 1)
|
|
{
|
|
aiNetworkId = NetworkId(Unicode::wideToNarrow(argv[1]));
|
|
}
|
|
else
|
|
{
|
|
aiNetworkId = user.getLookAtTarget();
|
|
}
|
|
|
|
CreatureObject * const aiCreatureObject = CreatureObject::getCreatureObject(aiNetworkId);
|
|
|
|
if ( (aiCreatureObject == nullptr)
|
|
|| aiCreatureObject->isPlayerControlled())
|
|
{
|
|
Chat::sendSystemMessage(user, Unicode::narrowToWide(FormattedString<1024>().sprintf("[FAILURE] Unable to resolve %s to an AI", aiNetworkId.getValueString().c_str())), Unicode::emptyString);
|
|
}
|
|
|
|
return aiCreatureObject;
|
|
}
|
|
|
|
using namespace ConsoleCommandParserAiNamespace;
|
|
|
|
// ======================================================================
|
|
//
|
|
// ConsoleCommandParserAi
|
|
//
|
|
// ======================================================================
|
|
|
|
//-----------------------------------------------------------------
|
|
|
|
ConsoleCommandParserAi::ConsoleCommandParserAi()
|
|
: CommandParser("ai", 0, "...", "Ai related commands.", 0)
|
|
{
|
|
createDelegateCommands (cmds);
|
|
}
|
|
|
|
//-----------------------------------------------------------------
|
|
|
|
bool ConsoleCommandParserAi::performParsing(const NetworkId & userId, const StringVector_t & argv, const String_t & originalCommand, String_t & result, const CommandParser * node)
|
|
{
|
|
NOT_NULL (node);
|
|
UNREF (userId);
|
|
UNREF(originalCommand);
|
|
|
|
FormattedString<1024> fs;
|
|
|
|
if (isAbbrev(argv[0], "log"))
|
|
{
|
|
CreatureObject * const userCreatureObject = CreatureObject::getCreatureObject(userId);
|
|
|
|
if (userCreatureObject == nullptr)
|
|
{
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
else
|
|
{
|
|
CreatureObject * const aiCreatureObject = getAiCreatureObject(*userCreatureObject, argv);
|
|
|
|
if (aiCreatureObject == nullptr)
|
|
{
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
else
|
|
{
|
|
AICreatureController * const aiCreatureController = AICreatureController::asAiCreatureController(aiCreatureObject->getController());
|
|
|
|
if (aiCreatureController == nullptr)
|
|
{
|
|
Chat::sendSystemMessage(*userCreatureObject, Unicode::narrowToWide(fs.sprintf("[FAILURE] Unable to resolve %s to an AI", aiCreatureObject->getNetworkId().getValueString().c_str())), Unicode::emptyString);
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
else
|
|
{
|
|
aiCreatureController->setLogging(!aiCreatureController->isLogging());
|
|
|
|
Chat::sendSystemMessage(*userCreatureObject, Unicode::narrowToWide(fs.sprintf("[%s] Ai logging %s", (aiCreatureController->isLogging() ? "ENABLED" : "DISABLED"), aiCreatureObject->getNetworkId().getValueString().c_str())), Unicode::emptyString);
|
|
result += getErrorMessage(argv[0], ERR_SUCCESS);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (isAbbrev(argv[0], "info"))
|
|
{
|
|
CreatureObject * const userCreatureObject = CreatureObject::getCreatureObject(userId);
|
|
|
|
if (userCreatureObject == nullptr)
|
|
{
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
else
|
|
{
|
|
NetworkId targetNetworkId;
|
|
|
|
if (argv.size () > 1)
|
|
{
|
|
targetNetworkId = NetworkId(Unicode::wideToNarrow(argv[1]));
|
|
}
|
|
else
|
|
{
|
|
targetNetworkId = userCreatureObject->getLookAtTarget();
|
|
}
|
|
|
|
AICreatureController * const aiCreatureController = AICreatureController::getAiCreatureController(targetNetworkId);
|
|
|
|
if (aiCreatureController == nullptr)
|
|
{
|
|
result = Unicode::narrowToWide(fs.sprintf("[FAILURE] Unable to resolve %s to an AI\n", targetNetworkId.getValueString().c_str()));
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
else
|
|
{
|
|
CreatureObject const * const creatureOwner = aiCreatureController->getCreature();
|
|
|
|
result += Unicode::narrowToWide(fs.sprintf("\nobj_id: %s\n", aiCreatureController->getCreature()->getNetworkId().getValueString().c_str()));
|
|
result += Unicode::narrowToWide(fs.sprintf("creatureName: %s\n", aiCreatureController->getCreatureName().getString()));
|
|
result += Unicode::narrowToWide(fs.sprintf("level: %i\n", aiCreatureController->getCreature()->getLevel()));
|
|
|
|
// World position
|
|
{
|
|
Vector const & position_w = creatureOwner->getPosition_w();
|
|
result += Unicode::narrowToWide(fs.sprintf("world position: pos(%.1f, %.1f, %.1f)\n", position_w.x, position_w.y, position_w.z));
|
|
}
|
|
|
|
// Cell position
|
|
{
|
|
CellProperty const * const cellProperty = creatureOwner->getParentCell();
|
|
|
|
if (cellProperty != nullptr)
|
|
{
|
|
Vector const & position_p = creatureOwner->getPosition_p();
|
|
|
|
result += Unicode::narrowToWide(fs.sprintf("cell location: pos(%.1f, %.1f, %.1f) cell(%s:%s)\n", position_p.x, position_p.y, position_p.z, cellProperty->getOwner().getNetworkId().getValueString().c_str(), cellProperty->getCellName()));
|
|
}
|
|
}
|
|
|
|
Location const & location = aiCreatureController->getHomeLocation();
|
|
result += Unicode::narrowToWide(fs.sprintf("homeLocation: pos(%.1f, %.1f, %.1f) cell(%s:%s) scene(%s)\n", location.getCoordinates().x, location.getCoordinates().y, location.getCoordinates().z, location.getCell().getValueString().c_str(), (location.getCell() == NetworkId::cms_invalid) ? ":world" : "", location.getSceneId()));
|
|
result += Unicode::narrowToWide(fs.sprintf("invulnerable: %s\n", aiCreatureController->getCreature()->isInvulnerable() ? "yes" : "no"));
|
|
result += Unicode::narrowToWide(fs.sprintf("hibernating: %s\n", aiCreatureController->getHibernate() ? "yes" : "no"));
|
|
result += Unicode::narrowToWide(fs.sprintf("movement state: %s\n", AiMovementBase::getMovementString(aiCreatureController->getMovementType())));
|
|
result += Unicode::narrowToWide(fs.sprintf("walk speed(%.1f)\n", creatureOwner->getWalkSpeed()));
|
|
result += Unicode::narrowToWide(fs.sprintf("run speed(%.1f) modifier(%.2f)\n", creatureOwner->getRunSpeed(), aiCreatureController->getMovementSpeedPercent()));
|
|
|
|
if (aiCreatureController->isAggressive())
|
|
{
|
|
result += Unicode::narrowToWide(fs.sprintf("aggressive: yes @ %.1fm\n", aiCreatureController->getAggroRadius()));
|
|
}
|
|
else
|
|
{
|
|
result += Unicode::narrowToWide("aggressive: no\n");
|
|
}
|
|
if (aiCreatureController->isAssist())
|
|
{
|
|
result += Unicode::narrowToWide(fs.sprintf("assist: yes @ %.1fm\n", aiCreatureController->getAssistRadius()));
|
|
}
|
|
else
|
|
{
|
|
result += Unicode::narrowToWide("assist: no\n");
|
|
}
|
|
result += Unicode::narrowToWide(fs.sprintf("killer: %s\n", aiCreatureController->isKiller() ? "yes" : "no"));
|
|
|
|
// Hate List
|
|
{
|
|
HateList::SortedList hateList;
|
|
aiCreatureController->getCreature()->getSortedHateList(hateList);
|
|
|
|
if (hateList.empty())
|
|
{
|
|
result += Unicode::narrowToWide(fs.sprintf("* NO HATE TARGETS *\n"));
|
|
}
|
|
else
|
|
{
|
|
result += Unicode::narrowToWide(fs.sprintf("* HATE LIST *\n"));
|
|
|
|
HateList::SortedList::const_iterator iterHateList = hateList.begin();
|
|
|
|
for (; iterHateList != hateList.end(); ++iterHateList)
|
|
{
|
|
CachedNetworkId const & hateTarget = iterHateList->first;
|
|
TangibleObject const * const hateTargetTangibleObject = TangibleObject::asTangibleObject(hateTarget.getObject());
|
|
float const hate = iterHateList->second;
|
|
std::string hateTargetName;
|
|
if (hateTargetTangibleObject != nullptr)
|
|
{
|
|
hateTargetName = Unicode::wideToNarrow(hateTargetTangibleObject->getEncodedObjectName()).c_str();
|
|
}
|
|
else
|
|
{
|
|
hateTargetName = "nullptr";
|
|
}
|
|
|
|
result += Unicode::narrowToWide(fs.sprintf("%s:%s(%.1f)\n", hateTargetName.c_str(), hateTarget.getValueString().c_str(), hate));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Hate Over Time List
|
|
{
|
|
std::map<NetworkId, std::pair<float, std::pair<unsigned long, unsigned long> > > const & hateOverTime = aiCreatureController->getCreature()->getHateOverTime();
|
|
if (!hateOverTime.empty())
|
|
{
|
|
result += Unicode::narrowToWide(fs.sprintf("* HATE OVER TIME LIST currentGameTime=(%lu)*\n", ServerClock::getInstance().getGameTimeSeconds()));
|
|
|
|
for (std::map<NetworkId, std::pair<float, std::pair<unsigned long, unsigned long> > >::const_iterator iter = hateOverTime.begin(); iter != hateOverTime.end(); ++iter)
|
|
{
|
|
CachedNetworkId const hateTarget(iter->first);
|
|
TangibleObject const * const hateTargetTangibleObject = TangibleObject::asTangibleObject(hateTarget.getObject());
|
|
std::string hateTargetName;
|
|
if (hateTargetTangibleObject != nullptr)
|
|
{
|
|
hateTargetName = Unicode::wideToNarrow(hateTargetTangibleObject->getEncodedObjectName()).c_str();
|
|
}
|
|
else
|
|
{
|
|
hateTargetName = "nullptr";
|
|
}
|
|
|
|
result += Unicode::narrowToWide(fs.sprintf("%s:%s (%.2f, %lu, %lu)\n", hateTargetName.c_str(), hateTarget.getValueString().c_str(), iter->second.first, iter->second.second.first, iter->second.second.second));
|
|
}
|
|
}
|
|
}
|
|
|
|
result += Unicode::narrowToWide(aiCreatureController->getCombatActionsString());
|
|
|
|
result += getErrorMessage(argv[0], ERR_SUCCESS);
|
|
}
|
|
}
|
|
}
|
|
else if (isAbbrev(argv[0], "hatelist"))
|
|
{
|
|
CreatureObject * const userCreatureObject = CreatureObject::getCreatureObject(userId);
|
|
|
|
if (userCreatureObject == nullptr)
|
|
{
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
else
|
|
{
|
|
NetworkId targetNetworkId;
|
|
|
|
if (argv.size () > 1)
|
|
{
|
|
targetNetworkId = NetworkId(Unicode::wideToNarrow(argv[1]));
|
|
}
|
|
else
|
|
{
|
|
targetNetworkId = userCreatureObject->getLookAtTarget();
|
|
}
|
|
|
|
TangibleObject const * const to = TangibleObject::asTangibleObject(NetworkIdManager::getObjectById(targetNetworkId));
|
|
if (to == nullptr)
|
|
{
|
|
result += Unicode::narrowToWide(fs.sprintf("Target %s not found or not TangibleObject\n", targetNetworkId.getValueString().c_str()));
|
|
}
|
|
else
|
|
{
|
|
result += Unicode::narrowToWide(fs.sprintf("Displaying hate list for %s\n", targetNetworkId.getValueString().c_str()));
|
|
|
|
// Hate List
|
|
{
|
|
HateList::SortedList hateList;
|
|
to->getSortedHateList(hateList);
|
|
|
|
if (hateList.empty())
|
|
{
|
|
result += Unicode::narrowToWide(fs.sprintf("* NO HATE TARGETS *\n"));
|
|
}
|
|
else
|
|
{
|
|
result += Unicode::narrowToWide(fs.sprintf("* HATE LIST *\n"));
|
|
|
|
HateList::SortedList::const_iterator iterHateList = hateList.begin();
|
|
|
|
for (; iterHateList != hateList.end(); ++iterHateList)
|
|
{
|
|
CachedNetworkId const & hateTarget = iterHateList->first;
|
|
TangibleObject const * const hateTargetTangibleObject = TangibleObject::asTangibleObject(hateTarget.getObject());
|
|
float const hate = iterHateList->second;
|
|
std::string hateTargetName;
|
|
if (hateTargetTangibleObject != nullptr)
|
|
{
|
|
hateTargetName = Unicode::wideToNarrow(hateTargetTangibleObject->getEncodedObjectName()).c_str();
|
|
}
|
|
else
|
|
{
|
|
hateTargetName = "nullptr";
|
|
}
|
|
|
|
result += Unicode::narrowToWide(fs.sprintf("%s:%s(%.1f)\n", hateTargetName.c_str(), hateTarget.getValueString().c_str(), hate));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Hate Over Time List
|
|
{
|
|
std::map<NetworkId, std::pair<float, std::pair<unsigned long, unsigned long> > > const & hateOverTime = to->getHateOverTime();
|
|
if (!hateOverTime.empty())
|
|
{
|
|
result += Unicode::narrowToWide(fs.sprintf("* HATE OVER TIME LIST currentGameTime=(%lu)*\n", ServerClock::getInstance().getGameTimeSeconds()));
|
|
|
|
for (std::map<NetworkId, std::pair<float, std::pair<unsigned long, unsigned long> > >::const_iterator iter = hateOverTime.begin(); iter != hateOverTime.end(); ++iter)
|
|
{
|
|
CachedNetworkId const hateTarget(iter->first);
|
|
TangibleObject const * const hateTargetTangibleObject = TangibleObject::asTangibleObject(hateTarget.getObject());
|
|
std::string hateTargetName;
|
|
if (hateTargetTangibleObject != nullptr)
|
|
{
|
|
hateTargetName = Unicode::wideToNarrow(hateTargetTangibleObject->getEncodedObjectName()).c_str();
|
|
}
|
|
else
|
|
{
|
|
hateTargetName = "nullptr";
|
|
}
|
|
|
|
result += Unicode::narrowToWide(fs.sprintf("%s:%s (%.2f, %lu, %lu)\n", hateTargetName.c_str(), hateTarget.getValueString().c_str(), iter->second.first, iter->second.second.first, iter->second.second.second));
|
|
}
|
|
}
|
|
}
|
|
|
|
result += getErrorMessage(argv[0], ERR_SUCCESS);
|
|
}
|
|
}
|
|
}
|
|
else if (isAbbrev(argv[0], "kill"))
|
|
{
|
|
CreatureObject * const userCreatureObject = CreatureObject::getCreatureObject(userId);
|
|
|
|
if (userCreatureObject == nullptr)
|
|
{
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
else
|
|
{
|
|
CreatureObject * const aiCreatureObject = getAiCreatureObject(*userCreatureObject, argv);
|
|
|
|
if (aiCreatureObject == nullptr)
|
|
{
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
else
|
|
{
|
|
aiCreatureObject->setIncapacitated(true, NetworkId::cms_invalid);
|
|
|
|
Chat::sendSystemMessage(*userCreatureObject, Unicode::narrowToWide(fs.sprintf("[SUCCESS] AI %s terminated", aiCreatureObject->getNetworkId().getValueString().c_str())), Unicode::emptyString);
|
|
|
|
result += getErrorMessage(argv[0], ERR_SUCCESS);
|
|
}
|
|
}
|
|
}
|
|
else if (isAbbrev(argv[0], "retreat"))
|
|
{
|
|
CreatureObject * const userCreatureObject = CreatureObject::getCreatureObject(userId);
|
|
|
|
if (userCreatureObject == nullptr)
|
|
{
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
else
|
|
{
|
|
CreatureObject * const aiCreatureObject = getAiCreatureObject(*userCreatureObject, argv);
|
|
|
|
if (aiCreatureObject == nullptr)
|
|
{
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
else
|
|
{
|
|
aiCreatureObject->setHateListAutoExpireTargetEnabled(!aiCreatureObject->isHateListAutoExpireTargetEnabled());
|
|
|
|
Chat::sendSystemMessage(*userCreatureObject, Unicode::narrowToWide(fs.sprintf("[SUCCESS] AI %s %s retreat", aiCreatureObject->getNetworkId().getValueString().c_str(), aiCreatureObject->isHateListAutoExpireTargetEnabled() ? "will now" : "will no longer")), Unicode::emptyString);
|
|
|
|
result += getErrorMessage(argv[0], ERR_SUCCESS);
|
|
}
|
|
}
|
|
}
|
|
else if (isAbbrev(argv[0], "walkspeed"))
|
|
{
|
|
CreatureObject * const userCreatureObject = CreatureObject::getCreatureObject(userId);
|
|
|
|
if (userCreatureObject == nullptr)
|
|
{
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
else
|
|
{
|
|
NetworkId aiNetworkId;
|
|
CreatureObject * aiCreatureObject = nullptr;
|
|
|
|
if (argv.size() > 2)
|
|
{
|
|
// Get the network id and speed
|
|
|
|
aiNetworkId = NetworkId(Unicode::wideToNarrow(argv[1]));
|
|
aiCreatureObject = CreatureObject::getCreatureObject(aiNetworkId);
|
|
|
|
if ( (aiCreatureObject != nullptr)
|
|
&& !aiCreatureObject->isPlayerControlled())
|
|
{
|
|
aiCreatureObject->setBaseWalkSpeed(Unicode::toFloat(argv[2]));
|
|
}
|
|
}
|
|
else if (argv.size() > 1)
|
|
{
|
|
// Get the look at target and speed
|
|
|
|
aiNetworkId = userCreatureObject->getLookAtTarget();
|
|
aiCreatureObject = CreatureObject::getCreatureObject(aiNetworkId);
|
|
|
|
if ( (aiCreatureObject != nullptr)
|
|
&& !aiCreatureObject->isPlayerControlled())
|
|
{
|
|
aiCreatureObject->setBaseWalkSpeed(Unicode::toFloat(argv[1]));
|
|
}
|
|
}
|
|
|
|
if ( (aiCreatureObject == nullptr)
|
|
|| aiCreatureObject->isPlayerControlled())
|
|
{
|
|
Chat::sendSystemMessage(*userCreatureObject, Unicode::narrowToWide(fs.sprintf("[FAILURE] Unable to resolve %s to an AI", aiNetworkId.getValueString().c_str())), Unicode::emptyString);
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
else
|
|
{
|
|
Chat::sendSystemMessage(*userCreatureObject, Unicode::narrowToWide(fs.sprintf("[SUCCESS] AI %s has a walk speed of %.1fm/s", aiCreatureObject->getNetworkId().getValueString().c_str(), aiCreatureObject->getBaseWalkSpeed())), Unicode::emptyString);
|
|
result += getErrorMessage(argv[0], ERR_SUCCESS);
|
|
}
|
|
}
|
|
}
|
|
else if (isAbbrev(argv[0], "runspeed"))
|
|
{
|
|
CreatureObject * const userCreatureObject = CreatureObject::getCreatureObject(userId);
|
|
|
|
if (userCreatureObject == nullptr)
|
|
{
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
else
|
|
{
|
|
NetworkId aiNetworkId;
|
|
CreatureObject * aiCreatureObject = nullptr;
|
|
|
|
if (argv.size() > 2)
|
|
{
|
|
// Get the network id and speed
|
|
|
|
aiNetworkId = NetworkId(Unicode::wideToNarrow(argv[1]));
|
|
aiCreatureObject = CreatureObject::getCreatureObject(aiNetworkId);
|
|
|
|
if ( (aiCreatureObject != nullptr)
|
|
&& !aiCreatureObject->isPlayerControlled())
|
|
{
|
|
aiCreatureObject->setBaseRunSpeed(Unicode::toFloat(argv[2]));
|
|
}
|
|
}
|
|
else if (argv.size() > 1)
|
|
{
|
|
// Get the look at target and speed
|
|
|
|
aiNetworkId = userCreatureObject->getLookAtTarget();
|
|
aiCreatureObject = CreatureObject::getCreatureObject(aiNetworkId);
|
|
|
|
if ( (aiCreatureObject != nullptr)
|
|
&& !aiCreatureObject->isPlayerControlled())
|
|
{
|
|
aiCreatureObject->setBaseRunSpeed(Unicode::toFloat(argv[1]));
|
|
}
|
|
}
|
|
|
|
if ( (aiCreatureObject == nullptr)
|
|
|| aiCreatureObject->isPlayerControlled())
|
|
{
|
|
Chat::sendSystemMessage(*userCreatureObject, Unicode::narrowToWide(fs.sprintf("[FAILURE] Unable to resolve %s to an AI", aiNetworkId.getValueString().c_str())), Unicode::emptyString);
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
else
|
|
{
|
|
Chat::sendSystemMessage(*userCreatureObject, Unicode::narrowToWide(fs.sprintf("[SUCCESS] AI %s has a run speed of %.1fm/s", aiCreatureObject->getNetworkId().getValueString().c_str(), aiCreatureObject->getBaseRunSpeed())), Unicode::emptyString);
|
|
result += getErrorMessage(argv[0], ERR_SUCCESS);
|
|
}
|
|
}
|
|
}
|
|
#ifdef _DEBUG
|
|
else if (isAbbrev(argv[0], "killall"))
|
|
{
|
|
CreatureObject * const userCreatureObject = CreatureObject::getCreatureObject(userId);
|
|
|
|
if (userCreatureObject != nullptr)
|
|
{
|
|
NetworkId sparedAiNetworkId;
|
|
|
|
// See if we need to spare any single AI
|
|
{
|
|
if (argv.size() > 1)
|
|
{
|
|
sparedAiNetworkId = NetworkId(Unicode::wideToNarrow(argv[1]));
|
|
}
|
|
else
|
|
{
|
|
sparedAiNetworkId = userCreatureObject->getLookAtTarget();
|
|
}
|
|
}
|
|
|
|
// Run through all the AI on the server and kill them
|
|
|
|
int const serverObjectCount = ServerWorld::getNumObjects();
|
|
int killCount = 0;
|
|
|
|
for (int i = 0; i < serverObjectCount; ++i)
|
|
{
|
|
ServerObject * const serverObject = ServerWorld::getObject(i);
|
|
CreatureObject * const creatureObject = (serverObject != nullptr) ? serverObject->asCreatureObject() : nullptr;
|
|
|
|
if ( (creatureObject != nullptr)
|
|
&& !creatureObject->isDead()
|
|
&& !creatureObject->isPlayerControlled()
|
|
&& (creatureObject->getNetworkId() != sparedAiNetworkId))
|
|
{
|
|
creatureObject->setIncapacitated(true, NetworkId::cms_invalid);
|
|
++killCount;
|
|
}
|
|
}
|
|
|
|
Chat::sendSystemMessage(*userCreatureObject, Unicode::narrowToWide(fs.sprintf("[SUCCESS] %d AI terminated.", killCount)), Unicode::emptyString);
|
|
|
|
result += getErrorMessage(argv[0], ERR_SUCCESS);
|
|
}
|
|
else
|
|
{
|
|
result += getErrorMessage(argv[0], ERR_FAIL);
|
|
}
|
|
}
|
|
else if (isAbbrev(argv[0], "debug"))
|
|
{
|
|
Object * const object = NetworkIdManager::getObjectById(userId);
|
|
ServerObject * const serverObject = (object != nullptr) ? object->asServerObject() : nullptr;
|
|
int temp;
|
|
|
|
if (serverObject != nullptr)
|
|
{
|
|
if ( serverObject->getObjVars().getItem("ai_debug_string", temp)
|
|
&& (temp > 0))
|
|
{
|
|
if (!AiShipController::isClientDebugEnabled())
|
|
{
|
|
AiShipController::setClientDebugEnabled(true);
|
|
|
|
Chat::sendSystemMessage(*serverObject, Unicode::narrowToWide("[ENABLED] Your client is requesting ai debugging."), Unicode::emptyString);
|
|
}
|
|
else
|
|
{
|
|
IGNORE_RETURN(serverObject->setObjVarItem("ai_debug_string", 0));
|
|
|
|
Chat::sendSystemMessage(*serverObject, Unicode::narrowToWide("[DISABLED] Your client is NO LONGER requesting ai debugging."), Unicode::emptyString);
|
|
|
|
// Tell the client to remove all ai debugging
|
|
|
|
Client * const client = serverObject->getClient();
|
|
|
|
if (client != nullptr)
|
|
{
|
|
AiDebugString aiDebugString;
|
|
aiDebugString.enableClearClientFlag();
|
|
bool const reliable = true;
|
|
GenericValueTypeMessage<std::pair<NetworkId, std::string> > message("AiDebugString", std::make_pair(serverObject->getNetworkId(), aiDebugString.toString()));
|
|
|
|
client->send(message, reliable);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IGNORE_RETURN(serverObject->setObjVarItem("ai_debug_string", 1));
|
|
|
|
Chat::sendSystemMessage(*serverObject, Unicode::narrowToWide("[ENABLED] Your client is requesting ai debugging."), Unicode::emptyString);
|
|
|
|
if (!AiShipController::isClientDebugEnabled())
|
|
{
|
|
AiShipController::setClientDebugEnabled(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
result += getErrorMessage(argv[0], ERR_SUCCESS);
|
|
}
|
|
else if (isAbbrev(argv[0], "debugText"))
|
|
{
|
|
Object * const object = NetworkIdManager::getObjectById(userId);
|
|
ServerObject * const serverObject = (object != nullptr) ? object->asServerObject() : nullptr;
|
|
|
|
if (serverObject != nullptr)
|
|
{
|
|
AiDebugString::setTextEnabled(!AiDebugString::isTextEnabled());
|
|
|
|
Unicode::String systemMessage;
|
|
systemMessage = Unicode::narrowToWide(AiDebugString::isTextEnabled() ? "[ENABLED] Client-side debug text is enabled." : "[DISABLED] Client-side debug text is disabled.");
|
|
Chat::sendSystemMessage(*serverObject, systemMessage, Unicode::emptyString);
|
|
}
|
|
|
|
result += getErrorMessage(argv[0], ERR_SUCCESS);
|
|
}
|
|
#endif //_DEBUG
|
|
else
|
|
{
|
|
result += getErrorMessage(argv[0], ERR_NO_HANDLER);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// ======================================================================
|