Files
src-1.2/engine/server/library/serverGame/src/shared/controller/CreatureController.cpp
T
2014-01-15 03:59:18 -07:00

2193 lines
71 KiB
C++

//========================================================================
//
// CreatureController.cpp
//
// copyright 2001 Sony Online Entertainment
//
//========================================================================
#include "serverGame/FirstServerGame.h"
#include "serverGame/CreatureController.h"
#include "SwgGameServer/CombatEngine.h"
#include "SwgGameServer/ConfigCombatEngine.h"
#include "serverGame/Chat.h"
#include "serverGame/ConfigServerGame.h"
#include "serverGame/ContainerInterface.h"
#include "serverGame/CreatureObject.h"
#include "serverGame/GameServer.h"
#include "serverGame/GroupObject.h"
#include "serverGame/HarvesterInstallationObject.h"
#include "serverGame/InstallationObject.h"
#include "serverGame/ObjectTracker.h"
#include "serverGame/PlayerCreatureController.h"
#include "serverGame/PlayerObject.h"
#include "serverGame/ServerSecureTrade.h"
#include "serverGame/ServerSecureTradeManager.h"
#include "serverGame/ServerUniverse.h"
#include "serverGame/ServerWeaponObjectTemplate.h"
#include "serverGame/ServerWorld.h"
#include "serverGame/ShipObject.h"
#include "serverGame/WeaponObject.h"
#include "serverNetworkMessages/MessageQueueAlterAttribute.h"
#include "serverNetworkMessages/MessageQueueCommandQueueEnqueueFwd.h"
#include "serverNetworkMessages/MessageQueueSetState.h"
#include "serverScript/GameScriptObject.h"
#include "serverScript/ScriptParameters.h"
#include "serverUtility/ServerClock.h"
#include "sharedCollision/CollisionProperty.h"
#include "sharedCollision/Footprint.h"
#include "sharedDebug/Profiler.h"
#include "sharedFoundation/GameControllerMessage.h"
#include "sharedLog/Log.h"
#include "sharedGame/CommandTable.h"
#include "sharedUtility/Location.h"
#include "sharedGame/GameObjectTypes.h"
#include "sharedGame/ProsePackage.h"
#include "sharedGame/Waypoint.h"
#include "sharedNetworkMessages/GenericValueTypeMessage.h"
#include "sharedNetworkMessages/IncubatorCommitMessage.h"
#include "sharedNetworkMessages/MessageQueueCombatCommand.h"
#include "sharedNetworkMessages/MessageQueueCommandQueueEnqueue.h"
#include "sharedNetworkMessages/MessageQueueCommandQueueRemove.h"
#include "sharedNetworkMessages/MessageQueueCyberneticsChangeRequest.h"
#include "sharedNetworkMessages/MessageQueueDataTransform.h"
#include "sharedNetworkMessages/MessageQueueDataTransformWithParent.h"
#include "sharedNetworkMessages/MessageQueueGeneric.h"
#include "sharedNetworkMessages/MessageQueueGenericIntResponse.h"
#include "sharedNetworkMessages/MessageQueueGenericResponse.h"
#include "sharedNetworkMessages/MessageQueueGenericString.h"
#include "sharedNetworkMessages/MessageQueueGenericValueType.h"
#include "sharedNetworkMessages/MessageQueueHarvesterResourceData.h"
#include "sharedNetworkMessages/MessageQueueNetworkId.h"
#include "sharedNetworkMessages/MessageQueueNetworkIdPair.h"
#include "sharedNetworkMessages/MessageQueuePosture.h"
#include "sharedNetworkMessages/MessageQueuePushCreature.h"
#include "sharedNetworkMessages/MessageQueueResourceEmptyHopper.h"
#include "sharedNetworkMessages/MessageQueueSecureTrade.h"
#include "sharedNetworkMessages/MessageQueueSitOnObject.h"
#include "sharedNetworkMessages/MessageQueueSlowDownEffect.h"
#include "sharedNetworkMessages/ObjectChannelMessages.h"
#include "sharedNetworkMessages/UpdateTransformMessage.h"
#include "sharedNetworkMessages/UpdateTransformWithParentMessage.h"
#include "sharedObject/AlterResult.h"
#include "sharedObject/CellProperty.h"
#include "sharedObject/MovementTable.h"
#include "sharedObject/NetworkIdManager.h"
#include "sharedObject/ObjectTemplateList.h"
#include "sharedSkillSystem/SkillManager.h"
#include "sharedTerrain/TerrainObject.h"
#include "sharedTerrain/WaterTypeManager.h"
#include "swgSharedNetworkMessages/MessageQueueCombatAction.h"
#include "Unicode.h"
#include "UnicodeUtils.h"
//-----------------------------------------------------------------------
namespace CreatureControllerNamespace
{
template<typename ObjectType>
ObjectType & getOwner(Controller * controller)
{
NOT_NULL(controller);
NOT_NULL(controller->getOwner());
ObjectType * owner = static_cast<ObjectType *>(controller->getOwner());
return *owner;
}
}
//-----------------------------------------------------------------------
CreatureController::CreatureController(CreatureObject * newOwner) :
TangibleController(newOwner),
m_secureTrade(0),
m_secureTradeInitiator(0)
{
}
//-----------------------------------------------------------------------
CreatureController::~CreatureController()
{
if (getHibernate())
ObjectTracker::removeHibernatingAI();
if (m_secureTrade)
m_secureTrade->cancelTrade(*getCreature());
}
//-----------------------------------------------------------------------
void CreatureController::handleMessage (const int message, const float value, const MessageQueue::Data* const data, const uint32 flags)
{
CreatureObject * const owner = static_cast<CreatureObject*>(getOwner());
DEBUG_FATAL(!owner, ("Owner is NULL in CreatureController::handleMessage\n"));
switch(message)
{
case CM_netUpdateTransform:
{
// if the auth server sent this to us, forward it to clients
const MessageQueueDataTransform * const msg = NON_NULL (dynamic_cast<const MessageQueueDataTransform *>(data));
owner->setLookAtYaw(msg->getLookAtYaw(), msg->getUseLookAtYaw());
if (flags&GameControllerMessageFlags::SOURCE_REMOTE_SERVER)
{
// If we're not contained by what we are attached to, then transform
// updates are not relevant to clients because our position is
// dictated purely by our containing object.
if (owner->getAttachedTo() == ContainerInterface::getContainedByObject(*owner))
{
UpdateTransformMessage utm(owner->getNetworkId(), msg->getSequenceNumber(), msg->getTransform(), static_cast<int8>(msg->getSpeed()), msg->getLookAtYaw(), msg->getUseLookAtYaw());
owner->sendToClientsInUpdateRange(utm, flags & GameControllerMessageFlags::RELIABLE, false);
}
}
TangibleController::handleMessage(message, value, data, flags);
}
break;
case CM_netUpdateTransformWithParent:
{
// if the auth server sent this to us, forward it to clients
const MessageQueueDataTransformWithParent * const msg = NON_NULL (dynamic_cast<const MessageQueueDataTransformWithParent *>(data));
owner->setLookAtYaw(msg->getLookAtYaw(), msg->getUseLookAtYaw());
if (flags&GameControllerMessageFlags::SOURCE_REMOTE_SERVER)
{
// If we're not contained by what we are attached to, then transform
// updates are not relevant to clients because our position is
// dictated purely by our containing object.
if (owner->getAttachedTo() == ContainerInterface::getContainedByObject(*owner))
{
UpdateTransformWithParentMessage utm(owner->getNetworkId(), msg->getSequenceNumber(), msg->getParent(), msg->getTransform(), static_cast<int8>(msg->getSpeed()), msg->getLookAtYaw(), msg->getUseLookAtYaw());
owner->sendToClientsInUpdateRange(utm, flags & GameControllerMessageFlags::RELIABLE, false);
}
}
TangibleController::handleMessage(message, value, data, flags);
}
break;
case CM_clientResourceHarvesterActivate:
{
const MessageQueueNetworkId * const msg = NON_NULL (dynamic_cast<const MessageQueueNetworkId *>(data));
InstallationObject * const harvester = dynamic_cast<InstallationObject *>(ServerWorld::findObjectByNetworkId (msg->getNetworkId ()));
UNREF (harvester);
if (harvester && harvester->isOnAdminList(*owner))
harvester->activate (owner->getNetworkId());
}
break;
case CM_clientResourceHarvesterDeactivate:
{
const MessageQueueNetworkId * const msg = NON_NULL (dynamic_cast<const MessageQueueNetworkId *>(data));
InstallationObject * const harvester = dynamic_cast<InstallationObject *>(ServerWorld::findObjectByNetworkId (msg->getNetworkId ()));
if (harvester && harvester->isOnAdminList(*owner))
harvester->deactivate ();
}
break;
case CM_clientResourceHarvesterListen:
{
const MessageQueueNetworkId * const msg = NON_NULL (dynamic_cast<const MessageQueueNetworkId *>(data));
HarvesterInstallationObject * const harvester = dynamic_cast<HarvesterInstallationObject *>(ServerWorld::findObjectByNetworkId (msg->getNetworkId ()));
if (harvester && owner)
harvester->addSynchronizedUiClient (*owner);
}
break;
case CM_clientResourceHarvesterStopListening:
{
const MessageQueueNetworkId * const msg = NON_NULL (dynamic_cast<const MessageQueueNetworkId *>(data));
HarvesterInstallationObject * const harvester = dynamic_cast<HarvesterInstallationObject *>(ServerWorld::findObjectByNetworkId (msg->getNetworkId ()));
if (harvester && owner)
harvester->removeSynchronizedUiClient (owner->getNetworkId ());
}
break;
case CM_clientResourceHarvesterResourceSelect:
{
const MessageQueueNetworkIdPair * const msg = NON_NULL (dynamic_cast<const MessageQueueNetworkIdPair *>(data));
HarvesterInstallationObject * const harvester = dynamic_cast<HarvesterInstallationObject *>(ServerWorld::findObjectByNetworkId (msg->getFirstNetworkId ()));
harvester->selectResource (msg->getSecondNetworkId (), owner->getNetworkId());
}
break;
case CM_clientResourceHarvesterGetResourceData:
{
const MessageQueueNetworkId * const msg = NON_NULL (dynamic_cast<const MessageQueueNetworkId *>(data));
typedef stdvector<InstallationResourceData>::fwd DataVector;
DataVector dv;
HarvesterInstallationObject * const harvester = dynamic_cast<HarvesterInstallationObject *>(ServerWorld::findObjectByNetworkId (msg->getNetworkId ()));
ServerObject * const player = owner;
if (harvester && player)
{
harvester->getResourceData (dv);
if (!dv.empty ())
{
MessageQueueHarvesterResourceData * const newData = new MessageQueueHarvesterResourceData (msg->getNetworkId (), dv);
appendMessage(static_cast<int>(CM_clientResourceHarvesterResourceData), 0.0f, newData, GameControllerMessageFlags::SEND | GameControllerMessageFlags::RELIABLE | GameControllerMessageFlags::DEST_AUTH_CLIENT);
}
}
}
break;
case CM_clientResourceHarvesterEmptyHopper:
{
const MessageQueueResourceEmptyHopper * const msg = NON_NULL (dynamic_cast<const MessageQueueResourceEmptyHopper *>(data));
HarvesterInstallationObject * const harvester = dynamic_cast<HarvesterInstallationObject *>(ServerWorld::findObjectByNetworkId (msg->getHarvesterId ()));
if (harvester && owner && harvester->isOnHopperList(*owner))
harvester->emptyHopper (msg->getPlayerId(),msg->getResourceId(), msg->getAmount(),msg->getDiscard(),msg->getSequenceId());
}
break;
case CM_getTokenForObject:
{
WARNING_STRICT_FATAL(true, ("Received CM_getTokenForObject controller message. This message is depracated"));
}
break;
case CM_getWaypointForObject:
{
const MessageQueueNetworkId * const msg = NON_NULL (dynamic_cast<const MessageQueueNetworkId *>(data));
if(msg)
{
if(owner)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
const ServerObject * target = ServerWorld::findObjectByNetworkId(msg->getNetworkId());
if(target)
{
const Object * topMost = ContainerInterface::getFirstParentInWorld(*target);
if(topMost)
{
const Vector pos = topMost->getPosition_w();
IGNORE_RETURN(player->createWaypoint(Location(pos, NetworkId::cms_invalid, Location::getCrcBySceneName(ServerWorld::getSceneId())), true));
}
}
}
}
}
}
break;
case CM_secureTrade:
{
if (owner->isAuthoritative())
{
handleSecureTradeMessage(dynamic_cast<const MessageQueueSecureTrade *>(data));
}
// @todo else
//resend to auth
}
break;
case CM_clientLookAtTarget:
{
const MessageQueueNetworkId * const msg = NON_NULL (dynamic_cast<const MessageQueueNetworkId *>(data));
owner->setLookAtTarget (msg->getNetworkId ());
}
break;
case CM_clientIntendedTarget:
{
const MessageQueueNetworkId * const msg = NON_NULL (dynamic_cast<const MessageQueueNetworkId *>(data));
owner->setIntendedTarget (msg->getNetworkId ());
}
break;
case CM_clientMoodChange:
if (value < 0.0f || value > 255.0f)
WARNING (true, ("Out of range mood: %f", value));
else
owner->setMood (static_cast<uint32>(value));
break;
case CM_setState:
{
if (!(flags&GameControllerMessageFlags::SOURCE_REMOTE_CLIENT))
{
MessageQueueSetState const *msg = safe_cast<MessageQueueSetState const *>(data);
owner->setState(static_cast<States::Enumerator>(msg->getState()), msg->getValue());
}
}
break;
case CM_setAttribute:
{
const MessageQueueGenericValueType<std::pair<Attributes::Enumerator, Attributes::Value> > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<Attributes::Enumerator, Attributes::Value> > *>(data);
if(owner)
{
const std::pair<Attributes::Enumerator, Attributes::Value> & attributePair = msg->getValue();
if(msg)
{
owner->setAttribute(attributePair.first, attributePair.second);
}
DEBUG_WARNING(! msg, ("CreatureController (%s:%s) received a CM_setAttribute message but could not retrieve data from the message supplied", owner->getObjectTemplateName(), owner->getNetworkId().getValueString().c_str()));
}
}
break;
case CM_setMaxAttribute:
{
const MessageQueueGenericValueType<std::pair<Attributes::Enumerator, Attributes::Value> > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<Attributes::Enumerator, Attributes::Value> > *>(data);
// set the object value and send a message to all it's proxies
if(msg)
{
owner->setMaxAttribute(msg->getValue().first, msg->getValue().second);
}
DEBUG_WARNING(! msg, ("CreatureController (%s:%s) received a CM_setMaxAttribute message but could not retrieve data from the message supplied", owner->getObjectTemplateName(), owner->getNetworkId().getValueString().c_str()));
}
break;
case CM_setMentalState:
{
const MessageQueueGenericValueType<std::pair<MentalStates::Enumerator, MentalStates::Value> > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<MentalStates::Enumerator, MentalStates::Value> > *>(data);
// set the object value and send a message to all it's proxies
if(msg)
{
owner->setMentalState(msg->getValue().first, msg->getValue().second);
}
DEBUG_WARNING(! msg, ("CreatureController (%s:%s) received a CM_setMentalState message but could not retrieve data from the message supplied", owner->getObjectTemplateName(), owner->getNetworkId().getValueString().c_str()));
}
break;
case CM_setMentalStateToward:
{
const MessageQueueGenericValueType<std::pair<NetworkId, std::pair<MentalStates::Enumerator, MentalStates::Value> > > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<NetworkId, std::pair<MentalStates::Enumerator, MentalStates::Value> > > *>(data);
if(msg)
{
owner->setMentalStateToward(msg->getValue().first, msg->getValue().second.first, msg->getValue().second.second);
}
DEBUG_WARNING(! msg, ("CreatureController (%s:%s) received a CM_setMentalStateToward message but could not retrieve data from the message supplied", owner->getObjectTemplateName(), owner->getNetworkId().getValueString().c_str()));
}
break;
case CM_setCover:
{
const MessageQueueGenericValueType<int> * const msg = safe_cast<const MessageQueueGenericValueType<int> *>(data);
if(msg)
{
owner->setCover(msg->getValue());
}
DEBUG_WARNING(! msg, ("CreatureController (%s:%s) received a CM_setCover message but could not retrieve data from the message supplied", owner->getObjectTemplateName(), owner->getNetworkId().getValueString().c_str()));
}
break;
case CM_setMentalStateTowardClampBehavior:
{
const MessageQueueGenericValueType<std::pair<NetworkId, std::pair<MentalStates::Enumerator, std::pair<MentalStates::Value, Behaviors::Enumerator> > > > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<NetworkId, std::pair<MentalStates::Enumerator, std::pair<MentalStates::Value, Behaviors::Enumerator> > > > *>(data);
if(msg)
{
owner->setMentalStateTowardClampBehavior(
msg->getValue().first,
msg->getValue().second.first,
msg->getValue().second.second.first,
msg->getValue().second.second.second);
}
DEBUG_WARNING(! msg, ("CreatureController (%s:%s) received a CM_setMentalStateTowardClampBehavior message but could not retrieve data from the message supplied", owner->getObjectTemplateName(), owner->getNetworkId().getValueString().c_str()));
}
break;
case CM_setMaxMentalState:
{
const MessageQueueGenericValueType<std::pair<MentalStates::Enumerator, MentalStates::Value> > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<MentalStates::Enumerator, MentalStates::Value> > *>(data);
if(msg)
{
owner->setMaxMentalState(msg->getValue().first, msg->getValue().second);
}
DEBUG_WARNING(! msg, ("CreatureController (%s:%s) received a CM_setMaxMentalState message but could not retrieve data from the message supplied", owner->getObjectTemplateName(), owner->getNetworkId().getValueString().c_str()));
}
break;
case CM_setMentalStateDecay:
{
const MessageQueueGenericValueType<std::pair<MentalStates::Enumerator, float> > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<MentalStates::Enumerator, float> > *>(data);
if(msg)
{
owner->setMentalStateDecay(msg->getValue().first, msg->getValue().second);
}
DEBUG_WARNING(! msg, ("CreatureController (%s:%s) received a CM_setMentalStateDecay message but could not retrieve data from the message supplied", owner->getObjectTemplateName(), owner->getNetworkId().getValueString().c_str()));
}
break;
case CM_setPosture:
{
const MessageQueuePosture * const msg = safe_cast<const MessageQueuePosture *>(data);
if(msg)
{
owner->setPosture(msg->getPosture(), msg->isClientImmediate());
}
DEBUG_WARNING(! msg, ("CreatureController (%s:%s) received a CM_setPosture message but could not retrieve data from the message supplied", owner->getObjectTemplateName(), owner->getNetworkId().getValueString().c_str()));
}
break;
case CM_setLocomotion:
{
const MessageQueueGenericValueType<Locomotions::Enumerator> * const msg = safe_cast<const MessageQueueGenericValueType<Locomotions::Enumerator> *>(data);
if(msg)
{
owner->setLocomotion(msg->getValue());
}
DEBUG_WARNING(! msg, ("CreatureController (%s:%s) received a CM_setLocomotion message but could not retrieve data from the message supplied", owner->getObjectTemplateName(), owner->getNetworkId().getValueString().c_str()));
}
break;
case CM_setGroupInviter:
{
const MessageQueueGenericValueType<std::pair<std::string, std::pair<NetworkId, NetworkId> > > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<std::string, std::pair<NetworkId, NetworkId> > > *>(data);
if (msg)
{
owner->setGroupInviter(msg->getValue().second.first, msg->getValue().first, msg->getValue().second.second);
}
}
break;
case CM_setPerformanceType:
{
const MessageQueueGenericValueType<int> * const msg = safe_cast<const MessageQueueGenericValueType<int> *>(data);
if (msg)
{
owner->setPerformanceType(msg->getValue());
}
}
break;
case CM_setPerformanceStartTime:
{
const MessageQueueGenericValueType<int> * const msg = safe_cast<const MessageQueueGenericValueType<int> *>(data);
if (msg)
{
owner->setPerformanceStartTime(msg->getValue());
}
}
break;
case CM_setPerformanceListenTarget:
{
const MessageQueueGenericValueType<NetworkId> * const msg = safe_cast<const MessageQueueGenericValueType<NetworkId> *>(data);
if (msg)
{
owner->setPerformanceListenTarget(msg->getValue());
}
}
break;
case CM_setPerformanceWatchTarget:
{
const MessageQueueGenericValueType<NetworkId> * const msg = safe_cast<const MessageQueueGenericValueType<NetworkId> *>(data);
if (msg)
{
owner->setPerformanceWatchTarget(msg->getValue());
}
}
break;
case CM_setModValue:
{
const
MessageQueueGenericValueType<std::pair<std::string, int> > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<std::string, int> > *>(data);
if(msg)
{
owner->setModValue(msg->getValue().first, msg->getValue().second);
}
}
break;
case CM_grantCommand:
{
const MessageQueueGenericValueType<std::string> * const msg = safe_cast<const MessageQueueGenericValueType<std::string> *>(data);
if(msg)
{
owner->grantCommand(msg->getValue(), false);
}
}
break;
case CM_grantExperiencePoints:
{
const MessageQueueGenericValueType<std::pair<std::string, int> > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<std::string, int> > *>(data);
if(msg)
{
owner->grantExperiencePoints(msg->getValue().first, msg->getValue().second);
}
}
break;
case CM_incrementKillMeter:
{
const MessageQueueGenericValueType<int> * const msg = safe_cast<const MessageQueueGenericValueType<int> *>(data);
if(msg)
{
owner->incrementKillMeter(msg->getValue());
}
}
break;
case CM_grantSkill:
{
const MessageQueueGenericValueType<std::string> * const msg = safe_cast<const MessageQueueGenericValueType<std::string> *>(data);
if(msg)
{
const SkillObject * newSkill = SkillManager::getInstance().getSkill(msg->getValue());
if(newSkill)
{
owner->grantSkill(*newSkill);
}
}
}
break;
case CM_revokeCommand:
{
const MessageQueueGenericValueType<std::string> * const msg = safe_cast<const MessageQueueGenericValueType<std::string> *>(data);
if(msg)
{
owner->revokeCommand(msg->getValue(), false);
}
}
break;
case CM_revokeSkill:
{
const MessageQueueGenericValueType<std::string> * const msg = safe_cast<const MessageQueueGenericValueType<std::string> *>(data);
if(msg)
{
const SkillObject * oldSkill = SkillManager::getInstance().getSkill(msg->getValue());
if(oldSkill)
{
LOG("CustomerService", ("Skill: Removing skill %s from character %s via controller message.",
msg->getValue().c_str(), owner->getNetworkId().getValueString().c_str()));
owner->revokeSkill(*oldSkill);
}
}
}
break;
case CM_alterAttribute:
{
const MessageQueueAlterAttribute * const msg = safe_cast<const MessageQueueAlterAttribute *>(data);
if(msg)
{
owner->alterAttribute(msg->getAttrib(),
msg->getDelta(),
msg->getCheckIncapacitation(),
msg->getSource()
);
}
}
break;
case CM_addAttributeModifier:
{
const MessageQueueGenericValueType<AttribMod::AttribMod> * const msg = safe_cast<const MessageQueueGenericValueType<AttribMod::AttribMod> *>(data);
if(msg)
{
owner->addAttributeModifier(msg->getValue());
}
}
break;
case CM_removeAttributeModifiers:
{
const MessageQueueGenericValueType<Attributes::Enumerator> * const msg = safe_cast<const MessageQueueGenericValueType<Attributes::Enumerator> *>(data);
if(msg)
{
owner->removeAttributeModifiers(msg->getValue());
}
}
break;
case CM_removeAllAttributeModifiers:
{
owner->removeAllAttributeModifiers();
}
break;
case CM_removeAllAttributeAndSkillmodModifiers:
{
owner->removeAllAttributeAndSkillmodMods();
}
break;
case CM_setCurrentWeapon:
{
const MessageQueueGenericValueType<NetworkId> * const msg = safe_cast<const MessageQueueGenericValueType<NetworkId> *>(data);
if(msg)
{
WeaponObject * weapon = safe_cast<WeaponObject *>(NetworkIdManager::getObjectById(msg->getValue()));
if(weapon)
owner->setCurrentWeapon(*weapon);
}
}
break;
case CM_setGroup:
{
const MessageQueueGenericValueType<std::pair<bool, NetworkId> > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<bool, NetworkId> > *>(data);
if(msg)
{
GroupObject * group = safe_cast<GroupObject *>(NetworkIdManager::getObjectById(msg->getValue().second));
if (group)
{
owner->setGroup(group, msg->getValue().first);
}
else if (!msg->getValue().second.isValid())
{
if (owner->getGroup())
owner->getGroup()->onGroupMemberRemoved(owner->getNetworkId(), msg->getValue().first);
}
}
}
break;
case CM_setIncapacitated:
{
const MessageQueueGenericValueType<std::pair<bool, NetworkId> > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<bool, NetworkId> > *>(data);
if (msg != NULL)
owner->setIncapacitated(msg->getValue().first, msg->getValue().second);
}
break;
case CM_setSayMode:
{
const MessageQueueGenericValueType<unsigned long> * const msg = safe_cast<const MessageQueueGenericValueType<unsigned long> *>(data);
if(msg)
{
owner->setSayMode(msg->getValue());
}
}
break;
case CM_setAnimationMood:
{
const MessageQueueGenericValueType<std::string> * const msg = safe_cast<const MessageQueueGenericValueType<std::string> *>(data);
if(msg)
{
owner->setAnimationMood(msg->getValue());
}
}
break;
case CM_setScaleFactor:
{
const MessageQueueGenericValueType<float> * const msg = safe_cast<const MessageQueueGenericValueType<float> *>(data);
if(msg)
{
owner->setScaleFactor(msg->getValue());
}
}
break;
case CM_setShockWounds:
{
const MessageQueueGenericValueType<int> * const msg = safe_cast<const MessageQueueGenericValueType<int> *>(data);
if(msg)
{
owner->setShockWounds(msg->getValue());
}
}
break;
case CM_setLookAtTarget:
{
const MessageQueueGenericValueType<NetworkId> * const msg = safe_cast<const MessageQueueGenericValueType<NetworkId> *>(data);
if(msg)
{
owner->setLookAtTarget(msg->getValue());
}
}
break;
case CM_setIntendedTarget:
{
const MessageQueueGenericValueType<NetworkId> * const msg = safe_cast<const MessageQueueGenericValueType<NetworkId> *>(data);
if(msg)
{
owner->setIntendedTarget(msg->getValue());
}
}
break;
case CM_setMovementStationary:
{
owner->setMovementStationary();
}
break;
case CM_setMovementWalk:
{
owner->setMovementWalk();
}
break;
case CM_setMovementRun:
{
owner->setMovementRun();
}
break;
case CM_setSlopeModAngle:
{
const MessageQueueGenericValueType<float> * const msg = safe_cast<const MessageQueueGenericValueType<float> *>(data);
if(msg)
{
owner->setSlopeModAngle(msg->getValue());
}
}
break;
case CM_setSlopeModPercent:
{
const MessageQueueGenericValueType<float> * const msg = safe_cast<const MessageQueueGenericValueType<float> *>(data);
if(msg)
{
owner->setSlopeModPercent(msg->getValue());
}
}
break;
case CM_setWaterModPercent:
{
const MessageQueueGenericValueType<float> * const msg = safe_cast<const MessageQueueGenericValueType<float> *>(data);
if(msg)
{
owner->setWaterModPercent(msg->getValue());
}
}
break;
case CM_setMovementScale:
{
const MessageQueueGenericValueType<float> * const msg = safe_cast<const MessageQueueGenericValueType<float> *>(data);
if(msg)
{
owner->setMovementScale(msg->getValue());
}
}
break;
case CM_setMovementPercent:
{
const MessageQueueGenericValueType<float> * const msg = safe_cast<const MessageQueueGenericValueType<float> *>(data);
if(msg)
{
owner->setMovementPercent(msg->getValue());
}
}
break;
case CM_setTurnPercent:
{
const MessageQueueGenericValueType<float> * const msg = safe_cast<const MessageQueueGenericValueType<float> *>(data);
if(msg)
{
owner->setTurnPercent(msg->getValue());
}
}
break;
case CM_setAccelScale:
{
const MessageQueueGenericValueType<float> * const msg = safe_cast<const MessageQueueGenericValueType<float> *>(data);
if(msg)
{
owner->setAccelScale(msg->getValue());
}
}
break;
case CM_setAccelPercent:
{
const MessageQueueGenericValueType<float> * const msg = safe_cast<const MessageQueueGenericValueType<float> *>(data);
if(msg)
{
owner->setAccelPercent(msg->getValue());
}
}
break;
case CM_sitOnObject:
{
const MessageQueueSitOnObject * const msg = safe_cast<const MessageQueueSitOnObject *>(data);
if(msg)
{
owner->sitOnObject(msg->getChairCellId(), msg->getChairPosition_p());
}
}
break;
case CM_setMasterId:
{
const MessageQueueGenericValueType<NetworkId> * const msg = safe_cast<const MessageQueueGenericValueType<NetworkId> *>(data);
if (msg)
{
owner->setMasterId(msg->getValue());
}
}
break;
case CM_setHouse:
{
const MessageQueueGenericValueType<NetworkId> * const msg = safe_cast<const MessageQueueGenericValueType<NetworkId> *>(data);
if (msg)
{
owner->setHouse(CachedNetworkId(msg->getValue()));
}
}
break;
case CM_setDifficulty:
case CM_setLevel:
{
MessageQueueGenericValueType<int> const *msg = safe_cast<MessageQueueGenericValueType<int> const *>(data);
if (msg)
owner->setLevel(static_cast<int16>(msg->getValue()));
}
break;
case CM_recalculateLevel:
{
MessageQueueGenericValueType<int> const *msg = safe_cast<MessageQueueGenericValueType<int> const *>(data);
if (msg)
owner->recalculateLevel();
}
break;
case CM_creatureSetBaseWalkSpeed:
owner->setBaseWalkSpeed(value);
break;
case CM_creatureSetBaseRunSpeed:
owner->setBaseRunSpeed(value);
break;
case CM_emergencyDismountForRider:
owner->emergencyDismountForRider();
break;
case CM_detachRiderForMount:
{
typedef MessageQueueGenericValueType<NetworkId> Message;
Message const * const msg = safe_cast<Message const *>(data);
if (msg != 0)
{
owner->detachRider(msg->getValue());
}
break;
}
case CM_detachAllRidersForMount:
owner->detachAllRiders();
break;
case CM_setAppearanceFromObjectTemplate:
{
MessageQueueGenericValueType<std::string> const *const msg = dynamic_cast<MessageQueueGenericValueType<std::string> const *>(data);
if (owner && msg)
owner->setAlternateAppearance(msg->getValue());
else
WARNING(true, ("CreatureController: received CM_setAppearanceFromObjectTemplate but owner or message was NULL."));
}
break;
case CM_makeDead:
{
const MessageQueueGenericValueType<std::pair<NetworkId, NetworkId> > * msg = dynamic_cast<const MessageQueueGenericValueType<std::pair<NetworkId, NetworkId> > *>(data);
if (msg)
{
owner->makeDead(msg->getValue().first, msg->getValue().second);
}
}
break;
case CM_pushCreature:
{
const MessageQueuePushCreature * const msg = safe_cast<const MessageQueuePushCreature *>(data);
if (msg)
{
ServerObject * defender = safe_cast<ServerObject *>(NetworkIdManager::getObjectById(msg->getDefender()));
if (defender != NULL)
{
if (defender->asCreatureObject() != NULL)
{
defender->asCreatureObject()->pushedMe(msg->getAttacker(), msg->getAttackerPos(), msg->getDefenderPos(), msg->getDistance());
}
else
{
WARNING(true, ("Received MessageQueuePushCreature for non-creature defender %s", msg->getDefender().getValueString().c_str()));
}
}
}
}
break;
case CM_slowDownEffect:
{
const MessageQueueSlowDownEffect * const msg = safe_cast<const MessageQueueSlowDownEffect * const>(data);
if (msg)
{
ServerObject * target = safe_cast<ServerObject *>(NetworkIdManager::getObjectById(msg->getTarget()));
if (target != NULL && target->asTangibleObject() != NULL)
{
if (owner->isAuthoritative())
owner->addSlowDownEffect(*(target->asTangibleObject()), msg->getConeLength(), msg->getConeAngle(), msg->getSlopeAngle(), msg->getExpireTime());
else
owner->addSlowDownEffectProxy(*(target->asTangibleObject()), msg->getConeLength(), msg->getConeAngle(), msg->getSlopeAngle(), msg->getExpireTime());
}
else
{
WARNING(true, ("Received slow down effect messge for creature %s "
"with unknown target %s",
owner->getNetworkId().getValueString().c_str(),
msg->getTarget().getValueString().c_str()));
}
}
}
break;
case CM_removeSlowDownEffect:
{
if (owner->isAuthoritative())
owner->removeSlowDownEffect();
else
{
WARNING(true, ("CM_removeSlowDownEffect message recieved by proxy object %s", owner->getNetworkId().getValueString().c_str()));
}
}
break;
case CM_removeSlowDownEffectProxy:
{
if (!owner->isAuthoritative())
owner->removeSlowDownEffectProxy();
else
{
WARNING(true, ("CM_removeSlowDownEffectProxy message recieved by authoritative object %s", owner->getNetworkId().getValueString().c_str()));
}
}
break;
case CM_groupLotteryWindowCloseResults:
{
typedef std::pair<NetworkId, std::vector<NetworkId> > Payload;
MessageQueueGenericValueType<Payload> const * const msg = safe_cast<MessageQueueGenericValueType<Payload> const *>(data);
if (msg != 0)
{
Payload const & incomingPayload = msg->getValue();
typedef std::vector<NetworkId> Ids;
NetworkId const & player = incomingPayload.first;
Ids const & selectedItems = incomingPayload.second;
GameScriptObject * const scriptObject = owner->getScriptObject();
if (scriptObject != 0)
{
ScriptParams params;
params.addParam(player);
params.addParam(selectedItems);
IGNORE_RETURN(scriptObject->trigAllScripts(Scripting::TRIG_LOOT_LOTTERY_SELECTED, params));
}
}
}
break;
case CM_cyberneticsChangeRequestToNPC:
{
MessageQueueCyberneticsChangeRequest const * const msg = safe_cast<MessageQueueCyberneticsChangeRequest const *>(data);
NOT_NULL(msg);
if (msg != NULL)
{
NetworkId const & playerId = msg->getTarget();
GameScriptObject * const scriptObject = owner->getScriptObject();
if (scriptObject)
{
ScriptParams params;
params.addParam(playerId);
params.addParam(static_cast<int>(msg->getChangeType()));
params.addParam(msg->getCyberneticPiece());
IGNORE_RETURN(scriptObject->trigAllScripts(Scripting::TRIG_CYBERNETIC_CHANGE_REQUEST, params));
}
}
}
break;
case CM_setCurrentQuest:
{
MessageQueueGenericValueType<uint32> const * const msg = safe_cast<MessageQueueGenericValueType<uint32> const *>(data);
if (msg != NULL)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if (player != NULL)
{
player->setCurrentQuest(msg->getValue());
}
else
{
DEBUG_WARNING(true, ("Non-player creature %s sent CM_setCurrentQuest message (%u)",
owner->getNetworkId().getValueString().c_str(), msg->getValue()));
}
}
}
break;
case CM_setRegenRate:
{
MessageQueueGenericValueType<std::pair<int, float> > const * const msg = safe_cast<MessageQueueGenericValueType<std::pair<int, float> > const *>(data);
if (msg != NULL)
{
owner->setRegenRate(static_cast<Attributes::Enumerator>(msg->getValue().first), msg->getValue().second);
}
}
break;
case CM_modifyCurrentGcwPoints:
{
const MessageQueueGenericValueType<std::pair<int, int> > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<int, int> > *>(data);
if(msg)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->modifyCurrentGcwPoints(msg->getValue().first, (msg->getValue().second != 0));
}
}
}
break;
case CM_modifyCurrentGcwRating:
{
const MessageQueueGenericValueType<std::pair<int, int> > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<int, int> > *>(data);
if(msg)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->modifyCurrentGcwRating(msg->getValue().first, (msg->getValue().second != 0));
}
}
}
break;
case CM_modifyCurrentPvpKills:
{
const MessageQueueGenericValueType<std::pair<int, int> > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<int, int> > *>(data);
if(msg)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->modifyCurrentPvpKills(msg->getValue().first, (msg->getValue().second != 0));
}
}
}
break;
case CM_modifyLifetimeGcwPoints:
{
const MessageQueueGenericValueType<int> * const msg = safe_cast<const MessageQueueGenericValueType<int> *>(data);
if(msg)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->modifyLifetimeGcwPoints(msg->getValue());
}
}
}
break;
case CM_modifyMaxGcwImperialRating:
{
const MessageQueueGenericValueType<int> * const msg = safe_cast<const MessageQueueGenericValueType<int> *>(data);
if(msg)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->modifyMaxGcwImperialRating(msg->getValue());
}
}
}
break;
case CM_modifyMaxGcwRebelRating:
{
const MessageQueueGenericValueType<int> * const msg = safe_cast<const MessageQueueGenericValueType<int> *>(data);
if(msg)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->modifyMaxGcwRebelRating(msg->getValue());
}
}
}
break;
case CM_modifyLifetimePvpKills:
{
const MessageQueueGenericValueType<int> * const msg = safe_cast<const MessageQueueGenericValueType<int> *>(data);
if(msg)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->modifyLifetimePvpKills(msg->getValue());
}
}
}
break;
case CM_modifyNextGcwRatingCalcTime:
{
const MessageQueueGenericValueType<int> * const msg = safe_cast<const MessageQueueGenericValueType<int> *>(data);
if(msg)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->modifyNextGcwRatingCalcTime(msg->getValue());
}
}
}
break;
case CM_customizeFinished:
{
typedef std::pair<NetworkId, std::string > Payload;
MessageQueueGenericValueType<Payload> const * const msg = safe_cast<MessageQueueGenericValueType<Payload> const *>(data);
if (msg != 0)
{
Payload const & incomingPayload = msg->getValue();
NetworkId const & object = incomingPayload.first;
std::string const & msgValue = incomingPayload.second;
GameScriptObject * const scriptObject = owner->getScriptObject();
if (scriptObject != 0)
{
ScriptParams params;
params.addParam(object);
params.addParam(msgValue.c_str());
IGNORE_RETURN(scriptObject->trigAllScripts(Scripting::TRIG_ON_CUSTOMIZE_FINISHED, params));
}
}
}
break;
case CM_clearSessionActivity:
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->clearSessionActivity();
}
}
break;
case CM_addSessionActivity:
{
const MessageQueueGenericValueType<unsigned long> * const msg = safe_cast<const MessageQueueGenericValueType<unsigned long> *>(data);
if(msg)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->addSessionActivity(static_cast<uint32>(msg->getValue()));
}
}
}
break;
case CM_modifyHologramType:
{
MessageQueueGenericValueType<int32> const *msg = safe_cast<MessageQueueGenericValueType<int32> const *>(data);
if (msg)
owner->setHologramType(msg->getValue());
}
break;
case CM_modifyVisibleOnMapAndRadar:
{
MessageQueueGenericValueType<bool> const *msg = safe_cast<MessageQueueGenericValueType<bool> const *>(data);
if (msg)
owner->setVisibleOnMapAndRadar(msg->getValue());
}
break;
case CM_setCoverVisibility:
{
const MessageQueueGenericValueType<bool> * const msg = safe_cast<const MessageQueueGenericValueType<bool> *>(data);
if (msg)
{
owner->setCoverVisibility(msg->getValue());
}
}
break;
case CM_incubatorCancel:
{
IncubatorCommitMessage const * const msg = safe_cast<IncubatorCommitMessage const *>(data);
if (msg)
{
ServerObject * incubatorSo = ServerWorld::findObjectByNetworkId(msg->getTerminalId());
if (incubatorSo)
{
TangibleObject * incubatorTo = incubatorSo->asTangibleObject();
if (incubatorTo)
incubatorTo->handleIncubatorCancel(*owner);
}
}
}
break;
case CM_incubatorCommit:
{
IncubatorCommitMessage const * const msg = safe_cast<IncubatorCommitMessage const *>(data);
if (msg)
{
ServerObject * incubatorSo = ServerWorld::findObjectByNetworkId(msg->getTerminalId());
if (incubatorSo)
{
TangibleObject * incubatorTo = incubatorSo->asTangibleObject();
if (incubatorTo)
incubatorTo->handleIncubatorCommit(*owner, *msg);
}
}
}
break;
case CM_modifyCollectionSlotValue:
{
const MessageQueueGenericValueType<std::pair<std::string, int64> > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<std::string, int64> > *>(data);
if(msg)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->modifyCollectionSlotValue(msg->getValue().first, msg->getValue().second);
}
}
}
break;
case CM_adjustLotCount:
{
const MessageQueueGenericValueType<int> * const msg = safe_cast<const MessageQueueGenericValueType<int> *>(data);
if(msg)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->adjustLotCount(msg->getValue());
}
}
}
break;
case CM_squelch:
{
const MessageQueueGenericValueType<std::pair<std::string, std::pair<NetworkId, int> > > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<std::string, std::pair<NetworkId, int> > > *>(data);
if(msg)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->squelch(msg->getValue().second.first, msg->getValue().first, msg->getValue().second.second);
}
}
}
break;
case CM_unsquelch:
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->unsquelch();
}
}
break;
case CM_setPriviledgedTitle:
{
const MessageQueueGenericValueType<int> * const msg = safe_cast<const MessageQueueGenericValueType<int> *>(data);
if(msg)
{
PlayerObject * player = PlayerCreatureController::getPlayerObject(owner);
if(player)
{
player->setPriviledgedTitle(static_cast<int8>(msg->getValue()));
}
}
}
break;
case CM_addBuff:
{
const MessageQueueGenericValueType<std::pair<int, std::pair<float, std::pair<float, std::pair< float, NetworkId > > > > > * const msg = safe_cast<const MessageQueueGenericValueType<std::pair<int, std::pair<float, std::pair<float, std::pair< float, NetworkId > > > > > *>(data);
if(msg)
{
owner->addBuff (static_cast<uint32>(msg->getValue ().first), msg->getValue ().second.first, msg->getValue ().second.second.first, msg->getValue ().second.second.second.first, msg->getValue ().second.second.second.second);
}
}
break;
case CM_removeBuff:
{
const MessageQueueGenericValueType<int> * const msg = safe_cast<const MessageQueueGenericValueType<int> * >(data);
if(msg)
{
owner->removeBuff (static_cast<uint32>(msg->getValue ()));
}
}
break;
case CM_ratingFinished:
{
const MessageQueueGenericValueType<int> * const msg = safe_cast<const MessageQueueGenericValueType<int> * >(data);
if(msg)
{
if(owner->getScriptObject())
{
ScriptParams params;
params.addParam(msg->getValue());
IGNORE_RETURN(owner->getScriptObject()->trigAllScripts(Scripting::TRIG_ON_RATING_FINISHED, params));
}
}
}
break;
case CM_abandonPlayerQuest:
{
const MessageQueueGenericValueType<NetworkId> * const msg = safe_cast<const MessageQueueGenericValueType<NetworkId> * >(data);
if(msg)
{
if(owner->getScriptObject())
{
ScriptParams params;
params.addParam(msg->getValue());
IGNORE_RETURN(owner->getScriptObject()->trigAllScripts(Scripting::TRIG_ON_ABANDON_PLAYER_QUEST, params));
}
}
}
break;
default:
TangibleController::handleMessage(message, value, data, flags);
break;
}
}
//-----------------------------------------------------------------------
float CreatureController::realAlter(float time)
{
PROFILER_AUTO_BLOCK_DEFINE("CreatureController::realAlter");
float alterResult = TangibleController::realAlter(time);
CreatureObject * const owner = NON_NULL(getCreature());
if(getHibernate())
return alterResult;
if (owner->isAuthoritative())
owner->decayAttributes(time);
if (owner->isInWorld())
{
bool isBurning = false;
float lavaResistance = 0.0f;
if (owner->isAuthoritative())
{
//owner->decayMentalStates(time);
owner->reportMonitoredCreatures(time);
//-- Handle swimming state.
bool const currentSwimState = owner->getState(States::Swimming);
bool newSwimState = false;
float waterHeight = 0.0f;
calculateWaterState(newSwimState,isBurning,lavaResistance,waterHeight);
bool const isVehicle = GameObjectTypes::isTypeOf (owner->getGameObjectType (), static_cast<int>(SharedObjectTemplate::GOT_vehicle));
if(!isVehicle) // make everything but vehicles walk on lava
{
const Vector & position = owner->getPosition_w ();
Footprint *const footprint = owner->getFootprint();
if(footprint)
{
if(isBurning)
{
footprint->setSwimHeight(owner->getSwimHeight() * 0.2f);
owner->move_p(Vector::unitY * (waterHeight - position.y));
}
else
{
footprint->setSwimHeight(owner->getSwimHeight());
}
}
}
if (currentSwimState && !newSwimState)
{
// We've just detected that the owner stopped swimming.
onExitSwimming();
}
else if (!currentSwimState && newSwimState)
{
// We've just detected that the owner started swimming.
onEnterSwimming();
}
setObjectStopWalkRun();
}
CollisionProperty *const collisionProperty = owner->getCollisionProperty();
if (owner->getState(States::RidingMount))
{
// Tell the rider's CollisionProperty to update its extent. Since
// the rider is yanked out of the CollisionWorld, the
// CollisionProperty doesn't get updated properly. Failure to
// update the rider's CollisionProperty extent causes line of sight
// to fail (line of sight ends up using the value present in CollisionProperty
// at the time of mounting).
if (collisionProperty)
collisionProperty->updateExtents();
}
const bool isPlayerControlled = (collisionProperty && collisionProperty->isPlayerControlled());
// lava damage
if(WaterTypeManager::getCausesDamage(TGWT_lava)
&& isBurning
&& (isPlayerControlled || owner->isBeast())
)
{
const unsigned long serverTime = ServerClock::getInstance().getGameTimeSeconds();
const unsigned long lastBurnTime = owner->getLastWaterDamageTime();
const unsigned long waterDamageInterval = WaterTypeManager::getDamageInterval(TGWT_lava);
if(serverTime - lastBurnTime > (waterDamageInterval*3)) // skip the first lava damage frame
{
owner->setLastWaterDamageTime(serverTime - waterDamageInterval);
//DEBUG_WARNING(true,("LAVA DAMAGE SLUSH TIME- serverTime=%ul, lastBurnTime=%ul, diff=%d",serverTime,lastBurnTime,serverTime-lastBurnTime));
}
else if(serverTime - lastBurnTime > waterDamageInterval && !owner->isDead())
{
owner->setLastWaterDamageTime(serverTime);
const float percentWaterDamagePerInterval = WaterTypeManager::getDamagePerInterval(TGWT_lava)/100.0f;
const float lavaResistanceModifier = 1.0f - lavaResistance/100.0f;
const int damageValue =
static_cast<int> (
-( owner->getMaxAttribute(Attributes::Health)
* percentWaterDamagePerInterval
* lavaResistanceModifier
)
);
StringId stringId = StringId("combat_effects", "environment_damage_lava");
owner->showFlyText(stringId,5.0f,255,0,0);
if(WaterTypeManager::getDamageKills(TGWT_lava)
&& (owner->getAttribute(Attributes::Health) + damageValue) <= 0)
{
owner->makeDead(NetworkId::cms_invalid, NetworkId::cms_invalid);
ScriptParams params;
owner->getScriptObject()->trigAllScripts(Scripting::TRIG_ENVIRONMENTAL_DEATH,params);
}
else
{
CombatEngineData::DamageData damageData;
struct AttribMod::AttribMod damage;
damage.tag = 0;
damage.attrib = Attributes::Health;
damage.attack = 0;
damage.sustain = 0;
damage.decay = AttribMod::AMDS_pool;
damage.flags = AttribMod::AMF_directDamage;
damage.value = damageValue;
damageData.damage.push_back(damage);
owner->applyDamage(damageData);
}
}
}
}
return alterResult;
}
// ----------------------------------------------------------------------
void CreatureController::conclude()
{
PROFILER_AUTO_BLOCK_DEFINE("CreatureController::conclude");
MessageQueue::Data* data;
int message;
real value;
uint32 flags;
NetworkId networkId;
int const messageCount = getNumberOfMessages();
for(int i = 0; i < messageCount; ++i)
{
//-- Get the message.
getMessage(i, &message, &value, &data, &flags); //@todo why does getMessage need a signed size?
if(message == CM_combatAction)
{
//-- Check if it's a combat action message. If so, the message's end postures for the
// combatants must be adjusted to reflect the server's idea of the post-alter end posture.
// This information was not known at the time the message was constructed.
MessageQueueCombatAction * combatMessage = safe_cast<MessageQueueCombatAction *>(data);
if (combatMessage != NULL)
{
//-- Fix up end postures in messages.
// @todo: change postures to locomotion
// set the attacker's posture
MessageQueueCombatAction::AttackerData & attackerData =
const_cast<MessageQueueCombatAction::AttackerData &>(
combatMessage->getAttacker());
const CreatureObject * attacker = dynamic_cast<const CreatureObject *>(
NetworkIdManager::getObjectById(attackerData.id));
attackerData.endPosture = (attacker != NULL) ? attacker->getPosture() : static_cast<Postures::Enumerator>(0);
// set the defenders' posture
const MessageQueueCombatAction::DefenderDataVector & defenderData =
combatMessage->getDefenders();
for (MessageQueueCombatAction::DefenderDataVector::const_iterator
iter(defenderData.begin()); iter != defenderData.end(); ++iter)
{
MessageQueueCombatAction::DefenderData & defenderData =
const_cast<MessageQueueCombatAction::DefenderData &>(*iter);
const CreatureObject * defender = dynamic_cast<const CreatureObject *>(
NetworkIdManager::getObjectById(defenderData.id));
defenderData.endPosture = (defender != NULL) ? defender->getPosture() : static_cast<Postures::Enumerator>(0);
}
}
}
}
CreatureObject * const owner = static_cast<CreatureObject*>(getOwner());
if(owner)
{
owner->checkNotifyRegions();
}
//-- Chain up to parent controller.
TangibleController::conclude();
}
//--------------------------------------------------------------------
void CreatureController::setObjectStopWalkRun()
{
float vel = getCurrentVelocity().magnitude();
CreatureObject* owner = static_cast<CreatureObject *>(getOwner());
float walkSpeed = owner->getWalkSpeed();
float runSpeed = owner->getRunSpeed();
if (vel == 0)
owner->setMovementStationary();
else if (runSpeed == 0 || (vel < (walkSpeed + runSpeed) * 0.5f))
owner->setMovementWalk();
else
owner->setMovementRun();
}
//----------------------------------------------------------------------
void CreatureController::setOwner(Object *newOwner)
{
NOT_NULL(safe_cast<CreatureObject*>(newOwner));
Controller::setOwner(newOwner);
}
// ----------------------------------------------------------------------
void CreatureController::setSecureTrade(ServerSecureTrade * t)
{
m_secureTrade = t;
}
//----------------------------------------------------------
ServerSecureTrade* CreatureController::getSecureTrade() const
{
return m_secureTrade;
}
//----------------------------------------------------------
void CreatureController::handleSecureTradeMessage(const MessageQueueSecureTrade * data)
{
if (!data)
return;
CreatureObject * owner = getCreature();
NOT_NULL(owner);
switch (data->getTradeMessageId())
{
case MessageQueueSecureTrade::TMI_RequestTrade:
{
if (data->getRecipient() == owner->getNetworkId())
{
DEBUG_REPORT_LOG(true, ("Creature %s tried to trade with himself.", getOwner()->getNetworkId().getValueString().c_str()));
return;
}
if (m_secureTrade)
{
DEBUG_REPORT_LOG(true, ("Creature %s is already trading\n", getOwner()->getNetworkId().getValueString().c_str()));
return;
}
CreatureObject * recipient = dynamic_cast<CreatureObject*>(ServerWorld::findObjectByNetworkId(data->getRecipient()));
if (!recipient)
{
DEBUG_REPORT_LOG(true, ("Could not find recipient for secure trade message\n"));
MessageQueueSecureTrade * m = new MessageQueueSecureTrade(MessageQueueSecureTrade::TMI_DeniedPlayerUnreachable, owner->getNetworkId(), data->getRecipient());
appendMessage(static_cast<int>(CM_secureTrade), 0.0f, m, GameControllerMessageFlags::SEND | GameControllerMessageFlags::RELIABLE | GameControllerMessageFlags::DEST_AUTH_CLIENT);
return;
}
if (owner->isIncapacitated() || owner->isDead())
{
DEBUG_REPORT_LOG(true, ("Owner creature %s is incapacitated or dead.\n", getOwner()->getNetworkId().getValueString().c_str()));
MessageQueueSecureTrade * m = new MessageQueueSecureTrade(MessageQueueSecureTrade::TMI_DeniedPlayerUnreachable, owner->getNetworkId(), data->getRecipient());
appendMessage(static_cast<int>(CM_secureTrade), 0.0f, m, GameControllerMessageFlags::SEND | GameControllerMessageFlags::RELIABLE | GameControllerMessageFlags::DEST_AUTH_CLIENT);
return;
}
else if (recipient->isIncapacitated() || recipient->isDead())
{
DEBUG_REPORT_LOG(true, ("Recipient creature %s is incapacitated or dead.\n", getOwner()->getNetworkId().getValueString().c_str()));
MessageQueueSecureTrade * m = new MessageQueueSecureTrade(MessageQueueSecureTrade::TMI_DeniedPlayerUnreachable, owner->getNetworkId(), data->getRecipient());
appendMessage(static_cast<int>(CM_secureTrade), 0.0f, m, GameControllerMessageFlags::SEND | GameControllerMessageFlags::RELIABLE | GameControllerMessageFlags::DEST_AUTH_CLIENT);
return;
}
if (! recipient->isAuthoritative())
{
if (owner->isInWorldCell())
{
// transfer player to authoritative server
owner->transferAuthority(recipient->getAuthServerProcessId(), true, false, true);
owner->sendControllerMessageToAuthServer(CM_secureTrade, new MessageQueueSecureTrade(MessageQueueSecureTrade::TMI_RequestTrade, owner->getNetworkId(), data->getRecipient()));
}
else if (recipient->isInWorldCell())
{
recipient->sendControllerMessageToAuthServer(CM_secureTrade, new MessageQueueSecureTrade(MessageQueueSecureTrade::TMI_RequestTradeReversed, owner->getNetworkId(), data->getRecipient()));
}
else
{
DEBUG_REPORT_LOG(true, ("Player %s tried to trade with player "
"%s, but both were in interiors that are on different "
"servers. Cell/server= (%s/%lu), (%s/%lu)",
owner->getNetworkId().getValueString().c_str(),
recipient->getNetworkId().getValueString().c_str(),
ContainerInterface::getTopmostContainer(*owner)->getNetworkId().getValueString().c_str(),
owner->getAuthServerProcessId(),
ContainerInterface::getTopmostContainer(*recipient)->getNetworkId().getValueString().c_str(),
recipient->getAuthServerProcessId()
));
}
}
else if (recipient->getClient() == NULL)
{
// GameServer::getInstance().sendToPlanetServer(
// GenericValueTypeMessage<std::pair<NetworkId, NetworkId> >(
// "RequestSameServer",
// std::make_pair(
// ContainerInterface::getTopmostContainer(*owner)->getNetworkId(),
// ContainerInterface::getTopmostContainer(*recipient)->getNetworkId())),
// true);
// transfer player to authoritative server
//owner->transferAuthority(recipient->getAuthServerProcessId(), true, false);
//owner->sendControllerMessageToAuthServer(CM_secureTrade, new MessageQueueSecureTrade(MessageQueueSecureTrade::TMI_RequestTrade, owner->getNetworkId(), data->getRecipient()));
// try again next frame
owner->sendControllerMessageToAuthServer(CM_secureTrade, new MessageQueueSecureTrade(MessageQueueSecureTrade::TMI_RequestTrade, owner->getNetworkId(), data->getRecipient()));
}
else if (!ServerSecureTradeManager::requestTradeWith(*owner, *recipient))
{
MessageQueueSecureTrade * m = new MessageQueueSecureTrade(MessageQueueSecureTrade::TMI_DeniedPlayerBusy, owner->getNetworkId(), recipient->getNetworkId());
appendMessage(static_cast<int>(CM_secureTrade), 0.0f, m, GameControllerMessageFlags::SEND | GameControllerMessageFlags::RELIABLE | GameControllerMessageFlags::DEST_AUTH_CLIENT);
}
}
break;
// we get this when the traders are on different servers, but the trade
// initiator can't be moved to our server
case MessageQueueSecureTrade::TMI_RequestTradeReversed:
{
CreatureObject * initiator = dynamic_cast<CreatureObject*>(ServerWorld::findObjectByNetworkId(data->getInitiator()));
if (!initiator)
{
DEBUG_REPORT_LOG(true, ("Could not find initiator for reversed secure trade message\n"));
return;
}
if (! initiator->isAuthoritative())
{
if (owner->isInWorldCell())
{
// transfer player to authoritative server
owner->transferAuthority(initiator->getAuthServerProcessId(), true, false, true);
owner->sendControllerMessageToAuthServer(CM_secureTrade, new MessageQueueSecureTrade(MessageQueueSecureTrade::TMI_RequestTradeReversed, initiator->getNetworkId(), owner->getNetworkId()));
}
else
{
WARNING(true, ("Got TMI_RequestTradeReversed, but we are not in the world! Trade request abandoned."));
return;
}
}
else
initiator->sendControllerMessageToAuthServer(CM_secureTrade, new MessageQueueSecureTrade(MessageQueueSecureTrade::TMI_RequestTrade, initiator->getNetworkId(), owner->getNetworkId()));
}
break;
case MessageQueueSecureTrade::TMI_TradeRequested:
{
WARNING_STRICT_FATAL(true, ("Server should not receive this message\n"));
return;
}
break;
case MessageQueueSecureTrade::TMI_AcceptTrade:
{
if (m_secureTrade || !m_secureTradeInitiator)
{
DEBUG_REPORT_LOG(true, ("Trade acceptance denied because of previous trade or failed startup steps\n"));
return;
}
ServerSecureTradeManager::acceptTradeRequest(*m_secureTradeInitiator, *(static_cast<CreatureObject *>(getOwner())));
m_secureTradeInitiator = 0;
}
break;
case MessageQueueSecureTrade::TMI_DeniedTrade:
{
if (m_secureTrade || !m_secureTradeInitiator)
{
DEBUG_REPORT_LOG(true, ("Trade acceptance denied because of previous trade or failed startup steps\n"));
return;
}
ServerSecureTradeManager::refuseTrade(*m_secureTradeInitiator, *(static_cast<CreatureObject *>(getOwner())));
m_secureTradeInitiator = 0;
}
break;
default:
{
DEBUG_REPORT_LOG(true, ("Unhandled secure trade message type\n"));
}
break;
}
}
//----------------------------------------------------------
bool CreatureController::tradeRequested(CreatureObject & initiator)
{
//Check for outstanding trade requests.
if (m_secureTradeInitiator || m_secureTrade)
return false;
m_secureTradeInitiator = &initiator;
MessageQueueSecureTrade * m = new MessageQueueSecureTrade(MessageQueueSecureTrade::TMI_TradeRequested, initiator.getNetworkId(), getOwner()->getNetworkId());
appendMessage(static_cast<int>(CM_secureTrade), 0.0f, m, GameControllerMessageFlags::SEND | GameControllerMessageFlags::RELIABLE | GameControllerMessageFlags::DEST_AUTH_CLIENT);
return true;
}
//----------------------------------------------------------------------
void CreatureController::sendGenericResponse (int responseType, int requestType, bool success, uint8 sequenceId)
{
// send result back to player
MessageQueueGenericResponse * response = new MessageQueueGenericResponse (requestType, success, sequenceId);
appendMessage(responseType, 0.0f, response, GameControllerMessageFlags::SEND | GameControllerMessageFlags::RELIABLE | GameControllerMessageFlags::DEST_AUTH_CLIENT);
}
//----------------------------------------------------------------------
void CreatureController::steeringChanged()
{
return;
}
//-----------------------------------------------------------------------
bool CreatureController::setSlopeModAngle(float angle)
{
CreatureObject * owner = static_cast<CreatureObject *>(getOwner());
bool result = owner->setSlopeModAngle(angle);
steeringChanged();
return result;
}
//-----------------------------------------------------------------------
bool CreatureController::setSlopeModPercent(float percent)
{
CreatureObject * owner = static_cast<CreatureObject *>(getOwner());
bool result = owner->setSlopeModPercent(percent);
steeringChanged();
return result;
}
//-----------------------------------------------------------------------
bool CreatureController::setWaterModPercent(float percent)
{
CreatureObject * owner = static_cast<CreatureObject *>(getOwner());
bool result = owner->setWaterModPercent(percent);
steeringChanged();
return result;
}
//-----------------------------------------------------------------------
bool CreatureController::setMovementScale(float scale)
{
CreatureObject * owner = static_cast<CreatureObject *>(getOwner());
return owner->setMovementScale(scale);
}
//-----------------------------------------------------------------------
bool CreatureController::setMovementPercent(float percent)
{
CreatureObject * owner = static_cast<CreatureObject *>(getOwner());
return owner->setMovementPercent(percent);
}
// ----------------------------------------------------------------------
bool CreatureController::setAccelScale(float scale)
{
CreatureObject * owner = static_cast<CreatureObject *>(getOwner());
return owner->setAccelScale(scale);
}
//-----------------------------------------------------------------------
bool CreatureController::setAccelPercent(float percent)
{
CreatureObject * owner = static_cast<CreatureObject *>(getOwner());
return owner->setAccelPercent(percent);
}
// ----------------------------------------------------------------------
void CreatureController::setAppearanceFromObjectTemplate(std::string const &serverObjectTemplateName)
{
CreatureObject * owner = dynamic_cast<CreatureObject *>(getOwner());
if (!owner)
{
WARNING(true, ("setAppearanceFromObjectTemplate(): owner is NULL or not a CreatureObject."));
return;
}
if (owner->isAuthoritative())
owner->setAlternateAppearance(serverObjectTemplateName);
else
owner->sendControllerMessageToAuthServer(CM_setAppearanceFromObjectTemplate, new MessageQueueGenericValueType<std::string>(serverObjectTemplateName));
}
//-----------------------------------------------------------------------
CreatureObject * CreatureController::getCreature()
{
return safe_cast<CreatureObject *>(getOwner());
}
//-----------------------------------------------------------------------
CreatureObject const * CreatureController::getCreature() const
{
return safe_cast<CreatureObject const *>(getOwner());
}
// ----------------------------------------------------------------------
void CreatureController::endBaselines()
{
updateHibernate();
}
// ----------------------------------------------------------------------
void CreatureController::updateHibernate()
{
if (getOwner()->isAuthoritative())
{
setHibernate(shouldHibernate());
}
}
// ----------------------------------------------------------------------
bool CreatureController::shouldHibernate() const
{
if(!ConfigServerGame::getHibernateEnabled())
return false;
// ----------
CreatureObject const * creature = getCreature();
NOT_NULL(creature);
// If the creature is static, it hibernates.
if(creature->getIsStatic())
return true;
// If proxied creatures aren't allowed to hibernate and this creature is proxied,
// it's not hibernating.
if(!ConfigServerGame::getHibernateProxies() && (creature->getProxyCount() > 0))
return false;
// if any players are observing me, don't hibernate
return creature->getObserversCount() <= 0;
}
// ----------------------------------------------------------------------
bool CreatureController::getHibernate() const
{
CreatureObject const * owner = static_cast<CreatureObject const *>(getOwner());
return owner->hasCondition(ServerTangibleObjectTemplate::C_hibernating);
}
// ----------------------------------------------------------------------
void CreatureController::setHibernate(bool newHibernate)
{
bool oldHibernate = getHibernate();
if (oldHibernate == newHibernate)
return;
CreatureObject * owner = static_cast<CreatureObject*>(getOwner());
if (!owner->isAuthoritative())
return;
// ----------
bool transitionOk = true;
if(newHibernate)
{
ScriptParams params;
int result = getServerOwner()->getScriptObject()->trigAllScripts(Scripting::TRIG_HIBERNATE_BEGIN, params);
if(result == SCRIPT_OVERRIDE) transitionOk = false;
}
else
{
ScriptParams params;
int result = getServerOwner()->getScriptObject()->trigAllScripts(Scripting::TRIG_HIBERNATE_END, params);
if(result == SCRIPT_OVERRIDE) transitionOk = false;
}
// ----------
if(transitionOk)
{
if(newHibernate)
{
// DEBUG_REPORT_LOG(true, ("[aitest] Hibernating %s\n", owner->getNetworkId().getValueString().c_str()));
owner->setCondition(ServerTangibleObjectTemplate::C_hibernating);
owner->setDefaultAlterTime(AlterResult::cms_keepNoAlter);
}
else
{
// DEBUG_REPORT_LOG(true, ("[aitest] Waking up %s\n", owner->getNetworkId().getValueString().c_str()));
owner->clearCondition(ServerTangibleObjectTemplate::C_hibernating);
if (owner->isPlayerControlled())
owner->setDefaultAlterTime(0);
else
owner->setDefaultAlterTime(AlterResult::cms_alterQuickly);
}
owner->scheduleForAlter();
// update the planet server for our hibernation change
owner->updatePlanetServerInternal(true);
}
}
//====================================================================
void CreatureController::calculateWaterState(bool& isSwimming, bool &isBurning, float& lavaResistance, float& waterHeight) const
{
//-- Mounts: if this is a rider, take the swim state from the mount.
CreatureObject const *const ownerCreature = safe_cast<CreatureObject const*>(getOwner());
if (!ownerCreature)
return;
if (ownerCreature->getState(States::RidingMount))
{
CreatureObject const *const mountCreature = ownerCreature->getMountedCreature();
CreatureController const *const mountCreatureController = mountCreature ? safe_cast<CreatureController const*>(mountCreature->getController()) : NULL;
if (mountCreatureController)
{
// Note: we do the real computation for the mount here because the rider gets
// an alter prior to the mount. If we just checked the mount's swim state here,
// we would be a frame behind on determining the player's swim state.
mountCreatureController->calculateWaterState(isSwimming,isBurning,lavaResistance,waterHeight);
return;
}
}
//-- Determine if the owner is swimming.
CollisionProperty const * const collisionProperty = ownerCreature->getCollisionProperty ();
if (!collisionProperty)
return;
// JU_TODO: disabled - possibly make burning a persistant state
#if 0
//-- Don't recompute if we're idle --- it shouldn't have changed.
bool const isIdle = collisionProperty && collisionProperty->isIdle();
if (isIdle)
return ownerCreature->getState(States::Swimming);
#endif
// JU_TODO: end disabled
TerrainObject const * const terrainObject = TerrainObject::getConstInstance ();
bool const isOnSolidFloor = collisionProperty && collisionProperty->getFootprint () && collisionProperty->getFootprint ()->isOnSolidFloor ();
isSwimming = false;
if (collisionProperty && ownerCreature->isInWorldCell () && !isOnSolidFloor)
{
Vector const position = ownerCreature->getPosition_w ();
float terrainHeight;
Footprint const * foot = collisionProperty->getFootprint();
lavaResistance = ownerCreature->getLavaResistance();
bool const isImmuneToLava = (lavaResistance == 100.0f);
TerrainGeneratorWaterType waterType = terrainObject->getWaterType(position);
if(!foot || !foot->getTerrainHeight(terrainHeight))
{
if(!terrainObject->getHeight(position,terrainHeight))
{
if(!terrainObject->getHeightForceChunkCreation(position,terrainHeight))
{
return;
}
}
}
//-- see if the object is swimming and/or burning
if (terrainObject->getWaterHeight (position, waterHeight))
{
if(position.y - waterHeight < 1.0f && waterHeight >= terrainHeight)
{
float const swimHeight = ownerCreature->getSwimHeight ();
isSwimming = (terrainHeight + swimHeight) < waterHeight;
if(waterType == TGWT_lava)
{
isSwimming = false;
if(!isImmuneToLava)
{
isBurning = true;
}
}
}
}
}
}
// ----------------------------------------------------------------------
/**
* Called when the owner CreatureObject has first been detected to start swimming.
*/
void CreatureController::onEnterSwimming()
{
CreatureObject *const owner = safe_cast<CreatureObject*>(getOwner());
if (!owner)
return;
//-- Set the state to swimming.
owner->setState(States::Swimming, true);
//-- Fire off the script trigger indicating that the owner is now swimming.
ScriptParams params;
IGNORE_RETURN(owner->getScriptObject()->trigAllScripts(Scripting::TRIG_ENTER_SWIMMING, params));
}
// ----------------------------------------------------------------------
/**
* Called when the owner CreatureObject has first been detected to stop swimming.
*/
void CreatureController::onExitSwimming()
{
CreatureObject *const owner = safe_cast<CreatureObject*>(getOwner());
if (!owner)
return;
//-- Clear the state to swimming.
owner->setState(States::Swimming, false);
//-- Fire off the script trigger indicating that the owner is no longer swimming.
ScriptParams params;
IGNORE_RETURN(owner->getScriptObject()->trigAllScripts(Scripting::TRIG_EXIT_SWIMMING, params));
}
//----------------------------------------------------------------------
CreatureController * CreatureController::asCreatureController()
{
return this;
}
//----------------------------------------------------------------------
CreatureController const * CreatureController::asCreatureController() const
{
return this;
}
//----------------------------------------------------------------------
PlayerCreatureController * CreatureController::asPlayerCreatureController()
{
return NULL;
}
//----------------------------------------------------------------------
PlayerCreatureController const * CreatureController::asPlayerCreatureController() const
{
return NULL;
}
//----------------------------------------------------------------------
AICreatureController * CreatureController::asAiCreatureController()
{
return NULL;
}
//----------------------------------------------------------------------
AICreatureController const * CreatureController::asAiCreatureController() const
{
return NULL;
}
//-----------------------------------------------------------------------
CreatureController * CreatureController::getCreatureController(NetworkId const & networkId)
{
return getCreatureController(NetworkIdManager::getObjectById(networkId));
}
//-----------------------------------------------------------------------
CreatureController * CreatureController::getCreatureController(Object * object)
{
Controller * controller = (object != NULL) ? object->getController() : NULL;
return (controller != NULL) ? controller->asCreatureController() : NULL;
}
// ----------------------------------------------------------------------
CreatureController * CreatureController::asCreatureController(Controller * controller)
{
return (controller != NULL) ? controller->asCreatureController() : NULL;
}
// ----------------------------------------------------------------------
CreatureController const * CreatureController::asCreatureController(Controller const * controller)
{
return (controller != NULL) ? controller->asCreatureController() : NULL;
}
// ======================================================================