mirror of
https://gitlab.com/Scribble/gdlenhanced.git
synced 2026-08-17 14:23:04 -04:00
714 lines
18 KiB
C++
714 lines
18 KiB
C++
|
|
#include "StdAfx.h"
|
|
#include "FellowshipManager.h"
|
|
#include "World.h"
|
|
#include "WeenieObject.h"
|
|
#include "Player.h"
|
|
#include "ChatMsgs.h"
|
|
|
|
#define MAX_FELLOWSHIP_MEMBERS 9
|
|
#define FELLOWSHIP_OPTIONAL_UPDATING 1
|
|
|
|
DEFINE_PACK(Fellow)
|
|
{
|
|
pWriter->Write<unsigned int>(_cp_cache);
|
|
pWriter->Write<unsigned int>(_lum_cache);
|
|
pWriter->Write<unsigned int>(_level);
|
|
pWriter->Write<unsigned int>(_max_health);
|
|
pWriter->Write<unsigned int>(_max_stamina);
|
|
pWriter->Write<unsigned int>(_max_mana);
|
|
pWriter->Write<unsigned int>(_current_health);
|
|
pWriter->Write<unsigned int>(_current_stamina);
|
|
pWriter->Write<unsigned int>(_current_mana);
|
|
pWriter->Write<unsigned int>(_share_loot);
|
|
pWriter->WriteString(_name);
|
|
}
|
|
|
|
DEFINE_UNPACK(Fellow)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
DEFINE_PACK(Fellowship)
|
|
{
|
|
_fellowship_table.Pack(pWriter);
|
|
|
|
pWriter->WriteString(_name);
|
|
pWriter->Write<DWORD>(_leader);
|
|
pWriter->Write<int>(_share_xp);
|
|
pWriter->Write<int>(_even_xp_split);
|
|
pWriter->Write<int>(_open_fellow);
|
|
pWriter->Write<int>(_locked);
|
|
|
|
_fellows_departed.Pack(pWriter);
|
|
|
|
}
|
|
|
|
DEFINE_UNPACK(Fellowship)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void Fellowship::UpdateData()
|
|
{
|
|
bool bAllOver50 = false;
|
|
int minLevel = -1;
|
|
int maxLevel = -1;
|
|
int leaderLevel = -1;
|
|
|
|
for (auto &entry : _fellowship_table)
|
|
{
|
|
std::shared_ptr<CPlayerWeenie> player = g_pWorld->FindPlayer(entry.first);
|
|
if (player)
|
|
{
|
|
entry.second._name = player->GetName();
|
|
unsigned int level = entry.second._level = player->InqIntQuality(LEVEL_INT, 0);
|
|
|
|
entry.second._current_health = player->GetHealth();
|
|
entry.second._current_stamina = player->GetStamina();
|
|
entry.second._current_mana = player->GetMana();
|
|
|
|
entry.second._max_health = player->GetMaxHealth();
|
|
entry.second._max_stamina = player->GetMaxStamina();
|
|
entry.second._max_mana = player->GetMaxMana();
|
|
|
|
entry.second._cp_cache = 0; // TODO
|
|
entry.second._lum_cache = 0; // TODO
|
|
entry.second._share_loot = _share_loot ? 0x0010 : 0;
|
|
|
|
if (minLevel <= 0 || level < minLevel)
|
|
minLevel = level;
|
|
if (maxLevel <= 0 || level > maxLevel)
|
|
maxLevel = level;
|
|
|
|
entry.second._cachedWeenie = player;
|
|
|
|
if (entry.first == _leader)
|
|
leaderLevel = level;
|
|
}
|
|
}
|
|
|
|
if (minLevel >= 50)
|
|
bAllOver50 = true;
|
|
|
|
/*
|
|
int levelSpread = maxLevel - minLevel;
|
|
_even_xp_split = (bAllOver50 || levelSpread <= 5) && _desiredShareXP;
|
|
_share_xp = (bAllOver50 || levelSpread <= 10) && _desiredShareXP;
|
|
*/
|
|
|
|
bool bWithin5Levels = ((abs(leaderLevel - maxLevel) <= 5) && (abs(leaderLevel - minLevel) <= 5)) ? true : false;
|
|
bool bWithin10Levels = ((abs(leaderLevel - maxLevel) <= 10) && (abs(leaderLevel - minLevel) <= 10)) ? true : false;
|
|
|
|
_even_xp_split = (bAllOver50 || bWithin5Levels) && _desiredShareXP;
|
|
_share_xp = (bAllOver50 || bWithin10Levels) && _desiredShareXP;
|
|
|
|
unsigned int xpPortionSum = CalculateExperienceProportionSum();
|
|
|
|
for (auto &entry : _fellowship_table)
|
|
{
|
|
if (_even_xp_split)
|
|
entry.second.splitPercent = FellowshipManager::GetEvenSplitXPPctg((DWORD) _fellowship_table.size());
|
|
else
|
|
entry.second.splitPercent = FellowshipManager::GetExperienceProportion(entry.second._level) / (double)xpPortionSum;
|
|
}
|
|
}
|
|
|
|
double Fellowship::CalculateDegradeMod(std::shared_ptr<CWeenieObject> source, std::shared_ptr<CWeenieObject> target)
|
|
{
|
|
WORD source_block_id = source->m_Position.objcell_id >> 16;
|
|
WORD source_cell_id = source->m_Position.objcell_id & 0xFFFF;
|
|
WORD target_block_id = target->m_Position.objcell_id >> 16;
|
|
WORD target_cell_id = target->m_Position.objcell_id & 0xFFFF;
|
|
|
|
if (source_cell_id >= 0x100 || target_cell_id >= 0x100)
|
|
{
|
|
if (source_block_id != target_block_id)
|
|
return 0.0;
|
|
}
|
|
|
|
// both are outside, or in a building/dungeon in the same land block
|
|
double dist = source->DistanceTo(target);
|
|
double numClicks = (dist / 24.0);
|
|
|
|
if (numClicks <= 25)
|
|
return 1.0; // full XP within 2.5 map units
|
|
if (numClicks >= 50)
|
|
return 0.0; // no XP beyond 5.0 map units
|
|
|
|
return max(0.0, min(1.0, 1.0 - ((numClicks - 25.0) / 25.0)));
|
|
}
|
|
|
|
void Fellowship::GiveXP(std::shared_ptr<CWeenieObject> source, long long amount, bool bShowText)
|
|
{
|
|
UpdateData();
|
|
|
|
if (!_share_xp)
|
|
{
|
|
source->GiveXP(amount, bShowText);
|
|
}
|
|
else
|
|
{
|
|
for (auto &entry : _fellowship_table)
|
|
{
|
|
if (entry.first == source->GetID())
|
|
entry.second._cp_cache += amount;
|
|
|
|
std::shared_ptr<CWeenieObject> other = entry.second._cachedWeenie.lock();
|
|
if (other)
|
|
{
|
|
double degradeMod = CalculateDegradeMod(source, other);
|
|
|
|
long long xpGained = (long long) (amount * entry.second.splitPercent * degradeMod);
|
|
if (xpGained > 0)
|
|
other->GiveXP(xpGained, bShowText);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned int Fellowship::CalculateExperienceProportionSum()
|
|
{
|
|
// make sure the levels are correct in the data before calling this
|
|
unsigned int sum = 0;
|
|
|
|
for (auto &entry : _fellowship_table)
|
|
sum += FellowshipManager::GetExperienceProportion(entry.second._level);
|
|
|
|
return sum;
|
|
}
|
|
|
|
void Fellowship::TickUpdate()
|
|
{
|
|
|
|
// check if any need updating
|
|
|
|
#if FELLOWSHIP_OPTIONAL_UPDATING
|
|
bool bNeedUpdate = false;
|
|
for (auto &entry : _fellowship_table)
|
|
{
|
|
if (entry.second._updates)
|
|
{
|
|
bNeedUpdate = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!bNeedUpdate)
|
|
return;
|
|
#endif
|
|
UpdateData();
|
|
|
|
BinaryWriter updateMessage;
|
|
updateMessage.Write<DWORD>(0x2BE);
|
|
Pack(&updateMessage);
|
|
|
|
for (auto &entry : _fellowship_table)
|
|
{
|
|
#if FELLOWSHIP_OPTIONAL_UPDATING
|
|
if (entry.second._updates)
|
|
#endif
|
|
{
|
|
std::shared_ptr<CPlayerWeenie> player = g_pWorld->FindPlayer(entry.first);
|
|
if (player)
|
|
player->SendNetMessage(&updateMessage, PRIVATE_MSG, TRUE, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Fellowship::SendUpdate(int updateType)
|
|
{
|
|
UpdateData();
|
|
|
|
switch (updateType)
|
|
{
|
|
case Fellow_UpdateFull:
|
|
{
|
|
BinaryWriter updateMessage;
|
|
updateMessage.Write<DWORD>(0x2BE);
|
|
Pack(&updateMessage);
|
|
|
|
for (auto &entry : _fellowship_table)
|
|
{
|
|
std::shared_ptr<CPlayerWeenie> player = g_pWorld->FindPlayer(entry.first);
|
|
if (player)
|
|
player->SendNetMessage(&updateMessage, PRIVATE_MSG, TRUE, FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool Fellowship::IsEmpty()
|
|
{
|
|
return _fellowship_table.empty();
|
|
}
|
|
|
|
bool Fellowship::IsLocked()
|
|
{
|
|
return _locked ? true : false;
|
|
}
|
|
|
|
bool Fellowship::IsOpen()
|
|
{
|
|
return _open_fellow ? true : false;
|
|
}
|
|
|
|
bool Fellowship::IsFull()
|
|
{
|
|
if (_fellowship_table.size() >= MAX_FELLOWSHIP_MEMBERS)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
void Fellowship::Disband(DWORD disbander_id)
|
|
{
|
|
BinaryWriter disbandMessage;
|
|
disbandMessage.Write<DWORD>(0x2BF);
|
|
for (auto &entry : _fellowship_table)
|
|
{
|
|
std::shared_ptr<CPlayerWeenie> player = g_pWorld->FindPlayer(entry.first);
|
|
if (player)
|
|
{
|
|
player->SendNetMessage(&disbandMessage, PRIVATE_MSG, TRUE, FALSE);
|
|
player->m_Qualities.RemoveString(FELLOWSHIP_STRING);
|
|
}
|
|
}
|
|
_fellowship_table.clear();
|
|
}
|
|
|
|
void Fellowship::Dismiss(DWORD dismissee_id)
|
|
{
|
|
BinaryWriter dismissMessage;
|
|
dismissMessage.Write<DWORD>(0xA4);
|
|
dismissMessage.Write<DWORD>(dismissee_id);
|
|
|
|
for (auto &entry : _fellowship_table)
|
|
{
|
|
if (std::shared_ptr<CPlayerWeenie> player = g_pWorld->FindPlayer(entry.first))
|
|
{
|
|
player->SendNetMessage(&dismissMessage, PRIVATE_MSG, TRUE, FALSE);
|
|
}
|
|
}
|
|
|
|
_fellowship_table.remove(dismissee_id);
|
|
if (std::shared_ptr<CPlayerWeenie> player = g_pWorld->FindPlayer(dismissee_id))
|
|
{
|
|
player->m_Qualities.RemoveString(FELLOWSHIP_STRING);
|
|
}
|
|
|
|
SendUpdate(Fellow_UpdateFull);
|
|
}
|
|
|
|
void Fellowship::Quit(DWORD quitter_id)
|
|
{
|
|
BinaryWriter quitMessage;
|
|
quitMessage.Write<DWORD>(0xA3);
|
|
quitMessage.Write<DWORD>(quitter_id);
|
|
|
|
std::string quitter_name;
|
|
if (std::shared_ptr<CPlayerWeenie> player = g_pWorld->FindPlayer(quitter_id))
|
|
{
|
|
player->m_Qualities.RemoveString(FELLOWSHIP_STRING);
|
|
quitter_name = player->GetName();
|
|
}
|
|
// BinaryWriter *quitText = ServerText(csprintf("%s has left the Fellowship.", quitter_name.c_str()), LTT_DEFAULT);
|
|
|
|
for (auto &entry : _fellowship_table)
|
|
{
|
|
if (std::shared_ptr<CPlayerWeenie> player = g_pWorld->FindPlayer(entry.first))
|
|
{
|
|
player->SendNetMessage(&quitMessage, PRIVATE_MSG, TRUE, FALSE);
|
|
// player->SendNetMessage(quitText, PRIVATE_MSG, FALSE, FALSE);
|
|
}
|
|
}
|
|
|
|
// delete quitText;
|
|
|
|
_fellowship_table.remove(quitter_id);
|
|
if (quitter_id == _leader && _fellowship_table.size() >= 1)
|
|
{
|
|
AssignNewLeader(_fellowship_table.begin()->first);
|
|
}
|
|
|
|
SendUpdate(Fellow_UpdateFull);
|
|
}
|
|
|
|
void Fellowship::Recruit(DWORD recruitee_id)
|
|
{
|
|
Fellow newFellow;
|
|
_fellowship_table.add(recruitee_id, &newFellow);
|
|
|
|
UpdateData();
|
|
|
|
Fellow *f = _fellowship_table.lookup(recruitee_id);
|
|
|
|
BinaryWriter recruitMessage;
|
|
recruitMessage.Write<DWORD>(0x2C0);
|
|
recruitMessage.Write<DWORD>(recruitee_id);
|
|
f->Pack(&recruitMessage);
|
|
recruitMessage.Write<DWORD>(Fellow_UpdateFull);
|
|
|
|
for (auto &entry : _fellowship_table)
|
|
{
|
|
if (std::shared_ptr<CPlayerWeenie> player = g_pWorld->FindPlayer(entry.first))
|
|
{
|
|
if (entry.first == recruitee_id)
|
|
{
|
|
// full update to the new recruit
|
|
BinaryWriter updateMessage;
|
|
updateMessage.Write<DWORD>(0x2BE);
|
|
Pack(&updateMessage);
|
|
|
|
player->SendNetMessage(&updateMessage, PRIVATE_MSG, TRUE, FALSE);
|
|
player->m_Qualities.SetString(FELLOWSHIP_STRING, _name);
|
|
}
|
|
else
|
|
{
|
|
// partial update to everyone else
|
|
player->SendNetMessage(&recruitMessage, PRIVATE_MSG, TRUE, FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Fellowship::ChangeOpen(BOOL open)
|
|
{
|
|
_open_fellow = open;
|
|
|
|
std::string leader_name;
|
|
std::shared_ptr<CWeenieObject> leader_weenie = g_pWorld->FindPlayer(_leader);
|
|
if (leader_weenie)
|
|
leader_name = leader_weenie->GetName();
|
|
|
|
for (auto &entry : _fellowship_table)
|
|
{
|
|
std::shared_ptr<CPlayerWeenie> player = g_pWorld->FindPlayer(entry.first);
|
|
if (player)
|
|
{
|
|
if (entry.first == _leader)
|
|
player->SendNetMessage(ServerText(csprintf("You have %s your Fellowship.", open ? "opened" : "closed"), LTT_DEFAULT), PRIVATE_MSG, FALSE, TRUE);
|
|
else
|
|
player->SendNetMessage(ServerText(csprintf("%s has %s your Fellowship.", leader_name.c_str(), open ? "opened" : "closed"), LTT_DEFAULT), PRIVATE_MSG, FALSE, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Fellowship::AssignNewLeader(DWORD new_leader_id)
|
|
{
|
|
_leader = new_leader_id;
|
|
|
|
std::shared_ptr<CWeenieObject> leader_weenie = g_pWorld->FindPlayer(new_leader_id);
|
|
if (leader_weenie)
|
|
{
|
|
std::string new_leader_name = leader_weenie->GetName();
|
|
|
|
for (auto &entry : _fellowship_table)
|
|
{
|
|
std::shared_ptr<CPlayerWeenie> player = g_pWorld->FindPlayer(entry.first);
|
|
if (player)
|
|
{
|
|
if (entry.first == new_leader_id)
|
|
player->SendNetMessage(ServerText("You are now the leader of your Fellowship.", LTT_DEFAULT), PRIVATE_MSG, FALSE, TRUE);
|
|
else
|
|
player->SendNetMessage(ServerText(csprintf("%s is now the leader of your Fellowship.", new_leader_name.c_str()), LTT_DEFAULT), PRIVATE_MSG, FALSE, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
SendUpdate(Fellow_UpdateFull);
|
|
}
|
|
|
|
void Fellowship::Chat(DWORD sender_id, const char *text)
|
|
{
|
|
std::shared_ptr<CWeenieObject> sender_weenie = g_pWorld->FindPlayer(sender_id);
|
|
if (sender_weenie)
|
|
{
|
|
sender_weenie->SendNetMessage(ServerText(csprintf("You say to your fellowship, \"%s\"", text), LTT_FELLOWSHIP_CHANNEL), PRIVATE_MSG, FALSE, TRUE);
|
|
|
|
std::string sender_name = sender_weenie->GetName();
|
|
for (auto &entry : _fellowship_table)
|
|
{
|
|
if (entry.first != sender_id)
|
|
{
|
|
std::shared_ptr<CPlayerWeenie> player = g_pWorld->FindPlayer(entry.first);
|
|
if (player)
|
|
player->SendNetMessage(ServerText(csprintf("%s says to your fellowship, \"%s\"", sender_name.c_str(), text), LTT_FELLOWSHIP_CHANNEL), PRIVATE_MSG, FALSE, TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Fellowship::SetUpdates(DWORD fellow_id, BOOL on)
|
|
{
|
|
Fellow *f = _fellowship_table.lookup(fellow_id);
|
|
if (!f)
|
|
return;
|
|
|
|
f->_updates = on;
|
|
}
|
|
|
|
FellowshipManager::FellowshipManager()
|
|
{
|
|
}
|
|
|
|
FellowshipManager::~FellowshipManager()
|
|
{
|
|
for (auto &entry : m_Fellowships)
|
|
delete entry.second;
|
|
|
|
m_Fellowships.clear();
|
|
}
|
|
|
|
void FellowshipManager::Tick()
|
|
{
|
|
if (m_fNextUpdates <= Timer::cur_time)
|
|
{
|
|
for (auto &fs : m_Fellowships)
|
|
{
|
|
fs.second->TickUpdate();
|
|
}
|
|
|
|
m_fNextUpdates = Timer::cur_time + 1.0;
|
|
}
|
|
}
|
|
|
|
Fellowship *FellowshipManager::GetFellowship(const std::string &name)
|
|
{
|
|
std::unordered_map<std::string, Fellowship *>::iterator entry = m_Fellowships.find(name);
|
|
|
|
if (entry != m_Fellowships.end())
|
|
return entry->second;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int FellowshipManager::Create(const std::string &name, DWORD creator_id, BOOL shareXP)
|
|
{
|
|
if (GetFellowship(name))
|
|
return WERROR_FELLOWSHIP_UNCLEAN_NAME; // in use
|
|
|
|
Fellowship *fs = new Fellowship();
|
|
|
|
fs->_name = name;
|
|
fs->_leader = creator_id;
|
|
fs->_desiredShareXP = shareXP;
|
|
fs->_locked = false;
|
|
fs->_open_fellow = false;
|
|
fs->_even_xp_split = true;
|
|
fs->_share_loot = false;
|
|
|
|
Fellow f;
|
|
fs->_fellowship_table.add(creator_id, &f);
|
|
|
|
std::shared_ptr<CWeenieObject> playerWeenie = g_pWorld->FindPlayer(creator_id);
|
|
if (std::shared_ptr<CPlayerWeenie> player = playerWeenie->AsPlayer())
|
|
{
|
|
player->m_Qualities.SetString(FELLOWSHIP_STRING, name);
|
|
fs->_share_loot = player->ShareFellowshipLoot();
|
|
}
|
|
|
|
m_Fellowships[name] = fs;
|
|
|
|
fs->SendUpdate(Fellow_UpdateFull);
|
|
return WERROR_NONE;
|
|
}
|
|
|
|
int FellowshipManager::Disband(const std::string &name, DWORD disbander_id)
|
|
{
|
|
std::unordered_map<std::string, Fellowship *>::iterator i = m_Fellowships.find(name);
|
|
if (i == m_Fellowships.end())
|
|
return WERROR_FELLOWSHIP_NO_FELLOWSHIP;
|
|
|
|
Fellowship *fs = i->second;
|
|
if (fs->_leader != disbander_id)
|
|
return WERROR_FELLOWSHIP_NOT_LEADER;
|
|
|
|
m_Fellowships.erase(i);
|
|
fs->Disband(disbander_id);
|
|
delete fs;
|
|
|
|
return WERROR_NONE;
|
|
}
|
|
|
|
int FellowshipManager::Quit(const std::string &name, DWORD quitter_id)
|
|
{
|
|
std::unordered_map<std::string, Fellowship *>::iterator i = m_Fellowships.find(name);
|
|
if (i == m_Fellowships.end())
|
|
return WERROR_FELLOWSHIP_NO_FELLOWSHIP;
|
|
|
|
Fellowship *fs = i->second;
|
|
fs->Quit(quitter_id);
|
|
|
|
if (fs->IsEmpty())
|
|
{
|
|
m_Fellowships.erase(i);
|
|
delete fs;
|
|
}
|
|
|
|
return WERROR_NONE;
|
|
}
|
|
|
|
int FellowshipManager::Dismiss(const std::string &name, DWORD dismisser_id, DWORD dismissee_id)
|
|
{
|
|
std::unordered_map<std::string, Fellowship *>::iterator i = m_Fellowships.find(name);
|
|
if (i == m_Fellowships.end())
|
|
return WERROR_FELLOWSHIP_NO_FELLOWSHIP;
|
|
|
|
Fellowship *fs = i->second;
|
|
if (fs->_leader != dismisser_id)
|
|
return WERROR_FELLOWSHIP_NOT_LEADER;
|
|
|
|
std::shared_ptr<CWeenieObject> dismissee_weenie = g_pWorld->FindPlayer(dismissee_id);
|
|
if (!dismissee_weenie)
|
|
return WERROR_NO_OBJECT;
|
|
if (!dismissee_weenie->HasFellowship())
|
|
return WERROR_NO_OBJECT;
|
|
if (strcmp(dismissee_weenie->InqStringQuality(FELLOWSHIP_STRING, "").c_str(), name.c_str()))
|
|
return WERROR_NO_OBJECT;
|
|
|
|
fs->Dismiss(dismissee_id);
|
|
|
|
if (fs->IsEmpty())
|
|
{
|
|
m_Fellowships.erase(i);
|
|
delete fs;
|
|
}
|
|
|
|
return WERROR_NONE;
|
|
}
|
|
|
|
int FellowshipManager::Recruit(const std::string &name, DWORD recruiter_id, DWORD recruitee_id)
|
|
{
|
|
std::unordered_map<std::string, Fellowship *>::iterator i = m_Fellowships.find(name);
|
|
if (i == m_Fellowships.end())
|
|
return WERROR_FELLOWSHIP_NO_FELLOWSHIP;
|
|
|
|
Fellowship *fs = i->second;
|
|
if (fs->IsFull())
|
|
return WERROR_FELLOWSHIP_FULL;
|
|
if (!fs->IsOpen() && fs->_leader != recruiter_id)
|
|
return WERROR_FELLOWSHIP_NOT_LEADER;
|
|
if (fs->IsLocked())
|
|
return WERROR_FELLOWSHIP_LOCKED_RECRUITER;
|
|
|
|
std::shared_ptr<CPlayerWeenie> recruiter_weenie = g_pWorld->FindPlayer(recruiter_id);
|
|
if (!recruiter_weenie)
|
|
return WERROR_NO_OBJECT;
|
|
if (recruiter_weenie->IsBusyOrInAction())
|
|
return WERROR_ACTIONS_LOCKED;
|
|
|
|
std::shared_ptr<CPlayerWeenie> recruited_weenie = g_pWorld->FindPlayer(recruitee_id);
|
|
if (!recruited_weenie)
|
|
return WERROR_NO_OBJECT;
|
|
|
|
if (recruiter_weenie->DistanceTo(recruited_weenie, true) >= 3.0)
|
|
return WERROR_TOO_FAR;
|
|
|
|
if (recruited_weenie->IsBusyOrInAction())
|
|
return WERROR_ACTIONS_LOCKED;
|
|
if (recruited_weenie->HasFellowship())
|
|
return WERROR_FELLOWSHIP_MEMBER;
|
|
if (recruited_weenie->GetCharacterOptions() & IgnoreFellowshipRequests_CharacterOption)
|
|
return WERROR_FELLOWSHIP_IGNORING_REQUESTS;
|
|
|
|
fs->Recruit(recruitee_id);
|
|
|
|
if (fs->IsEmpty())
|
|
{
|
|
m_Fellowships.erase(i);
|
|
delete fs;
|
|
}
|
|
|
|
recruiter_weenie->DoForcedMotion(Motion_BowDeep);
|
|
|
|
return WERROR_NONE;
|
|
}
|
|
|
|
int FellowshipManager::ChangeOpen(const std::string &name, DWORD changer_id, BOOL open)
|
|
{
|
|
std::unordered_map<std::string, Fellowship *>::iterator i = m_Fellowships.find(name);
|
|
if (i == m_Fellowships.end())
|
|
return WERROR_FELLOWSHIP_NO_FELLOWSHIP;
|
|
|
|
Fellowship *fs = i->second;
|
|
if (fs->_leader != changer_id)
|
|
return WERROR_FELLOWSHIP_NOT_LEADER;
|
|
|
|
fs->ChangeOpen(open);
|
|
return WERROR_NONE;
|
|
}
|
|
|
|
int FellowshipManager::AssignNewLeader(const std::string &name, DWORD changer_id, DWORD new_leader_id)
|
|
{
|
|
std::unordered_map<std::string, Fellowship *>::iterator i = m_Fellowships.find(name);
|
|
if (i == m_Fellowships.end())
|
|
return WERROR_FELLOWSHIP_NO_FELLOWSHIP;
|
|
|
|
if (changer_id == new_leader_id)
|
|
return WERROR_FELLOWSHIP_MEMBER;
|
|
|
|
Fellowship *fs = i->second;
|
|
if (fs->_leader != changer_id)
|
|
return WERROR_FELLOWSHIP_NOT_LEADER;
|
|
if (!fs->_fellowship_table.lookup(new_leader_id))
|
|
return WERROR_NO_OBJECT;
|
|
|
|
fs->AssignNewLeader(new_leader_id);
|
|
return WERROR_NONE;
|
|
}
|
|
|
|
int FellowshipManager::RequestUpdates(const std::string &name, DWORD requester_id, BOOL on)
|
|
{
|
|
std::unordered_map<std::string, Fellowship *>::iterator i = m_Fellowships.find(name);
|
|
if (i == m_Fellowships.end())
|
|
return WERROR_FELLOWSHIP_NO_FELLOWSHIP;
|
|
|
|
Fellowship *fs = i->second;
|
|
fs->SetUpdates(requester_id, on);
|
|
return WERROR_NONE;
|
|
}
|
|
|
|
double FellowshipManager::GetEvenSplitXPPctg(unsigned int uiNumFellows)
|
|
{
|
|
switch (uiNumFellows)
|
|
{
|
|
case 1:
|
|
return 1.0;
|
|
case 2:
|
|
return 0.75;
|
|
case 3:
|
|
return 0.6;
|
|
case 4:
|
|
return 0.55;
|
|
case 5:
|
|
return 0.5;
|
|
case 6:
|
|
return 0.45;
|
|
case 7:
|
|
return 0.4;
|
|
case 8:
|
|
return 0.35;
|
|
case 9:
|
|
return 0.31111111;
|
|
case 0xA:
|
|
return 0.28;
|
|
default:
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
unsigned __int64 FellowshipManager::GetExperienceProportion(unsigned int level)
|
|
{
|
|
return ExperienceSystem::ExperienceToRaiseLevel(level, level + 1);
|
|
}
|
|
|
|
void FellowshipManager::Chat(const std::string &name, DWORD sender_id, const char *text)
|
|
{
|
|
std::unordered_map<std::string, Fellowship *>::iterator i = m_Fellowships.find(name);
|
|
if (i == m_Fellowships.end())
|
|
return;
|
|
|
|
Fellowship *fs = i->second;
|
|
fs->Chat(sender_id, text);
|
|
}
|