2022-03-05 12:44:06 +02:00
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "constants.h"
|
|
|
|
|
#include "sectree_manager.h"
|
|
|
|
|
#include "item_manager.h"
|
|
|
|
|
#include "buffer_manager.h"
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#include "packet.h"
|
|
|
|
|
#include "char.h"
|
|
|
|
|
#include "char_manager.h"
|
|
|
|
|
#include "guild.h"
|
|
|
|
|
#include "guild_manager.h"
|
|
|
|
|
#include "desc.h"
|
|
|
|
|
#include "desc_manager.h"
|
|
|
|
|
#include "desc_client.h"
|
|
|
|
|
#include "questmanager.h"
|
|
|
|
|
#include "building.h"
|
|
|
|
|
|
|
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
// ADD_SUPPLY_BUILDING
|
|
|
|
|
BUILDING_INCREASE_GUILD_MEMBER_COUNT_SMALL = 14061,
|
|
|
|
|
BUILDING_INCREASE_GUILD_MEMBER_COUNT_MEDIUM = 14062,
|
|
|
|
|
BUILDING_INCREASE_GUILD_MEMBER_COUNT_LARGE = 14063,
|
|
|
|
|
// END_OF_ADD_SUPPLY_BUILDING
|
|
|
|
|
|
|
|
|
|
FLAG_VNUM = 14200,
|
|
|
|
|
WALL_DOOR_VNUM = 14201,
|
|
|
|
|
WALL_BACK_VNUM = 14202,
|
|
|
|
|
WALL_LEFT_VNUM = 14203,
|
|
|
|
|
WALL_RIGHT_VNUM = 14204,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using namespace building;
|
|
|
|
|
|
|
|
|
|
CObject::CObject(TObject * pData, TObjectProto * pProto)
|
|
|
|
|
: m_pProto(pProto), m_dwVID(0), m_chNPC(NULL)
|
|
|
|
|
{
|
|
|
|
|
CEntity::Initialize(ENTITY_OBJECT);
|
|
|
|
|
|
2022-03-06 17:36:43 +02:00
|
|
|
|
memcpy(&m_data, pData, sizeof(TObject));
|
2022-03-05 12:44:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CObject::~CObject()
|
|
|
|
|
{
|
|
|
|
|
Destroy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CObject::Destroy()
|
|
|
|
|
{
|
|
|
|
|
if (m_pProto)
|
|
|
|
|
{
|
|
|
|
|
SECTREE_MANAGER::instance().ForAttrRegion(GetMapIndex(),
|
|
|
|
|
GetX() + m_pProto->lRegion[0],
|
|
|
|
|
GetY() + m_pProto->lRegion[1],
|
|
|
|
|
GetX() + m_pProto->lRegion[2],
|
|
|
|
|
GetY() + m_pProto->lRegion[3],
|
2022-03-12 11:39:41 +02:00
|
|
|
|
(int)m_data.zRot, // ADD_BUILDING_ROTATION
|
2022-03-05 12:44:06 +02:00
|
|
|
|
ATTR_OBJECT,
|
|
|
|
|
ATTR_REGION_MODE_REMOVE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CEntity::Destroy();
|
|
|
|
|
|
|
|
|
|
if (GetSectree())
|
|
|
|
|
GetSectree()->RemoveEntity(this);
|
|
|
|
|
|
|
|
|
|
// <Factor> NPC should be destroyed in CHARACTER_MANAGER
|
|
|
|
|
// BUILDING_NPC
|
|
|
|
|
/*
|
|
|
|
|
if (m_chNPC) {
|
|
|
|
|
M2_DESTROY_CHARACTER(m_chNPC);
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
RemoveSpecialEffect();
|
|
|
|
|
// END_OF_BUILDING_NPC
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BUILDING_NPC
|
|
|
|
|
void CObject::Reconstruct(DWORD dwVnum)
|
|
|
|
|
{
|
|
|
|
|
const TMapRegion * r = SECTREE_MANAGER::instance().GetMapRegion(m_data.lMapIndex);
|
|
|
|
|
if (!r)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
CLand* pLand = GetLand();
|
|
|
|
|
pLand->RequestDeleteObject(GetID());
|
|
|
|
|
pLand->RequestCreateObject(dwVnum, m_data.lMapIndex, m_data.x - r->sx, m_data.y - r->sy, m_data.xRot, m_data.yRot, m_data.zRot, false);
|
|
|
|
|
}
|
|
|
|
|
// END_OF_BUILDING_NPC
|
|
|
|
|
|
|
|
|
|
void CObject::EncodeInsertPacket(LPENTITY entity)
|
|
|
|
|
{
|
|
|
|
|
LPDESC d;
|
|
|
|
|
|
|
|
|
|
if (!(d = entity->GetDesc()))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
sys_log(0, "ObjectInsertPacket vid %u vnum %u rot %f %f %f",
|
|
|
|
|
m_dwVID, m_data.dwVnum, m_data.xRot, m_data.yRot, m_data.zRot);
|
|
|
|
|
|
|
|
|
|
TPacketGCCharacterAdd pack;
|
|
|
|
|
|
|
|
|
|
memset(&pack, 0, sizeof(TPacketGCCharacterAdd));
|
|
|
|
|
|
|
|
|
|
pack.header = HEADER_GC_CHARACTER_ADD;
|
|
|
|
|
pack.dwVID = m_dwVID;
|
|
|
|
|
pack.bType = CHAR_TYPE_BUILDING;
|
|
|
|
|
pack.angle = m_data.zRot;
|
|
|
|
|
pack.x = GetX();
|
|
|
|
|
pack.y = GetY();
|
|
|
|
|
pack.z = GetZ();
|
|
|
|
|
pack.wRaceNum = m_data.dwVnum;
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD> ȸ<><C8B8> <20><><EFBFBD><EFBFBD>(<28><><EFBFBD>϶<EFBFBD><CFB6><EFBFBD> <20><> <20><>ġ)<29><> <20><>ȯ
|
|
|
|
|
pack.dwAffectFlag[0] = unsigned(m_data.xRot);
|
|
|
|
|
pack.dwAffectFlag[1] = unsigned(m_data.yRot);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (GetLand())
|
|
|
|
|
{
|
|
|
|
|
// pack.dwGuild = GetLand()->GetOwner();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
d->Packet(&pack, sizeof(pack));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CObject::EncodeRemovePacket(LPENTITY entity)
|
|
|
|
|
{
|
|
|
|
|
LPDESC d;
|
|
|
|
|
|
|
|
|
|
if (!(d = entity->GetDesc()))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
sys_log(0, "ObjectRemovePacket vid %u", m_dwVID);
|
|
|
|
|
|
|
|
|
|
TPacketGCCharacterDelete pack;
|
|
|
|
|
|
|
|
|
|
pack.header = HEADER_GC_CHARACTER_DEL;
|
|
|
|
|
pack.id = m_dwVID;
|
|
|
|
|
|
|
|
|
|
d->Packet(&pack, sizeof(TPacketGCCharacterDelete));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CObject::SetVID(DWORD dwVID)
|
|
|
|
|
{
|
|
|
|
|
m_dwVID = dwVID;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-12 11:39:41 +02:00
|
|
|
|
bool CObject::Show(int lMapIndex, int x, int y)
|
2022-03-05 12:44:06 +02:00
|
|
|
|
{
|
|
|
|
|
LPSECTREE tree = SECTREE_MANAGER::instance().Get(lMapIndex, x, y);
|
|
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
|
{
|
|
|
|
|
sys_err("cannot find sectree by %dx%d mapindex %d", x, y, lMapIndex);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GetSectree())
|
|
|
|
|
{
|
|
|
|
|
GetSectree()->RemoveEntity(this);
|
|
|
|
|
ViewCleanup();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_data.lMapIndex = lMapIndex;
|
|
|
|
|
m_data.x = x;
|
|
|
|
|
m_data.y = y;
|
|
|
|
|
|
|
|
|
|
Save();
|
|
|
|
|
|
|
|
|
|
SetMapIndex(lMapIndex);
|
|
|
|
|
SetXYZ(x, y, 0);
|
|
|
|
|
|
|
|
|
|
tree->InsertEntity(this);
|
|
|
|
|
UpdateSectree();
|
|
|
|
|
|
|
|
|
|
SECTREE_MANAGER::instance().ForAttrRegion(lMapIndex,
|
|
|
|
|
x + m_pProto->lRegion[0],
|
|
|
|
|
y + m_pProto->lRegion[1],
|
|
|
|
|
x + m_pProto->lRegion[2],
|
|
|
|
|
y + m_pProto->lRegion[3],
|
2022-03-12 11:39:41 +02:00
|
|
|
|
(int)m_data.zRot,
|
2022-03-05 12:44:06 +02:00
|
|
|
|
ATTR_OBJECT,
|
|
|
|
|
ATTR_REGION_MODE_SET);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CObject::Save()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CObject::ApplySpecialEffect()
|
|
|
|
|
{
|
|
|
|
|
if (m_pProto)
|
|
|
|
|
{
|
|
|
|
|
// ADD_SUPPLY_BUILDING
|
|
|
|
|
if (m_pProto->dwVnum == BUILDING_INCREASE_GUILD_MEMBER_COUNT_SMALL ||
|
|
|
|
|
m_pProto->dwVnum == BUILDING_INCREASE_GUILD_MEMBER_COUNT_MEDIUM ||
|
|
|
|
|
m_pProto->dwVnum == BUILDING_INCREASE_GUILD_MEMBER_COUNT_LARGE)
|
|
|
|
|
{
|
|
|
|
|
CLand* pLand = GetLand();
|
|
|
|
|
DWORD guild_id = 0;
|
|
|
|
|
if (pLand)
|
|
|
|
|
guild_id = pLand->GetOwner();
|
|
|
|
|
CGuild* pGuild = CGuildManager::instance().FindGuild(guild_id);
|
|
|
|
|
if (pGuild)
|
|
|
|
|
{
|
|
|
|
|
switch (m_pProto->dwVnum)
|
|
|
|
|
{
|
|
|
|
|
case BUILDING_INCREASE_GUILD_MEMBER_COUNT_SMALL:
|
|
|
|
|
pGuild->SetMemberCountBonus(6);
|
|
|
|
|
break;
|
|
|
|
|
case BUILDING_INCREASE_GUILD_MEMBER_COUNT_MEDIUM:
|
|
|
|
|
pGuild->SetMemberCountBonus(12);
|
|
|
|
|
break;
|
|
|
|
|
case BUILDING_INCREASE_GUILD_MEMBER_COUNT_LARGE:
|
|
|
|
|
pGuild->SetMemberCountBonus(18);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (map_allow_find(pLand->GetMapIndex()))
|
|
|
|
|
{
|
|
|
|
|
pGuild->BroadcastMemberCountBonus();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// END_OF_ADD_SUPPLY_BUILDING
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CObject::RemoveSpecialEffect()
|
|
|
|
|
{
|
|
|
|
|
if (m_pProto)
|
|
|
|
|
{
|
|
|
|
|
// ADD_SUPPLY_BUILDING
|
|
|
|
|
if (m_pProto->dwVnum == BUILDING_INCREASE_GUILD_MEMBER_COUNT_SMALL ||
|
|
|
|
|
m_pProto->dwVnum == BUILDING_INCREASE_GUILD_MEMBER_COUNT_MEDIUM ||
|
|
|
|
|
m_pProto->dwVnum == BUILDING_INCREASE_GUILD_MEMBER_COUNT_LARGE)
|
|
|
|
|
{
|
|
|
|
|
CLand* pLand = GetLand();
|
|
|
|
|
DWORD guild_id = 0;
|
|
|
|
|
if (pLand)
|
|
|
|
|
guild_id = pLand->GetOwner();
|
|
|
|
|
CGuild* pGuild = CGuildManager::instance().FindGuild(guild_id);
|
|
|
|
|
if (pGuild)
|
|
|
|
|
{
|
|
|
|
|
pGuild->SetMemberCountBonus(0);
|
|
|
|
|
if (map_allow_find(pLand->GetMapIndex()))
|
|
|
|
|
pGuild->BroadcastMemberCountBonus();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// END_OF_ADD_SUPPLY_BUILDING
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BUILDING_NPC
|
|
|
|
|
void CObject::RegenNPC()
|
|
|
|
|
{
|
|
|
|
|
if (!m_pProto)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!m_pProto->dwNPCVnum)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!m_pkLand)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
DWORD dwGuildID = m_pkLand->GetOwner();
|
|
|
|
|
CGuild* pGuild = CGuildManager::instance().FindGuild(dwGuildID);
|
|
|
|
|
|
|
|
|
|
if (!pGuild)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
int x = m_pProto->lNPCX;
|
|
|
|
|
int y = m_pProto->lNPCY;
|
|
|
|
|
int newX, newY;
|
|
|
|
|
|
|
|
|
|
float rot = m_data.zRot * 2.0f * M_PI / 360.0f;
|
|
|
|
|
|
|
|
|
|
newX = (int)(( x * cosf(rot)) + ( y * sinf(rot)));
|
|
|
|
|
newY = (int)(( y * cosf(rot)) - ( x * sinf(rot)));
|
|
|
|
|
|
|
|
|
|
m_chNPC = CHARACTER_MANAGER::instance().SpawnMob(m_pProto->dwNPCVnum,
|
|
|
|
|
GetMapIndex(),
|
|
|
|
|
GetX() + newX,
|
|
|
|
|
GetY() + newY,
|
|
|
|
|
GetZ(),
|
|
|
|
|
false,
|
|
|
|
|
(int)m_data.zRot);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!m_chNPC)
|
|
|
|
|
{
|
|
|
|
|
sys_err("Cannot create guild npc");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_chNPC->SetGuild(pGuild);
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>渶<EFBFBD><E6B8B6><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>س<EFBFBD><D8B3>´<EFBFBD>
|
|
|
|
|
if ( m_pProto->dwVnum == 14061 || m_pProto->dwVnum == 14062 || m_pProto->dwVnum == 14063 )
|
|
|
|
|
{
|
|
|
|
|
quest::PC* pPC = quest::CQuestManager::instance().GetPC(pGuild->GetMasterPID());
|
|
|
|
|
|
|
|
|
|
if ( pPC != NULL )
|
|
|
|
|
{
|
|
|
|
|
pPC->SetFlag("alter_of_power.build_level", pGuild->GetLevel());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// END_OF_BUILDING_NPC
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
CLand::CLand(TLand * pData)
|
|
|
|
|
{
|
2022-03-06 17:36:43 +02:00
|
|
|
|
memcpy(&m_data, pData, sizeof(TLand));
|
2022-03-05 12:44:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CLand::~CLand()
|
|
|
|
|
{
|
|
|
|
|
Destroy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLand::Destroy()
|
|
|
|
|
{
|
|
|
|
|
itertype(m_map_pkObject) it = m_map_pkObject.begin();
|
|
|
|
|
|
|
|
|
|
while (it != m_map_pkObject.end())
|
|
|
|
|
{
|
|
|
|
|
LPOBJECT pkObj = (it++)->second;
|
|
|
|
|
CManager::instance().UnregisterObject(pkObj);
|
|
|
|
|
M2_DELETE(pkObj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_map_pkObject.clear();
|
|
|
|
|
m_map_pkObjectByVID.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const TLand & CLand::GetData()
|
|
|
|
|
{
|
|
|
|
|
return m_data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLand::PutData(const TLand * data)
|
|
|
|
|
{
|
|
|
|
|
memcpy(&m_data, data, sizeof(TLand));
|
|
|
|
|
|
|
|
|
|
if (m_data.dwGuildID)
|
|
|
|
|
{
|
|
|
|
|
const TMapRegion * r = SECTREE_MANAGER::instance().GetMapRegion(m_data.lMapIndex);
|
|
|
|
|
|
|
|
|
|
if (r)
|
|
|
|
|
{
|
|
|
|
|
CharacterVectorInteractor i;
|
|
|
|
|
|
|
|
|
|
if (CHARACTER_MANAGER::instance().GetCharactersByRaceNum(20040, i))
|
|
|
|
|
{
|
|
|
|
|
CharacterVectorInteractor::iterator it = i.begin();
|
|
|
|
|
|
|
|
|
|
while (it != i.end())
|
|
|
|
|
{
|
|
|
|
|
LPCHARACTER ch = *(it++);
|
|
|
|
|
|
|
|
|
|
if (ch->GetMapIndex() != m_data.lMapIndex)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
int x = ch->GetX() - r->sx;
|
|
|
|
|
int y = ch->GetY() - r->sy;
|
|
|
|
|
|
|
|
|
|
if (x > m_data.x + m_data.width || x < m_data.x)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (y > m_data.y + m_data.height || y < m_data.y)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
M2_DESTROY_CHARACTER(ch);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLand::InsertObject(LPOBJECT pkObj)
|
|
|
|
|
{
|
|
|
|
|
m_map_pkObject.insert(std::make_pair(pkObj->GetID(), pkObj));
|
|
|
|
|
m_map_pkObjectByVID.insert(std::make_pair(pkObj->GetVID(), pkObj));
|
|
|
|
|
|
|
|
|
|
pkObj->SetLand(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LPOBJECT CLand::FindObject(DWORD dwID)
|
|
|
|
|
{
|
|
|
|
|
std::map<DWORD, LPOBJECT>::iterator it = m_map_pkObject.find(dwID);
|
|
|
|
|
|
|
|
|
|
if (it == m_map_pkObject.end())
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return it->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LPOBJECT CLand::FindObjectByGroup(DWORD dwGroupVnum)
|
|
|
|
|
{
|
|
|
|
|
std::map<DWORD, LPOBJECT>::iterator it;
|
|
|
|
|
for (it = m_map_pkObject.begin(); it != m_map_pkObject.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
LPOBJECT pObj = it->second;
|
|
|
|
|
if (pObj->GetGroup() == dwGroupVnum)
|
|
|
|
|
return pObj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LPOBJECT CLand::FindObjectByVnum(DWORD dwVnum)
|
|
|
|
|
{
|
|
|
|
|
std::map<DWORD, LPOBJECT>::iterator it;
|
|
|
|
|
for (it = m_map_pkObject.begin(); it != m_map_pkObject.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
LPOBJECT pObj = it->second;
|
|
|
|
|
if (pObj->GetVnum() == dwVnum)
|
|
|
|
|
return pObj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BUILDING_NPC
|
|
|
|
|
LPOBJECT CLand::FindObjectByNPC(LPCHARACTER npc)
|
|
|
|
|
{
|
|
|
|
|
if (!npc)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
std::map<DWORD, LPOBJECT>::iterator it;
|
|
|
|
|
for (it = m_map_pkObject.begin(); it != m_map_pkObject.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
LPOBJECT pObj = it->second;
|
|
|
|
|
if (pObj->GetNPC() == npc)
|
|
|
|
|
return pObj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
// END_OF_BUILDING_NPC
|
|
|
|
|
|
|
|
|
|
LPOBJECT CLand::FindObjectByVID(DWORD dwVID)
|
|
|
|
|
{
|
|
|
|
|
std::map<DWORD, LPOBJECT>::iterator it = m_map_pkObjectByVID.find(dwVID);
|
|
|
|
|
|
|
|
|
|
if (it == m_map_pkObjectByVID.end())
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return it->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLand::DeleteObject(DWORD dwID)
|
|
|
|
|
{
|
|
|
|
|
LPOBJECT pkObj;
|
|
|
|
|
|
|
|
|
|
if (!(pkObj = FindObject(dwID)))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
sys_log(0, "Land::DeleteObject %u", dwID);
|
|
|
|
|
CManager::instance().UnregisterObject(pkObj);
|
|
|
|
|
M2_DESTROY_CHARACTER (pkObj->GetNPC());
|
|
|
|
|
|
|
|
|
|
m_map_pkObject.erase(dwID);
|
|
|
|
|
m_map_pkObjectByVID.erase(dwID);
|
|
|
|
|
|
|
|
|
|
M2_DELETE(pkObj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct FIsIn
|
|
|
|
|
{
|
2022-03-12 11:39:41 +02:00
|
|
|
|
int sx, sy;
|
|
|
|
|
int ex, ey;
|
2022-03-05 12:44:06 +02:00
|
|
|
|
|
|
|
|
|
bool bIn;
|
2022-03-12 11:39:41 +02:00
|
|
|
|
FIsIn ( int sx_, int sy_, int ex_, int ey_)
|
2022-03-05 12:44:06 +02:00
|
|
|
|
: sx(sx_), sy(sy_), ex(ex_), ey(ey_), bIn(false)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
void operator () (LPENTITY ent)
|
|
|
|
|
{
|
|
|
|
|
if (ent->IsType(ENTITY_CHARACTER))
|
|
|
|
|
{
|
|
|
|
|
LPCHARACTER ch = (LPCHARACTER) ent;
|
|
|
|
|
if (ch->IsMonster())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (sx <= ch->GetX() && ch->GetX() <= ex
|
|
|
|
|
&& sy <= ch->GetY() && ch->GetY() <= ey)
|
|
|
|
|
{
|
|
|
|
|
bIn = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2022-03-12 11:39:41 +02:00
|
|
|
|
bool CLand::RequestCreateObject(DWORD dwVnum, int lMapIndex, int x, int y, float xRot, float yRot, float zRot, bool checkAnother)
|
2022-03-05 12:44:06 +02:00
|
|
|
|
{
|
|
|
|
|
SECTREE_MANAGER& rkSecTreeMgr = SECTREE_MANAGER::instance();
|
|
|
|
|
TObjectProto * pkProto = CManager::instance().GetObjectProto(dwVnum);
|
|
|
|
|
|
|
|
|
|
if (!pkProto)
|
|
|
|
|
{
|
|
|
|
|
sys_err("Invalid Object vnum %u", dwVnum);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const TMapRegion * r = rkSecTreeMgr.GetMapRegion(lMapIndex);
|
|
|
|
|
if (!r)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
sys_log(0, "RequestCreateObject(vnum=%u, map=%d, pos=(%d,%d), rot=(%.1f,%.1f,%.1f) region(%d,%d ~ %d,%d)",
|
|
|
|
|
dwVnum, lMapIndex, x, y, xRot, yRot, zRot, r->sx, r->sy, r->ex, r->ey);
|
|
|
|
|
|
|
|
|
|
x += r->sx;
|
|
|
|
|
y += r->sy;
|
|
|
|
|
|
|
|
|
|
int sx = r->sx + m_data.x;
|
|
|
|
|
int ex = sx + m_data.width;
|
|
|
|
|
int sy = r->sy + m_data.y;
|
|
|
|
|
int ey = sy + m_data.height;
|
|
|
|
|
|
|
|
|
|
int osx = x + pkProto->lRegion[0];
|
|
|
|
|
int osy = y + pkProto->lRegion[1];
|
|
|
|
|
int oex = x + pkProto->lRegion[2];
|
|
|
|
|
int oey = y + pkProto->lRegion[3];
|
|
|
|
|
|
|
|
|
|
float rad = zRot * 2.0f * M_PI / 360.0f;
|
|
|
|
|
|
|
|
|
|
int tsx = (int)(pkProto->lRegion[0] * cosf(rad) + pkProto->lRegion[1] * sinf(rad) + x);
|
|
|
|
|
int tsy = (int)(pkProto->lRegion[0] * -sinf(rad) + pkProto->lRegion[1] * cosf(rad) + y);
|
|
|
|
|
|
|
|
|
|
int tex = (int)(pkProto->lRegion[2] * cosf(rad) + pkProto->lRegion[3] * sinf(rad) + x);
|
|
|
|
|
int tey = (int)(pkProto->lRegion[2] * -sinf(rad) + pkProto->lRegion[3] * cosf(rad) + y);
|
|
|
|
|
|
|
|
|
|
if (tsx < sx || tex > ex || tsy < sy || tey > ey)
|
|
|
|
|
{
|
|
|
|
|
sys_err("invalid position: object is outside of land region\nLAND: %d %d ~ %d %d\nOBJ: %d %d ~ %d %d", sx, sy, ex, ey, osx, osy, oex, oey);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ADD_BUILDING_ROTATION
|
|
|
|
|
if ( checkAnother )
|
|
|
|
|
{
|
2022-03-12 11:39:41 +02:00
|
|
|
|
if (rkSecTreeMgr.ForAttrRegion(lMapIndex, osx, osy, oex, oey, (int)zRot, ATTR_OBJECT, ATTR_REGION_MODE_CHECK))
|
2022-03-05 12:44:06 +02:00
|
|
|
|
{
|
|
|
|
|
sys_err("another object already exist");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
FIsIn f (osx, osy, oex, oey);
|
|
|
|
|
rkSecTreeMgr.GetMap(lMapIndex)->for_each(f);
|
|
|
|
|
|
|
|
|
|
if (f.bIn)
|
|
|
|
|
{
|
|
|
|
|
sys_err("another object already exist");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// END_OF_BUILDING_NPC
|
|
|
|
|
|
|
|
|
|
TPacketGDCreateObject p;
|
|
|
|
|
|
|
|
|
|
p.dwVnum = dwVnum;
|
|
|
|
|
p.dwLandID = m_data.dwID;
|
|
|
|
|
p.lMapIndex = lMapIndex;
|
|
|
|
|
p.x = x;
|
|
|
|
|
p.y = y;
|
|
|
|
|
p.xRot = xRot;
|
|
|
|
|
p.yRot = yRot;
|
|
|
|
|
p.zRot = zRot;
|
|
|
|
|
|
|
|
|
|
db_clientdesc->DBPacket(HEADER_GD_CREATE_OBJECT, 0, &p, sizeof(TPacketGDCreateObject));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLand::RequestDeleteObject(DWORD dwID)
|
|
|
|
|
{
|
|
|
|
|
if (!FindObject(dwID))
|
|
|
|
|
{
|
|
|
|
|
sys_err("no object by id %u", dwID);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
db_clientdesc->DBPacket(HEADER_GD_DELETE_OBJECT, 0, &dwID, sizeof(DWORD));
|
|
|
|
|
sys_log(0, "RequestDeleteObject id %u", dwID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLand::RequestDeleteObjectByVID(DWORD dwVID)
|
|
|
|
|
{
|
|
|
|
|
LPOBJECT pkObj;
|
|
|
|
|
|
|
|
|
|
if (!(pkObj = FindObjectByVID(dwVID)))
|
|
|
|
|
{
|
|
|
|
|
sys_err("no object by vid %u", dwVID);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD dwID = pkObj->GetID();
|
|
|
|
|
db_clientdesc->DBPacket(HEADER_GD_DELETE_OBJECT, 0, &dwID, sizeof(DWORD));
|
|
|
|
|
sys_log(0, "RequestDeleteObject vid %u id %u", dwVID, dwID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLand::SetOwner(DWORD dwGuild)
|
|
|
|
|
{
|
|
|
|
|
if (m_data.dwGuildID != dwGuild)
|
|
|
|
|
{
|
|
|
|
|
m_data.dwGuildID = dwGuild;
|
|
|
|
|
RequestUpdate(dwGuild);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLand::RequestUpdate(DWORD dwGuild)
|
|
|
|
|
{
|
|
|
|
|
DWORD a[2];
|
|
|
|
|
|
|
|
|
|
a[0] = GetID();
|
|
|
|
|
a[1] = dwGuild;
|
|
|
|
|
|
|
|
|
|
db_clientdesc->DBPacket(HEADER_GD_UPDATE_LAND, 0, &a[0], sizeof(DWORD) * 2);
|
|
|
|
|
sys_log(0, "RequestUpdate id %u guild %u", a[0], a[1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
CManager::CManager()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CManager::~CManager()
|
|
|
|
|
{
|
|
|
|
|
Destroy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CManager::Destroy()
|
|
|
|
|
{
|
|
|
|
|
itertype(m_map_pkLand) it = m_map_pkLand.begin();
|
|
|
|
|
for ( ; it != m_map_pkLand.end(); ++it) {
|
|
|
|
|
M2_DELETE(it->second);
|
|
|
|
|
}
|
|
|
|
|
m_map_pkLand.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CManager::LoadObjectProto(const TObjectProto * pProto, int size) // from DB
|
|
|
|
|
{
|
|
|
|
|
m_vec_kObjectProto.resize(size);
|
2022-03-06 17:36:43 +02:00
|
|
|
|
memcpy(&m_vec_kObjectProto[0], pProto, sizeof(TObjectProto) * size);
|
2022-03-05 12:44:06 +02:00
|
|
|
|
|
|
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
|
{
|
|
|
|
|
TObjectProto & r = m_vec_kObjectProto[i];
|
|
|
|
|
|
|
|
|
|
// BUILDING_NPC
|
|
|
|
|
sys_log(0, "ObjectProto %u price %u upgrade %u upg_limit %u life %d NPC %u",
|
|
|
|
|
r.dwVnum, r.dwPrice, r.dwUpgradeVnum, r.dwUpgradeLimitTime, r.lLife, r.dwNPCVnum);
|
|
|
|
|
// END_OF_BUILDING_NPC
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < OBJECT_MATERIAL_MAX_NUM; ++j)
|
|
|
|
|
{
|
|
|
|
|
if (!r.kMaterials[j].dwItemVnum)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (NULL == ITEM_MANAGER::instance().GetTable(r.kMaterials[j].dwItemVnum))
|
|
|
|
|
{
|
|
|
|
|
sys_err(" mat: ERROR!! no item by vnum %u", r.kMaterials[j].dwItemVnum);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sys_log(0, " mat: %u %u", r.kMaterials[j].dwItemVnum, r.kMaterials[j].dwCount);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_map_pkObjectProto.insert(std::make_pair(r.dwVnum, &m_vec_kObjectProto[i]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TObjectProto * CManager::GetObjectProto(DWORD dwVnum)
|
|
|
|
|
{
|
|
|
|
|
itertype(m_map_pkObjectProto) it = m_map_pkObjectProto.find(dwVnum);
|
|
|
|
|
|
|
|
|
|
if (it == m_map_pkObjectProto.end())
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return it->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CManager::LoadLand(TLand * pTable) // from DB
|
|
|
|
|
{
|
|
|
|
|
// MapAllow<6F><77> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> load<61><64> <20>ؾ<EFBFBD><D8BE>Ѵ<EFBFBD>.
|
|
|
|
|
// <09>ǹ<EFBFBD>(object)<29><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>忡 <20><><EFBFBD><EFBFBD> <20>ִ<EFBFBD><D6B4><EFBFBD> <20>˱<EFBFBD> <20><><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD> <20>ǹ<EFBFBD><C7B9><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD> <20>˾<EFBFBD><CBBE>Ѵ<EFBFBD>.
|
|
|
|
|
// <09><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> load<61><64> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ǹ<EFBFBD><C7B9><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>忡 <20>Ҽӵ<D2BC> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ؼ<EFBFBD>
|
|
|
|
|
// <09><><EFBFBD><EFBFBD> <20>ǹ<EFBFBD><C7B9><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ѵ<EFBFBD>.
|
|
|
|
|
//if (!map_allow_find(pTable->lMapIndex))
|
|
|
|
|
// return false;
|
|
|
|
|
|
|
|
|
|
CLand * pkLand = M2_NEW CLand(pTable);
|
|
|
|
|
m_map_pkLand.insert(std::make_pair(pkLand->GetID(), pkLand));
|
|
|
|
|
|
|
|
|
|
sys_log(0, "LAND: %u map %d %dx%d w %u h %u",
|
|
|
|
|
pTable->dwID, pTable->lMapIndex, pTable->x, pTable->y, pTable->width, pTable->height);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CManager::UpdateLand(TLand * pTable)
|
|
|
|
|
{
|
|
|
|
|
CLand * pkLand = FindLand(pTable->dwID);
|
|
|
|
|
|
|
|
|
|
if (!pkLand)
|
|
|
|
|
{
|
|
|
|
|
sys_err("cannot find land by id %u", pTable->dwID);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pkLand->PutData(pTable);
|
|
|
|
|
|
|
|
|
|
const DESC_MANAGER::DESC_SET & cont = DESC_MANAGER::instance().GetClientSet();
|
|
|
|
|
|
|
|
|
|
itertype(cont) it = cont.begin();
|
|
|
|
|
|
|
|
|
|
TPacketGCLandList p;
|
|
|
|
|
|
|
|
|
|
p.header = HEADER_GC_LAND_LIST;
|
|
|
|
|
p.size = sizeof(TPacketGCLandList) + sizeof(TLandPacketElement);
|
|
|
|
|
|
|
|
|
|
TLandPacketElement e;
|
|
|
|
|
|
|
|
|
|
e.dwID = pTable->dwID;
|
|
|
|
|
e.x = pTable->x;
|
|
|
|
|
e.y = pTable->y;
|
|
|
|
|
e.width = pTable->width;
|
|
|
|
|
e.height = pTable->height;
|
|
|
|
|
e.dwGuildID = pTable->dwGuildID;
|
|
|
|
|
|
|
|
|
|
sys_log(0, "BUILDING: UpdateLand %u pos %dx%d guild %u", e.dwID, e.x, e.y, e.dwGuildID);
|
|
|
|
|
|
|
|
|
|
CGuild *guild = CGuildManager::instance().FindGuild(pTable->dwGuildID);
|
|
|
|
|
while (it != cont.end())
|
|
|
|
|
{
|
|
|
|
|
LPDESC d = *(it++);
|
|
|
|
|
|
|
|
|
|
if (d->GetCharacter() && d->GetCharacter()->GetMapIndex() == pTable->lMapIndex)
|
|
|
|
|
{
|
|
|
|
|
// we must send the guild name first
|
|
|
|
|
d->GetCharacter()->SendGuildName(guild);
|
|
|
|
|
|
2022-03-12 11:39:41 +02:00
|
|
|
|
d->RawPacket(&p, sizeof(TPacketGCLandList));
|
2022-03-05 12:44:06 +02:00
|
|
|
|
d->Packet(&e, sizeof(TLandPacketElement));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CLand * CManager::FindLand(DWORD dwID)
|
|
|
|
|
{
|
|
|
|
|
std::map<DWORD, CLand *>::iterator it = m_map_pkLand.find(dwID);
|
|
|
|
|
|
|
|
|
|
if (it == m_map_pkLand.end())
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return it->second;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-12 11:39:41 +02:00
|
|
|
|
CLand * CManager::FindLand(int lMapIndex, int x, int y)
|
2022-03-05 12:44:06 +02:00
|
|
|
|
{
|
|
|
|
|
sys_log(0, "BUILDING: FindLand %d %d %d", lMapIndex, x, y);
|
|
|
|
|
|
|
|
|
|
const TMapRegion * r = SECTREE_MANAGER::instance().GetMapRegion(lMapIndex);
|
|
|
|
|
|
|
|
|
|
if (!r)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
x -= r->sx;
|
|
|
|
|
y -= r->sy;
|
|
|
|
|
|
|
|
|
|
itertype(m_map_pkLand) it = m_map_pkLand.begin();
|
|
|
|
|
|
|
|
|
|
while (it != m_map_pkLand.end())
|
|
|
|
|
{
|
|
|
|
|
CLand * pkLand = (it++)->second;
|
|
|
|
|
const TLand & r = pkLand->GetData();
|
|
|
|
|
|
|
|
|
|
if (r.lMapIndex != lMapIndex)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (x < r.x || y < r.y)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (x > r.x + r.width || y > r.y + r.height)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
return pkLand;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CLand * CManager::FindLandByGuild(DWORD GID)
|
|
|
|
|
{
|
|
|
|
|
itertype(m_map_pkLand) it = m_map_pkLand.begin();
|
|
|
|
|
|
|
|
|
|
while (it != m_map_pkLand.end())
|
|
|
|
|
{
|
|
|
|
|
CLand * pkLand = (it++)->second;
|
|
|
|
|
|
|
|
|
|
if (pkLand->GetData().dwGuildID == GID)
|
|
|
|
|
return pkLand;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CManager::LoadObject(TObject * pTable, bool isBoot) // from DB
|
|
|
|
|
{
|
|
|
|
|
CLand * pkLand = FindLand(pTable->dwLandID);
|
|
|
|
|
|
|
|
|
|
if (!pkLand)
|
|
|
|
|
{
|
|
|
|
|
sys_log(0, "Cannot find land by id %u", pTable->dwLandID);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TObjectProto * pkProto = GetObjectProto(pTable->dwVnum);
|
|
|
|
|
|
|
|
|
|
if (!pkProto)
|
|
|
|
|
{
|
|
|
|
|
sys_err("Cannot find object %u in prototype (id %u)", pTable->dwVnum, pTable->dwID);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sys_log(0, "OBJ: id %u vnum %u map %d pos %dx%d", pTable->dwID, pTable->dwVnum, pTable->lMapIndex, pTable->x, pTable->y);
|
|
|
|
|
|
|
|
|
|
LPOBJECT pkObj = M2_NEW CObject(pTable, pkProto);
|
|
|
|
|
|
|
|
|
|
DWORD dwVID = CHARACTER_MANAGER::instance().AllocVID();
|
|
|
|
|
pkObj->SetVID(dwVID);
|
|
|
|
|
|
|
|
|
|
m_map_pkObjByVID.insert(std::make_pair(dwVID, pkObj));
|
|
|
|
|
m_map_pkObjByID.insert(std::make_pair(pTable->dwID, pkObj));
|
|
|
|
|
|
|
|
|
|
pkLand->InsertObject(pkObj);
|
|
|
|
|
|
|
|
|
|
if (!isBoot)
|
|
|
|
|
pkObj->Show(pTable->lMapIndex, pTable->x, pTable->y);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
pkObj->SetMapIndex(pTable->lMapIndex);
|
|
|
|
|
pkObj->SetXYZ(pTable->x, pTable->y, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BUILDING_NPC
|
|
|
|
|
if (!isBoot)
|
|
|
|
|
{
|
|
|
|
|
if (pkProto->dwNPCVnum)
|
|
|
|
|
pkObj->RegenNPC();
|
|
|
|
|
|
|
|
|
|
pkObj->ApplySpecialEffect();
|
|
|
|
|
}
|
|
|
|
|
// END_OF_BUILDING_NPC
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CManager::FinalizeBoot()
|
|
|
|
|
{
|
|
|
|
|
itertype(m_map_pkObjByID) it = m_map_pkObjByID.begin();
|
|
|
|
|
|
|
|
|
|
while (it != m_map_pkObjByID.end())
|
|
|
|
|
{
|
|
|
|
|
LPOBJECT pkObj = (it++)->second;
|
|
|
|
|
|
|
|
|
|
pkObj->Show(pkObj->GetMapIndex(), pkObj->GetX(), pkObj->GetY());
|
|
|
|
|
// BUILDING_NPC
|
|
|
|
|
pkObj->RegenNPC();
|
|
|
|
|
pkObj->ApplySpecialEffect();
|
|
|
|
|
// END_OF_BUILDING_NPC
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BUILDING_NPC
|
|
|
|
|
sys_log(0, "FinalizeBoot");
|
|
|
|
|
// END_OF_BUILDING_NPC
|
|
|
|
|
|
|
|
|
|
itertype(m_map_pkLand) it2 = m_map_pkLand.begin();
|
|
|
|
|
|
|
|
|
|
while (it2 != m_map_pkLand.end())
|
|
|
|
|
{
|
|
|
|
|
CLand * pkLand = (it2++)->second;
|
|
|
|
|
|
|
|
|
|
const TLand & r = pkLand->GetData();
|
|
|
|
|
|
|
|
|
|
// LAND_MASTER_LOG
|
|
|
|
|
sys_log(0, "LandMaster map_index=%d pos=(%d, %d)", r.lMapIndex, r.x, r.y);
|
|
|
|
|
// END_OF_LAND_MASTER_LOG
|
|
|
|
|
|
|
|
|
|
if (r.dwGuildID != 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!map_allow_find(r.lMapIndex))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
const TMapRegion * region = SECTREE_MANAGER::instance().GetMapRegion(r.lMapIndex);
|
|
|
|
|
if (!region)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
CHARACTER_MANAGER::instance().SpawnMob(20040, r.lMapIndex, region->sx + r.x + (r.width / 2), region->sy + r.y + (r.height / 2), 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CManager::DeleteObject(DWORD dwID) // from DB
|
|
|
|
|
{
|
|
|
|
|
sys_log(0, "OBJ_DEL: %u", dwID);
|
|
|
|
|
|
|
|
|
|
itertype(m_map_pkObjByID) it = m_map_pkObjByID.find(dwID);
|
|
|
|
|
|
|
|
|
|
if (it == m_map_pkObjByID.end())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
it->second->GetLand()->DeleteObject(dwID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LPOBJECT CManager::FindObjectByVID(DWORD dwVID)
|
|
|
|
|
{
|
|
|
|
|
itertype(m_map_pkObjByVID) it = m_map_pkObjByVID.find(dwVID);
|
|
|
|
|
|
|
|
|
|
if (it == m_map_pkObjByVID.end())
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return it->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CManager::UnregisterObject(LPOBJECT pkObj)
|
|
|
|
|
{
|
|
|
|
|
m_map_pkObjByID.erase(pkObj->GetID());
|
|
|
|
|
m_map_pkObjByVID.erase(pkObj->GetVID());
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-12 11:39:41 +02:00
|
|
|
|
void CManager::SendLandList(LPDESC d, int lMapIndex)
|
2022-03-05 12:44:06 +02:00
|
|
|
|
{
|
|
|
|
|
TLandPacketElement e;
|
|
|
|
|
|
|
|
|
|
TEMP_BUFFER buf;
|
|
|
|
|
|
|
|
|
|
WORD wCount = 0;
|
|
|
|
|
|
|
|
|
|
itertype(m_map_pkLand) it = m_map_pkLand.begin();
|
|
|
|
|
|
|
|
|
|
while (it != m_map_pkLand.end())
|
|
|
|
|
{
|
|
|
|
|
CLand * pkLand = (it++)->second;
|
|
|
|
|
const TLand & r = pkLand->GetData();
|
|
|
|
|
|
|
|
|
|
if (r.lMapIndex != lMapIndex)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
LPCHARACTER ch = d->GetCharacter();
|
|
|
|
|
if (ch)
|
|
|
|
|
{
|
|
|
|
|
CGuild *guild = CGuildManager::instance().FindGuild(r.dwGuildID);
|
|
|
|
|
ch->SendGuildName(guild);
|
|
|
|
|
}
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
e.dwID = r.dwID;
|
|
|
|
|
e.x = r.x;
|
|
|
|
|
e.y = r.y;
|
|
|
|
|
e.width = r.width;
|
|
|
|
|
e.height = r.height;
|
|
|
|
|
e.dwGuildID = r.dwGuildID;
|
|
|
|
|
|
|
|
|
|
buf.write(&e, sizeof(TLandPacketElement));
|
|
|
|
|
++wCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sys_log(0, "SendLandList map %d count %u elem_size: %d", lMapIndex, wCount, buf.size());
|
|
|
|
|
|
|
|
|
|
if (wCount != 0)
|
|
|
|
|
{
|
|
|
|
|
TPacketGCLandList p;
|
|
|
|
|
|
|
|
|
|
p.header = HEADER_GC_LAND_LIST;
|
|
|
|
|
p.size = sizeof(TPacketGCLandList) + buf.size();
|
|
|
|
|
|
2022-03-12 11:39:41 +02:00
|
|
|
|
d->RawPacket(&p, sizeof(TPacketGCLandList));
|
2022-03-05 12:44:06 +02:00
|
|
|
|
d->Packet(buf.read_peek(), buf.size());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// LAND_CLEAR
|
|
|
|
|
void CManager::ClearLand(DWORD dwLandID)
|
|
|
|
|
{
|
|
|
|
|
CLand* pLand = FindLand(dwLandID);
|
|
|
|
|
|
|
|
|
|
if ( pLand == NULL )
|
|
|
|
|
{
|
|
|
|
|
sys_log(0, "LAND_CLEAR: there is no LAND id like %d", dwLandID);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pLand->ClearLand();
|
|
|
|
|
|
|
|
|
|
sys_log(0, "LAND_CLEAR: request Land Clear. LandID: %d", pLand->GetID());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CManager::ClearLandByGuildID(DWORD dwGuildID)
|
|
|
|
|
{
|
|
|
|
|
CLand* pLand = FindLandByGuild(dwGuildID);
|
|
|
|
|
|
|
|
|
|
if ( pLand == NULL )
|
|
|
|
|
{
|
|
|
|
|
sys_log(0, "LAND_CLEAR: there is no GUILD id like %d", dwGuildID);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pLand->ClearLand();
|
|
|
|
|
|
|
|
|
|
sys_log(0, "LAND_CLEAR: request Land Clear. LandID: %d", pLand->GetID());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLand::ClearLand()
|
|
|
|
|
{
|
|
|
|
|
itertype(m_map_pkObject) iter = m_map_pkObject.begin();
|
|
|
|
|
|
|
|
|
|
while ( iter != m_map_pkObject.end() )
|
|
|
|
|
{
|
|
|
|
|
RequestDeleteObject(iter->second->GetID());
|
|
|
|
|
iter++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SetOwner(0);
|
|
|
|
|
|
|
|
|
|
const TLand & r = GetData();
|
|
|
|
|
const TMapRegion * region = SECTREE_MANAGER::instance().GetMapRegion(r.lMapIndex);
|
|
|
|
|
|
|
|
|
|
CHARACTER_MANAGER::instance().SpawnMob(20040, r.lMapIndex, region->sx + r.x + (r.width / 2), region->sy + r.y + (r.height / 2), 0);
|
|
|
|
|
}
|
|
|
|
|
// END_LAND_CLEAR
|
|
|
|
|
|
|
|
|
|
// BUILD_WALL
|
2022-03-12 11:39:41 +02:00
|
|
|
|
void CLand::DrawWall(DWORD dwVnum, int nMapIndex, int& x, int& y, char length, float zRot)
|
2022-03-05 12:44:06 +02:00
|
|
|
|
{
|
|
|
|
|
int rot = (int)zRot;
|
|
|
|
|
rot = ((rot%360) / 90) * 90;
|
|
|
|
|
|
|
|
|
|
int dx=0, dy=0;
|
|
|
|
|
|
|
|
|
|
switch ( rot )
|
|
|
|
|
{
|
|
|
|
|
case 0 :
|
|
|
|
|
dx = -500;
|
|
|
|
|
dy = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 90 :
|
|
|
|
|
dx = 0;
|
|
|
|
|
dy = 500;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 180 :
|
|
|
|
|
dx = 500;
|
|
|
|
|
dy = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 270 :
|
|
|
|
|
dx = 0;
|
|
|
|
|
dy = -500;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ( int i=0; i < length; i++ )
|
|
|
|
|
{
|
|
|
|
|
this->RequestCreateObject(dwVnum, nMapIndex, x, y, 0, 0, rot, false);
|
|
|
|
|
x += dx;
|
|
|
|
|
y += dy;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-03-12 11:39:41 +02:00
|
|
|
|
bool CLand::RequestCreateWall(int nMapIndex, float rot)
|
2022-03-05 12:44:06 +02:00
|
|
|
|
{
|
|
|
|
|
const bool WALL_ANOTHER_CHECKING_ENABLE = false;
|
|
|
|
|
|
|
|
|
|
const TLand& land = GetData();
|
|
|
|
|
|
|
|
|
|
int center_x = land.x + land.width / 2;
|
|
|
|
|
int center_y = land.y + land.height / 2;
|
|
|
|
|
|
|
|
|
|
int wall_x = center_x;
|
|
|
|
|
int wall_y = center_y;
|
|
|
|
|
int wall_half_w = 1000;
|
|
|
|
|
int wall_half_h = 1362;
|
|
|
|
|
|
|
|
|
|
if (rot == 0.0f) // <20><><EFBFBD><EFBFBD> <20><>
|
|
|
|
|
{
|
|
|
|
|
int door_x = wall_x;
|
|
|
|
|
int door_y = wall_y + wall_half_h;
|
|
|
|
|
RequestCreateObject(WALL_DOOR_VNUM, nMapIndex, wall_x, wall_y + wall_half_h, door_x, door_y, 0.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(WALL_BACK_VNUM, nMapIndex, wall_x, wall_y - wall_half_h, door_x, door_y, 0.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(WALL_LEFT_VNUM, nMapIndex, wall_x - wall_half_w, wall_y, door_x, door_y, 0.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(WALL_RIGHT_VNUM, nMapIndex, wall_x + wall_half_w, wall_y, door_x, door_y, 0.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
}
|
|
|
|
|
else if (rot == 180.0f) // <20><><EFBFBD><EFBFBD> <20><>
|
|
|
|
|
{
|
|
|
|
|
int door_x = wall_x;
|
|
|
|
|
int door_y = wall_y - wall_half_h;
|
|
|
|
|
RequestCreateObject(WALL_DOOR_VNUM, nMapIndex, wall_x, wall_y - wall_half_h, door_x, door_y, 180.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(WALL_BACK_VNUM, nMapIndex, wall_x, wall_y + wall_half_h, door_x, door_y, 0.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(WALL_LEFT_VNUM, nMapIndex, wall_x - wall_half_w, wall_y, door_x, door_y, 0.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(WALL_RIGHT_VNUM, nMapIndex, wall_x + wall_half_w, wall_y, door_x, door_y, 0.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
}
|
|
|
|
|
else if (rot == 90.0f) // <20><><EFBFBD><EFBFBD> <20><>
|
|
|
|
|
{
|
|
|
|
|
int door_x = wall_x + wall_half_h;
|
|
|
|
|
int door_y = wall_y;
|
|
|
|
|
RequestCreateObject(WALL_DOOR_VNUM, nMapIndex, wall_x + wall_half_h, wall_y, door_x, door_y, 90.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(WALL_BACK_VNUM, nMapIndex, wall_x - wall_half_h, wall_y, door_x, door_y, 90.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(WALL_LEFT_VNUM, nMapIndex, wall_x, wall_y - wall_half_w, door_x, door_y, 90.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(WALL_RIGHT_VNUM, nMapIndex, wall_x, wall_y + wall_half_w, door_x, door_y, 90.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
}
|
|
|
|
|
else if (rot == 270.0f) // <20><><EFBFBD><EFBFBD> <20><>
|
|
|
|
|
{
|
|
|
|
|
int door_x = wall_x - wall_half_h;
|
|
|
|
|
int door_y = wall_y;
|
|
|
|
|
RequestCreateObject(WALL_DOOR_VNUM, nMapIndex, wall_x - wall_half_h, wall_y, door_x, door_y, 90.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(WALL_BACK_VNUM, nMapIndex, wall_x + wall_half_h, wall_y, door_x, door_y, 90.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(WALL_LEFT_VNUM, nMapIndex, wall_x, wall_y - wall_half_w, door_x, door_y, 90.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(WALL_RIGHT_VNUM, nMapIndex, wall_x, wall_y + wall_half_w, door_x, door_y, 90.0f, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (test_server)
|
|
|
|
|
{
|
|
|
|
|
RequestCreateObject(FLAG_VNUM, nMapIndex, land.x + 50, land.y + 50, 0, 0, 0.0, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(FLAG_VNUM, nMapIndex, land.x + land.width - 50, land.y + 50, 0, 0, 90.0, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(FLAG_VNUM, nMapIndex, land.x + land.width - 50, land.y + land.height - 50, 0, 0, 180.0, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
RequestCreateObject(FLAG_VNUM, nMapIndex, land.x + 50, land.y + land.height - 50, 0, 0, 270.0, WALL_ANOTHER_CHECKING_ENABLE);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLand::RequestDeleteWall()
|
|
|
|
|
{
|
|
|
|
|
itertype(m_map_pkObject) iter = m_map_pkObject.begin();
|
|
|
|
|
|
|
|
|
|
while (iter != m_map_pkObject.end())
|
|
|
|
|
{
|
|
|
|
|
unsigned id = iter->second->GetID();
|
|
|
|
|
unsigned vnum = iter->second->GetVnum();
|
|
|
|
|
|
|
|
|
|
switch (vnum)
|
|
|
|
|
{
|
|
|
|
|
case WALL_DOOR_VNUM:
|
|
|
|
|
case WALL_BACK_VNUM:
|
|
|
|
|
case WALL_LEFT_VNUM:
|
|
|
|
|
case WALL_RIGHT_VNUM:
|
|
|
|
|
RequestDeleteObject(id);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (test_server)
|
|
|
|
|
{
|
|
|
|
|
if (FLAG_VNUM == vnum)
|
|
|
|
|
RequestDeleteObject(id);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
iter++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-12 11:39:41 +02:00
|
|
|
|
bool CLand::RequestCreateWallBlocks(DWORD dwVnum, int nMapIndex, char wallSize, bool doorEast, bool doorWest, bool doorSouth, bool doorNorth)
|
2022-03-05 12:44:06 +02:00
|
|
|
|
{
|
|
|
|
|
const TLand & r = GetData();
|
|
|
|
|
|
2022-03-12 11:39:41 +02:00
|
|
|
|
int startX = r.x + (r.width / 2) - (1300 + wallSize*500);
|
|
|
|
|
int startY = r.y + (r.height / 2) + (1300 + wallSize*500);
|
2022-03-05 12:44:06 +02:00
|
|
|
|
|
|
|
|
|
DWORD corner = dwVnum - 4;
|
|
|
|
|
DWORD wall = dwVnum - 3;
|
|
|
|
|
DWORD door = dwVnum - 1;
|
|
|
|
|
|
|
|
|
|
bool checkAnother = false;
|
2022-03-12 11:39:41 +02:00
|
|
|
|
int* ptr = NULL;
|
2022-03-05 12:44:06 +02:00
|
|
|
|
int delta = 1;
|
|
|
|
|
int rot = 270;
|
|
|
|
|
|
|
|
|
|
bool doorOpen[4];
|
|
|
|
|
doorOpen[0] = doorWest;
|
|
|
|
|
doorOpen[1] = doorNorth;
|
|
|
|
|
doorOpen[2] = doorEast;
|
|
|
|
|
doorOpen[3] = doorSouth;
|
|
|
|
|
|
|
|
|
|
if ( wallSize > 3 ) wallSize = 3;
|
|
|
|
|
else if ( wallSize < 0 ) wallSize = 0;
|
|
|
|
|
|
|
|
|
|
for ( int i=0; i < 4; i++, rot -= 90 )
|
|
|
|
|
{
|
|
|
|
|
switch ( i )
|
|
|
|
|
{
|
|
|
|
|
case 0 :
|
|
|
|
|
delta = -1;
|
|
|
|
|
ptr = &startY;
|
|
|
|
|
break;
|
|
|
|
|
case 1 :
|
|
|
|
|
delta = 1;
|
|
|
|
|
ptr = &startX;
|
|
|
|
|
break;
|
|
|
|
|
case 2 :
|
|
|
|
|
ptr = &startY;
|
|
|
|
|
delta = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 3 :
|
|
|
|
|
ptr = &startX;
|
|
|
|
|
delta = -1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->RequestCreateObject(corner, nMapIndex, startX, startY, 0, 0, rot, checkAnother);
|
|
|
|
|
|
|
|
|
|
*ptr = *ptr + ( 700 * delta );
|
|
|
|
|
|
|
|
|
|
if ( doorOpen[i] )
|
|
|
|
|
{
|
|
|
|
|
this->DrawWall(wall, nMapIndex, startX, startY, wallSize, rot);
|
|
|
|
|
|
|
|
|
|
*ptr = *ptr + ( 700 * delta );
|
|
|
|
|
|
|
|
|
|
this->RequestCreateObject(door, nMapIndex, startX, startY, 0, 0, rot, checkAnother);
|
|
|
|
|
|
|
|
|
|
*ptr = *ptr + ( 1300 * delta );
|
|
|
|
|
|
|
|
|
|
this->DrawWall(wall, nMapIndex, startX, startY, wallSize, rot);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this->DrawWall(wall, nMapIndex, startX, startY, wallSize*2 + 4, rot);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*ptr = *ptr + ( 100 * delta );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLand::RequestDeleteWallBlocks(DWORD dwID)
|
|
|
|
|
{
|
|
|
|
|
itertype(m_map_pkObject) iter = m_map_pkObject.begin();
|
|
|
|
|
|
|
|
|
|
DWORD corner = dwID - 4;
|
|
|
|
|
DWORD wall = dwID - 3;
|
|
|
|
|
DWORD door = dwID - 1;
|
|
|
|
|
DWORD dwVnum = 0;
|
|
|
|
|
|
|
|
|
|
while ( iter != m_map_pkObject.end() )
|
|
|
|
|
{
|
|
|
|
|
dwVnum = iter->second->GetVnum();
|
|
|
|
|
|
|
|
|
|
if ( dwVnum == corner || dwVnum == wall || dwVnum == door )
|
|
|
|
|
{
|
|
|
|
|
RequestDeleteObject(iter->second->GetID());
|
|
|
|
|
}
|
|
|
|
|
iter++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// END_BUILD_WALL
|
|
|
|
|
|