396 lines
9.1 KiB
C++
396 lines
9.1 KiB
C++
#include "stdafx.h"
|
|
#include "Knights.h"
|
|
#include "DBAgent.h"
|
|
|
|
using std::string;
|
|
|
|
CKnights::CKnights()
|
|
{
|
|
m_sIndex = 0;
|
|
m_byFlag = ClanTypeNone;
|
|
m_byNation = 0;
|
|
m_byGrade = 5;
|
|
m_byRanking = 0;
|
|
m_sMembers = 1;
|
|
memset(&m_Image, 0, sizeof(m_Image));
|
|
m_nMoney = 0;
|
|
m_sDomination = 0;
|
|
m_nPoints = 0;
|
|
m_nClanPointFund = 0;
|
|
m_sCape = -1;
|
|
m_sAlliance = 0;
|
|
m_sMarkLen = 0;
|
|
m_sMarkVersion = 0;
|
|
m_bCapeR = m_bCapeG = m_bCapeB = 0;
|
|
m_sClanPointMethod = 0;
|
|
}
|
|
|
|
void CKnights::OnLogin(CUser *pUser)
|
|
{
|
|
Packet result, result2;
|
|
string Name = "", myName = pUser->GetName();
|
|
STRTOUPPER(myName);
|
|
// Set the active session for this user
|
|
foreach_array (i, m_arKnightsUser)
|
|
{
|
|
_KNIGHTS_USER * p = &m_arKnightsUser[i];
|
|
if (!p->byUsed)
|
|
continue;
|
|
|
|
Name = p->strUserName;
|
|
STRTOUPPER(Name);
|
|
|
|
if(Name != myName)
|
|
continue;
|
|
|
|
p->pSession = pUser;
|
|
pUser->m_pKnightsUser = p;
|
|
break;
|
|
}
|
|
|
|
// Send login notice
|
|
// TODO: Shift this to SERVER_RESOURCE
|
|
std::string buffer = string_format("%s is online.", pUser->GetName().c_str());
|
|
ChatPacket::Construct(&result, KNIGHTS_CHAT, &buffer);
|
|
Send(&result);
|
|
|
|
// Construct the clan notice packet to send to the logged in player
|
|
if (!m_strClanNotice.empty())
|
|
{
|
|
ConstructClanNoticePacket(&result);
|
|
pUser->Send(&result);
|
|
}
|
|
|
|
if(m_sAlliance != 0)
|
|
{
|
|
std::string buffer2 = string_format("%s is online.", pUser->GetName().c_str());
|
|
ChatPacket::Construct(&result2, ALLIANCE_CHAT, &buffer2);
|
|
g_pMain->Send_KnightsAlliance(GetAllianceID(), &result2);
|
|
}
|
|
}
|
|
|
|
|
|
void CKnights::ConstructClanNoticePacket(Packet *result)
|
|
{
|
|
result->Initialize(WIZ_NOTICE);
|
|
result->DByte();
|
|
*result << uint8(4) // type
|
|
<< uint8(1) // total blocks
|
|
<< m_strName // header
|
|
<< m_strClanNotice;
|
|
}
|
|
|
|
/**
|
|
* @brief Updates this clan's notice with clanNotice
|
|
* and informs logged in clan members.
|
|
*
|
|
* @param clanNotice The clan notice.
|
|
*/
|
|
void CKnights::UpdateClanNotice(std::string & clanNotice)
|
|
{
|
|
if (clanNotice.length() > MAX_CLAN_NOTICE_LENGTH || clanNotice.size() == 0)
|
|
return;
|
|
|
|
Packet result;
|
|
|
|
// Update the stored clan notice
|
|
m_strClanNotice = clanNotice;
|
|
|
|
// Construct the update notice packet to inform players the clan notice has changed
|
|
std::string updateNotice = string_format("%s updated the clan notice.", m_strChief.c_str());
|
|
ChatPacket::Construct(&result, KNIGHTS_CHAT, &updateNotice);
|
|
Send(&result);
|
|
|
|
// Construct the new clan notice packet
|
|
ConstructClanNoticePacket(&result);
|
|
Send(&result);
|
|
|
|
// Tell the database to update the clan notice.
|
|
result.Initialize(WIZ_CHAT);
|
|
result << uint8(CLAN_NOTICE) << GetID() << clanNotice;
|
|
g_pMain->AddDatabaseRequest(result);
|
|
}
|
|
|
|
/**
|
|
* @brief Sends a request to update the clan's fund in the database.
|
|
*/
|
|
void CKnights::UpdateClanFund()
|
|
{
|
|
Packet result(WIZ_KNIGHTS_PROCESS, uint8(KNIGHTS_UPDATE_FUND));
|
|
result << GetID() << uint32(m_nClanPointFund);
|
|
g_pMain->AddDatabaseRequest(result);
|
|
}
|
|
|
|
void CKnights::OnLogout(CUser *pUser)
|
|
{
|
|
|
|
|
|
// Unset the active session for this user
|
|
if (pUser->m_pKnightsUser != nullptr)
|
|
{
|
|
|
|
pUser->m_pKnightsUser->m_lastLogin = UNIXTIME;
|
|
pUser->m_pKnightsUser->m_lastLogined = uint32(UNIXTIME);
|
|
pUser->m_pKnightsUser->pSession = nullptr;
|
|
pUser->m_pKnightsUser = nullptr;
|
|
}
|
|
|
|
|
|
Packet logoutNotice;
|
|
// TODO: Shift this to SERVER_RESOURCE
|
|
std::string buffer = string_format("%s is offline.", pUser->GetName().c_str());
|
|
ChatPacket::Construct(&logoutNotice, KNIGHTS_CHAT, &buffer);
|
|
Send(&logoutNotice);
|
|
|
|
|
|
Packet result2;
|
|
|
|
if(m_sAlliance != 0)
|
|
{
|
|
std::string buffer2 = string_format("%s is offline.", pUser->GetName().c_str());
|
|
ChatPacket::Construct(&result2, ALLIANCE_CHAT, &buffer2);
|
|
g_pMain->Send_KnightsAlliance(GetAllianceID(), &result2);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
bool CKnights::AddUser(std::string & strUserID)
|
|
{
|
|
for (int i = 0; i < MAX_CLAN_USERS; i++)
|
|
{
|
|
_KNIGHTS_USER * p = &m_arKnightsUser[i];
|
|
if (p->byUsed)
|
|
continue;
|
|
|
|
p->byUsed = 1;
|
|
p->strUserName = strUserID;
|
|
p->pSession = g_pMain->GetUserPtr(strUserID, TYPE_CHARACTER);
|
|
if (p->pSession != nullptr)
|
|
{
|
|
p->pSession->m_pKnightsUser = p;
|
|
p->m_sFame = p->pSession->m_bFame;
|
|
p->m_bLevel = p->pSession->GetLevel();
|
|
p->m_sClass = p->pSession->GetClass();
|
|
}
|
|
if(p->pSession == nullptr)
|
|
g_DBAgent.GetClanUserData(GetID(),m_arKnightsUser[i]);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CKnights::AddUser(CUser *pUser)
|
|
{
|
|
if (pUser == nullptr
|
|
|| !AddUser(pUser->GetName()))
|
|
return false;
|
|
|
|
pUser->SetClanID(m_sIndex);
|
|
pUser->m_bFame = TRAINEE;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Removes the specified user from the clan array.
|
|
*
|
|
* @param strUserID Identifier for the user.
|
|
*
|
|
* @return .
|
|
*/
|
|
bool CKnights::RemoveUser(std::string & strUserID)
|
|
{
|
|
string Name;
|
|
STRTOUPPER(strUserID);
|
|
for (int i = 0; i < MAX_CLAN_USERS; i++)
|
|
{
|
|
_KNIGHTS_USER * p = &m_arKnightsUser[i];
|
|
if (p->byUsed == 0)
|
|
continue;
|
|
|
|
Name = p->strUserName;
|
|
STRTOUPPER(Name);
|
|
|
|
if(Name != strUserID)
|
|
continue;
|
|
|
|
// If they're not logged in (note: logged in users being removed have their NP refunded in the other handler)
|
|
// but they've donated NP, ensure they're refunded for the next time they login.
|
|
if (p->nDonatedNP > 0)
|
|
RefundDonatedNP(p->nDonatedNP, p->pSession, p->strUserName.c_str());
|
|
|
|
p->Initialise();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @brief Removes the specified user from this clan.
|
|
*
|
|
* @param pUser The user.
|
|
*/
|
|
bool CKnights::RemoveUser(CUser *pUser)
|
|
{
|
|
if (pUser == nullptr)
|
|
//|| pUser->m_pKnightsUser == nullptr)
|
|
return false;
|
|
|
|
uint32 nDonatedNP = 0;
|
|
if( pUser->m_pKnightsUser != nullptr )
|
|
nDonatedNP = pUser->m_pKnightsUser->nDonatedNP;
|
|
|
|
if (nDonatedNP > 0)
|
|
RefundDonatedNP(nDonatedNP, pUser);
|
|
|
|
pUser->SetClanID(0);
|
|
pUser->m_bFame = 0;
|
|
|
|
if( pUser->m_pKnightsUser != nullptr )
|
|
pUser->m_pKnightsUser->Initialise();
|
|
|
|
pUser->m_pKnightsUser = nullptr;
|
|
|
|
if (!pUser->isClanLeader())
|
|
pUser->SendClanUserStatusUpdate();
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Refunds 30% of the user's donated NP.
|
|
* If the user has the item "CONT Recovery", refund ALL of the user's
|
|
* donated NP.
|
|
*
|
|
* @param nDonatedNP The donated NP.
|
|
* @param pUser The user's session, when refunding the user in-game.
|
|
* Set to nullptr to indicate the use of the character's name
|
|
* and consequently a database update instead.
|
|
* @param strUserID Logged out character's name.
|
|
* Used to refund logged out characters' national points
|
|
* when pUser is set to nullptr.
|
|
*/
|
|
void CKnights::RefundDonatedNP(uint32 nDonatedNP, CUser * pUser /*= nullptr*/, const char * strUserID /*= nullptr*/)
|
|
{
|
|
// Refund 30% of NP unless the user has the item "CONT Recovery".
|
|
// In this case, ALL of the donated NP will be refunded.
|
|
|
|
if (pUser != nullptr)
|
|
{
|
|
if (pUser->CheckExistItem(ITEM_CONT_RECOVERY))
|
|
pUser->RobItem(ITEM_CONT_RECOVERY);
|
|
else
|
|
nDonatedNP = (nDonatedNP * 30) / 100;
|
|
}
|
|
else
|
|
nDonatedNP = (nDonatedNP * 30) / 100;
|
|
|
|
// Remove the refunded NP from the clan fund
|
|
if(m_nClanPointFund > nDonatedNP)
|
|
m_nClanPointFund -= nDonatedNP;
|
|
else
|
|
m_nClanPointFund = 0;
|
|
|
|
// If the player's logged in, just adjust their national points in-game.
|
|
if (pUser != nullptr)
|
|
{
|
|
pUser->m_iLoyalty += nDonatedNP;
|
|
pUser->SendLoyaltyChange(0);
|
|
return;
|
|
}
|
|
// For logged out players, we must update the player's national points in the database.
|
|
Packet result(WIZ_KNIGHTS_PROCESS, uint8(KNIGHTS_REFUND_POINTS));
|
|
result << strUserID << nDonatedNP;
|
|
g_pMain->AddDatabaseRequest(result);
|
|
}
|
|
|
|
void CKnights::SendToRegion(Packet *pkt)
|
|
{
|
|
foreach_array (i, m_arKnightsUser)
|
|
{
|
|
_KNIGHTS_USER *p = &m_arKnightsUser[i];
|
|
if (p->byUsed && p->pSession != nullptr
|
|
&& p->pSession->GetClanID() == m_sIndex)
|
|
p->pSession->SendToRegion(pkt);
|
|
}
|
|
}
|
|
|
|
void CKnights::Disband(CUser *pLeader /*= nullptr*/)
|
|
{
|
|
std::string clanNotice;
|
|
g_pMain->GetServerResource(m_byFlag == ClanTypeTraining ? IDS_CLAN_DESTROY : IDS_KNIGHTS_DESTROY,
|
|
&clanNotice, m_strName.c_str());
|
|
SendChat(clanNotice.c_str());
|
|
|
|
foreach_array (i, m_arKnightsUser)
|
|
{
|
|
_KNIGHTS_USER *p = &m_arKnightsUser[i];
|
|
if (!p->byUsed)
|
|
continue;
|
|
|
|
// If the user's logged in, handle the player data removal in-game.
|
|
// It will be saved to the database when they log out.
|
|
if (p->pSession != nullptr)
|
|
RemoveUser(p->pSession);
|
|
else
|
|
RemoveUser(p->strUserName);
|
|
|
|
}
|
|
g_pMain->m_KnightsArray.DeleteData(m_sIndex);
|
|
|
|
Packet result(WIZ_KNIGHTS_PROCESS, uint8(KNIGHTS_DESTROY));
|
|
result << uint8(1);
|
|
pLeader->Send(&result);
|
|
}
|
|
|
|
void CKnights::SendUpdate()
|
|
{
|
|
CKnights *aKnights = g_pMain->GetClanPtr(GetAllianceID());
|
|
|
|
Packet result(WIZ_KNIGHTS_PROCESS, uint8(KNIGHTS_UPDATE));
|
|
result << GetID() << m_byFlag << GetCapeID(aKnights);
|
|
Send(&result);
|
|
}
|
|
|
|
void CKnights::SendChat(const char * format, ...)
|
|
{
|
|
char buffer[128];
|
|
va_list ap;
|
|
va_start(ap, format);
|
|
vsnprintf(buffer, 128, format, ap);
|
|
va_end(ap);
|
|
|
|
Packet result;
|
|
ChatPacket::Construct(&result, KNIGHTS_CHAT, buffer);
|
|
Send(&result);
|
|
}
|
|
|
|
void CKnights::SendChatAlliance(const char * format, ...)
|
|
{
|
|
char buffer[128];
|
|
va_list ap;
|
|
va_start(ap, format);
|
|
vsnprintf(buffer, 128, format, ap);
|
|
va_end(ap);
|
|
|
|
Packet result;
|
|
ChatPacket::Construct(&result, ALLIANCE_CHAT, buffer);
|
|
Send(&result);
|
|
}
|
|
|
|
void CKnights::Send(Packet *pkt)
|
|
{
|
|
foreach_array (i, m_arKnightsUser)
|
|
{
|
|
_KNIGHTS_USER *p = &m_arKnightsUser[i];
|
|
if (p->byUsed && p->pSession != nullptr)
|
|
p->pSession->Send(pkt);
|
|
}
|
|
}
|
|
|
|
CKnights::~CKnights()
|
|
{
|
|
} |