server/game/src/sectree_manager.cpp

1673 lines
37 KiB
C++
Raw Normal View History

2022-03-05 12:44:06 +02:00
#include "stdafx.h"
#include <sstream>
#include "../../libgame/include/targa.h"
#include "../../libgame/include/attribute.h"
#include "config.h"
#include "utils.h"
#include "sectree_manager.h"
#include "regen.h"
#include "lzo_manager.h"
#include "desc.h"
#include "desc_manager.h"
#include "char.h"
#include "char_manager.h"
#include "item.h"
#include "item_manager.h"
#include "buffer_manager.h"
#include "packet.h"
#include "start_position.h"
#include "dev_log.h"
WORD SECTREE_MANAGER::current_sectree_version = MAKEWORD(0, 3);
SECTREE_MAP::SECTREE_MAP()
{
memset( &m_setting, 0, sizeof(m_setting) );
}
SECTREE_MAP::~SECTREE_MAP()
{
MapType::iterator it = map_.begin();
while (it != map_.end()) {
LPSECTREE sectree = (it++)->second;
M2_DELETE(sectree);
}
map_.clear();
}
SECTREE_MAP::SECTREE_MAP(SECTREE_MAP & r)
{
m_setting = r.m_setting;
MapType::iterator it = r.map_.begin();
while (it != r.map_.end())
{
LPSECTREE tree = M2_NEW SECTREE;
tree->m_id.coord = it->second->m_id.coord;
tree->CloneAttribute(it->second);
map_.insert(MapType::value_type(it->first, tree));
++it;
}
Build();
}
LPSECTREE SECTREE_MAP::Find(DWORD dwPackage)
{
MapType::iterator it = map_.find(dwPackage);
if (it == map_.end())
return NULL;
return it->second;
}
LPSECTREE SECTREE_MAP::Find(DWORD x, DWORD y)
{
SECTREEID id;
id.coord.x = x / SECTREE_SIZE;
id.coord.y = y / SECTREE_SIZE;
return Find(id.package);
}
void SECTREE_MAP::Build()
{
// Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD> <20>ݰ<EFBFBD> 150m ij<><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD>
// 3x3ĭ -> 5x5 ĭ<><C4AD><EFBFBD><EFBFBD> <20>ֺ<EFBFBD>sectree Ȯ<><C8AE>(<28>ѱ<EFBFBD>)
if (LC_IsYMIR() || LC_IsKorea())
{
#define NEIGHBOR_LENGTH 5
#define NUM_OF_NEIGHBORS (NEIGHBOR_LENGTH * NEIGHBOR_LENGTH - 1)
int width = NEIGHBOR_LENGTH / 2;
struct neighbor_coord_s
{
int x;
int y;
} neighbor_coord[NUM_OF_NEIGHBORS];
{
int i = 0;
for (int x = -width; x <= width; ++x)
{
for (int y = -width; y <= width; ++y)
{
if (x == 0 && y == 0)
continue;
neighbor_coord[i].x = x * SECTREE_SIZE;
neighbor_coord[i].y = y * SECTREE_SIZE;
++i;
}
}
}
//
// <20><><EFBFBD><EFBFBD> sectree<65><65> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> sectree<65><65> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
//
MapType::iterator it = map_.begin();
while (it != map_.end())
{
LPSECTREE tree = it->second;
tree->m_neighbor_list.push_back(tree); // <20>ڽ<EFBFBD><DABD><EFBFBD> <20>ִ´<D6B4>.
sys_log(3, "%dx%d", tree->m_id.coord.x, tree->m_id.coord.y);
int x = tree->m_id.coord.x * SECTREE_SIZE;
int y = tree->m_id.coord.y * SECTREE_SIZE;
for (DWORD i = 0; i < NUM_OF_NEIGHBORS; ++i)
{
LPSECTREE tree2 = Find(x + neighbor_coord[i].x, y + neighbor_coord[i].y);
if (tree2)
{
sys_log(3, " %d %dx%d", i, tree2->m_id.coord.x, tree2->m_id.coord.y);
tree->m_neighbor_list.push_back(tree2);
}
}
++it;
}
}
else
{
struct neighbor_coord_s
{
int x;
int y;
} neighbor_coord[8] = {
{ -SECTREE_SIZE, 0 },
{ SECTREE_SIZE, 0 },
{ 0 , -SECTREE_SIZE },
{ 0 , SECTREE_SIZE },
{ -SECTREE_SIZE, SECTREE_SIZE },
{ SECTREE_SIZE, -SECTREE_SIZE },
{ -SECTREE_SIZE, -SECTREE_SIZE },
{ SECTREE_SIZE, SECTREE_SIZE },
};
//
// <20><><EFBFBD><EFBFBD> sectree<65><65> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> sectree<65><65> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
//
MapType::iterator it = map_.begin();
while (it != map_.end())
{
LPSECTREE tree = it->second;
tree->m_neighbor_list.push_back(tree); // <20>ڽ<EFBFBD><DABD><EFBFBD> <20>ִ´<D6B4>.
sys_log(3, "%dx%d", tree->m_id.coord.x, tree->m_id.coord.y);
int x = tree->m_id.coord.x * SECTREE_SIZE;
int y = tree->m_id.coord.y * SECTREE_SIZE;
for (DWORD i = 0; i < 8; ++i)
{
LPSECTREE tree2 = Find(x + neighbor_coord[i].x, y + neighbor_coord[i].y);
if (tree2)
{
sys_log(3, " %d %dx%d", i, tree2->m_id.coord.x, tree2->m_id.coord.y);
tree->m_neighbor_list.push_back(tree2);
}
}
++it;
}
}
}
SECTREE_MANAGER::SECTREE_MANAGER()
{
}
SECTREE_MANAGER::~SECTREE_MANAGER()
{
/*
std::map<DWORD, LPSECTREE_MAP>::iterator it = m_map_pkSectree.begin();
while (it != m_map_pkSectree.end())
{
M2_DELETE(it->second);
++it;
}
*/
}
LPSECTREE_MAP SECTREE_MANAGER::GetMap(long lMapIndex)
{
std::map<DWORD, LPSECTREE_MAP>::iterator it = m_map_pkSectree.find(lMapIndex);
if (it == m_map_pkSectree.end())
return NULL;
return it->second;
}
LPSECTREE SECTREE_MANAGER::Get(DWORD dwIndex, DWORD package)
{
LPSECTREE_MAP pkSectreeMap = GetMap(dwIndex);
if (!pkSectreeMap)
return NULL;
return pkSectreeMap->Find(package);
}
LPSECTREE SECTREE_MANAGER::Get(DWORD dwIndex, DWORD x, DWORD y)
{
SECTREEID id;
id.coord.x = x / SECTREE_SIZE;
id.coord.y = y / SECTREE_SIZE;
return Get(dwIndex, id.package);
}
// -----------------------------------------------------------------------------
// Setting.txt <20><> <20><><EFBFBD><EFBFBD> SECTREE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// -----------------------------------------------------------------------------
int SECTREE_MANAGER::LoadSettingFile(long lMapIndex, const char * c_pszSettingFileName, TMapSetting & r_setting)
{
memset(&r_setting, 0, sizeof(TMapSetting));
FILE * fp = fopen(c_pszSettingFileName, "r");
if (!fp)
{
sys_err("cannot open file: %s", c_pszSettingFileName);
return 0;
}
char buf[256], cmd[256];
int iWidth = 0, iHeight = 0;
while (fgets(buf, 256, fp))
{
sscanf(buf, " %s ", cmd);
if (!strcasecmp(cmd, "MapSize"))
{
sscanf(buf, " %s %d %d ", cmd, &iWidth, &iHeight);
}
else if (!strcasecmp(cmd, "BasePosition"))
{
sscanf(buf, " %s %d %d", cmd, &r_setting.iBaseX, &r_setting.iBaseY);
}
else if (!strcasecmp(cmd, "CellScale"))
{
sscanf(buf, " %s %d ", cmd, &r_setting.iCellScale);
}
}
fclose(fp);
if ((iWidth == 0 && iHeight == 0) || r_setting.iCellScale == 0)
{
sys_err("Invalid Settings file: %s", c_pszSettingFileName);
return 0;
}
r_setting.iIndex = lMapIndex;
r_setting.iWidth = (r_setting.iCellScale * 128 * iWidth);
r_setting.iHeight = (r_setting.iCellScale * 128 * iHeight);
return 1;
}
LPSECTREE_MAP SECTREE_MANAGER::BuildSectreeFromSetting(TMapSetting & r_setting)
{
LPSECTREE_MAP pkMapSectree = M2_NEW SECTREE_MAP;
pkMapSectree->m_setting = r_setting;
int x, y;
LPSECTREE tree;
for (x = r_setting.iBaseX; x < r_setting.iBaseX + r_setting.iWidth; x += SECTREE_SIZE)
{
for (y = r_setting.iBaseY; y < r_setting.iBaseY + r_setting.iHeight; y += SECTREE_SIZE)
{
tree = M2_NEW SECTREE;
tree->m_id.coord.x = x / SECTREE_SIZE;
tree->m_id.coord.y = y / SECTREE_SIZE;
pkMapSectree->Add(tree->m_id.package, tree);
sys_log(3, "new sectree %d x %d", tree->m_id.coord.x, tree->m_id.coord.y);
}
}
if ((r_setting.iBaseX + r_setting.iWidth) % SECTREE_SIZE)
{
tree = M2_NEW SECTREE;
tree->m_id.coord.x = ((r_setting.iBaseX + r_setting.iWidth) / SECTREE_SIZE) + 1;
tree->m_id.coord.y = ((r_setting.iBaseY + r_setting.iHeight) / SECTREE_SIZE);
pkMapSectree->Add(tree->m_id.package, tree);
}
if ((r_setting.iBaseY + r_setting.iHeight) % SECTREE_SIZE)
{
tree = M2_NEW SECTREE;
tree->m_id.coord.x = ((r_setting.iBaseX + r_setting.iWidth) / SECTREE_SIZE);
tree->m_id.coord.y = ((r_setting.iBaseX + r_setting.iHeight) / SECTREE_SIZE) + 1;
pkMapSectree->Add(tree->m_id.package, tree);
}
return pkMapSectree;
}
void SECTREE_MANAGER::LoadDungeon(int iIndex, const char * c_pszFileName)
{
FILE* fp = fopen(c_pszFileName, "r");
if (!fp)
return;
int count = 0; // for debug
while (!feof(fp))
{
char buf[1024];
if (NULL == fgets(buf, 1024, fp))
break;
if (buf[0] == '#' || buf[0] == '/' && buf[1] == '/')
continue;
std::istringstream ins(buf, std::ios_base::in);
std::string position_name;
int x, y, sx, sy, dir;
ins >> position_name >> x >> y >> sx >> sy >> dir;
if (ins.fail())
continue;
x -= sx;
y -= sy;
sx *= 2;
sy *= 2;
sx += x;
sy += y;
m_map_pkArea[iIndex].insert(std::make_pair(position_name, TAreaInfo(x, y, sx, sy, dir)));
count++;
}
fclose(fp);
sys_log(0, "Dungeon Position Load [%3d]%s count %d", iIndex, c_pszFileName, count);
}
// Fix me
// <20><><EFBFBD><EFBFBD> Town.txt<78><74><EFBFBD><EFBFBD> x, y<><79> <20>׳<EFBFBD> <20>ް<EFBFBD>, <20>װ<EFBFBD> <20><> <20>ڵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> base <20><>ǥ<EFBFBD><C7A5> <20><><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20>ٸ<EFBFBD> <20>ʿ<EFBFBD> <20>ִ<EFBFBD> Ÿ<><C5B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>̵<EFBFBD><CCB5><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD><C7BE>ִ<EFBFBD>.
// <20>տ<EFBFBD> map<61>̶<EFBFBD><CCB6>ų<EFBFBD>, <20><>Ÿ <20>ٸ<EFBFBD> <20>ĺ<EFBFBD><C4BA>ڰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,
// <20>ٸ<EFBFBD> <20><><EFBFBD><EFBFBD> Ÿ<><C5B8><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD> <20>̵<EFBFBD><CCB5><EFBFBD> <20><> <20>ְ<EFBFBD> <20><><EFBFBD><EFBFBD>.
// by rtsummit
bool SECTREE_MANAGER::LoadMapRegion(const char * c_pszFileName, TMapSetting & r_setting, const char * c_pszMapName)
{
FILE * fp = fopen(c_pszFileName, "r");
if ( test_server )
sys_log( 0, "[LoadMapRegion] file(%s)", c_pszFileName );
if (!fp)
return false;
int iX=0, iY=0;
PIXEL_POSITION pos[3] = { {0,0,0}, {0,0,0}, {0,0,0} };
fscanf(fp, " %d %d ", &iX, &iY);
int iEmpirePositionCount = fscanf(fp, " %d %d %d %d %d %d ",
&pos[0].x, &pos[0].y,
&pos[1].x, &pos[1].y,
&pos[2].x, &pos[2].y);
fclose(fp);
if( iEmpirePositionCount == 6 )
{
for ( int n = 0; n < 3; ++n )
sys_log( 0 ,"LoadMapRegion %d %d ", pos[n].x, pos[n].y );
}
else
{
sys_log( 0, "LoadMapRegion no empire specific start point" );
}
TMapRegion region;
region.index = r_setting.iIndex;
region.sx = r_setting.iBaseX;
region.sy = r_setting.iBaseY;
region.ex = r_setting.iBaseX + r_setting.iWidth;
region.ey = r_setting.iBaseY + r_setting.iHeight;
region.strMapName = c_pszMapName;
region.posSpawn.x = r_setting.iBaseX + (iX * 100);
region.posSpawn.y = r_setting.iBaseY + (iY * 100);
r_setting.posSpawn = region.posSpawn;
sys_log(0, "LoadMapRegion %d x %d ~ %d y %d ~ %d, town %d %d",
region.index,
region.sx,
region.ex,
region.sy,
region.ey,
region.posSpawn.x,
region.posSpawn.y);
if (iEmpirePositionCount == 6)
{
region.bEmpireSpawnDifferent = true;
for (int i = 0; i < 3; i++)
{
region.posEmpire[i].x = r_setting.iBaseX + (pos[i].x * 100);
region.posEmpire[i].y = r_setting.iBaseY + (pos[i].y * 100);
}
}
else
{
region.bEmpireSpawnDifferent = false;
}
m_vec_mapRegion.push_back(region);
sys_log(0,"LoadMapRegion %d End", region.index);
return true;
}
bool SECTREE_MANAGER::LoadAttribute(LPSECTREE_MAP pkMapSectree, const char * c_pszFileName, TMapSetting & r_setting)
{
FILE * fp = fopen(c_pszFileName, "rb");
if (!fp)
{
sys_err("SECTREE_MANAGER::LoadAttribute : cannot open %s", c_pszFileName);
return false;
}
int iWidth, iHeight;
fread(&iWidth, sizeof(int), 1, fp);
fread(&iHeight, sizeof(int), 1, fp);
int maxMemSize = LZOManager::instance().GetMaxCompressedSize(sizeof(DWORD) * (SECTREE_SIZE / CELL_SIZE) * (SECTREE_SIZE / CELL_SIZE));
unsigned int uiSize;
unsigned int uiDestSize;
#ifndef _MSC_VER
BYTE abComp[maxMemSize];
#else
BYTE* abComp = M2_NEW BYTE[maxMemSize];
#endif
DWORD * attr = M2_NEW DWORD[maxMemSize];
for (int y = 0; y < iHeight; ++y)
for (int x = 0; x < iWidth; ++x)
{
// UNION <20><><EFBFBD><EFBFBD> <20><>ǥ<EFBFBD><C7A5> <20><><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD> DWORD<52><44><EFBFBD><EFBFBD> <20><><EFBFBD>̵<EFBFBD><CCB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
SECTREEID id;
id.coord.x = (r_setting.iBaseX / SECTREE_SIZE) + x;
id.coord.y = (r_setting.iBaseY / SECTREE_SIZE) + y;
LPSECTREE tree = pkMapSectree->Find(id.package);
// SERVER_ATTR_LOAD_ERROR
if (tree == NULL)
{
sys_err("FATAL ERROR! LoadAttribute(%s) - cannot find sectree(package=%x, coord=(%u, %u), map_index=%u, map_base=(%u, %u))",
c_pszFileName, id.package, id.coord.x, id.coord.y, r_setting.iIndex, r_setting.iBaseX, r_setting.iBaseY);
sys_err("ERROR_ATTR_POS(%d, %d) attr_size(%d, %d)", x, y, iWidth, iHeight);
sys_err("CHECK! 'Setting.txt' and 'server_attr' MAP_SIZE!!");
pkMapSectree->DumpAllToSysErr();
abort();
M2_DELETE_ARRAY(attr);
#ifdef _MSC_VER
M2_DELETE_ARRAY(abComp);
#endif
return false;
}
// END_OF_SERVER_ATTR_LOAD_ERROR
if (tree->m_id.package != id.package)
{
sys_err("returned tree id mismatch! return %u, request %u",
tree->m_id.package, id.package);
fclose(fp);
M2_DELETE_ARRAY(attr);
#ifdef _MSC_VER
M2_DELETE_ARRAY(abComp);
#endif
return false;
}
fread(&uiSize, sizeof(int), 1, fp);
fread(abComp, sizeof(char), uiSize, fp);
//LZOManager::instance().Decompress(abComp, uiSize, (BYTE *) tree->GetAttributePointer(), &uiDestSize);
uiDestSize = sizeof(DWORD) * maxMemSize;
LZOManager::instance().Decompress(abComp, uiSize, (BYTE *) attr, &uiDestSize);
if (uiDestSize != sizeof(DWORD) * (SECTREE_SIZE / CELL_SIZE) * (SECTREE_SIZE / CELL_SIZE))
{
sys_err("SECTREE_MANAGER::LoadAttribte : %s : %d %d size mismatch! %d",
c_pszFileName, tree->m_id.coord.x, tree->m_id.coord.y, uiDestSize);
fclose(fp);
M2_DELETE_ARRAY(attr);
#ifdef _MSC_VER
M2_DELETE_ARRAY(abComp);
#endif
return false;
}
tree->BindAttribute(M2_NEW CAttribute(attr, SECTREE_SIZE / CELL_SIZE, SECTREE_SIZE / CELL_SIZE));
}
fclose(fp);
M2_DELETE_ARRAY(attr);
#ifdef _MSC_VER
M2_DELETE_ARRAY(abComp);
#endif
return true;
}
bool SECTREE_MANAGER::GetRecallPositionByEmpire(int iMapIndex, BYTE bEmpire, PIXEL_POSITION & r_pos)
{
std::vector<TMapRegion>::iterator it = m_vec_mapRegion.begin();
// 10000<30><30> <20>Ѵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ν<EFBFBD><CEBD>Ͻ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><C7BE>ִ<EFBFBD>.
if (iMapIndex >= 10000)
{
iMapIndex /= 10000;
}
while (it != m_vec_mapRegion.end())
{
TMapRegion & rRegion = *(it++);
if (rRegion.index == iMapIndex)
{
if (rRegion.bEmpireSpawnDifferent && bEmpire >= 1 && bEmpire <= 3)
r_pos = rRegion.posEmpire[bEmpire - 1];
else
r_pos = rRegion.posSpawn;
return true;
}
}
return false;
}
bool SECTREE_MANAGER::GetCenterPositionOfMap(long lMapIndex, PIXEL_POSITION & r_pos)
{
std::vector<TMapRegion>::iterator it = m_vec_mapRegion.begin();
while (it != m_vec_mapRegion.end())
{
TMapRegion & rRegion = *(it++);
if (rRegion.index == lMapIndex)
{
r_pos.x = rRegion.sx + (rRegion.ex - rRegion.sx) / 2;
r_pos.y = rRegion.sy + (rRegion.ey - rRegion.sy) / 2;
r_pos.z = 0;
return true;
}
}
return false;
}
bool SECTREE_MANAGER::GetSpawnPositionByMapIndex(long lMapIndex, PIXEL_POSITION& r_pos)
{
if (lMapIndex> 10000) lMapIndex /= 10000;
std::vector<TMapRegion>::iterator it = m_vec_mapRegion.begin();
while (it != m_vec_mapRegion.end())
{
TMapRegion & rRegion = *(it++);
if (lMapIndex == rRegion.index)
{
r_pos = rRegion.posSpawn;
return true;
}
}
return false;
}
bool SECTREE_MANAGER::GetSpawnPosition(long x, long y, PIXEL_POSITION & r_pos)
{
std::vector<TMapRegion>::iterator it = m_vec_mapRegion.begin();
while (it != m_vec_mapRegion.end())
{
TMapRegion & rRegion = *(it++);
if (x >= rRegion.sx && y >= rRegion.sy && x < rRegion.ex && y < rRegion.ey)
{
r_pos = rRegion.posSpawn;
return true;
}
}
return false;
}
bool SECTREE_MANAGER::GetMapBasePositionByMapIndex(long lMapIndex, PIXEL_POSITION & r_pos)
{
if (lMapIndex> 10000) lMapIndex /= 10000;
std::vector<TMapRegion>::iterator it = m_vec_mapRegion.begin();
while (it != m_vec_mapRegion.end())
{
TMapRegion & rRegion = *(it++);
//if (x >= rRegion.sx && y >= rRegion.sy && x < rRegion.ex && y < rRegion.ey)
if (lMapIndex == rRegion.index)
{
r_pos.x = rRegion.sx;
r_pos.y = rRegion.sy;
r_pos.z = 0;
return true;
}
}
return false;
}
bool SECTREE_MANAGER::GetMapBasePosition(long x, long y, PIXEL_POSITION & r_pos)
{
std::vector<TMapRegion>::iterator it = m_vec_mapRegion.begin();
while (it != m_vec_mapRegion.end())
{
TMapRegion & rRegion = *(it++);
if (x >= rRegion.sx && y >= rRegion.sy && x < rRegion.ex && y < rRegion.ey)
{
r_pos.x = rRegion.sx;
r_pos.y = rRegion.sy;
r_pos.z = 0;
return true;
}
}
return false;
}
const TMapRegion * SECTREE_MANAGER::FindRegionByPartialName(const char* szMapName)
{
std::vector<TMapRegion>::iterator it = m_vec_mapRegion.begin();
while (it != m_vec_mapRegion.end())
{
TMapRegion & rRegion = *(it++);
//if (rRegion.index == lMapIndex)
//return &rRegion;
if (rRegion.strMapName.find(szMapName))
return &rRegion; // ij<><C4B3> <20>ؼ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
}
return NULL;
}
const TMapRegion * SECTREE_MANAGER::GetMapRegion(long lMapIndex)
{
std::vector<TMapRegion>::iterator it = m_vec_mapRegion.begin();
while (it != m_vec_mapRegion.end())
{
TMapRegion & rRegion = *(it++);
if (rRegion.index == lMapIndex)
return &rRegion;
}
return NULL;
}
int SECTREE_MANAGER::GetMapIndex(long x, long y)
{
std::vector<TMapRegion>::iterator it = m_vec_mapRegion.begin();
while (it != m_vec_mapRegion.end())
{
TMapRegion & rRegion = *(it++);
if (x >= rRegion.sx && y >= rRegion.sy && x < rRegion.ex && y < rRegion.ey)
return rRegion.index;
}
sys_log(0, "SECTREE_MANAGER::GetMapIndex(%d, %d)", x, y);
std::vector<TMapRegion>::iterator i;
for (i = m_vec_mapRegion.begin(); i !=m_vec_mapRegion.end(); ++i)
{
TMapRegion & rRegion = *i;
sys_log(0, "%d: (%d, %d) ~ (%d, %d)", rRegion.index, rRegion.sx, rRegion.sy, rRegion.ex, rRegion.ey);
}
return 0;
}
int SECTREE_MANAGER::Build(const char * c_pszListFileName, const char* c_pszMapBasePath)
{
if (true == test_server)
{
sys_log ( 0, "[BUILD] Build %s %s ", c_pszListFileName, c_pszMapBasePath );
}
FILE* fp = fopen(c_pszListFileName, "r");
if (NULL == fp)
return 0;
char buf[256 + 1];
char szFilename[256];
char szMapName[256];
int iIndex;
while (fgets(buf, 256, fp))
{
*strrchr(buf, '\n') = '\0';
if (!strncmp(buf, "//", 2) || *buf == '#')
continue;
sscanf(buf, " %d %s ", &iIndex, szMapName);
snprintf(szFilename, sizeof(szFilename), "%s/%s/Setting.txt", c_pszMapBasePath, szMapName);
TMapSetting setting;
setting.iIndex = iIndex;
if (!LoadSettingFile(iIndex, szFilename, setting))
{
sys_err("can't load file %s in LoadSettingFile", szFilename);
fclose(fp);
return 0;
}
snprintf(szFilename, sizeof(szFilename), "%s/%s/Town.txt", c_pszMapBasePath, szMapName);
if (!LoadMapRegion(szFilename, setting, szMapName))
{
sys_err("can't load file %s in LoadMapRegion", szFilename);
fclose(fp);
return 0;
}
if (true == test_server)
sys_log ( 0,"[BUILD] Build %s %s %d ",c_pszMapBasePath, szMapName, iIndex );
// <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD> <20>ϴ°<CFB4> Ȯ<><C8AE> <20>Ѵ<EFBFBD>.
if (map_allow_find(iIndex))
{
LPSECTREE_MAP pkMapSectree = BuildSectreeFromSetting(setting);
m_map_pkSectree.insert(std::map<DWORD, LPSECTREE_MAP>::value_type(iIndex, pkMapSectree));
snprintf(szFilename, sizeof(szFilename), "%s/%s/server_attr", c_pszMapBasePath, szMapName);
LoadAttribute(pkMapSectree, szFilename, setting);
snprintf(szFilename, sizeof(szFilename), "%s/%s/regen.txt", c_pszMapBasePath, szMapName);
regen_load(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY);
snprintf(szFilename, sizeof(szFilename), "%s/%s/npc.txt", c_pszMapBasePath, szMapName);
regen_load(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY);
snprintf(szFilename, sizeof(szFilename), "%s/%s/boss.txt", c_pszMapBasePath, szMapName);
regen_load(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY);
snprintf(szFilename, sizeof(szFilename), "%s/%s/stone.txt", c_pszMapBasePath, szMapName);
regen_load(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY);
snprintf(szFilename, sizeof(szFilename), "%s/%s/dungeon.txt", c_pszMapBasePath, szMapName);
LoadDungeon(iIndex, szFilename);
pkMapSectree->Build();
}
}
fclose(fp);
return 1;
}
bool SECTREE_MANAGER::IsMovablePosition(long lMapIndex, long x, long y)
{
LPSECTREE tree = SECTREE_MANAGER::instance().Get(lMapIndex, x, y);
if (!tree)
return false;
return (!tree->IsAttr(x, y, ATTR_BLOCK | ATTR_OBJECT));
}
bool SECTREE_MANAGER::GetMovablePosition(long lMapIndex, long x, long y, PIXEL_POSITION & pos)
{
int i = 0;
do
{
long dx = x + aArroundCoords[i].x;
long dy = y + aArroundCoords[i].y;
LPSECTREE tree = SECTREE_MANAGER::instance().Get(lMapIndex, dx, dy);
if (!tree)
continue;
if (!tree->IsAttr(dx, dy, ATTR_BLOCK | ATTR_OBJECT))
{
pos.x = dx;
pos.y = dy;
return true;
}
} while (++i < ARROUND_COORD_MAX_NUM);
pos.x = x;
pos.y = y;
return false;
}
bool SECTREE_MANAGER::GetValidLocation(long lMapIndex, long x, long y, long & r_lValidMapIndex, PIXEL_POSITION & r_pos, BYTE empire)
{
LPSECTREE_MAP pkSectreeMap = GetMap(lMapIndex);
if (!pkSectreeMap)
{
if (lMapIndex >= 10000)
{
/* long m = lMapIndex / 10000;
if (m == 216)
{
if (GetRecallPositionByEmpire (m, empire, r_pos))
{
r_lValidMapIndex = m;
return true;
}
else
return false;
}*/
return GetValidLocation(lMapIndex / 10000, x, y, r_lValidMapIndex, r_pos);
}
else
{
sys_err("cannot find sectree_map by map index %d", lMapIndex);
return false;
}
}
long lRealMapIndex = lMapIndex;
if (lRealMapIndex >= 10000)
lRealMapIndex = lRealMapIndex / 10000;
std::vector<TMapRegion>::iterator it = m_vec_mapRegion.begin();
while (it != m_vec_mapRegion.end())
{
TMapRegion & rRegion = *(it++);
if (rRegion.index == lRealMapIndex)
{
LPSECTREE tree = pkSectreeMap->Find(x, y);
if (!tree)
{
sys_err("cannot find tree by %d %d (map index %d)", x, y, lMapIndex);
return false;
}
r_lValidMapIndex = lMapIndex;
r_pos.x = x;
r_pos.y = y;
return true;
}
}
sys_err("invalid location (map index %d %d x %d)", lRealMapIndex, x, y);
return false;
}
bool SECTREE_MANAGER::GetRandomLocation(long lMapIndex, PIXEL_POSITION & r_pos, DWORD dwCurrentX, DWORD dwCurrentY, int iMaxDistance)
{
LPSECTREE_MAP pkSectreeMap = GetMap(lMapIndex);
if (!pkSectreeMap)
return false;
DWORD x, y;
std::vector<TMapRegion>::iterator it = m_vec_mapRegion.begin();
while (it != m_vec_mapRegion.end())
{
TMapRegion & rRegion = *(it++);
if (rRegion.index != lMapIndex)
continue;
int i = 0;
while (i++ < 100)
{
x = number(rRegion.sx + 50, rRegion.ex - 50);
y = number(rRegion.sy + 50, rRegion.ey - 50);
if (iMaxDistance != 0)
{
int d;
d = abs((float)dwCurrentX - x);
if (d > iMaxDistance)
{
if (x < dwCurrentX)
x = dwCurrentX - iMaxDistance;
else
x = dwCurrentX + iMaxDistance;
}
d = abs((float)dwCurrentY - y);
if (d > iMaxDistance)
{
if (y < dwCurrentY)
y = dwCurrentY - iMaxDistance;
else
y = dwCurrentY + iMaxDistance;
}
}
LPSECTREE tree = pkSectreeMap->Find(x, y);
if (!tree)
continue;
if (tree->IsAttr(x, y, ATTR_BLOCK | ATTR_OBJECT))
continue;
r_pos.x = x;
r_pos.y = y;
return true;
}
}
return false;
}
long SECTREE_MANAGER::CreatePrivateMap(long lMapIndex)
{
if (lMapIndex >= 10000) // 10000<30><30> <20>̻<EFBFBD><CCBB><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. (Ȥ<><C8A4> <20>̹<EFBFBD> private <20>̴<EFBFBD>)
return 0;
LPSECTREE_MAP pkMapSectree = GetMap(lMapIndex);
if (!pkMapSectree)
{
sys_err("Cannot find map index %d", lMapIndex);
return 0;
}
// <Factor> Circular private map indexing
long base = lMapIndex * 10000;
int index_cap = 10000;
if ( lMapIndex == 107 || lMapIndex == 108 || lMapIndex == 109 ) {
index_cap = (test_server ? 1 : 51);
}
PrivateIndexMapType::iterator it = next_private_index_map_.find(lMapIndex);
if (it == next_private_index_map_.end()) {
it = next_private_index_map_.insert(PrivateIndexMapType::value_type(lMapIndex, 0)).first;
}
int i, next_index = it->second;
for (i = 0; i < index_cap; ++i) {
if (GetMap(base + next_index) == NULL) {
break; // available
}
if (++next_index >= index_cap) {
next_index = 0;
}
}
if (i == index_cap) {
// No available index
return 0;
}
long lNewMapIndex = base + next_index;
if (++next_index >= index_cap) {
next_index = 0;
}
it->second = next_index;
/*
int i;
for (i = 0; i < 10000; ++i)
{
if (!GetMap((lMapIndex * 10000) + i))
break;
}
if ( test_server )
sys_log( 0, "Create Dungeon : OrginalMapindex %d NewMapindex %d", lMapIndex, i );
if ( lMapIndex == 107 || lMapIndex == 108 || lMapIndex == 109 )
{
if ( test_server )
{
if ( i > 0 )
return NULL;
}
else
{
if ( i > 50 )
return NULL;
}
}
if (i == 10000)
{
sys_err("not enough private map index (map_index %d)", lMapIndex);
return 0;
}
long lNewMapIndex = lMapIndex * 10000 + i;
*/
pkMapSectree = M2_NEW SECTREE_MAP(*pkMapSectree);
m_map_pkSectree.insert(std::map<DWORD, LPSECTREE_MAP>::value_type(lNewMapIndex, pkMapSectree));
sys_log(0, "PRIVATE_MAP: %d created (original %d)", lNewMapIndex, lMapIndex);
return lNewMapIndex;
}
struct FDestroyPrivateMapEntity
{
void operator() (LPENTITY ent)
{
if (ent->IsType(ENTITY_CHARACTER))
{
LPCHARACTER ch = (LPCHARACTER) ent;
sys_log(0, "PRIVAE_MAP: removing character %s", ch->GetName());
if (ch->GetDesc())
DESC_MANAGER::instance().DestroyDesc(ch->GetDesc());
else
M2_DESTROY_CHARACTER(ch);
}
else if (ent->IsType(ENTITY_ITEM))
{
LPITEM item = (LPITEM) ent;
sys_log(0, "PRIVATE_MAP: removing item %s", item->GetName());
M2_DESTROY_ITEM(item);
}
else
sys_err("PRIVAE_MAP: trying to remove unknown entity %d", ent->GetType());
}
};
void SECTREE_MANAGER::DestroyPrivateMap(long lMapIndex)
{
if (lMapIndex < 10000) // private map <20><> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> 10000 <20>̻<EFBFBD> <20>̴<EFBFBD>.
return;
LPSECTREE_MAP pkMapSectree = GetMap(lMapIndex);
if (!pkMapSectree)
return;
// <20><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>͵<EFBFBD><CDB5><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ش<EFBFBD>.
// WARNING:
// <20><> <20>ʿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> Sectree<65><65><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>⼭ delete <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20>ؾ<EFBFBD><D8BE><EFBFBD>
FDestroyPrivateMapEntity f;
pkMapSectree->for_each(f);
m_map_pkSectree.erase(lMapIndex);
M2_DELETE(pkMapSectree);
sys_log(0, "PRIVATE_MAP: %d destroyed", lMapIndex);
}
TAreaMap& SECTREE_MANAGER::GetDungeonArea(long lMapIndex)
{
itertype(m_map_pkArea) it = m_map_pkArea.find(lMapIndex);
if (it == m_map_pkArea.end())
{
return m_map_pkArea[-1]; // <20>ӽ÷<D3BD> <20><> Area<65><61> <20><><EFBFBD><EFBFBD>
}
return it->second;
}
void SECTREE_MANAGER::SendNPCPosition(LPCHARACTER ch)
{
LPDESC d = ch->GetDesc();
if (!d)
return;
long lMapIndex = ch->GetMapIndex();
if (m_mapNPCPosition[lMapIndex].empty())
return;
TEMP_BUFFER buf;
TPacketGCNPCPosition p;
p.header = HEADER_GC_NPC_POSITION;
p.count = m_mapNPCPosition[lMapIndex].size();
TNPCPosition np;
// TODO m_mapNPCPosition[lMapIndex] <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ּ<EFBFBD><D6BC><EFBFBD>
itertype(m_mapNPCPosition[lMapIndex]) it;
for (it = m_mapNPCPosition[lMapIndex].begin(); it != m_mapNPCPosition[lMapIndex].end(); ++it)
{
np.bType = it->bType;
strlcpy(np.name, it->name, sizeof(np.name));
np.x = it->x;
np.y = it->y;
buf.write(&np, sizeof(np));
}
p.size = sizeof(p) + buf.size();
if (buf.size())
{
d->BufferedPacket(&p, sizeof(TPacketGCNPCPosition));
d->Packet(buf.read_peek(), buf.size());
}
else
d->Packet(&p, sizeof(TPacketGCNPCPosition));
}
void SECTREE_MANAGER::InsertNPCPosition(long lMapIndex, BYTE bType, const char* szName, long x, long y)
{
m_mapNPCPosition[lMapIndex].push_back(npc_info(bType, szName, x, y));
}
BYTE SECTREE_MANAGER::GetEmpireFromMapIndex(long lMapIndex)
{
if (lMapIndex >= 1 && lMapIndex <= 20)
return 1;
if (lMapIndex >= 21 && lMapIndex <= 40)
return 2;
if (lMapIndex >= 41 && lMapIndex <= 60)
return 3;
if ( lMapIndex == 184 || lMapIndex == 185 )
return 1;
if ( lMapIndex == 186 || lMapIndex == 187 )
return 2;
if ( lMapIndex == 188 || lMapIndex == 189 )
return 3;
switch ( lMapIndex )
{
case 190 :
return 1;
case 191 :
return 2;
case 192 :
return 3;
}
return 0;
}
class FRemoveIfAttr
{
public:
FRemoveIfAttr(LPSECTREE pkTree, DWORD dwAttr) : m_pkTree(pkTree), m_dwCheckAttr(dwAttr)
{
}
void operator () (LPENTITY entity)
{
if (!m_pkTree->IsAttr(entity->GetX(), entity->GetY(), m_dwCheckAttr))
return;
if (entity->IsType(ENTITY_ITEM))
{
M2_DESTROY_ITEM((LPITEM) entity);
}
else if (entity->IsType(ENTITY_CHARACTER))
{
LPCHARACTER ch = (LPCHARACTER) entity;
if (ch->IsPC())
{
PIXEL_POSITION pos;
if (SECTREE_MANAGER::instance().GetRecallPositionByEmpire(ch->GetMapIndex(), ch->GetEmpire(), pos))
ch->WarpSet(pos.x, pos.y);
else
ch->WarpSet(EMPIRE_START_X(ch->GetEmpire()), EMPIRE_START_Y(ch->GetEmpire()));
}
else
ch->Dead();
}
}
LPSECTREE m_pkTree;
DWORD m_dwCheckAttr;
};
bool SECTREE_MANAGER::ForAttrRegionCell( long lMapIndex, long lCX, long lCY, DWORD dwAttr, EAttrRegionMode mode )
{
SECTREEID id;
id.coord.x = lCX / (SECTREE_SIZE / CELL_SIZE);
id.coord.y = lCY / (SECTREE_SIZE / CELL_SIZE);
long lTreeCX = id.coord.x * (SECTREE_SIZE / CELL_SIZE);
long lTreeCY = id.coord.y * (SECTREE_SIZE / CELL_SIZE);
LPSECTREE pSec = Get( lMapIndex, id.package );
if ( !pSec )
return false;
switch (mode)
{
case ATTR_REGION_MODE_SET:
pSec->SetAttribute( lCX - lTreeCX, lCY - lTreeCY, dwAttr );
break;
case ATTR_REGION_MODE_REMOVE:
pSec->RemoveAttribute( lCX - lTreeCX, lCY - lTreeCY, dwAttr );
break;
case ATTR_REGION_MODE_CHECK:
if ( pSec->IsAttr( lCX * CELL_SIZE, lCY * CELL_SIZE, ATTR_OBJECT ) )
return true;
break;
default:
sys_err("Unknown region mode %u", mode);
break;
}
return false;
}
bool SECTREE_MANAGER::ForAttrRegionRightAngle( long lMapIndex, long lCX, long lCY, long lCW, long lCH, long lRotate, DWORD dwAttr, EAttrRegionMode mode )
{
if (1 == lRotate/90 || 3 == lRotate/90)
{
for (int x = 0; x < lCH; ++x)
for (int y = 0; y < lCW; ++y)
{
if ( ForAttrRegionCell( lMapIndex, lCX + x, lCY + y, dwAttr, mode ) )
return true;
}
}
if (0 == lRotate/90 || 2 == lRotate/90)
{
for (int x = 0; x < lCW; ++x)
for (int y = 0; y < lCH; ++y)
{
if ( ForAttrRegionCell( lMapIndex, lCX + x, lCY + y, dwAttr, mode) )
return true;
}
}
return mode == ATTR_REGION_MODE_CHECK ? false : true;
}
#define min( l, r ) ((l) < (r) ? (l) : (r))
#define max( l, r ) ((l) < (r) ? (r) : (l))
bool SECTREE_MANAGER::ForAttrRegionFreeAngle( long lMapIndex, long lCX, long lCY, long lCW, long lCH, long lRotate, DWORD dwAttr, EAttrRegionMode mode )
{
float fx1 = (-lCW/2) * sinf(float(lRotate)/180.0f*3.14f) + (-lCH/2) * cosf(float(lRotate)/180.0f*3.14f);
float fy1 = (-lCW/2) * cosf(float(lRotate)/180.0f*3.14f) - (-lCH/2) * sinf(float(lRotate)/180.0f*3.14f);
float fx2 = (+lCW/2) * sinf(float(lRotate)/180.0f*3.14f) + (-lCH/2) * cosf(float(lRotate)/180.0f*3.14f);
float fy2 = (+lCW/2) * cosf(float(lRotate)/180.0f*3.14f) - (-lCH/2) * sinf(float(lRotate)/180.0f*3.14f);
float fx3 = (-lCW/2) * sinf(float(lRotate)/180.0f*3.14f) + (+lCH/2) * cosf(float(lRotate)/180.0f*3.14f);
float fy3 = (-lCW/2) * cosf(float(lRotate)/180.0f*3.14f) - (+lCH/2) * sinf(float(lRotate)/180.0f*3.14f);
float fx4 = (+lCW/2) * sinf(float(lRotate)/180.0f*3.14f) + (+lCH/2) * cosf(float(lRotate)/180.0f*3.14f);
float fy4 = (+lCW/2) * cosf(float(lRotate)/180.0f*3.14f) - (+lCH/2) * sinf(float(lRotate)/180.0f*3.14f);
float fdx1 = fx2 - fx1;
float fdy1 = fy2 - fy1;
float fdx2 = fx1 - fx3;
float fdy2 = fy1 - fy3;
if (0 == fdx1 || 0 == fdx2)
{
sys_err( "SECTREE_MANAGER::ForAttrRegion - Unhandled exception. MapIndex: %d", lMapIndex );
return false;
}
float fTilt1 = float(fdy1) / float(fdx1);
float fTilt2 = float(fdy2) / float(fdx2);
float fb1 = fy1 - fTilt1*fx1;
float fb2 = fy1 - fTilt2*fx1;
float fb3 = fy4 - fTilt1*fx4;
float fb4 = fy4 - fTilt2*fx4;
float fxMin = min(fx1, min(fx2, min(fx3, fx4)));
float fxMax = max(fx1, max(fx2, max(fx3, fx4)));
for (int i = int(fxMin); i < int(fxMax); ++i)
{
float fyValue1 = fTilt1*i + min(fb1, fb3);
float fyValue2 = fTilt2*i + min(fb2, fb4);
float fyValue3 = fTilt1*i + max(fb1, fb3);
float fyValue4 = fTilt2*i + max(fb2, fb4);
float fMinValue;
float fMaxValue;
if (abs(int(fyValue1)) < abs(int(fyValue2)))
fMaxValue = fyValue1;
else
fMaxValue = fyValue2;
if (abs(int(fyValue3)) < abs(int(fyValue4)))
fMinValue = fyValue3;
else
fMinValue = fyValue4;
for (int j = int(min(fMinValue, fMaxValue)); j < int(max(fMinValue, fMaxValue)); ++j) {
if ( ForAttrRegionCell( lMapIndex, lCX + (lCW / 2) + i, lCY + (lCH / 2) + j, dwAttr, mode ) )
return true;
}
}
return mode == ATTR_REGION_MODE_CHECK ? false : true;
}
bool SECTREE_MANAGER::ForAttrRegion(long lMapIndex, long lStartX, long lStartY, long lEndX, long lEndY, long lRotate, DWORD dwAttr, EAttrRegionMode mode)
{
LPSECTREE_MAP pkMapSectree = GetMap(lMapIndex);
if (!pkMapSectree)
{
sys_err("Cannot find SECTREE_MAP by map index %d", lMapIndex);
return mode == ATTR_REGION_MODE_CHECK ? true : false;
}
//
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ǥ<EFBFBD><C7A5> Cell <20><> ũ<><20><><EFBFBD><EFBFBD> Ȯ<><C8AE><EFBFBD>Ѵ<EFBFBD>.
//
lStartX -= lStartX % CELL_SIZE;
lStartY -= lStartY % CELL_SIZE;
lEndX += lEndX % CELL_SIZE;
lEndY += lEndY % CELL_SIZE;
//
// Cell <20><>ǥ<EFBFBD><C7A5> <20><><EFBFBD>Ѵ<EFBFBD>.
//
long lCX = lStartX / CELL_SIZE;
long lCY = lStartY / CELL_SIZE;
long lCW = (lEndX - lStartX) / CELL_SIZE;
long lCH = (lEndY - lStartY) / CELL_SIZE;
sys_log(1, "ForAttrRegion %d %d ~ %d %d", lStartX, lStartY, lEndX, lEndY);
lRotate = lRotate % 360;
if (0 == lRotate % 90)
return ForAttrRegionRightAngle( lMapIndex, lCX, lCY, lCW, lCH, lRotate, dwAttr, mode );
return ForAttrRegionFreeAngle( lMapIndex, lCX, lCY, lCW, lCH, lRotate, dwAttr, mode );
}
bool SECTREE_MANAGER::SaveAttributeToImage(int lMapIndex, const char * c_pszFileName, LPSECTREE_MAP pMapSrc)
{
LPSECTREE_MAP pMap = SECTREE_MANAGER::GetMap(lMapIndex);
if (!pMap)
{
if (pMapSrc)
pMap = pMapSrc;
else
{
sys_err("cannot find sectree_map %d", lMapIndex);
return false;
}
}
int iMapHeight = pMap->m_setting.iHeight / 128 / 200;
int iMapWidth = pMap->m_setting.iWidth / 128 / 200;
if (iMapHeight < 0 || iMapWidth < 0)
{
sys_err("map size error w %d h %d", iMapWidth, iMapHeight);
return false;
}
sys_log(0, "SaveAttributeToImage w %d h %d file %s", iMapWidth, iMapHeight, c_pszFileName);
CTargaImage image;
image.Create(512 * iMapWidth, 512 * iMapHeight);
sys_log(0, "1");
DWORD * pdwDest = (DWORD *) image.GetBasePointer();
int pixels = 0;
int x, x2;
int y, y2;
sys_log(0, "2 %p", pdwDest);
DWORD * pdwLine = M2_NEW DWORD[SECTREE_SIZE / CELL_SIZE];
for (y = 0; y < 4 * iMapHeight; ++y)
{
for (y2 = 0; y2 < SECTREE_SIZE / CELL_SIZE; ++y2)
{
for (x = 0; x < 4 * iMapWidth; ++x)
{
SECTREEID id;
id.coord.x = x + pMap->m_setting.iBaseX / SECTREE_SIZE;
id.coord.y = y + pMap->m_setting.iBaseY / SECTREE_SIZE;
LPSECTREE pSec = pMap->Find(id.package);
if (!pSec)
{
sys_err("cannot get sectree for %d %d %d %d", id.coord.x, id.coord.y, pMap->m_setting.iBaseX, pMap->m_setting.iBaseY);
continue;
}
pSec->m_pkAttribute->CopyRow(y2, pdwLine);
if (!pdwLine)
{
sys_err("cannot get attribute line pointer");
M2_DELETE_ARRAY(pdwLine);
continue;
}
for (x2 = 0; x2 < SECTREE_SIZE / CELL_SIZE; ++x2)
{
DWORD dwColor;
if (IS_SET(pdwLine[x2], ATTR_WATER))
dwColor = 0xff0000ff;
else if (IS_SET(pdwLine[x2], ATTR_BANPK))
dwColor = 0xff00ff00;
else if (IS_SET(pdwLine[x2], ATTR_BLOCK))
dwColor = 0xffff0000;
else
dwColor = 0xffffffff;
*(pdwDest++) = dwColor;
pixels++;
}
}
}
}
M2_DELETE_ARRAY(pdwLine);
sys_log(0, "3");
if (image.Save(c_pszFileName))
{
sys_log(0, "SECTREE: map %d attribute saved to %s (%d bytes)", lMapIndex, c_pszFileName, pixels);
return true;
}
else
{
sys_err("cannot save file, map_index %d filename %s", lMapIndex, c_pszFileName);
return false;
}
}
struct FPurgeMonsters
{
void operator() (LPENTITY ent)
{
if ( ent->IsType(ENTITY_CHARACTER) == true )
{
LPCHARACTER lpChar = (LPCHARACTER)ent;
if ( lpChar->IsMonster() == true && !lpChar->IsPet())
{
M2_DESTROY_CHARACTER(lpChar);
}
}
}
};
void SECTREE_MANAGER::PurgeMonstersInMap(long lMapIndex)
{
LPSECTREE_MAP sectree = SECTREE_MANAGER::instance().GetMap(lMapIndex);
if ( sectree != NULL )
{
struct FPurgeMonsters f;
sectree->for_each( f );
}
}
struct FPurgeStones
{
void operator() (LPENTITY ent)
{
if ( ent->IsType(ENTITY_CHARACTER) == true )
{
LPCHARACTER lpChar = (LPCHARACTER)ent;
if ( lpChar->IsStone() == true )
{
M2_DESTROY_CHARACTER(lpChar);
}
}
}
};
void SECTREE_MANAGER::PurgeStonesInMap(long lMapIndex)
{
LPSECTREE_MAP sectree = SECTREE_MANAGER::instance().GetMap(lMapIndex);
if ( sectree != NULL )
{
struct FPurgeStones f;
sectree->for_each( f );
}
}
struct FPurgeNPCs
{
void operator() (LPENTITY ent)
{
if ( ent->IsType(ENTITY_CHARACTER) == true )
{
LPCHARACTER lpChar = (LPCHARACTER)ent;
if ( lpChar->IsNPC() == true && !lpChar->IsPet())
{
M2_DESTROY_CHARACTER(lpChar);
}
}
}
};
void SECTREE_MANAGER::PurgeNPCsInMap(long lMapIndex)
{
LPSECTREE_MAP sectree = SECTREE_MANAGER::instance().GetMap(lMapIndex);
if ( sectree != NULL )
{
struct FPurgeNPCs f;
sectree->for_each( f );
}
}
struct FCountMonsters
{
std::map<VID, VID> m_map_Monsters;
void operator() (LPENTITY ent)
{
if ( ent->IsType(ENTITY_CHARACTER) == true )
{
LPCHARACTER lpChar = (LPCHARACTER)ent;
if ( lpChar->IsMonster() == true )
{
m_map_Monsters[lpChar->GetVID()] = lpChar->GetVID();
}
}
}
};
size_t SECTREE_MANAGER::GetMonsterCountInMap(long lMapIndex)
{
LPSECTREE_MAP sectree = SECTREE_MANAGER::instance().GetMap(lMapIndex);
if ( sectree != NULL )
{
struct FCountMonsters f;
sectree->for_each( f );
return f.m_map_Monsters.size();
}
return 0;
}
struct FCountSpecifiedMonster
{
DWORD SpecifiedVnum;
size_t cnt;
FCountSpecifiedMonster(DWORD id)
: SpecifiedVnum(id), cnt(0)
{}
void operator() (LPENTITY ent)
{
if (true == ent->IsType(ENTITY_CHARACTER))
{
LPCHARACTER pChar = static_cast<LPCHARACTER>(ent);
if (true == pChar->IsStone())
{
if (pChar->GetMobTable().dwVnum == SpecifiedVnum)
cnt++;
}
}
}
};
size_t SECTREE_MANAGER::GetMonsterCountInMap(long lMapIndex, DWORD dwVnum)
{
LPSECTREE_MAP sectree = SECTREE_MANAGER::instance().GetMap(lMapIndex);
if (NULL != sectree)
{
struct FCountSpecifiedMonster f(dwVnum);
sectree->for_each( f );
return f.cnt;
}
return 0;
}