272 lines
6.3 KiB
C++
272 lines
6.3 KiB
C++
#include "stdafx.h"
|
|
#include "Map.h"
|
|
#include "../shared/DateTime.h"
|
|
|
|
CBot::CBot()
|
|
{
|
|
Initialize();
|
|
}
|
|
|
|
void CBot::Initialize()
|
|
{
|
|
MerchantChat.clear();
|
|
LastWarpTime = 0;
|
|
m_tLastKillTime = 0;
|
|
m_sChallangeAchieveID = 0;
|
|
m_pktcount = 0;
|
|
m_strUserID.clear();
|
|
m_strMemo.clear();
|
|
m_strAccountID.clear();
|
|
for (int i = 0; i < STAT_COUNT; i++)
|
|
m_bRebStats[i] = 0;
|
|
m_sAchieveCoverTitle = 0;
|
|
|
|
memset(&m_arSellMerchantItems, 0, sizeof(m_arSellMerchantItems));
|
|
memset(&m_arBuyMerchantItems, 0, sizeof(m_arBuyMerchantItems));
|
|
m_bMerchantState = MERCHANT_STATE_NONE;
|
|
m_bAuthority = 1;
|
|
m_sBind = -1;
|
|
m_state = GAME_STATE_CONNECTED;
|
|
m_bPartyLeader = false;
|
|
m_bIsChicken = false;
|
|
m_bIsHidingHelmet = false;
|
|
m_bIsHidingCospre = false;
|
|
|
|
m_bPremiumMerchant = false;
|
|
m_bInParty = false;
|
|
|
|
m_bInvisibilityType = INVIS_NONE;
|
|
|
|
m_sDirection = 0;
|
|
|
|
memset(&m_bStats, 0, sizeof(m_bStats));
|
|
|
|
m_bAuthority = AUTHORITY_PLAYER;
|
|
m_bLevel = 1;
|
|
m_iExp = 0;
|
|
m_iBank = m_iGold = 0;
|
|
m_iLoyalty = 100;
|
|
m_iLoyaltyMonthly = 0;
|
|
m_iMannerPoint = 0;
|
|
m_sHp = m_sMp = m_sSp = 0;
|
|
|
|
m_iMaxHp = 0;
|
|
m_iMaxMp = 1;
|
|
m_iMaxSp = 120;
|
|
m_sMerchantsSocketID = -1;
|
|
m_bResHpType = USER_STANDING;
|
|
m_bBlockPrivateChat = false;
|
|
m_sPrivateChatUser = -1;
|
|
m_bNeedParty = 0x01;
|
|
|
|
|
|
m_bAbnormalType = ABNORMAL_NORMAL; // User starts out in normal size.
|
|
m_nOldAbnormalType = m_bAbnormalType;
|
|
|
|
|
|
m_teamColour = TeamColourNone;
|
|
|
|
}
|
|
|
|
bool CBot::RegisterRegion()
|
|
{
|
|
uint16
|
|
new_region_x = GetNewRegionX(), new_region_z = GetNewRegionZ(),
|
|
old_region_x = GetRegionX(), old_region_z = GetRegionZ();
|
|
|
|
if (GetRegion() == nullptr || (old_region_x == new_region_x && old_region_z == new_region_z))
|
|
return false;
|
|
|
|
AddToRegion(new_region_x, new_region_z);
|
|
|
|
RemoveRegion(old_region_x - new_region_x, old_region_z - new_region_z);
|
|
InsertRegion(new_region_x - old_region_x, new_region_z - old_region_z);
|
|
|
|
return true;
|
|
}
|
|
|
|
void CBot::AddToRegion(int16 new_region_x, int16 new_region_z)
|
|
{
|
|
GetRegion()->Remove(this);
|
|
SetRegion(new_region_x, new_region_z);
|
|
GetRegion()->Add(this);
|
|
}
|
|
|
|
void CBot::RemoveRegion(int16 del_x, int16 del_z)
|
|
{
|
|
ASSERT(GetMap() != nullptr);
|
|
|
|
Packet result;
|
|
GetInOut(result, INOUT_OUT);
|
|
g_pMain->Send_OldRegions(&result, del_x, del_z, GetMap(), GetRegionX(), GetRegionZ(),nullptr,0);
|
|
}
|
|
|
|
void CBot::InsertRegion(int16 insert_x, int16 insert_z)
|
|
{
|
|
ASSERT(GetMap() != nullptr);
|
|
|
|
Packet result;
|
|
GetInOut(result, INOUT_IN);
|
|
g_pMain->Send_NewRegions(&result, insert_x, insert_z, GetMap(), GetRegionX(), GetRegionZ(),nullptr,0);
|
|
}
|
|
|
|
void CBot::SetRegion(uint16 x /*= -1*/, uint16 z /*= -1*/)
|
|
{
|
|
m_sRegionX = x; m_sRegionZ = z;
|
|
m_pRegion = m_pMap->GetRegion(x, z); // TODO: Clean this up
|
|
}
|
|
|
|
void CBot::StateChangeServerDirect(uint8 bType, uint32 nBuff)
|
|
{
|
|
uint8 buff = *(uint8 *)&nBuff; // don't ask
|
|
switch (bType)
|
|
{
|
|
case 1:
|
|
m_bResHpType = buff;
|
|
break;
|
|
|
|
case 2:
|
|
m_bNeedParty = buff;
|
|
break;
|
|
|
|
case 3:
|
|
m_nOldAbnormalType = m_bAbnormalType;
|
|
|
|
|
|
m_bAbnormalType = nBuff;
|
|
break;
|
|
|
|
case 5:
|
|
m_bAbnormalType = nBuff;
|
|
break;
|
|
|
|
case 6:
|
|
nBuff = m_bPartyLeader; // we don't set this here.
|
|
break;
|
|
|
|
case 7:
|
|
break;
|
|
|
|
case 8: // beginner quest
|
|
break;
|
|
|
|
case 14:
|
|
break;
|
|
}
|
|
|
|
Packet result(WIZ_STATE_CHANGE);
|
|
result << GetID() << bType << nBuff;
|
|
SendToRegion(&result);
|
|
}
|
|
|
|
void CBot::GetInOut(Packet & result, uint8 bType)
|
|
{
|
|
result.Initialize(WIZ_USER_INOUT);
|
|
result << uint16(bType) << GetID();
|
|
if (bType != INOUT_OUT)
|
|
GetUserInfo(result);
|
|
}
|
|
|
|
void CBot::UserInOut(uint8 bType)
|
|
{
|
|
Packet result;
|
|
GetInOut(result, bType);
|
|
|
|
Guard lock(g_pMain->m_BotcharacterNameLock);
|
|
if (bType == INOUT_OUT)
|
|
{
|
|
GetRegion()->Remove(this);
|
|
m_state = GAME_STATE_CONNECTED;
|
|
|
|
std::string upperName = GetName();
|
|
STRTOUPPER(upperName);
|
|
|
|
g_pMain->m_BotcharacterNameMap.erase(upperName);
|
|
}
|
|
else
|
|
{
|
|
GetRegion()->Add(this);
|
|
m_state = GAME_STATE_INGAME;
|
|
|
|
std::string upperName = GetName();
|
|
STRTOUPPER(upperName);
|
|
g_pMain->m_BotcharacterNameMap[upperName] = this;
|
|
|
|
}
|
|
SendToRegion(&result);
|
|
}
|
|
|
|
void CBot::SendToRegion(Packet *pkt)
|
|
{
|
|
g_pMain->Send_Region(pkt, GetMap(), GetRegionX(), GetRegionZ(), nullptr, 0);
|
|
}
|
|
|
|
void CBot::GetUserInfo(Packet & pkt)
|
|
{
|
|
|
|
pkt.SByte();
|
|
pkt << GetName()
|
|
<< uint16(m_bNation) << GetClanID() << m_bFame;
|
|
|
|
CKnights * pKnights = g_pMain->GetClanPtr(GetClanID());
|
|
if (pKnights == nullptr)
|
|
{
|
|
pkt << uint32(0) << uint16(0) << uint8(0) << uint16(-1) << uint32(0) << uint8(0);
|
|
}
|
|
else
|
|
{
|
|
CKnights *aKnights = g_pMain->GetClanPtr(pKnights->GetAllianceID());
|
|
|
|
pkt << pKnights->GetAllianceID()
|
|
<< pKnights->m_strName
|
|
<< pKnights->m_byGrade << pKnights->m_byRanking
|
|
<< uint16(pKnights->m_sMarkVersion) // symbol/mark version
|
|
<< pKnights->GetCapeID(aKnights) // cape ID
|
|
<< pKnights->m_bCapeR << pKnights->m_bCapeG << pKnights->m_bCapeB << uint8(0) // this is stored in 4 bytes after all.
|
|
// not sure what this is, but it (just?) enables the clan symbol on the cape
|
|
// value in dump was 9, but everything tested seems to behave as equally well...
|
|
// we'll probably have to implement logic to respect requirements.
|
|
<< uint8(1);
|
|
}
|
|
uint8 bInvisibilityType = m_bInvisibilityType;
|
|
if (bInvisibilityType != INVIS_NONE)
|
|
bInvisibilityType = INVIS_DISPEL_ON_MOVE;
|
|
|
|
pkt << m_bLevel << m_bRace << m_sClass
|
|
<< GetSPosX() << GetSPosZ() << GetSPosY()
|
|
<< m_bFace << m_nHair
|
|
<< m_bResHpType << uint32(m_bAbnormalType)
|
|
<< m_bNeedParty
|
|
<< m_bAuthority
|
|
<< m_bPartyLeader // is party leader (bool)
|
|
<< bInvisibilityType // visibility state
|
|
<< uint8(m_teamColour) // team colour (i.e. in soccer, 0=none, 1=blue, 2=red)
|
|
<< m_bIsHidingHelmet << m_bIsHidingCospre // either this is correct and items are super buggy, or it causes baldness. You choose.
|
|
<< m_sDirection // direction
|
|
<< m_bIsChicken // chicken/beginner flag
|
|
<< m_bRank // king flag
|
|
<< uint16(0)
|
|
<< int8(-1) << int8(-1); // NP ranks (total, monthly)
|
|
|
|
|
|
uint8 equippedItems[] =
|
|
{
|
|
BREAST, LEG, HEAD, GLOVE, FOOT, SHOULDER, RIGHTHAND, LEFTHAND, CWING, CHELMET, CLEFT, CRIGHT, CTOP, FAIRY
|
|
};
|
|
|
|
foreach_array (i, equippedItems)
|
|
{
|
|
_ITEM_DATA * pItem = &m_sItemArray[equippedItems[i]];
|
|
|
|
if(pItem == nullptr)
|
|
continue;
|
|
|
|
pkt << pItem->nNum << pItem->sDuration << pItem->bFlag;
|
|
}
|
|
|
|
|
|
|
|
pkt << m_bZone << uint8(-1) << uint8(-1) << uint16(0) << uint16(0) << uint16(0) << m_bIsHidingCospre << uint8(0) << uint8(GetRebLevel()) << uint16(m_sAchieveCoverTitle) << uint16(0) << uint8(0) << uint8(0);
|
|
|
|
}
|