mirror of
https://bitbucket.org/theswgsource/src-1.2.git
synced 2026-07-15 00:08:07 -04:00
1490 lines
42 KiB
C++
Executable File
1490 lines
42 KiB
C++
Executable File
// ======================================================================
|
|
//
|
|
// GroupObject.cpp
|
|
//
|
|
// Copyright 2002 Sony Online Entertainment
|
|
//
|
|
// ======================================================================
|
|
|
|
#include "serverGame/FirstServerGame.h"
|
|
#include "serverGame/GroupObject.h"
|
|
|
|
#include "UnicodeUtils.h"
|
|
#include "serverGame/Chat.h"
|
|
#include "serverGame/ConfigServerGame.h"
|
|
#include "serverGame/ContainerInterface.h"
|
|
#include "serverGame/CreatureObject.h"
|
|
#include "serverGame/GameServer.h"
|
|
#include "serverGame/GroupController.h"
|
|
#include "serverGame/GroupMissionCriticalObjectsBuilder.h"
|
|
#include "serverGame/GroupWaypointBuilder.h"
|
|
#include "serverGame/GroupStringId.h"
|
|
#include "serverGame/ObjectTracker.h"
|
|
#include "serverGame/ObserveTracker.h"
|
|
#include "serverGame/PlayerCreatureController.h"
|
|
#include "serverGame/PlayerObject.h"
|
|
#include "serverGame/GroupUpdateObserver.h"
|
|
#include "serverGame/ServerGroupObjectTemplate.h"
|
|
#include "serverGame/ServerWorld.h"
|
|
#include "serverGame/ServerUniverse.h"
|
|
#include "serverGame/ShipObject.h"
|
|
#include "serverScript/GameScriptObject.h"
|
|
#include "serverScript/ScriptParameters.h"
|
|
#include "serverNetworkMessages/GroupMemberParam.h"
|
|
#include "sharedFoundation/ConstCharCrcLowerString.h"
|
|
#include "sharedFoundation/Crc.h"
|
|
#include "sharedFoundation/GameControllerMessage.h"
|
|
#include "sharedGame/ProsePackage.h"
|
|
#include "sharedGame/SharedObjectTemplate.h"
|
|
#include "sharedLog/Log.h"
|
|
#include "sharedObject/Controller.h"
|
|
#include "sharedObject/ObjectTemplateList.h"
|
|
#include "sharedObject/NetworkIdManager.h"
|
|
#include "sharedObject/SlotIdManager.h"
|
|
#include "sharedObject/SlottedContainer.h"
|
|
#include "sharedObject/VolumeContainer.h"
|
|
#include "sharedNetworkMessages/MessageQueueGenericValueType.h"
|
|
|
|
// ======================================================================
|
|
|
|
SharedObjectTemplate const *GroupObject::m_defaultSharedTemplate = 0;
|
|
|
|
// ======================================================================
|
|
|
|
namespace GroupObjectNamespace
|
|
{
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
unsigned int const cs_maximumNumberInGroup = 8;
|
|
char const * const DEFAULT_GROUP_TEMPLATE = "object/group/group.iff";
|
|
std::map<NetworkId, NetworkId> s_leaderMap;
|
|
static const std::string cs_emptyString;
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
std::string const &getChatRoomPrefix()
|
|
{
|
|
static std::string prefix = std::string("SWG.") + GameServer::getInstance().getClusterName() + ".group.";
|
|
return prefix;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
std::string const &getChatRoomSuffix()
|
|
{
|
|
static std::string suffix(".GroupChat");
|
|
return suffix;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
|
|
}
|
|
using namespace GroupObjectNamespace;
|
|
|
|
// ======================================================================
|
|
|
|
GroupObject::GroupObject(ServerGroupObjectTemplate const *newTemplate)
|
|
: UniverseObject(newTemplate),
|
|
m_groupName(),
|
|
m_groupMembers(),
|
|
m_groupShipFormationMembers(),
|
|
m_groupPOBShipAndOwners(),
|
|
m_groupLevel(),
|
|
m_groupMemberLevels(),
|
|
m_groupMemberProfessions(),
|
|
m_formationNameCrc(Crc::crcNull),
|
|
m_allMembers(),
|
|
m_nonPCMembers(),
|
|
m_lootMaster(),
|
|
m_lootRule(0),
|
|
m_groupPickupTimer(std::make_pair(0, 0)),
|
|
m_groupPickupLocation(std::make_pair("", Vector()))
|
|
{
|
|
m_groupMembers.setSourceObject(this);
|
|
m_groupShipFormationMembers.setSourceObject(this);
|
|
m_groupPOBShipAndOwners.setSourceObject(this);
|
|
m_lootMaster.setSourceObject(this);
|
|
addMembersToPackages();
|
|
ObjectTracker::addGroupObject();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
GroupObject::~GroupObject()
|
|
{
|
|
if (!GameServer::getInstance().getDone())
|
|
{
|
|
for (GroupMemberVector::const_iterator i = m_groupMembers.begin(); i != m_groupMembers.end(); ++i)
|
|
onGroupMemberRemoved((*i).first, true);
|
|
}
|
|
|
|
if (isInWorld())
|
|
removeFromWorld();
|
|
ObjectTracker::removeGroupObject();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Controller* GroupObject::createDefaultController()
|
|
{
|
|
Controller* controller = new GroupController(this);
|
|
|
|
setController(controller);
|
|
return controller;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
bool GroupObject::isVisibleOnClient(const Client &) const
|
|
{
|
|
// Group objects are visible to all clients which are observing them, just which clients observe them
|
|
// are strictly managed to assure this. See GroupUpdateObserver for how this is done.
|
|
return true;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Returns a shared template if none was given for this object.
|
|
*
|
|
* @return the shared template
|
|
*/
|
|
const SharedObjectTemplate * GroupObject::getDefaultSharedTemplate() const
|
|
{
|
|
static const ConstCharCrcLowerString templateName("object/group/base/shared_group_default.iff");
|
|
|
|
if (!m_defaultSharedTemplate)
|
|
{
|
|
m_defaultSharedTemplate = safe_cast<SharedObjectTemplate const *>(ObjectTemplateList::fetch(templateName));
|
|
WARNING_STRICT_FATAL(!m_defaultSharedTemplate, ("Cannot create default shared object template %s", templateName.getString()));
|
|
if (m_defaultSharedTemplate)
|
|
ExitChain::add(removeDefaultTemplate, "GroupObject::removeDefaultTemplate");
|
|
}
|
|
return m_defaultSharedTemplate;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Cleans up the default shared template.
|
|
*/
|
|
void GroupObject::removeDefaultTemplate()
|
|
{
|
|
if (!m_defaultSharedTemplate)
|
|
{
|
|
m_defaultSharedTemplate->releaseReference();
|
|
m_defaultSharedTemplate = 0;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::addToLeaderMap(NetworkId const &leaderId, NetworkId const &groupId) // static
|
|
{
|
|
s_leaderMap[leaderId] = groupId;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::removeFromLeaderMap(NetworkId const &leaderId, NetworkId const &groupId) // static
|
|
{
|
|
std::map<NetworkId, NetworkId>::iterator i = s_leaderMap.find(leaderId);
|
|
if (i != s_leaderMap.end() && (*i).second == groupId)
|
|
s_leaderMap.erase(i);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
NetworkId GroupObject::getGroupIdForLeader(NetworkId const &leaderId) // static
|
|
{
|
|
NetworkId groupId = NetworkId::cms_invalid;
|
|
|
|
std::map<NetworkId, NetworkId>::iterator i = s_leaderMap.find(leaderId);
|
|
if (i != s_leaderMap.end())
|
|
groupId = (*i).second;
|
|
|
|
return groupId;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::createAllGroupChatRooms() // static
|
|
{
|
|
if (ServerUniverse::getInstance().isAuthoritative())
|
|
{
|
|
for (std::map<NetworkId, NetworkId>::const_iterator i = s_leaderMap.begin(); i != s_leaderMap.end(); ++i)
|
|
{
|
|
ServerObject const * const so = safe_cast<ServerObject const *>(NetworkIdManager::getObjectById((*i).second));
|
|
if (so)
|
|
{
|
|
GroupObject const * const groupObject = so->asGroupObject();
|
|
if (groupObject)
|
|
groupObject->createGroupChatRoom();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
int GroupObject::maximumMembersInGroup()
|
|
{
|
|
return cs_maximumNumberInGroup;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::createGroup(GroupMemberParam const & leader, GroupMemberParamVector const & members)
|
|
{
|
|
// If the leader already is leading a group, treat this as the specified member joining instead.
|
|
GroupObject *group = 0;
|
|
|
|
{
|
|
std::map<NetworkId, NetworkId>::const_iterator i = s_leaderMap.find(leader.m_memberId);
|
|
if (i != s_leaderMap.end())
|
|
{
|
|
Object *groupObj = NetworkIdManager::getObjectById((*i).second);
|
|
if (groupObj)
|
|
{
|
|
ServerObject *groupServerObj = groupObj->asServerObject();
|
|
if (groupServerObj)
|
|
group = groupServerObj->asGroupObject();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!group)
|
|
{
|
|
group = safe_cast<GroupObject *>(ServerWorld::createNewObject(DEFAULT_GROUP_TEMPLATE, Transform::identity, 0, false));
|
|
group->addToWorld();
|
|
group->addGroupMember(leader);
|
|
group->makeLootMaster(leader.m_memberId);
|
|
}
|
|
|
|
int const numberOfMembers = static_cast<int>(members.size());
|
|
|
|
for (int i = 0; i < numberOfMembers; ++i)
|
|
{
|
|
group->addGroupMember(members[i]);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::setupUniverse()
|
|
{
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::getGroupMemberIds(std::vector<NetworkId> &members) const
|
|
{
|
|
for (GroupMemberVector::const_iterator i = m_groupMembers.begin(); i != m_groupMembers.end(); ++i)
|
|
members.push_back((*i).first);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
NetworkId const &GroupObject::getGroupLeaderId() const
|
|
{
|
|
if (m_groupMembers.size())
|
|
return (*m_groupMembers.begin()).first;
|
|
return NetworkId::cms_invalid;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
std::string const &GroupObject::getGroupLeaderName() const
|
|
{
|
|
static std::string nullStr;
|
|
if (m_groupMembers.size())
|
|
return (*m_groupMembers.begin()).second;
|
|
return nullStr;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
bool GroupObject::isGroupFull() const
|
|
{
|
|
return m_groupMembers.size() == cs_maximumNumberInGroup;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
int GroupObject::getPCMemberCount() const
|
|
{
|
|
if (m_groupMembers.size() > m_nonPCMembers.size())
|
|
return static_cast<int>(m_groupMembers.size() - m_nonPCMembers.size());
|
|
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
bool GroupObject::isMemberPC(NetworkId const & memberId) const
|
|
{
|
|
return !m_nonPCMembers.contains(memberId);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
bool GroupObject::doesGroupHaveRoomFor(int additionalMembers) const
|
|
{
|
|
additionalMembers = std::max(0, additionalMembers);
|
|
return (m_groupMembers.size() + additionalMembers) <= cs_maximumNumberInGroup;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::makeLeader(NetworkId const &newLeaderId)
|
|
{
|
|
if (!isMemberPC(newLeaderId))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!isAuthoritative())
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller)
|
|
{
|
|
controller->appendMessage(
|
|
CM_groupMakeLeader,
|
|
0.0f,
|
|
new MessageQueueGenericValueType<NetworkId>(newLeaderId),
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// swap the specified person with the first person in the group
|
|
for (unsigned int pos = 1; pos < m_groupMembers.size(); ++pos)
|
|
{
|
|
if (m_groupMembers.get(pos).first == newLeaderId)
|
|
{
|
|
GroupUpdateObserver updater(this, Archive::ADOO_generic);
|
|
GroupMember tempMember = m_groupMembers.get(pos);
|
|
m_groupMembers.set(pos, m_groupMembers.get(0));
|
|
m_groupMembers.set(0, tempMember);
|
|
|
|
int16 tempMemberLevel = m_groupMemberLevels.get(pos);
|
|
m_groupMemberLevels.set(pos, m_groupMemberLevels.get(0));
|
|
m_groupMemberLevels.set(0, tempMemberLevel);
|
|
|
|
uint8 tempMemberProfession = m_groupMemberProfessions.get(pos);
|
|
m_groupMemberProfessions.set(pos, m_groupMemberProfessions.get(0));
|
|
m_groupMemberProfessions.set(0, tempMemberProfession);
|
|
|
|
GroupShipFormationMember tempMemberShip = m_groupShipFormationMembers.get(pos);
|
|
m_groupShipFormationMembers.set(pos, m_groupShipFormationMembers.get(0));
|
|
m_groupShipFormationMembers.set(0, tempMemberShip);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::setGroupName(std::string const &groupName)
|
|
{
|
|
if (!isAuthoritative())
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller)
|
|
{
|
|
controller->appendMessage(
|
|
CM_groupSetName,
|
|
0.0f,
|
|
new MessageQueueGenericValueType<std::string>(groupName),
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_groupName = groupName;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::addGroupMember(GroupMemberParam const & member)
|
|
{
|
|
if (!isAuthoritative())
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller)
|
|
{
|
|
controller->appendMessage(
|
|
CM_groupAddMember,
|
|
0.0f,
|
|
new MessageQueueGenericValueType<GroupMemberParam>(member),
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (isGroupFull())
|
|
{
|
|
Chat::sendSystemMessage(member.m_memberName, GroupStringId::SID_GROUP_JOIN_FULL, Unicode::String());
|
|
return;
|
|
}
|
|
|
|
// Don't try to add someone if they are already a member
|
|
if (isGroupMember(member.m_memberId))
|
|
{
|
|
return;
|
|
}
|
|
|
|
GroupUpdateObserver updater(this, Archive::ADOO_generic);
|
|
|
|
m_groupMembers.push_back(std::make_pair(member.m_memberId, member.m_memberName));
|
|
|
|
m_allMembers.insert(member.m_memberId);
|
|
if (!member.m_memberIsPC)
|
|
m_nonPCMembers.insert(member.m_memberId);
|
|
|
|
m_groupShipFormationMembers.push_back(std::make_pair(member.m_memberShipId, m_groupShipFormationMembers.size()));
|
|
|
|
if ((member.m_memberShipId.isValid()) && (member.m_memberShipIsPOB) && (member.m_memberOwnsPOB))
|
|
{
|
|
bool POBShipIsAdded = false;
|
|
int const numberOfGroupPOBShipAndOwners = m_groupPOBShipAndOwners.size();
|
|
|
|
for (int i = 0; i < numberOfGroupPOBShipAndOwners; ++i)
|
|
{
|
|
if (m_groupPOBShipAndOwners[i].first == member.m_memberShipId)
|
|
{
|
|
POBShipIsAdded = true;
|
|
}
|
|
}
|
|
|
|
if (!POBShipIsAdded)
|
|
{
|
|
m_groupPOBShipAndOwners.push_back(std::make_pair(member.m_memberShipId, member.m_memberId));
|
|
}
|
|
}
|
|
|
|
m_groupMemberLevels.push_back(static_cast<int16>(member.m_memberDifficulty));
|
|
m_groupMemberProfessions.push_back(static_cast<uint8>(member.m_memberProfession));
|
|
|
|
calcGroupLevel();
|
|
|
|
if (m_groupMembers.size() == 1)
|
|
createGroupChatRoom();
|
|
addToGroupChatRoom(member.m_memberName);
|
|
addToGroupVoiceChatRoom(member.m_memberId, member.m_memberName);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
GroupMemberParam const GroupObject::createGroupMemberParamForMember(NetworkId const & memberId) const
|
|
{
|
|
std::string const & memberName = getMemberName(memberId);
|
|
int const memberLevel = getMemberLevel(memberId);
|
|
LfgCharacterData::Profession const memberProfession = static_cast<LfgCharacterData::Profession>(getMemberProfession(memberId));
|
|
bool const memberIsPC = !m_nonPCMembers.contains(memberId);
|
|
NetworkId const & memberShipId = getMemberShip(memberId);
|
|
bool const memberShipIsPOB = memberShipId.isValid() && getShipIsPOB(memberShipId);
|
|
bool const memberOwnsPOB = memberShipId.isValid() && memberShipId == getPOBShipOwnedByMember(memberId);
|
|
|
|
return GroupMemberParam(memberId, memberName, memberLevel, memberProfession, memberIsPC, memberShipId, memberShipIsPOB, memberOwnsPOB);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::removeGroupMember(NetworkId const &memberId)
|
|
{
|
|
if (!isAuthoritative())
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller)
|
|
{
|
|
controller->appendMessage(
|
|
CM_groupRemoveMember,
|
|
0.0f,
|
|
new MessageQueueGenericValueType<NetworkId>(memberId),
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GroupUpdateObserver updater(this, Archive::ADOO_generic);
|
|
for (unsigned int i = 0; i < m_groupMembers.size(); ++i)
|
|
{
|
|
GroupMember const & member = m_groupMembers.get(i);
|
|
if (member.first == memberId)
|
|
{
|
|
removeFromGroupChatRoom(member.second);
|
|
removeFromGroupVoiceChatRoom(memberId, member.second);
|
|
|
|
m_groupMembers.erase(i);
|
|
m_allMembers.erase(memberId);
|
|
m_nonPCMembers.erase(memberId);
|
|
m_groupShipFormationMembers.erase(i);
|
|
m_groupMemberLevels.erase(i);
|
|
m_groupMemberProfessions.erase(i);
|
|
calcGroupLevel();
|
|
|
|
for (unsigned int j = 0; j < m_groupPOBShipAndOwners.size(); ++j)
|
|
{
|
|
if (m_groupPOBShipAndOwners.get(j).second == memberId)
|
|
{
|
|
m_groupPOBShipAndOwners.erase(j);
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (m_groupMembers.size() < 2)
|
|
{
|
|
disbandGroup();
|
|
}
|
|
else
|
|
{
|
|
NetworkId firstNonPet = getGroupLeaderId();
|
|
|
|
if (!isMemberPC(firstNonPet))
|
|
{
|
|
unsigned int const numberOfGroupMembers = m_groupMembers.size();
|
|
|
|
for (unsigned int i = 1; i < numberOfGroupMembers; ++i)
|
|
{
|
|
if (isMemberPC(m_groupMembers.get(i).first))
|
|
{
|
|
firstNonPet = m_groupMembers.get(i).first;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isMemberPC(firstNonPet))
|
|
{
|
|
makeLeader(firstNonPet);
|
|
}
|
|
}
|
|
|
|
if (getLootMasterId() == memberId)
|
|
{
|
|
m_lootMaster = getGroupLeaderId();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::disbandGroup()
|
|
{
|
|
if (!isAuthoritative())
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller)
|
|
{
|
|
controller->appendMessage(
|
|
CM_groupDisband,
|
|
0.0f,
|
|
0,
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
else if (!getKill())
|
|
{
|
|
for (unsigned int i = 0; i < m_groupMembers.size(); ++i)
|
|
{
|
|
GroupMember const & member = m_groupMembers.get(i);
|
|
removeFromGroupVoiceChatRoom(member.first, member.second);
|
|
}
|
|
|
|
permanentlyDestroy(DeleteReasons::Player);
|
|
m_groupMembers.clear();
|
|
m_allMembers.clear();
|
|
m_nonPCMembers.clear();
|
|
m_groupShipFormationMembers.clear();
|
|
m_groupPOBShipAndOwners.clear();
|
|
destroyGroupChatRoom();
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
std::string GroupObject::getChatRoomPath() const
|
|
{
|
|
return getChatRoomPrefix() + getNetworkId().getValueString() + getChatRoomSuffix();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
std::string GroupObject::getVoiceChatDisplayName() const
|
|
{
|
|
static std::string displayName("GroupChat");
|
|
return displayName;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
std::string GroupObject::getChatName(std::string const &memberName) const
|
|
{
|
|
std::string firstName;
|
|
size_t pos = 0;
|
|
Unicode::getFirstToken(memberName, 0, pos, firstName);
|
|
return firstName;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::createGroupChatRoom() const
|
|
{
|
|
if (ConfigServerGame::getDebugGroupChat())
|
|
LOG("GroupChat", ("Creating group chat room %s (group id %s)", getChatRoomPath().c_str(), getNetworkId().getValueString().c_str()));
|
|
|
|
Chat::createRoom("System", false, getChatRoomPath(), getNetworkId().getValueString());
|
|
|
|
//TODO: temporary separation of voice and text
|
|
Chat::requestGetChannel(getChatRoomPath(), getVoiceChatDisplayName());
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::destroyGroupChatRoom() const
|
|
{
|
|
if (ConfigServerGame::getDebugGroupChat())
|
|
LOG("GroupChat", ("Destroying group chat room %s (group id %s)", getChatRoomPath().c_str(), getNetworkId().getValueString().c_str()));
|
|
|
|
Chat::destroyRoom(getChatRoomPath());
|
|
|
|
Chat::requestDestroyChannel(getChatRoomPath());
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
bool GroupObject::chatRoomCreated() const
|
|
{
|
|
return hasAttributeAttained(1);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::setChatRoomCreated()
|
|
{
|
|
setAttributeAttained(1);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::addToGroupChatRoom(std::string const &memberName) const
|
|
{
|
|
// note: if the room has not already been created, everyone will be added when the notification of its creation arrives.
|
|
if (chatRoomCreated() && memberName.find("(") == std::string::npos)
|
|
{
|
|
if (ConfigServerGame::getDebugGroupChat())
|
|
LOG("GroupChat", ("Invite and enter: member %s (group id %s), chat room %s", getChatName(memberName).c_str(), getNetworkId().getValueString().c_str(), getChatRoomPath().c_str()));
|
|
Chat::invite(getChatName(memberName), getChatRoomPath());
|
|
Chat::enterRoom(getChatName(memberName), getChatRoomPath(), false, false);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::addToGroupVoiceChatRoom(NetworkId const & memberId, std::string const & memberName) const
|
|
{
|
|
//TODO: temporary separation of voice and text
|
|
Chat::requestAddClientToChannel(memberId, getChatName(memberName), getChatRoomPath(), true);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::removeFromGroupChatRoom(std::string const &memberName) const
|
|
{
|
|
if (memberName.find("(") == std::string::npos)
|
|
{
|
|
if (ConfigServerGame::getDebugGroupChat())
|
|
LOG("GroupChat", ("Exit and uninvite: member %s (group id %s), chat room %s", getChatName(memberName).c_str(), getNetworkId().getValueString().c_str(), getChatRoomPath().c_str()));
|
|
Chat::exitRoom(getChatName(memberName), getChatRoomPath());
|
|
Chat::uninvite(getChatName(memberName), getChatRoomPath());
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::removeFromGroupVoiceChatRoom(NetworkId const & memberId, std::string const & memberName) const
|
|
{
|
|
//TODO: temporary separation of voice and text
|
|
Chat::requestRemoveClientFromChannel(memberId, memberName, getChatRoomPath());
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::sendGroupChat(NetworkId const &memberId, Unicode::String const &text) const
|
|
{
|
|
bool sent = false;
|
|
for (unsigned int i = 0; i < m_groupMembers.size(); ++i)
|
|
{
|
|
if (m_groupMembers.get(i).first == memberId)
|
|
{
|
|
sent = true;
|
|
if (ConfigServerGame::getDebugGroupChat())
|
|
LOG("GroupChat", ("sendGroupChat: member %s (group id %s), chat room %s, text %s", getChatName(m_groupMembers.get(i).second).c_str(), getNetworkId().getValueString().c_str(), getChatRoomPath().c_str(), Unicode::wideToNarrow(text).c_str()));
|
|
Chat::sendToRoom(getChatName(m_groupMembers.get(i).second), getChatRoomPath(), text, Unicode::String());
|
|
}
|
|
}
|
|
|
|
if (!sent && ConfigServerGame::getDebugGroupChat())
|
|
LOG("GroupChat", ("sendGroupChat could not find member id %s (group id %s)", memberId.getValueString().c_str(), getNetworkId().getValueString().c_str()));
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::onGroupChatRoomCreated()
|
|
{
|
|
if (ConfigServerGame::getDebugGroupChat())
|
|
LOG("GroupChat", ("group chat room created (group id %s)", getNetworkId().getValueString().c_str()));
|
|
|
|
setChatRoomCreated();
|
|
for (unsigned int i = 0; i < m_groupMembers.size(); ++i)
|
|
addToGroupChatRoom(m_groupMembers.get(i).second);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::onGroupVoiceChatRoomCreated()
|
|
{
|
|
if (ConfigServerGame::getDebugGroupChat())
|
|
LOG("GroupChat", ("group voice chat room created (group id %s)", getNetworkId().getValueString().c_str()));
|
|
|
|
for (unsigned int i = 0; i < m_groupMembers.size(); ++i)
|
|
{
|
|
GroupMember const & member = m_groupMembers.get(i);
|
|
addToGroupVoiceChatRoom(member.first, member.second);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::onChatRoomCreate(std::string const &path) // static
|
|
{
|
|
if (ConfigServerGame::getDebugGroupChat())
|
|
LOG("GroupChat", ("onChatRoomCreate (%s)", path.c_str()));
|
|
|
|
std::string const &prefix = getChatRoomPrefix();
|
|
// is it a group channel?
|
|
if (!path.compare(0, prefix.length(), prefix))
|
|
{
|
|
// it's a group channel, so extract the networkId
|
|
NetworkId id(path.substr(prefix.length(), path.length()-prefix.length()-getChatRoomSuffix().length()));
|
|
Object *obj = NetworkIdManager::getObjectById(id);
|
|
if (obj)
|
|
{
|
|
ServerObject *serverObject = obj->asServerObject();
|
|
if (serverObject)
|
|
{
|
|
GroupObject *groupObject = serverObject->asGroupObject();
|
|
if (groupObject && groupObject->isAuthoritative())
|
|
groupObject->onGroupChatRoomCreated();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::onVoiceChatRoomCreate(std::string const &name) // static
|
|
{
|
|
if (ConfigServerGame::getDebugGroupChat())
|
|
LOG("GroupChat", ("onVoiceChatRoomCreate (%s)", name.c_str()));
|
|
|
|
std::string const &prefix = getChatRoomPrefix();
|
|
// is it a group channel?
|
|
if (!name.compare(0, prefix.length(), prefix))
|
|
{
|
|
// it's a group channel, so extract the networkId
|
|
std::string strid = name.substr(prefix.length());
|
|
NetworkId id(strid);
|
|
Object *obj = NetworkIdManager::getObjectById(id);
|
|
if (obj)
|
|
{
|
|
ServerObject *serverObject = obj->asServerObject();
|
|
if (serverObject)
|
|
{
|
|
GroupObject *groupObject = serverObject->asGroupObject();
|
|
if (groupObject && groupObject->isAuthoritative())
|
|
groupObject->onGroupVoiceChatRoomCreated();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::getAttributes(stdvector<std::pair<std::string, Unicode::String> >::fwd &data) const
|
|
{
|
|
UniverseObject::getAttributes(data);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::calcGroupLevel()
|
|
{
|
|
FATAL(!isAuthoritative(), ("calcGroupLevel called on nonauth group"));
|
|
|
|
int maxPlayerLevel = 0;
|
|
int groupLevel = 0;
|
|
|
|
const unsigned int numMembers = m_groupMembers.size();
|
|
|
|
if (numMembers > 0)
|
|
{
|
|
for (unsigned int i = 0; i < numMembers; ++i)
|
|
{
|
|
if (isMemberPC(m_groupMembers.get(i).first))
|
|
{
|
|
const int memberLevel = m_groupMemberLevels.get(i);
|
|
maxPlayerLevel = (maxPlayerLevel < memberLevel) ? memberLevel : maxPlayerLevel;
|
|
}
|
|
}
|
|
|
|
groupLevel = maxPlayerLevel;
|
|
}
|
|
|
|
m_groupLevel = static_cast<int16>(groupLevel);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::setMemberLevel(NetworkId const &memberId, int memberLevel)
|
|
{
|
|
if (!isAuthoritative())
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller)
|
|
{
|
|
controller->appendMessage(
|
|
CM_setGroupMemberDifficulty,
|
|
0.0f,
|
|
new MessageQueueGenericValueType<std::pair<NetworkId, int> >(std::make_pair(memberId, memberLevel)),
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (unsigned int i = 0; i < m_groupMembers.size(); ++i)
|
|
{
|
|
if (m_groupMembers.get(i).first == memberId)
|
|
{
|
|
m_groupMemberLevels.set(i, static_cast<int16>(memberLevel));
|
|
calcGroupLevel();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::setMemberProfession(NetworkId const &memberId, uint8 profession)
|
|
{
|
|
if (!isAuthoritative())
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller)
|
|
{
|
|
controller->appendMessage(
|
|
CM_setGroupMemberProfession,
|
|
0.0f,
|
|
new MessageQueueGenericValueType<std::pair<NetworkId, uint32> >(std::make_pair(memberId, static_cast<uint32>(profession))),
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (unsigned int i = 0; i < m_groupMembers.size(); ++i)
|
|
{
|
|
if (m_groupMembers.get(i).first == memberId)
|
|
{
|
|
m_groupMemberProfessions.set(i, profession);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::onGroupMemberConnect(NetworkId const &memberId)
|
|
{
|
|
// try to add them to the group chat room again
|
|
for (unsigned int i = 0; i < m_groupMembers.size(); ++i)
|
|
if (m_groupMembers.get(i).first == memberId)
|
|
{
|
|
GroupMember const & member = m_groupMembers.get(i);
|
|
addToGroupChatRoom(member.second);
|
|
addToGroupVoiceChatRoom(member.first, member.second);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
GroupObject *GroupObject::asGroupObject()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
GroupObject const *GroupObject::asGroupObject() const
|
|
{
|
|
return this;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::onGroupMemberRemoved(NetworkId const &memberId, bool disbanding)
|
|
{
|
|
// have removed members with clients unobserve the group object, clear their group id, and get remove or disband messages
|
|
Object *o = NetworkIdManager::getObjectById(memberId);
|
|
if (o)
|
|
{
|
|
ServerObject *so = o->asServerObject();
|
|
if (so)
|
|
{
|
|
CreatureObject *creature = so->asCreatureObject();
|
|
if (creature && creature->isAuthoritative())
|
|
{
|
|
if (creature->getGroup() == this)
|
|
{
|
|
if (creature->getScriptObject())
|
|
{
|
|
ScriptParams scriptParams;
|
|
scriptParams.addParam(getNetworkId());
|
|
IGNORE_RETURN(creature->getScriptObject()->trigAllScripts(Scripting::TRIG_REMOVED_FROM_GROUP, scriptParams));
|
|
if (disbanding)
|
|
{
|
|
IGNORE_RETURN(creature->getScriptObject()->trigAllScripts(Scripting::TRIG_GROUP_DISBANDED, scriptParams));
|
|
}
|
|
}
|
|
|
|
creature->setGroup(0, disbanding);
|
|
Client *client = creature->getClient();
|
|
if (client)
|
|
{
|
|
ObserveTracker::onClientLeftGroup(*client, *this);
|
|
ProsePackage pp;
|
|
pp.stringId = disbanding ? GroupStringId::SID_GROUP_DISBANDED : GroupStringId::SID_GROUP_REMOVED;
|
|
Chat::sendSystemMessage(*creature, pp);
|
|
}
|
|
|
|
//-- Update just the creature. The group will be updated in ~GroupMemberObserver
|
|
GroupMissionCriticalObjectsBuilder::updateGroupMissionCriticalObjects(*creature, false);
|
|
if (creature->isPlayerControlled())
|
|
{
|
|
PlayerObject * const playerObject = PlayerCreatureController::getPlayerObject(creature);
|
|
if (playerObject)
|
|
GroupWaypointBuilder::updateGroupWaypoints(*playerObject, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::setFormationNameCrc(uint32 const formationNameCrc)
|
|
{
|
|
m_formationNameCrc.set(formationNameCrc);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::setShipForMember(NetworkId const & memberId, NetworkId const & shipId)
|
|
{
|
|
if (isAuthoritative())
|
|
{
|
|
FATAL((m_groupMembers.size() != m_groupShipFormationMembers.size()), ("GroupObject::setShipForMember: m_groupMembers should always be the same size as m_groupShipFormationMembers"));
|
|
|
|
int const numberOfGroupMembers = m_groupMembers.size();
|
|
|
|
for (int i = 0; i < numberOfGroupMembers; ++i)
|
|
{
|
|
if (m_groupMembers[i].first == memberId)
|
|
{
|
|
GroupShipFormationMember data = m_groupShipFormationMembers[i];
|
|
data.first = shipId;
|
|
m_groupShipFormationMembers.set(i, data);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller != 0)
|
|
{
|
|
controller->appendMessage(
|
|
CM_setGroupShipForMember,
|
|
0.0f,
|
|
new MessageQueueGenericValueType<std::pair<NetworkId, NetworkId> >(std::make_pair(memberId, shipId)),
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::setShipFormationSlotForMember(NetworkId const & memberId, int const formationSlot)
|
|
{
|
|
if (isAuthoritative())
|
|
{
|
|
FATAL((m_groupMembers.size() != m_groupShipFormationMembers.size()), ("GroupObject::setShipForMember: m_groupMembers should always be the same size as m_groupShipFormationMembers"));
|
|
|
|
int const numberOfGroupMembers = m_groupMembers.size();
|
|
int previousFormationSlotOwnerIndex = -1;
|
|
int newFormationSlotOwnerIndex = -1;
|
|
|
|
for (int i = 0; i < numberOfGroupMembers; ++i)
|
|
{
|
|
// find the previous owner of this slot
|
|
if (m_groupShipFormationMembers[i].second == formationSlot)
|
|
{
|
|
previousFormationSlotOwnerIndex = i;
|
|
}
|
|
|
|
// find the next owner of this slot
|
|
if (m_groupMembers[i].first == memberId)
|
|
{
|
|
newFormationSlotOwnerIndex = i;
|
|
}
|
|
}
|
|
|
|
// set the previous owner's slot to the current member's slot
|
|
// and then set the member's slot to the new value.
|
|
// since we always set the slot values in ::addGroupMember
|
|
// we can just swap the slots to keep someone from sitting
|
|
// in 2 slots at the same time.
|
|
if (newFormationSlotOwnerIndex > -1)
|
|
{
|
|
GroupShipFormationMember data = m_groupShipFormationMembers[newFormationSlotOwnerIndex];
|
|
int const slotToSwapOccupantTo = data.second;
|
|
data.second = formationSlot;
|
|
m_groupShipFormationMembers.set(newFormationSlotOwnerIndex, data);
|
|
|
|
if (previousFormationSlotOwnerIndex > -1)
|
|
{
|
|
GroupShipFormationMember previousData = m_groupShipFormationMembers[previousFormationSlotOwnerIndex];
|
|
previousData.second = slotToSwapOccupantTo;
|
|
m_groupShipFormationMembers.set(previousFormationSlotOwnerIndex, previousData);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller != 0)
|
|
{
|
|
controller->appendMessage(
|
|
CM_setGroupShipFormationSlotForMember,
|
|
0.0f,
|
|
new MessageQueueGenericValueType<std::pair<NetworkId, int> >(std::make_pair(memberId, formationSlot)),
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::addPOBShipAndOwner(NetworkId const & shipId, NetworkId const & ownerId)
|
|
{
|
|
if (isAuthoritative())
|
|
{
|
|
// make sure that the POB ship isn't already in the list
|
|
int const numberOfGroupPOBShipAndOwners = m_groupPOBShipAndOwners.size();
|
|
|
|
for (int i = 0; i < numberOfGroupPOBShipAndOwners; ++i)
|
|
{
|
|
if (m_groupPOBShipAndOwners[i].first == shipId)
|
|
{
|
|
if (m_groupPOBShipAndOwners[i].second != ownerId)
|
|
{
|
|
GroupPOBShipAndOwner data = m_groupPOBShipAndOwners[i];
|
|
data.second = ownerId;
|
|
m_groupPOBShipAndOwners.set(i, data);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
// add if doesn't exist
|
|
m_groupPOBShipAndOwners.push_back(std::make_pair(shipId, ownerId));
|
|
}
|
|
else
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller != 0)
|
|
{
|
|
controller->appendMessage(
|
|
CM_addGroupPOBShipAndOwner,
|
|
0.0f,
|
|
new MessageQueueGenericValueType<std::pair<NetworkId, NetworkId> >(std::make_pair(shipId, ownerId)),
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::removePOBShip(NetworkId const & shipId)
|
|
{
|
|
if (isAuthoritative())
|
|
{
|
|
int const numberOfGroupPOBShipAndOwners = m_groupPOBShipAndOwners.size();
|
|
|
|
for (int i = 0; i < numberOfGroupPOBShipAndOwners; ++i)
|
|
{
|
|
if (m_groupPOBShipAndOwners[i].first == shipId)
|
|
{
|
|
m_groupPOBShipAndOwners.erase(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller != 0)
|
|
{
|
|
controller->appendMessage(
|
|
CM_removeGroupPOBShip,
|
|
0.0f,
|
|
new MessageQueueGenericValueType<NetworkId>(shipId),
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
NetworkId const & GroupObject::getPOBShipOwnedByMember(NetworkId const & memberId) const
|
|
{
|
|
int const numberOfGroupPOBShipAndOwners = m_groupPOBShipAndOwners.size();
|
|
|
|
for (int i = 0; i < numberOfGroupPOBShipAndOwners; ++i)
|
|
{
|
|
if (m_groupPOBShipAndOwners[i].second == memberId)
|
|
{
|
|
return m_groupPOBShipAndOwners[i].first;
|
|
}
|
|
}
|
|
return NetworkId::cms_invalid;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
NetworkId const & GroupObject::getPOBShipMemberIsContainedIn(NetworkId const & memberId) const
|
|
{
|
|
NetworkId const & shipId = getMemberShip(memberId);
|
|
|
|
if (shipId.isValid())
|
|
{
|
|
int const numberOfGroupPOBShipAndOwners = m_groupPOBShipAndOwners.size();
|
|
|
|
for (int i = 0; i < numberOfGroupPOBShipAndOwners; ++i)
|
|
{
|
|
if (m_groupPOBShipAndOwners[i].first == shipId)
|
|
{
|
|
return shipId;
|
|
}
|
|
}
|
|
}
|
|
return NetworkId::cms_invalid;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
NetworkId const & GroupObject::getMemberShip(NetworkId const & memberId) const
|
|
{
|
|
int const numberOfGroupMembers = m_groupMembers.size();
|
|
|
|
for (int i = 0; i < numberOfGroupMembers; ++i)
|
|
{
|
|
if (m_groupMembers[i].first == memberId)
|
|
{
|
|
return m_groupShipFormationMembers[i].first;
|
|
}
|
|
}
|
|
return NetworkId::cms_invalid;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
std::string const & GroupObject::getMemberName(NetworkId const & memberId) const
|
|
{
|
|
int const numberOfGroupMembers = m_groupMembers.size();
|
|
|
|
for (int i = 0; i < numberOfGroupMembers; ++i)
|
|
{
|
|
if (m_groupMembers[i].first == memberId)
|
|
{
|
|
return m_groupMembers.get(i).second;
|
|
}
|
|
}
|
|
|
|
return cs_emptyString;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
int GroupObject::getMemberLevel(NetworkId const & memberId) const
|
|
{
|
|
int const numberOfGroupMembers = m_groupMembers.size();
|
|
|
|
for (int i = 0; i < numberOfGroupMembers; ++i)
|
|
{
|
|
if (m_groupMembers[i].first == memberId)
|
|
{
|
|
return m_groupMemberLevels.get(i);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
int GroupObject::getMemberLevelByMemberIndex(unsigned int memberIndex) const
|
|
{
|
|
if (memberIndex < m_groupMembers.size())
|
|
return m_groupMemberLevels.get(memberIndex);
|
|
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
uint8 GroupObject::getMemberProfession(NetworkId const & memberId) const
|
|
{
|
|
int const numberOfGroupMembers = m_groupMembers.size();
|
|
|
|
for (int i = 0; i < numberOfGroupMembers; ++i)
|
|
{
|
|
if (m_groupMembers[i].first == memberId)
|
|
{
|
|
return m_groupMemberProfessions.get(i);
|
|
}
|
|
}
|
|
|
|
return static_cast<uint8>(LfgCharacterData::Prof_Unknown);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
uint8 GroupObject::getMemberProfessionByMemberIndex(unsigned int memberIndex) const
|
|
{
|
|
if (memberIndex < m_groupMembers.size())
|
|
return m_groupMemberProfessions.get(memberIndex);
|
|
|
|
return static_cast<uint8>(LfgCharacterData::Prof_Unknown);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
bool GroupObject::getShipIsPOB(NetworkId const & shipId) const
|
|
{
|
|
int const numberOfGroupPOBShipAndOwners = m_groupPOBShipAndOwners.size();
|
|
|
|
for (int i = 0; i < numberOfGroupPOBShipAndOwners; ++i)
|
|
{
|
|
if (m_groupPOBShipAndOwners[i].first == shipId)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
NetworkId const & GroupObject::getLootMasterId() const
|
|
{
|
|
return m_lootMaster.get();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::makeLootMaster(NetworkId const & newLootMasterId)
|
|
{
|
|
if (!isMemberPC(newLootMasterId))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!isAuthoritative())
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller != 0)
|
|
{
|
|
controller->appendMessage(
|
|
CM_groupMakeLootMaster,
|
|
0.0f,
|
|
new MessageQueueGenericValueType<NetworkId>(newLootMasterId),
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GroupUpdateObserver updater(this, Archive::ADOO_generic);
|
|
|
|
int const numberOfGroupMembers = m_groupMembers.size();
|
|
|
|
for (int i = 0; i < numberOfGroupMembers; ++i)
|
|
{
|
|
if (m_groupMembers[i].first == newLootMasterId)
|
|
{
|
|
m_lootMaster = newLootMasterId;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
int GroupObject::getLootRule() const
|
|
{
|
|
return m_lootRule.get();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::setLootRule(int const rule)
|
|
{
|
|
if (!isAuthoritative())
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller != 0)
|
|
{
|
|
controller->appendMessage(
|
|
CM_groupSetLootRule,
|
|
0.0f,
|
|
new MessageQueueGenericValueType<int>(rule),
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_lootRule = static_cast<uint32>(rule);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
unsigned int GroupObject::getSecondsLeftOnGroupPickup() const
|
|
{
|
|
std::pair<int32, int32> const & groupPickupTimer = m_groupPickupTimer.get();
|
|
if ((groupPickupTimer.first > 0) && (groupPickupTimer.second > 0))
|
|
{
|
|
time_t const timeNow = ::time(NULL);
|
|
if (groupPickupTimer.second > timeNow)
|
|
return (groupPickupTimer.second - (int)timeNow);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::setGroupPickupTimer(time_t startTime, time_t endTime)
|
|
{
|
|
if (!isAuthoritative())
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller)
|
|
{
|
|
controller->appendMessage(
|
|
CM_setGroupPickupTimer,
|
|
0.0f,
|
|
new MessageQueueGenericValueType<std::pair<int32, int32> >(std::make_pair(static_cast<int32>(startTime), static_cast<int32>(endTime))),
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_groupPickupTimer.set(std::make_pair(static_cast<int32>(startTime), static_cast<int32>(endTime)));
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::setGroupPickupLocation(std::string const & planetName, Vector const & location)
|
|
{
|
|
if (!isAuthoritative())
|
|
{
|
|
Controller *controller = getController();
|
|
if (controller)
|
|
{
|
|
controller->appendMessage(
|
|
CM_setGroupPickupLocation,
|
|
0.0f,
|
|
new MessageQueueGenericValueType<std::pair<std::string, Vector> >(std::make_pair(planetName, location)),
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_SERVER);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_groupPickupLocation.set(std::make_pair(planetName, location));
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void GroupObject::reenterGroupChatRoom(CreatureObject const &who) const
|
|
{
|
|
if (who.getGroup() != this)
|
|
return;
|
|
|
|
std::string firstName;
|
|
size_t pos = 0;
|
|
IGNORE_RETURN(Unicode::getFirstToken(Unicode::wideToNarrow(who.getObjectName()), 0, pos, firstName));
|
|
|
|
std::string const groupChatRoomPath = getChatRoomPath();
|
|
Chat::exitRoom(firstName, groupChatRoomPath);
|
|
Chat::uninvite(firstName, groupChatRoomPath);
|
|
Chat::invite(firstName, groupChatRoomPath);
|
|
Chat::enterRoom(firstName, groupChatRoomPath, false, false);
|
|
}
|
|
|
|
// ======================================================================
|