Files
src-1.2/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserShip.cpp
T

570 lines
19 KiB
C++
Executable File

//======================================================================
//
// ConsoleCommandParserShip.cpp
// copyright (c) 2004 Sony Online Entertainment
//
//======================================================================
#include "serverGame/FirstServerGame.h"
#include "serverGame/ConsoleCommandParserShip.h"
#include "UnicodeUtils.h"
#include "serverGame/CreatureObject.h"
#include "serverGame/ServerWorld.h"
#include "serverGame/ShipComponentDataManager.h"
#include "serverGame/ShipInternalDamageOverTime.h"
#include "serverGame/ShipInternalDamageOverTimeManager.h"
#include "serverGame/ShipObject.h"
#include "sharedFoundation/ConstCharCrcString.h"
#include "sharedFoundation/Crc.h"
#include "sharedFoundation/PersistentCrcString.h"
#include "sharedGame/ShipChassis.h"
#include "sharedGame/ShipChassisSlot.h"
#include "sharedGame/ShipComponentAttachmentManager.h"
#include "sharedGame/ShipComponentData.h"
#include "sharedGame/ShipComponentDescriptor.h"
#include "sharedNetworkMessages/MessageQueueGenericValueType.h"
#include "sharedNetworkMessages/ShipDamageMessage.h"
#include "sharedObject/Controller.h"
#include "sharedObject/NetworkIdManager.h"
#include "sharedObject/ObjectTemplateList.h"
#include <cstdio>
// ======================================================================
//lint -e641
namespace
{
namespace CommandNames
{
#define MAKE_COMMAND(a) const char * const a = #a
MAKE_COMMAND(getSlotList);
MAKE_COMMAND(install);
MAKE_COMMAND(pseudoInstall);
MAKE_COMMAND(uninstall);
MAKE_COMMAND(purge);
MAKE_COMMAND(getComponentDescriptor);
MAKE_COMMAND(pseudoDamageShip);
MAKE_COMMAND(idotList);
MAKE_COMMAND(idotSet);
MAKE_COMMAND(idotRemove);
#undef MAKE_COMMAND
}
const CommandParser::CmdInfo cmds[] =
{
{CommandNames::getSlotList, 0, "[slot name] [ship OID]", "Lists slots on a ship"},
{CommandNames::install, 2, "<component id> <slot> [ship OID]", "Installs a component in a ship."},
{CommandNames::pseudoInstall, 2, "<component name> <slot> [ship OID]", "Installs a psuedo component in a ship."},
{CommandNames::uninstall, 1, "<slot> [target container Id] [ship OID]", "Uninstalls a component from a ship."},
{CommandNames::purge, 1, "<slot> [ship OID]", "Purges a component from a ship."},
{CommandNames::getComponentDescriptor, 0, "[component OID]", "View component descriptor info for a component"},
{CommandNames::pseudoDamageShip, 0, "", "Send a hit message to your piloted ship by the lookAt target."},
{CommandNames::idotList, 0, "[networkId]", "List all active IDOTS."},
{CommandNames::idotSet, 3, "<slot> <damage rate> <damage threshold> [networkId]", "Set an active IDOT."},
{CommandNames::idotRemove, 1, "<slot> [networkId]", "Remove an active IDOT."},
{"", 0, "", ""} // this must be last
};
//----------------------------------------------------------------------
TangibleObject * findTangible (const NetworkId & defaultId, const CommandParser::StringVector_t & argv, int index)
{
if (index < 0)
return 0;
NetworkId oid = defaultId;
if (argv.size () > static_cast<size_t>(index))
oid = NetworkId (Unicode::wideToNarrow (argv [static_cast<size_t>(index)]));
return dynamic_cast<TangibleObject *>(NetworkIdManager::getObjectById(oid));
}
}
//-----------------------------------------------------------------
ConsoleCommandParserShip::ConsoleCommandParserShip (void) :
CommandParser ("ship", 0, "...", "Ship related commands.", 0)
{
createDelegateCommands (cmds);
}
//----------------------------------------------------------------------
bool ConsoleCommandParserShip::performParsing (const NetworkId & userId, const StringVector_t & argv, const String_t & , String_t & result, const CommandParser *)
{
CreatureObject const * const user = dynamic_cast<const CreatureObject *>(NetworkIdManager::getObjectById (userId));
if (!user)
return false;
// ----------------------------------------------------------------
if (isCommand (argv[0], CommandNames::getSlotList))
{
ShipObject * const ship = dynamic_cast<ShipObject *>(findTangible (user->getLookAtTarget (), argv, 2));
std::string slotNameToken;
if (argv.size () > 1)
{
slotNameToken = Unicode::wideToNarrow (argv [1]);
if (!slotNameToken.empty () && slotNameToken [0] == '*')
slotNameToken.clear ();
}
if (ship == NULL)
{
result += getErrorMessage (argv[0], ERR_INVALID_OBJECT);
return true;
}
uint32 const chassisType = ship->getChassisType ();
ShipChassis const * const shipChassis = ShipChassis::findShipChassisByCrc (chassisType);
if (shipChassis == NULL)
{
result += Unicode::narrowToWide ("No chassis");
return true;
}
ShipChassis::SlotVector const & slotVector = shipChassis->getSlots ();
char buf [1024];
const size_t buf_size = sizeof (buf);
snprintf (buf, buf_size,
"Chassis type [%s] (%lu)\n"
" Slot count [%d], Hitpoints [%5.2f/%5.2f], Mass [%5.2f/%5.2f]\n",
shipChassis->getName ().getString (), shipChassis->getCrc (),
static_cast<int>(slotVector.size ()),
ship->getCurrentChassisHitPoints(), ship->getMaximumChassisHitPoints(),
ship->getChassisComponentMassCurrent(), ship->getChassisComponentMassMaximum());
result += Unicode::narrowToWide (buf);
for (int chassisSlot = ShipChassisSlotType::SCST_first; chassisSlot < ShipChassisSlotType::SCST_num_types; ++chassisSlot)
{
int effectiveCompatibilitySlot = chassisSlot;
// weapon slots beyond 7 wrap back to slot 0 for the purposes of compatibility checking on captial ships
if (ship->isCapitalShip() && chassisSlot >= ShipChassisSlotType::SCST_num_explicit_types && chassisSlot <= ShipChassisSlotType::SCST_weapon_last)
effectiveCompatibilitySlot = ShipChassisSlotType::SCST_weapon_first+((chassisSlot-ShipChassisSlotType::SCST_weapon_first)&7);
ShipChassisSlot const * const slot = shipChassis->getSlot(static_cast<ShipChassisSlotType::Type>(effectiveCompatibilitySlot));
if (!slot)
continue;
if (!slotNameToken.empty() && ShipChassisSlotType::getNameFromType(slot->getSlotType ()) != slotNameToken)
continue;
snprintf (buf, buf_size,
" \\#pcontrast1 [SLOT %s (%d)]\\#.\n"
" Hitweight [%d], compats: ",
ShipChassisSlotType::getNameFromType(static_cast<ShipChassisSlotType::Type>(chassisSlot)).c_str(),
chassisSlot,
slot->getHitWeight());
result += Unicode::narrowToWide (buf);
result += Unicode::narrowToWide(slot->getCompatibilityString());
result.push_back ('\n');
ShipComponentData * shipComponentData = 0;
if (ship->isSlotInstalled(chassisSlot))
shipComponentData = ship->createShipComponentData(chassisSlot);
if (shipComponentData == NULL)
{
result += Unicode::narrowToWide (" Loaded NONE\n");
}
else
{
result += Unicode::narrowToWide (" Loaded:\n");
shipComponentData->printDebugString (result, Unicode::narrowToWide (" "));
ShipComponentAttachmentManager::TemplateHardpointPairVector const & thpv =
ShipComponentAttachmentManager::getAttachmentsForShip (chassisType, shipComponentData->getDescriptor ().getCrc(), chassisSlot);
if (!thpv.empty ())
{
result += Unicode::narrowToWide (" Attachments: ");
for (ShipComponentAttachmentManager::TemplateHardpointPairVector::const_iterator thpv_it = thpv.begin (); thpv_it != thpv.end (); ++thpv_it)
{
uint32 const objectTemplateCrc = (*thpv_it).first;
CrcString const & hardpointName = (*thpv_it).second;
CrcString const & objectTemplateCrcString = ObjectTemplateList::lookUp(objectTemplateCrc);
result += Unicode::narrowToWide (objectTemplateCrcString.getString ());
result.push_back (':');
result += Unicode::narrowToWide (hardpointName.getString ());
result.push_back (',');
result.push_back (' ');
}
result.push_back ('\n');
}
delete shipComponentData;
}
}
return true;
}
//----------------------------------------------------------------------
else if (isCommand (argv[0], CommandNames::getComponentDescriptor))
{
TangibleObject * const component = findTangible (user->getLookAtTarget (), argv, 1);
if (component == NULL)
{
result += getErrorMessage (argv[0], ERR_INVALID_OBJECT);
return true;
}
ShipComponentData * const shipComponentData = ShipComponentDataManager::create (*component);
if (shipComponentData == NULL)
{
result += Unicode::narrowToWide ("Not a ship component");
return true;
}
shipComponentData->printDebugString (result, Unicode::emptyString);
delete shipComponentData;
return true;
}
//----------------------------------------------------------------------
else if (isCommand (argv[0], CommandNames::install))
{
ShipObject * const ship = dynamic_cast<ShipObject *>(findTangible (user->getLookAtTarget (), argv, 3));
TangibleObject * const component = findTangible (NetworkId::cms_invalid, argv, 1);
std::string const & slotName = Unicode::wideToNarrow (argv [2]);
if (ship == NULL)
{
result += Unicode::narrowToWide ("no ship");
return true;
}
if (component == NULL)
{
result += Unicode::narrowToWide ("no component");
return true;
}
ShipChassisSlotType::Type shipChassisSlotType = ShipChassisSlotType::getTypeFromName (slotName);
if (shipChassisSlotType == ShipChassisSlotType::SCST_num_types)
{
result += Unicode::narrowToWide ("not a valid slot name");
return true;
}
if (ship->isSlotInstalled (shipChassisSlotType))
{
result += Unicode::narrowToWide ("That slot is already filled");
return true;
}
ShipChassis const * const shipChassis = ShipChassis::findShipChassisByCrc (ship->getChassisType ());
if (shipChassis == NULL)
{
result += Unicode::narrowToWide ("Ship chassis invalid");
return true;
}
ShipChassisSlot const * const slot = shipChassis->getSlot (shipChassisSlotType);
if (slot == NULL)
{
result += Unicode::narrowToWide ("Ship chassis does not support that slot");
return true;
}
ShipComponentData * const shipComponentData = ShipComponentDataManager::create (*component);
if (shipComponentData == NULL)
{
result += Unicode::narrowToWide ("Not a ship component");
return true;
}
if (!slot->canAcceptComponent (shipComponentData->getDescriptor ()))
{
result += Unicode::narrowToWide ("Component cannot be installed here, may not be compatible.");
delete shipComponentData;
return true;
}
if (!ship->installComponent (user->getNetworkId(), static_cast<int>(shipChassisSlotType), *component))
result += Unicode::narrowToWide ("Installation failed. Check warnings");
else
result += Unicode::narrowToWide ("Installation Success");
delete shipComponentData;
return true;
}
//----------------------------------------------------------------------
else if (isCommand (argv[0], CommandNames::pseudoInstall))
{
ShipObject * const ship = dynamic_cast<ShipObject *>(findTangible (user->getLookAtTarget (), argv, 3));
std::string const & componentName = Unicode::wideToNarrow (argv [1]);
std::string const & slotName = Unicode::wideToNarrow (argv [2]);
if (ship == NULL)
{
result += Unicode::narrowToWide ("no ship");
return true;
}
uint32 const componentCrc = Crc::normalizeAndCalculate (componentName.c_str ());
ShipComponentDescriptor const * const shipComponentDescriptor = ShipComponentDescriptor::findShipComponentDescriptorByCrc (componentCrc);
if (shipComponentDescriptor == NULL)
{
result += Unicode::narrowToWide ("Invalid component name");
return true;
}
ShipChassisSlotType::Type const shipChassisSlotType = ShipChassisSlotType::getTypeFromName (slotName);
if (shipChassisSlotType == ShipChassisSlotType::SCST_num_types)
{
result += Unicode::narrowToWide ("not a valid slot name");
return true;
}
if (!ship->pseudoInstallComponent (static_cast<int>(shipChassisSlotType), componentCrc))
result += Unicode::narrowToWide ("Installation Failed... check warnings");
else
result += Unicode::narrowToWide ("Installation Success");
return true;
}
//----------------------------------------------------------------------
else if (isCommand (argv[0], CommandNames::uninstall))
{
ShipObject * const ship = dynamic_cast<ShipObject *>(findTangible (user->getLookAtTarget (), argv, 3));
TangibleObject * const targetContainer = findTangible (user->getInventory ()->getNetworkId (), argv, 2);
std::string const & slotName = Unicode::wideToNarrow (argv [1]);
if (ship == NULL)
{
result += Unicode::narrowToWide ("no ship");
return true;
}
if (targetContainer == NULL)
{
result += Unicode::narrowToWide ("no target container");
return true;
}
ShipChassisSlotType::Type shipChassisSlotType = ShipChassisSlotType::getTypeFromName (slotName);
if (shipChassisSlotType == ShipChassisSlotType::SCST_num_types)
{
result += Unicode::narrowToWide ("not a valid slot name");
return true;
}
if (!ship->isSlotInstalled (shipChassisSlotType))
{
result += Unicode::narrowToWide ("That slot is not filled");
return true;
}
if (!ship->uninstallComponent (user->getNetworkId(), static_cast<int>(shipChassisSlotType), *targetContainer))
result += Unicode::narrowToWide ("Uninstallation failed. Check warnings");
else
result += Unicode::narrowToWide ("Uninstallation Success");
return true;
}
//----------------------------------------------------------------------
else if (isCommand (argv[0], CommandNames::purge))
{
ShipObject * const ship = dynamic_cast<ShipObject *>(findTangible (user->getLookAtTarget (), argv, 2));
std::string const & slotName = Unicode::wideToNarrow (argv [1]);
if (ship == NULL)
{
result += Unicode::narrowToWide ("no ship");
return true;
}
ShipChassisSlotType::Type shipChassisSlotType = ShipChassisSlotType::getTypeFromName (slotName);
if (shipChassisSlotType == ShipChassisSlotType::SCST_num_types)
{
result += Unicode::narrowToWide ("not a valid slot name");
return true;
}
if (!ship->isSlotInstalled (shipChassisSlotType))
{
result += Unicode::narrowToWide ("That slot is not filled");
return true;
}
ship->purgeComponent (static_cast<int>(shipChassisSlotType));
result += Unicode::narrowToWide ("Purge Success");
return true;
}
//----------------------------------------------------------------------
else if (isCommand (argv[0], CommandNames::pseudoDamageShip))
{
ShipObject const * const victimShipObject = user->getPilotedShip();
if (victimShipObject == NULL)
{
result += Unicode::narrowToWide ("You are not piloting a ship.");
return true;
}
ShipObject const * const attackerShipObject = dynamic_cast<ShipObject *>(findTangible (user->getLookAtTarget (), argv, 2));
if (attackerShipObject == NULL)
{
result += Unicode::narrowToWide ("You don't have attacker ship targeted.");
return true;
}
Controller * const victimShipController = const_cast<Controller * const>(victimShipObject->getController());
if (victimShipController)
{
ShipDamageMessage shipDamage(attackerShipObject->getNetworkId(),
attackerShipObject->getPosition_w(),
1.0f );
MessageQueueGenericValueType<ShipDamageMessage> * const damageMessage = new MessageQueueGenericValueType<ShipDamageMessage>(shipDamage);
victimShipController->appendMessage(CM_shipDamageMessage, 0.0f, damageMessage,
GameControllerMessageFlags::SEND |
GameControllerMessageFlags::RELIABLE |
GameControllerMessageFlags::DEST_AUTH_CLIENT);
}
return true;
}
//----------------------------------------------------------------------
else if (isCommand (argv[0], CommandNames::idotList))
{
ShipObject * const ship = dynamic_cast<ShipObject *>(findTangible (user->getLookAtTarget (), argv, 1));
ShipInternalDamageOverTimeManager::IdotVector const & idotVector = ShipInternalDamageOverTimeManager::getActiveShipInternalDamageOverTime();
char buf[1024];
size_t const buf_size = sizeof(buf);
int displayCount = 0;
for (ShipInternalDamageOverTimeManager::IdotVector::const_iterator it = idotVector.begin(); it != idotVector.end(); ++it)
{
ShipInternalDamageOverTime const & idot = *it;
ShipObject const * const idotShip = idot.getShipObject();
if (ship != NULL && ship != idotShip)
continue;
uint32 const chassisType = idotShip->getChassisType();
ShipChassis const * const chassis = ShipChassis::findShipChassisByCrc(chassisType);
std::string const chassisTypeName = (chassis != NULL) ? chassis->getName().getString() : "<NO VALID CHASSIS>";
float hpCur = 0.0f;
float hpMax = 0.0f;
IGNORE_RETURN(idot.checkValidity(hpCur, hpMax));
float hpPercent = (hpMax > 0.0f) ? hpCur / hpMax : -1.0f;
snprintf(buf, buf_size,
"[%15s] [%15s]:[%-10s] rate=[%3.1f], threshold=[%3.1f], hp cur/max/pct=[%5.1f/%5.1f/%3.3f\n",
idotShip->getNetworkId().getValueString().c_str(), chassisTypeName.c_str(),
ShipChassisSlotType::getNameFromType(static_cast<ShipChassisSlotType::Type>(idot.getChassisSlot())).c_str(),
idot.getDamageRate(), idot.getDamageThreshold(), hpCur, hpMax, hpPercent);
buf[buf_size-1] = 0;
result += Unicode::narrowToWide(buf);
++displayCount;
}
snprintf(buf, buf_size, "%d/%d displayed", displayCount, idotVector.size());
buf[buf_size-1] = 0;
result += Unicode::narrowToWide(buf);
return true;
}
//----------------------------------------------------------------------
else if (isCommand (argv[0], CommandNames::idotSet))
{
ShipObject * const ship = dynamic_cast<ShipObject *>(findTangible (user->getLookAtTarget (), argv, 4));
if (ship == NULL)
{
result += Unicode::narrowToWide ("no ship");
return true;
}
std::string const & slotName = Unicode::wideToNarrow (argv [1]);
ShipChassisSlotType::Type const shipChassisSlotType = ShipChassisSlotType::getTypeFromName (slotName);
float const damageRate = static_cast<float>(atof(Unicode::wideToNarrow(argv[2]).c_str()));
float const damageThreshold = static_cast<float>(atof(Unicode::wideToNarrow(argv[3]).c_str()));
if (!ShipInternalDamageOverTimeManager::setEntry(*ship, static_cast<int>(shipChassisSlotType), damageRate, damageThreshold))
result += Unicode::narrowToWide("failed to set the IDOT entry");
return true;
}
//----------------------------------------------------------------------
else if (isCommand (argv[0], CommandNames::idotRemove))
{
ShipObject * const ship = dynamic_cast<ShipObject *>(findTangible (user->getLookAtTarget (), argv, 4));
if (ship == NULL)
{
result += Unicode::narrowToWide ("no ship");
return true;
}
std::string const & slotName = Unicode::wideToNarrow (argv [1]);
ShipChassisSlotType::Type const shipChassisSlotType = ShipChassisSlotType::getTypeFromName (slotName);
if (!ShipInternalDamageOverTimeManager::removeEntry(*ship, static_cast<int>(shipChassisSlotType)))
result += Unicode::narrowToWide("failed to remove the IDOT entry");
return true;
}
//----------------------------------------------------------------------
return false;
}
//----------------------------------------------------------------------