forked from metin2/server
768 lines
14 KiB
C++
768 lines
14 KiB
C++
|
#include "stdafx.h"
|
|||
|
#include "config.h"
|
|||
|
#include "char.h"
|
|||
|
#include "char_manager.h"
|
|||
|
#include "regen.h"
|
|||
|
#include "mob_manager.h"
|
|||
|
#include "dungeon.h"
|
|||
|
|
|||
|
LPREGEN regen_list = NULL;
|
|||
|
LPREGEN_EXCEPTION regen_exception_list = NULL;
|
|||
|
|
|||
|
enum ERegenModes
|
|||
|
{
|
|||
|
MODE_TYPE = 0,
|
|||
|
MODE_SX,
|
|||
|
MODE_SY,
|
|||
|
MODE_EX,
|
|||
|
MODE_EY,
|
|||
|
MODE_Z_SECTION,
|
|||
|
MODE_DIRECTION,
|
|||
|
MODE_REGEN_TIME,
|
|||
|
MODE_REGEN_PERCENT,
|
|||
|
MODE_MAX_COUNT,
|
|||
|
MODE_VNUM
|
|||
|
};
|
|||
|
|
|||
|
static bool get_word(FILE *fp, char *buf) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>´<DEB4>.
|
|||
|
{
|
|||
|
int i = 0;
|
|||
|
int c;
|
|||
|
|
|||
|
int semicolon_mode = 0;
|
|||
|
|
|||
|
while ((c = fgetc(fp)) != EOF)
|
|||
|
{
|
|||
|
if (i == 0)
|
|||
|
{
|
|||
|
if (c == '"')
|
|||
|
{
|
|||
|
semicolon_mode = 1;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (semicolon_mode)
|
|||
|
{
|
|||
|
if (c == '"')
|
|||
|
{
|
|||
|
buf[i] = '\0';
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
buf[i++] = c;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if ((c == ' ' || c == '\t' || c == '\n' || c == '\r'))
|
|||
|
{
|
|||
|
buf[i] = '\0';
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
buf[i++] = c;
|
|||
|
}
|
|||
|
|
|||
|
if (i == 2 && buf[0] == '/' && buf[1] == '/')
|
|||
|
{
|
|||
|
buf[i] = '\0';
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
buf[i] = '\0';
|
|||
|
return (i != 0);
|
|||
|
}
|
|||
|
|
|||
|
static void next_line(FILE *fp)
|
|||
|
{
|
|||
|
int c;
|
|||
|
|
|||
|
while ((c = fgetc(fp)) != EOF)
|
|||
|
if (c == '\n')
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
static bool read_line(FILE *fp, LPREGEN regen)
|
|||
|
{
|
|||
|
char szTmp[256];
|
|||
|
|
|||
|
int mode = MODE_TYPE;
|
|||
|
int tmpTime;
|
|||
|
DWORD i;
|
|||
|
|
|||
|
while (get_word(fp, szTmp))
|
|||
|
{
|
|||
|
if (!strncmp(szTmp, "//", 2))
|
|||
|
{
|
|||
|
next_line(fp);
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
switch (mode)
|
|||
|
{
|
|||
|
case MODE_TYPE:
|
|||
|
if (szTmp[0] == 'm')
|
|||
|
regen->type = REGEN_TYPE_MOB;
|
|||
|
else if (szTmp[0] == 'g')
|
|||
|
{
|
|||
|
regen->type = REGEN_TYPE_GROUP;
|
|||
|
|
|||
|
if (szTmp[1] == 'a')
|
|||
|
regen->is_aggressive = true;
|
|||
|
}
|
|||
|
else if (szTmp[0] == 'e')
|
|||
|
regen->type = REGEN_TYPE_EXCEPTION;
|
|||
|
else if (szTmp[0] == 'r')
|
|||
|
regen->type = REGEN_TYPE_GROUP_GROUP;
|
|||
|
else if (szTmp[0] == 's')
|
|||
|
regen->type = REGEN_TYPE_ANYWHERE;
|
|||
|
else
|
|||
|
{
|
|||
|
sys_err("read_line: unknown regen type %c", szTmp[0]);
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
++mode;
|
|||
|
break;
|
|||
|
|
|||
|
case MODE_SX:
|
|||
|
str_to_number(regen->sx, szTmp);
|
|||
|
++mode;
|
|||
|
break;
|
|||
|
|
|||
|
case MODE_SY:
|
|||
|
str_to_number(regen->sy, szTmp);
|
|||
|
++mode;
|
|||
|
break;
|
|||
|
|
|||
|
case MODE_EX:
|
|||
|
{
|
|||
|
int iX = 0;
|
|||
|
str_to_number(iX, szTmp);
|
|||
|
|
|||
|
regen->sx -= iX;
|
|||
|
regen->ex = regen->sx + iX * 2;
|
|||
|
|
|||
|
regen->sx *= 100;
|
|||
|
regen->ex *= 100;
|
|||
|
|
|||
|
++mode;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case MODE_EY:
|
|||
|
{
|
|||
|
int iY = 0;
|
|||
|
str_to_number(iY, szTmp);
|
|||
|
|
|||
|
regen->sy -= iY;
|
|||
|
regen->ey = regen->sy + iY * 2;
|
|||
|
|
|||
|
regen->sy *= 100;
|
|||
|
regen->ey *= 100;
|
|||
|
|
|||
|
++mode;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case MODE_Z_SECTION:
|
|||
|
str_to_number(regen->z_section, szTmp);
|
|||
|
|
|||
|
// <20>ͼ<EFBFBD><CDBC><EFBFBD> <20≯<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
|||
|
if (regen->type == REGEN_TYPE_EXCEPTION)
|
|||
|
return true;
|
|||
|
|
|||
|
++mode;
|
|||
|
break;
|
|||
|
|
|||
|
case MODE_DIRECTION:
|
|||
|
str_to_number(regen->direction, szTmp);
|
|||
|
++mode;
|
|||
|
break;
|
|||
|
|
|||
|
case MODE_REGEN_TIME:
|
|||
|
regen->time = 0;
|
|||
|
tmpTime = 0;
|
|||
|
|
|||
|
for (i = 0; i < strlen(szTmp); ++i)
|
|||
|
{
|
|||
|
switch (szTmp[i])
|
|||
|
{
|
|||
|
case 'h':
|
|||
|
regen->time += tmpTime * 3600;
|
|||
|
tmpTime = 0;
|
|||
|
break;
|
|||
|
|
|||
|
case 'm':
|
|||
|
regen->time += tmpTime * 60;
|
|||
|
tmpTime = 0;
|
|||
|
break;
|
|||
|
|
|||
|
case 's':
|
|||
|
regen->time += tmpTime;
|
|||
|
tmpTime = 0;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
if (szTmp[i] >= '0' && szTmp[i] <= '9')
|
|||
|
{
|
|||
|
tmpTime *= 10;
|
|||
|
tmpTime += (szTmp[i] - '0');
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
++mode;
|
|||
|
break;
|
|||
|
|
|||
|
case MODE_REGEN_PERCENT:
|
|||
|
++mode;
|
|||
|
break;
|
|||
|
|
|||
|
case MODE_MAX_COUNT:
|
|||
|
regen->count = 0;
|
|||
|
str_to_number(regen->max_count, szTmp);
|
|||
|
++mode;
|
|||
|
break;
|
|||
|
|
|||
|
case MODE_VNUM:
|
|||
|
str_to_number(regen->vnum, szTmp);
|
|||
|
++mode;
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
bool is_regen_exception(long x, long y)
|
|||
|
{
|
|||
|
LPREGEN_EXCEPTION exc;
|
|||
|
|
|||
|
for (exc = regen_exception_list; exc; exc = exc->next)
|
|||
|
{
|
|||
|
if (exc->sx <= x && exc->sy <= y)
|
|||
|
if (exc->ex >= x && exc->ey >= y)
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
static void regen_spawn_dungeon(LPREGEN regen, LPDUNGEON pDungeon, bool bOnce)
|
|||
|
{
|
|||
|
DWORD num;
|
|||
|
DWORD i;
|
|||
|
|
|||
|
num = (regen->max_count - regen->count);
|
|||
|
|
|||
|
if (!num)
|
|||
|
return;
|
|||
|
|
|||
|
for (i = 0; i < num; ++i)
|
|||
|
{
|
|||
|
LPCHARACTER ch = NULL;
|
|||
|
|
|||
|
if (regen->type == REGEN_TYPE_ANYWHERE)
|
|||
|
{
|
|||
|
ch = CHARACTER_MANAGER::instance().SpawnMobRandomPosition(regen->vnum, regen->lMapIndex);
|
|||
|
|
|||
|
if (ch)
|
|||
|
{
|
|||
|
++regen->count;
|
|||
|
ch->SetDungeon(pDungeon);
|
|||
|
}
|
|||
|
}
|
|||
|
else if (regen->sx == regen->ex && regen->sy == regen->ey)
|
|||
|
{
|
|||
|
ch = CHARACTER_MANAGER::instance().SpawnMob(regen->vnum,
|
|||
|
regen->lMapIndex,
|
|||
|
regen->sx,
|
|||
|
regen->sy,
|
|||
|
regen->z_section,
|
|||
|
false,
|
|||
|
regen->direction == 0 ? number(0, 7) * 45 : (regen->direction - 1) * 45);
|
|||
|
|
|||
|
if (ch)
|
|||
|
{
|
|||
|
++regen->count;
|
|||
|
ch->SetDungeon(pDungeon);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (regen->type == REGEN_TYPE_MOB)
|
|||
|
{
|
|||
|
ch = CHARACTER_MANAGER::Instance().SpawnMobRange(regen->vnum, regen->lMapIndex, regen->sx, regen->sy, regen->ex, regen->ey, true);
|
|||
|
|
|||
|
if (ch)
|
|||
|
{
|
|||
|
++regen->count;
|
|||
|
ch->SetDungeon(pDungeon);
|
|||
|
}
|
|||
|
}
|
|||
|
else if (regen->type == REGEN_TYPE_GROUP)
|
|||
|
{
|
|||
|
if (CHARACTER_MANAGER::Instance().SpawnGroup(regen->vnum, regen->lMapIndex, regen->sx, regen->sy, regen->ex, regen->ey, bOnce ? NULL : regen, regen->is_aggressive, pDungeon))
|
|||
|
++regen->count;
|
|||
|
}
|
|||
|
else if (regen->type == REGEN_TYPE_GROUP_GROUP)
|
|||
|
{
|
|||
|
if (CHARACTER_MANAGER::Instance().SpawnGroupGroup(regen->vnum, regen->lMapIndex, regen->sx, regen->sy, regen->ex, regen->ey, bOnce ? NULL : regen, regen->is_aggressive, pDungeon))
|
|||
|
++regen->count;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (ch && !bOnce)
|
|||
|
ch->SetRegen(regen);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static void regen_spawn(LPREGEN regen, bool bOnce)
|
|||
|
{
|
|||
|
DWORD num;
|
|||
|
DWORD i;
|
|||
|
|
|||
|
num = (regen->max_count - regen->count);
|
|||
|
|
|||
|
if (!num)
|
|||
|
return;
|
|||
|
|
|||
|
for (i = 0; i < num; ++i)
|
|||
|
{
|
|||
|
LPCHARACTER ch = NULL;
|
|||
|
|
|||
|
if (regen->type == REGEN_TYPE_ANYWHERE)
|
|||
|
{
|
|||
|
ch = CHARACTER_MANAGER::instance().SpawnMobRandomPosition(regen->vnum, regen->lMapIndex);
|
|||
|
|
|||
|
if (ch)
|
|||
|
++regen->count;
|
|||
|
}
|
|||
|
else if (regen->sx == regen->ex && regen->sy == regen->ey)
|
|||
|
{
|
|||
|
ch = CHARACTER_MANAGER::instance().SpawnMob(regen->vnum,
|
|||
|
regen->lMapIndex,
|
|||
|
regen->sx,
|
|||
|
regen->sy,
|
|||
|
regen->z_section,
|
|||
|
false,
|
|||
|
regen->direction == 0 ? number(0, 7) * 45 : (regen->direction - 1) * 45);
|
|||
|
|
|||
|
if (ch)
|
|||
|
++regen->count;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (regen->type == REGEN_TYPE_MOB)
|
|||
|
{
|
|||
|
ch = CHARACTER_MANAGER::Instance().SpawnMobRange(regen->vnum, regen->lMapIndex, regen->sx, regen->sy, regen->ex, regen->ey, true, regen->is_aggressive, regen->is_aggressive );
|
|||
|
|
|||
|
if (ch)
|
|||
|
++regen->count;
|
|||
|
}
|
|||
|
else if (regen->type == REGEN_TYPE_GROUP)
|
|||
|
{
|
|||
|
if (CHARACTER_MANAGER::Instance().SpawnGroup(regen->vnum, regen->lMapIndex, regen->sx, regen->sy, regen->ex, regen->ey, bOnce ? NULL : regen, regen->is_aggressive))
|
|||
|
++regen->count;
|
|||
|
}
|
|||
|
else if (regen->type == REGEN_TYPE_GROUP_GROUP)
|
|||
|
{
|
|||
|
if (CHARACTER_MANAGER::Instance().SpawnGroupGroup(regen->vnum, regen->lMapIndex, regen->sx, regen->sy, regen->ex, regen->ey, bOnce ? NULL : regen, regen->is_aggressive))
|
|||
|
++regen->count;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (ch && !bOnce)
|
|||
|
ch->SetRegen(regen);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
EVENTFUNC(dungeon_regen_event)
|
|||
|
{
|
|||
|
dungeon_regen_event_info* info = dynamic_cast<dungeon_regen_event_info*>( event->info );
|
|||
|
|
|||
|
if ( info == NULL )
|
|||
|
{
|
|||
|
sys_err( "dungeon_regen_event> <Factor> Null pointer" );
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
LPDUNGEON pDungeon = CDungeonManager::instance().Find(info->dungeon_id);
|
|||
|
if (pDungeon == NULL) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
LPREGEN regen = info->regen;
|
|||
|
if (regen->time == 0)
|
|||
|
{
|
|||
|
regen->event = NULL;
|
|||
|
}
|
|||
|
|
|||
|
regen_spawn_dungeon(regen, pDungeon, false);
|
|||
|
return PASSES_PER_SEC(regen->time);
|
|||
|
}
|
|||
|
|
|||
|
bool regen_do(const char* filename, long lMapIndex, int base_x, int base_y, LPDUNGEON pDungeon, bool bOnce)
|
|||
|
{
|
|||
|
if (g_bNoRegen)
|
|||
|
return true;
|
|||
|
|
|||
|
if ( lMapIndex >= 114 && lMapIndex <= 117 )
|
|||
|
return true;
|
|||
|
|
|||
|
LPREGEN regen = NULL;
|
|||
|
FILE* fp = fopen(filename, "rt");
|
|||
|
|
|||
|
if (NULL == fp)
|
|||
|
{
|
|||
|
sys_err("SYSTEM: regen_do: %s: file not found", filename);
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
while (true)
|
|||
|
{
|
|||
|
REGEN tmp;
|
|||
|
|
|||
|
memset(&tmp, 0, sizeof(tmp));
|
|||
|
|
|||
|
if (!read_line(fp, &tmp))
|
|||
|
break;
|
|||
|
|
|||
|
if (tmp.type == REGEN_TYPE_MOB ||
|
|||
|
tmp.type == REGEN_TYPE_GROUP ||
|
|||
|
tmp.type == REGEN_TYPE_GROUP_GROUP ||
|
|||
|
tmp.type == REGEN_TYPE_ANYWHERE)
|
|||
|
{
|
|||
|
if (!bOnce)
|
|||
|
{
|
|||
|
regen = M2_NEW REGEN;
|
|||
|
memcpy(regen, &tmp, sizeof(REGEN));
|
|||
|
}
|
|||
|
else
|
|||
|
regen = &tmp;
|
|||
|
|
|||
|
if (pDungeon)
|
|||
|
regen->is_aggressive = true;
|
|||
|
|
|||
|
regen->lMapIndex = lMapIndex;
|
|||
|
regen->count = 0;
|
|||
|
|
|||
|
regen->sx += base_x;
|
|||
|
regen->ex += base_x;
|
|||
|
|
|||
|
regen->sy += base_y;
|
|||
|
regen->ey += base_y;
|
|||
|
|
|||
|
if (regen->sx > regen->ex)
|
|||
|
{
|
|||
|
regen->sx ^= regen->ex;
|
|||
|
regen->ex ^= regen->sx;
|
|||
|
regen->sx ^= regen->ex;
|
|||
|
}
|
|||
|
|
|||
|
if (regen->sy > regen->ey)
|
|||
|
{
|
|||
|
regen->sy ^= regen->ey;
|
|||
|
regen->ey ^= regen->sy;
|
|||
|
regen->sy ^= regen->ey;
|
|||
|
}
|
|||
|
|
|||
|
if (regen->type == REGEN_TYPE_MOB)
|
|||
|
{
|
|||
|
const CMob * p = CMobManager::instance().Get(regen->vnum);
|
|||
|
|
|||
|
if (!p)
|
|||
|
{
|
|||
|
sys_err("No mob data by vnum %u", regen->vnum);
|
|||
|
if (!bOnce) {
|
|||
|
M2_DELETE(regen);
|
|||
|
}
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!bOnce && pDungeon != NULL)
|
|||
|
{
|
|||
|
dungeon_regen_event_info* info = AllocEventInfo<dungeon_regen_event_info>();
|
|||
|
|
|||
|
info->regen = regen;
|
|||
|
info->dungeon_id = pDungeon->GetId();
|
|||
|
|
|||
|
regen->event = event_create(dungeon_regen_event, info, PASSES_PER_SEC(number(0, 16)) + PASSES_PER_SEC(regen->time));
|
|||
|
|
|||
|
pDungeon->AddRegen(regen);
|
|||
|
// regen_id should be determined at this point,
|
|||
|
// before the call to CHARACTER::SetRegen()
|
|||
|
}
|
|||
|
|
|||
|
// ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ش<EFBFBD>.
|
|||
|
regen_spawn_dungeon(regen, pDungeon, bOnce);
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
fclose(fp);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
bool regen_load_in_file(const char* filename, long lMapIndex, int base_x, int base_y)
|
|||
|
{
|
|||
|
if (g_bNoRegen)
|
|||
|
return true;
|
|||
|
|
|||
|
LPREGEN regen = NULL;
|
|||
|
FILE * fp = fopen(filename, "rt");
|
|||
|
|
|||
|
if (NULL == fp)
|
|||
|
{
|
|||
|
sys_err("SYSTEM: regen_do: %s: file not found", filename);
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
while (true)
|
|||
|
{
|
|||
|
REGEN tmp;
|
|||
|
|
|||
|
memset(&tmp, 0, sizeof(tmp));
|
|||
|
|
|||
|
if (!read_line(fp, &tmp))
|
|||
|
break;
|
|||
|
|
|||
|
if (tmp.type == REGEN_TYPE_MOB ||
|
|||
|
tmp.type == REGEN_TYPE_GROUP ||
|
|||
|
tmp.type == REGEN_TYPE_GROUP_GROUP ||
|
|||
|
tmp.type == REGEN_TYPE_ANYWHERE)
|
|||
|
{
|
|||
|
regen = &tmp;
|
|||
|
|
|||
|
regen->is_aggressive = true;
|
|||
|
|
|||
|
regen->lMapIndex = lMapIndex;
|
|||
|
regen->count = 0;
|
|||
|
|
|||
|
regen->sx += base_x;
|
|||
|
regen->ex += base_x;
|
|||
|
|
|||
|
regen->sy += base_y;
|
|||
|
regen->ey += base_y;
|
|||
|
|
|||
|
if (regen->sx > regen->ex)
|
|||
|
{
|
|||
|
regen->sx ^= regen->ex;
|
|||
|
regen->ex ^= regen->sx;
|
|||
|
regen->sx ^= regen->ex;
|
|||
|
}
|
|||
|
|
|||
|
if (regen->sy > regen->ey)
|
|||
|
{
|
|||
|
regen->sy ^= regen->ey;
|
|||
|
regen->ey ^= regen->sy;
|
|||
|
regen->sy ^= regen->ey;
|
|||
|
}
|
|||
|
|
|||
|
if (regen->type == REGEN_TYPE_MOB)
|
|||
|
{
|
|||
|
const CMob * p = CMobManager::instance().Get(regen->vnum);
|
|||
|
|
|||
|
if (!p)
|
|||
|
{
|
|||
|
sys_err("No mob data by vnum %u", regen->vnum);
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ش<EFBFBD>.
|
|||
|
regen_spawn(regen, true);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
fclose(fp);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
EVENTFUNC(regen_event)
|
|||
|
{
|
|||
|
regen_event_info* info = dynamic_cast<regen_event_info*>( event->info );
|
|||
|
|
|||
|
if ( info == NULL )
|
|||
|
{
|
|||
|
sys_err( "regen_event> <Factor> Null pointer" );
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
LPREGEN regen = info->regen;
|
|||
|
|
|||
|
if (regen->time == 0)
|
|||
|
regen->event = NULL;
|
|||
|
|
|||
|
regen_spawn(regen, false);
|
|||
|
return PASSES_PER_SEC(regen->time);
|
|||
|
}
|
|||
|
|
|||
|
bool regen_load(const char* filename, long lMapIndex, int base_x, int base_y)
|
|||
|
{
|
|||
|
if (g_bNoRegen)
|
|||
|
return true;
|
|||
|
|
|||
|
LPREGEN regen = NULL;
|
|||
|
FILE* fp = fopen(filename, "rt");
|
|||
|
|
|||
|
if (NULL == fp)
|
|||
|
{
|
|||
|
sys_log(0, "SYSTEM: regen_load: %s: file not found", filename);
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
while (true)
|
|||
|
{
|
|||
|
REGEN tmp;
|
|||
|
|
|||
|
memset(&tmp, 0, sizeof(tmp));
|
|||
|
|
|||
|
if (!read_line(fp, &tmp))
|
|||
|
break;
|
|||
|
|
|||
|
if (tmp.type == REGEN_TYPE_MOB ||
|
|||
|
tmp.type == REGEN_TYPE_GROUP ||
|
|||
|
tmp.type == REGEN_TYPE_GROUP_GROUP ||
|
|||
|
tmp.type == REGEN_TYPE_ANYWHERE)
|
|||
|
{
|
|||
|
if (test_server)
|
|||
|
{
|
|||
|
CMobManager::instance().IncRegenCount(tmp.type, tmp.vnum, tmp.max_count, tmp.time);
|
|||
|
}
|
|||
|
|
|||
|
regen = M2_NEW REGEN;
|
|||
|
memcpy(regen, &tmp, sizeof(REGEN));
|
|||
|
INSERT_TO_TW_LIST(regen, regen_list, prev, next);
|
|||
|
|
|||
|
regen->lMapIndex = lMapIndex;
|
|||
|
regen->count = 0;
|
|||
|
|
|||
|
regen->sx += base_x;
|
|||
|
regen->ex += base_x;
|
|||
|
|
|||
|
regen->sy += base_y;
|
|||
|
regen->ey += base_y;
|
|||
|
|
|||
|
if (regen->sx > regen->ex)
|
|||
|
{
|
|||
|
regen->sx ^= regen->ex;
|
|||
|
regen->ex ^= regen->sx;
|
|||
|
regen->sx ^= regen->ex;
|
|||
|
}
|
|||
|
|
|||
|
if (regen->sy > regen->ey)
|
|||
|
{
|
|||
|
regen->sy ^= regen->ey;
|
|||
|
regen->ey ^= regen->sy;
|
|||
|
regen->sy ^= regen->ey;
|
|||
|
}
|
|||
|
|
|||
|
if (regen->type == REGEN_TYPE_MOB)
|
|||
|
{
|
|||
|
const CMob * p = CMobManager::instance().Get(regen->vnum);
|
|||
|
|
|||
|
if (!p)
|
|||
|
{
|
|||
|
sys_err("No mob data by vnum %u", regen->vnum);
|
|||
|
}
|
|||
|
else if (p->m_table.bType == CHAR_TYPE_NPC || p->m_table.bType == CHAR_TYPE_WARP || p->m_table.bType == CHAR_TYPE_GOTO)
|
|||
|
{
|
|||
|
SECTREE_MANAGER::instance().InsertNPCPosition(lMapIndex,
|
|||
|
p->m_table.bType,
|
|||
|
p->m_table.szLocaleName,
|
|||
|
(regen->sx+regen->ex) / 2 - base_x,
|
|||
|
(regen->sy+regen->ey) / 2 - base_y);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//NO_REGEN
|
|||
|
// Desc: regen.txt (<28><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ؽ<EFBFBD>Ʈ ) <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ð<EFBFBD><C3B0><EFBFBD> 0<><30><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ҽ<EFBFBD>
|
|||
|
// <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ѵ<EFBFBD>.
|
|||
|
if (regen->time != 0)
|
|||
|
{
|
|||
|
// ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ش<EFBFBD>.
|
|||
|
regen_spawn(regen, false);
|
|||
|
|
|||
|
regen_event_info* info = AllocEventInfo<regen_event_info>();
|
|||
|
|
|||
|
info->regen = regen;
|
|||
|
|
|||
|
regen->event = event_create(regen_event, info, PASSES_PER_SEC(number(0, 16)) + PASSES_PER_SEC(regen->time));
|
|||
|
}
|
|||
|
//END_NO_REGEN
|
|||
|
}
|
|||
|
else if (tmp.type == REGEN_TYPE_EXCEPTION)
|
|||
|
{
|
|||
|
LPREGEN_EXCEPTION exc;
|
|||
|
|
|||
|
exc = M2_NEW REGEN_EXCEPTION;
|
|||
|
|
|||
|
exc->sx = tmp.sx;
|
|||
|
exc->sy = tmp.sy;
|
|||
|
exc->ex = tmp.ex;
|
|||
|
exc->ey = tmp.ey;
|
|||
|
exc->z_section = tmp.z_section;
|
|||
|
|
|||
|
INSERT_TO_TW_LIST(exc, regen_exception_list, prev, next);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
fclose(fp);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
void regen_free(void)
|
|||
|
{
|
|||
|
LPREGEN regen, next_regen;
|
|||
|
LPREGEN_EXCEPTION exc, next_exc;
|
|||
|
|
|||
|
for (regen = regen_list; regen; regen = next_regen)
|
|||
|
{
|
|||
|
next_regen = regen->next;
|
|||
|
|
|||
|
event_cancel(®en->event);
|
|||
|
M2_DELETE(regen);
|
|||
|
}
|
|||
|
|
|||
|
regen_list = NULL;
|
|||
|
|
|||
|
for (exc = regen_exception_list; exc; exc = next_exc)
|
|||
|
{
|
|||
|
next_exc = exc->next;
|
|||
|
|
|||
|
M2_DELETE(exc);
|
|||
|
}
|
|||
|
|
|||
|
regen_exception_list = NULL;
|
|||
|
}
|
|||
|
|
|||
|
void regen_reset(int x, int y)
|
|||
|
{
|
|||
|
LPREGEN regen;
|
|||
|
|
|||
|
for (regen = regen_list; regen; regen = regen->next)
|
|||
|
{
|
|||
|
if (!regen->event)
|
|||
|
continue;
|
|||
|
|
|||
|
// <20><>ǥ<EFBFBD><C7A5> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ǥ <20><><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> <20><>Ų<EFBFBD><C5B2>.
|
|||
|
if (x != 0 || y != 0)
|
|||
|
{
|
|||
|
if (x >= regen->sx && x <= regen->ex)
|
|||
|
if (y >= regen->sy && y <= regen->ey)
|
|||
|
event_reset_time(regen->event, 1);
|
|||
|
}
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
|||
|
else
|
|||
|
event_reset_time(regen->event, 1);
|
|||
|
}
|
|||
|
}
|
|||
|
|