server/game/src/castle.cpp

1080 lines
21 KiB
C++

/*********************************************************************
* date : 2007.04.07
* file : castle.cpp
* author : mhh
* description :
* 봉화 번호 : 11506 - 11510
* 메틴석 번호 : 8012 - 8014, 8024-8027
*/
#define _castle_cpp_
#include "stdafx.h"
#include "constants.h"
#include "config.h"
#include "char_manager.h"
#include "castle.h"
#include "start_position.h"
#include "monarch.h"
#include "questlua.h"
#include "log.h"
#include "char.h"
#include "sectree_manager.h"
#define EMPIRE_NONE 0 // 아무국가 아님
#define EMPIRE_RED 1 // 신수
#define EMPIRE_YELLOW 2 // 천조
#define EMPIRE_BLUE 3 // 진노
#define SIEGE_EVENT_PULSE PASSES_PER_SEC(60*5) // 5분
#define GET_CAHR_MANAGER() CHARACTER_MANAGER::instance()
#define GET_CASTLE(empire) (s_castle+(empire))
#define GET_GUARD(empire, region_index, guard_index) (GET_CASTLE(empire)->guard[region_index][guard_index])
#define GET_GUARD_REGION(empire, region_index) (s_guard_region[empire][region_index])
#define GET_GUARD_GROUP(empire, region_index, guard_index) (GET_CASTLE(empire)->guard_group[region_index][guard_index])
#define GET_FROG(empire, index) (GET_CASTLE(empire)->frog[index])
#define GET_FROG_POS(empire, index) (s_frog_pos[empire][index])
#define GET_TOWER(empire, index) (GET_CASTLE(empire)->tower[index])
#define DO_ALL_EMPIRE(empire) for (int empire = 1; empire < 4; ++empire)
#define DO_ALL_TOWER(i) for (int i = 0; i < MAX_CASTLE_TOWER; ++i)
#define DO_ALL_FROG(i) for (int i = 0; i < MAX_CASTLE_FROG; ++i)
#define GET_SIEGE_STATE() s_siege_state
#define GET_SIEGE_EMPIRE() s_sige_empire
#define GET_SIEGE_EVENT(empire) (GET_CASTLE(empire)->siege_event)
#define GET_STONE_EVENT(empire) (GET_CASTLE(empire)->stone_event)
#define GET_TOWER_REGION(empire) s_tower_region[empire]
#define GET_STONE_REGION(empire) s_tower_region[empire]
static CASTLE_DATA *s_castle = NULL;
static CASTLE_STATE s_siege_state = CASTLE_SIEGE_NONE;
static int s_sige_empire = EMPIRE_NONE;
struct POSITION
{
int x, y;
};
static POSITION s_frog_pos[4][MAX_CASTLE_FROG] = {
// EMPIRE_NONE
{
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 }
},
// EMPIRE_RED
{
{ 225, 45 },
{ 231, 45 },
{ 237, 45 },
{ 243, 45 },
{ 249, 45 },
{ 225, 50 },
{ 231, 50 },
{ 237, 50 },
{ 243, 50 },
{ 249, 50 },
{ 261, 45 },
{ 267, 45 },
{ 273, 45 },
{ 279, 45 },
{ 285, 45 },
{ 261, 50 },
{ 267, 50 },
{ 273, 50 },
{ 279, 50 },
{ 285, 50 }
},
// EMPIRE_YELLOW
{
{ 221, 36 },
{ 227, 36 },
{ 233, 36 },
{ 239, 36 },
{ 245, 36 },
{ 269, 36 },
{ 275, 36 },
{ 281, 36 },
{ 287, 36 },
{ 293, 36 },
{ 221, 41 },
{ 227, 41 },
{ 233, 41 },
{ 239, 41 },
{ 245, 41 },
{ 269, 41 },
{ 275, 41 },
{ 281, 41 },
{ 287, 41 },
{ 293, 41 }
},
// EMPIRE_BLUE
{
{ 225, 45 },
{ 231, 45 },
{ 237, 45 },
{ 243, 45 },
{ 249, 45 },
{ 225, 50 },
{ 231, 50 },
{ 237, 50 },
{ 243, 50 },
{ 249, 50 },
{ 261, 45 },
{ 267, 45 },
{ 273, 45 },
{ 279, 45 },
{ 285, 45 },
{ 261, 50 },
{ 267, 50 },
{ 273, 50 },
{ 279, 50 },
{ 285, 50 }
}
};
/* 경비병 경비구역 */
struct GUARD_REGION
{
int sx, sy, ex, ey;
};
static GUARD_REGION s_guard_region[4][4] = {
// NULL_EMPIRE
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 }
},
// EMPIRE_RED
{
{ 74, 170, 96, 180 },
{ 237, 135, 270, 146 },
{ 235, 260, 278, 273 },
{ 421, 167, 435, 205 }
},
// EMPIRE_YELLOW
{
{ 109, 172, 128, 202 },
{ 237, 140, 282, 153 },
{ 232, 261, 279, 276 },
{ 390, 173, 403, 205 },
},
// EMPIRE_BLUE
{
{ 74, 170, 96, 120 },
{ 237, 135, 270, 146 },
{ 235, 260, 278, 273 },
{ 421, 167, 435, 205 }
}
};
static GUARD_REGION s_tower_region[4] = {
// NULL_EMPIRE
{ 0, 0, 0, 0 },
// EMPIRE_RED
{ 85, 135, 420, 265 },
// EMPIRE_YELLOW
{ 120, 130, 405, 276 },
// EMPIRE_BLUE
{ 85, 135, 420, 265 }
};
static int FN_castle_map_index(int empire);
EVENTINFO(castle_event_info)
{
int empire;
int pulse;
castle_event_info()
: empire( 0 )
, pulse( 0 )
{
}
};
EVENTFUNC(castle_siege_event)
{
char buf[1024] = {0};
struct castle_event_info *info = dynamic_cast<castle_event_info*>( event->info );
if ( info == NULL )
{
sys_err( "castle_siege_event> <Factor> Null pointer" );
return 0;
}
info->pulse += SIEGE_EVENT_PULSE;
// 공성 시작후 30분 이내라면 안내만 하자
if (info->pulse < PASSES_PER_SEC(30*60))
{
snprintf(buf, sizeof(buf), LC_TEXT("%s에서 봉화를 둘러싸고 전투가 진행중입니다."),
EMPIRE_NAME(GET_SIEGE_EMPIRE()));
BroadcastNotice(buf);
return SIEGE_EVENT_PULSE;
}
switch (GET_SIEGE_STATE())
{
case CASTLE_SIEGE_NONE:
break;
case CASTLE_SIEGE_STRUGGLE:
{
snprintf(buf, sizeof(buf), LC_TEXT("%s이 수성에 성공했습니다."), EMPIRE_NAME(GET_SIEGE_EMPIRE()));
BroadcastNotice(buf);
snprintf(buf, sizeof(buf), LC_TEXT("지금부터 %s은 30분간 봉화를 파괴하여 보상을 획득 할 수 있습니다."), EMPIRE_NAME(GET_SIEGE_EMPIRE()));
BroadcastNotice(buf);
GET_SIEGE_STATE() = CASTLE_SIEGE_END;
return PASSES_PER_SEC(60*30); // 30분
}
break;
case CASTLE_SIEGE_END:
BroadcastNotice(LC_TEXT("30분이 경과했습니다.. 봉화가 사라집니다."));
castle_end_siege();
break;
}
return 0;
}
static DWORD FN_random_stone()
{
DWORD vnum[7] = {
8012,
8013,
8014,
8024,
8025,
8026,
8027
};
int index = Random::get(0, 6);
return vnum[index];
}
EVENTINFO(castle_stone_event_info)
{
int empire;
int spawn_count;
castle_stone_event_info()
: empire( 0 )
, spawn_count( 0 )
{
}
};
EVENTFUNC(castle_stone_event)
{
struct castle_stone_event_info *info = dynamic_cast<castle_stone_event_info*>( event->info );
if (info == NULL)
{
sys_err( "castle_stone_event> <Factor> Null pointer" );
return 0;
}
int map_index = FN_castle_map_index(GET_SIEGE_EMPIRE());
SECTREE_MAP *sectree_map = SECTREE_MANAGER::instance().GetMap(map_index);
if (NULL == sectree_map)
return 0;
/* 15마리씩 2번 소환 */
const int SPAWN_COUNT = 15;
if (info->spawn_count < (SPAWN_COUNT * 2))
{
for (int i = 0; i < SPAWN_COUNT; ++i)
{
DWORD sx = sectree_map->m_setting.iBaseX + 100 * GET_TOWER_REGION(info->empire).sx;
DWORD sy = sectree_map->m_setting.iBaseY + 100 * GET_TOWER_REGION(info->empire).sy;
DWORD ex = sectree_map->m_setting.iBaseX + 100 * GET_TOWER_REGION(info->empire).ex;
DWORD ey = sectree_map->m_setting.iBaseY + 100 * GET_TOWER_REGION(info->empire).ey;
CHARACTER_MANAGER::instance().SpawnMobRange(FN_random_stone(),
FN_castle_map_index(info->empire),
sx, sy, ex, ey);
}
info->spawn_count += SPAWN_COUNT;
if (info->spawn_count < (SPAWN_COUNT * 2))
return PASSES_PER_SEC(30 * 60); // 30분
else
return 0;
}
return 0;
}
LPCHARACTER castle_spawn_frog_force(int empire, int empty_index);
static int FN_castle_map_index(int empire)
{
switch (empire)
{
case EMPIRE_RED: return 181;
case EMPIRE_YELLOW: return 183;
case EMPIRE_BLUE: return 182;
}
return 0;
}
static int FN_empty_frog_index(int empire)
{
DO_ALL_FROG(i)
{
if (NULL == GET_FROG(empire, i))
return i;
}
return (-1);
}
static POSITION* FN_empty_frog_pos(int empire)
{
int frog_index = FN_empty_frog_index(empire);
if (frog_index < 0)
return NULL;
switch (empire)
{
case EMPIRE_RED:
case EMPIRE_YELLOW:
case EMPIRE_BLUE:
return &GET_FROG_POS(empire, frog_index);
}
return NULL;
}
static int FN_empty_guard_pos(int empire, int region_index)
{
for (int i = 0; i < MAX_CASTLE_GUARD_PER_REGION; ++i)
{
if (NULL == GET_GUARD(empire, region_index, i))
{
return i;
}
}
return -1;
}
static bool FN_is_castle_map(int map_index)
{
switch (map_index)
{
case 181:
case 182:
case 183:
return true;
}
return false;
}
bool castle_boot()
{
FILE *fp;
char one_line[256];
const char *delim = " \t\r\n";
char *v;
int empire = 0;
int guard_region = 0;
CREATE(s_castle, CASTLE_DATA, 4);
const char *castle_file = "castle_data.txt";
if ((fp = fopen(castle_file, "r")) == 0)
return false;
while (fgets(one_line, 256, fp))
{
int value = 0;
if (one_line[0] == '#')
continue;
const char* token_string = strtok(one_line, delim);
if (NULL == token_string)
continue;
TOKEN("section")
{
continue;
}
else TOKEN("empire")
{
v = strtok(NULL, delim);
if (v)
{
str_to_number(empire, v);
}
else
{
fclose(fp);
sys_err("wrong empire number is null");
return false;
}
}
else TOKEN("frog")
{
int pos = 0;
while ((v = strtok(NULL, delim)))
{
str_to_number(value, v);
if (value)
{
castle_spawn_frog_force(empire, pos);
}
++pos;
}
}
else TOKEN("guard")
{
int group_vnum = 0;
while ((v = strtok(NULL, delim)))
{
str_to_number(group_vnum, v);
if (group_vnum)
{
castle_spawn_guard(empire, group_vnum, guard_region);
}
}
++guard_region;
}
else TOKEN("end")
{
guard_region = 0;
}
}
fclose(fp);
return true;
}
void castle_save()
{
if (NULL == s_castle)
return;
const char *castle_file = "castle_data.txt";
FILE *fp;
fp = fopen(castle_file, "w");
if (NULL == fp)
{
sys_err("<FAIL> fopen(%s)", castle_file);
return;
}
// write castle data
DO_ALL_EMPIRE(empire)
{
fprintf(fp, "section\n");
// write empire
fprintf(fp, "\tempire %d\n", empire);
// write frog
fprintf(fp, "\tfrog ");
for (int i = 0; i < MAX_CASTLE_FROG; ++i)
{
fprintf(fp, " %d", GET_FROG(empire, i) ? 1 : 0);
}
fprintf(fp, "\n");
// write guard group
for (int region_index = 0; region_index < MAX_CASTLE_GUARD_REGION; ++region_index)
{
fprintf(fp, "\tguard ");
for (int guard_index = 0; guard_index < MAX_CASTLE_GUARD_PER_REGION; ++guard_index)
{
fprintf(fp, " %u", GET_GUARD_GROUP(empire, region_index, guard_index));
}
fprintf(fp, "\n");
}
fprintf(fp, "end\n");
}
fclose(fp);
}
int castle_siege(int empire, int tower_count)
{
// check siege map
{
if (NULL == SECTREE_MANAGER::instance().GetMap(181)) return 0;
if (NULL == SECTREE_MANAGER::instance().GetMap(182)) return 0;
if (NULL == SECTREE_MANAGER::instance().GetMap(183)) return 0;
}
switch (GET_SIEGE_STATE())
{
case CASTLE_SIEGE_NONE:
castle_start_siege(empire, tower_count);
return 1;
break;
case CASTLE_SIEGE_STRUGGLE:
case CASTLE_SIEGE_END:
castle_end_siege();
return 2;
break;
}
return 0;
}
void castle_start_siege(int empire, int tower_count)
{
if (CASTLE_SIEGE_NONE != GET_SIEGE_STATE())
return;
GET_SIEGE_STATE() = CASTLE_SIEGE_STRUGGLE;
GET_SIEGE_EMPIRE() = empire;
castle_spawn_tower(empire, tower_count);
/* 공성 타이머 시작 */
{
castle_event_info* info = AllocEventInfo<castle_event_info>();
info->empire = empire;
info->pulse = 0;
GET_SIEGE_EVENT(empire) = event_create(castle_siege_event, info, /*5분*/SIEGE_EVENT_PULSE);
}
/* 메틴석 소환 타이머 시작 */
{
castle_stone_event_info* info = AllocEventInfo<castle_stone_event_info>();
info->spawn_count = 0;
info->empire = empire;
GET_STONE_EVENT(empire) = event_create(castle_stone_event, info, /* 1초 */PASSES_PER_SEC(1));
}
}
void castle_end_siege()
{
GET_SIEGE_EMPIRE() = EMPIRE_NONE;
GET_SIEGE_STATE() = CASTLE_SIEGE_NONE;
DO_ALL_EMPIRE(empire)
{
if (GET_SIEGE_EVENT(empire))
{
event_cancel(&GET_SIEGE_EVENT(empire));
}
DO_ALL_TOWER(i)
{
if (GET_TOWER(empire, i))
{
LPCHARACTER npc = GET_TOWER(empire, i);
M2_DESTROY_CHARACTER(npc);
GET_TOWER(empire, i) = NULL;
}
}
}
}
LPCHARACTER castle_spawn_frog(int empire)
{
int dir = 1;
int map_index = FN_castle_map_index(empire);
/* 황금두꺼비 소환할 곳이 있나? */
POSITION *empty_pos = FN_empty_frog_pos(empire);
if (NULL == empty_pos)
return NULL;
SECTREE_MAP *sectree_map = SECTREE_MANAGER::instance().GetMap(map_index);
if (NULL == sectree_map)
return NULL;
DWORD x = sectree_map->m_setting.iBaseX + 100*empty_pos->x;
DWORD y = sectree_map->m_setting.iBaseY + 100*empty_pos->y;
LPCHARACTER frog = CHARACTER_MANAGER::instance().SpawnMob(CASTLE_FROG_VNUM, map_index,
x, y, 0 ,
false, dir);
if (frog)
{
frog->SetEmpire(empire);
int empty_index = FN_empty_frog_index(empire);
// 스폰성공
GET_FROG(empire, empty_index) = frog;
return frog;
}
return NULL;
}
LPCHARACTER castle_spawn_frog_force(int empire, int empty_index)
{
int dir = 1;
int map_index = FN_castle_map_index(empire);
POSITION *empty_pos = &GET_FROG_POS(empire, empty_index);
SECTREE_MAP *sectree_map = SECTREE_MANAGER::instance().GetMap(map_index);
if (NULL == sectree_map)
{
return NULL;
}
DWORD x = sectree_map->m_setting.iBaseX + 100*empty_pos->x;
DWORD y = sectree_map->m_setting.iBaseY + 100*empty_pos->y;
LPCHARACTER frog = CHARACTER_MANAGER::instance().SpawnMob(CASTLE_FROG_VNUM, map_index,
x, y, 0 ,
false, dir);
if (frog)
{
frog->SetEmpire(empire);
GET_FROG(empire, empty_index) = frog;
return frog;
}
return NULL;
}
LPCHARACTER castle_spawn_guard(int empire, DWORD group_vnum, int region_index)
{
LPCHARACTER mob;
int sx, sy, ex, ey;
int map_index = FN_castle_map_index(empire);
SECTREE_MAP *sectree_map = SECTREE_MANAGER::instance().GetMap(map_index);
if (NULL == sectree_map)
return NULL;
if (castle_guard_count(empire, region_index) >= MAX_CASTLE_GUARD_PER_REGION)
return NULL;
sx = sectree_map->m_setting.iBaseX + 100*GET_GUARD_REGION(empire, region_index).sx;
sy = sectree_map->m_setting.iBaseY + 100*GET_GUARD_REGION(empire, region_index).sy;
ex = sectree_map->m_setting.iBaseX + 100*GET_GUARD_REGION(empire, region_index).ex;
ey = sectree_map->m_setting.iBaseY + 100*GET_GUARD_REGION(empire, region_index).ey;
mob = CHARACTER_MANAGER::instance().SpawnGroup(group_vnum, map_index,
sx, sy, ex, ey);
if (mob)
{
mob->SetEmpire(empire);
int pos = FN_empty_guard_pos(empire, region_index);
GET_GUARD(empire, region_index, pos) = mob;
GET_GUARD_GROUP(empire, region_index, pos) = group_vnum;
}
return mob;
}
static DWORD FN_random_tower()
{
DWORD vnum[5] =
{
11506,
11507,
11508,
11509,
11510
};
int index = Random::get(0, 4);
return vnum[index];
}
static void FN_spawn_tower(int empire, LPSECTREE_MAP sectree_map)
{
DO_ALL_TOWER(i)
{
if (GET_TOWER(empire, i))
continue;
DWORD sx = sectree_map->m_setting.iBaseX + 100 * GET_TOWER_REGION(empire).sx;
DWORD sy = sectree_map->m_setting.iBaseY + 100 * GET_TOWER_REGION(empire).sy;
DWORD ex = sectree_map->m_setting.iBaseX + 100 * GET_TOWER_REGION(empire).ex;
DWORD ey = sectree_map->m_setting.iBaseY + 100 * GET_TOWER_REGION(empire).ey;
GET_TOWER(empire, i) =
CHARACTER_MANAGER::instance().SpawnMobRange(FN_random_tower(),
FN_castle_map_index(empire),
sx, sy, ex, ey);
GET_TOWER(empire, i)->SetEmpire(empire);
return;
}
}
bool castle_spawn_tower(int empire, int tower_count)
{
int map_index = FN_castle_map_index(empire);
SECTREE_MAP *sectree_map = SECTREE_MANAGER::instance().GetMap(map_index);
if (NULL == sectree_map)
return false;
// 초기화
DO_ALL_TOWER(i)
{
if (GET_TOWER(empire, i))
GET_TOWER(empire, i)->Dead(NULL, true);
GET_TOWER(empire, i) = NULL;
}
int spawn_count = MINMAX(MIN_CASTLE_TOWER, tower_count, MAX_CASTLE_TOWER); // 5 ~ 10마리
for (int j = 0; j < spawn_count; ++j)
{
FN_spawn_tower(empire, sectree_map);
}
// broad cast
{
char buf[1024];
snprintf(buf, sizeof(buf), LC_TEXT("%s에 전쟁의 시작을 알리는 봉화가 나타났습니다."), EMPIRE_NAME(empire));
BroadcastNotice(buf);
}
return true;
}
/* 경비병리더가 죽으면 단순하게 슬롯만 비운다. */
void castle_guard_die(LPCHARACTER ch, LPCHARACTER killer)
{
int empire = ch->GetEmpire();
for (int region_index = 0; region_index < MAX_CASTLE_GUARD_REGION; ++region_index)
{
for (int i = 0; i < MAX_CASTLE_GUARD_PER_REGION; ++i)
{
if (GET_GUARD(empire, region_index, i) == ch)
{
GET_GUARD(empire, region_index, i) = NULL;
GET_GUARD_GROUP(empire, region_index, i) = 0;
}
}
}
castle_save();
}
/* 황금 두꺼비가 죽으면 killer에게 1천만냥 */
void castle_frog_die(LPCHARACTER ch, LPCHARACTER killer)
{
if (NULL == ch || NULL == killer)
return;
int empire = ch->GetEmpire();
DO_ALL_FROG(i)
{
if (ch == GET_FROG(empire, i))
{
GET_FROG(empire, i) = NULL;
killer->PointChange(POINT_GOLD, 10000000 /*1천만*/, true);
//CMonarch::instance().SendtoDBAddMoney(30000000/*3천만*/, killer->GetEmpire(), killer);
castle_save();
return;
}
}
}
/* 봉화가 모두 죽으면(?) 공성전이 끝난다 */
void castle_tower_die(LPCHARACTER ch, LPCHARACTER killer)
{
char buf[1024] = {0};
if (NULL == ch || NULL == killer)
return;
int killer_empire = killer->GetEmpire();
switch (GET_SIEGE_STATE())
{
case CASTLE_SIEGE_NONE:
break;
case CASTLE_SIEGE_STRUGGLE:
case CASTLE_SIEGE_END:
{
int siege_end = true;
snprintf(buf, sizeof(buf), LC_TEXT("%s이 봉화를 파괴했습니다."), EMPIRE_NAME(killer_empire));
BroadcastNotice(buf);
LogManager::instance().CharLog(killer, 0, "CASTLE_TORCH_KILL", "");
DO_ALL_TOWER(i)
{
if (ch == GET_TOWER(GET_SIEGE_EMPIRE(), i))
GET_TOWER(GET_SIEGE_EMPIRE(), i) = NULL;
}
DO_ALL_TOWER(i)
{
if (GET_TOWER(GET_SIEGE_EMPIRE(), i))
siege_end = false;
}
if (siege_end)
{
if (GET_SIEGE_STATE() == CASTLE_SIEGE_STRUGGLE)
{
snprintf(buf, sizeof(buf), LC_TEXT("%s이 수성에 실패하여 전쟁에 패배하였습니다.."), EMPIRE_NAME(GET_SIEGE_EMPIRE()));
BroadcastNotice(buf);
}
else
{
snprintf(buf, sizeof(buf), LC_TEXT("%s이 모든 봉화를 파괴하였습니다."), EMPIRE_NAME(GET_SIEGE_EMPIRE()));
BroadcastNotice(buf);
}
castle_end_siege();
}
}
break;
}
}
int castle_guard_count(int empire, int region_index)
{
int count = 0;
for (int i = 0; i < MAX_CASTLE_GUARD_PER_REGION; ++i)
{
if ( GET_GUARD(empire, region_index, i) )
++count;
}
return count;
}
int castle_frog_count(int empire)
{
int count = 0;
DO_ALL_FROG(i)
{
if (GET_FROG(empire, i))
++count;
}
return count;
}
bool castle_is_guard_vnum(DWORD vnum)
{
switch (vnum)
{
/* 상급 창경비병 */
case 11112:
case 11114:
case 11116:
/* 중급 창경비병 */
case 11106:
case 11108:
case 11110:
/* 하급 창경비병 */
case 11100:
case 11102:
case 11104:
/* 상급 활경비병 */
case 11113:
case 11115:
case 11117:
/* 중급 활경비병 */
case 11107:
case 11109:
case 11111:
/* 하급 활경비병 */
case 11101:
case 11103:
case 11105:
return true;
}
return false;
}
int castle_cost_of_hiring_guard(DWORD group_vnum)
{
switch (group_vnum)
{
/* 하급 */
case 9501: /* 신수 창경비 */
case 9511: /* 진노 창경비 */
case 9521: /* 천조 창경비 */
case 9502: /* 신수 활경비 */
case 9512: /* 진노 활경비 */
case 9522: /* 천조 활경비 */
return (100*10000);
/* 중급 */
case 9503: /* 신수 창경비 */
case 9513: /* 진노 창경비 */
case 9523: /* 천조 창경비 */
case 9504: /* 신수 활경비 */
case 9514: /* 진노 활경비 */
case 9524: /* 천조 활경비 */
return (300*10000);
/* 상급 */
case 9505: /* 신수 창경비 */
case 9515: /* 진노 창경비 */
case 9525: /* 천조 창경비 */
case 9506: /* 신수 활경비 */
case 9516: /* 진노 활경비 */
case 9526: /* 천조 활경비 */
return (1000*10000);
}
return 0;
}
bool castle_can_attack(LPCHARACTER ch, LPCHARACTER victim)
{
if (NULL == ch || NULL == victim)
return false;
if (false == FN_is_castle_map(ch->GetMapIndex()))
return false;
if (ch->IsPC() && victim->IsPC())
return true;
if (CASTLE_SIEGE_END == GET_SIEGE_STATE())
{
// 수성에 성공했을때 같은 제국만 봉화를 칠 수 있음
if (castle_is_tower_vnum(victim->GetRaceNum()))
{
if (ch->GetEmpire() == victim->GetEmpire())
return true;
else
return false;
}
}
// 같은 제국은 파괴 불가
if (ch->GetEmpire() == victim->GetEmpire())
return false;
return true;
}
bool castle_frog_to_empire_money(LPCHARACTER ch)
{
if (NULL == ch)
return false;
int empire = ch->GetEmpire();
DO_ALL_FROG(i)
{
if (NULL == GET_FROG(empire, i))
continue;
LPCHARACTER npc = GET_FROG(empire, i);
if (false == CMonarch::instance().SendtoDBAddMoney(CASTLE_FROG_PRICE, empire, ch))
return false;
GET_FROG(empire, i) = NULL; // 등록해제
npc->Dead(/*killer*/NULL, /*immediate_dead*/true);
return true;
}
return false;
}
bool castle_is_my_castle(int empire, int map_index)
{
switch (empire)
{
case EMPIRE_RED: return (181 == map_index);
case EMPIRE_YELLOW: return (183 == map_index);
case EMPIRE_BLUE: return (182 == map_index);
}
return false;
}
bool castle_is_tower_vnum(DWORD vnum)
{
switch (vnum)
{
case 11506:
case 11507:
case 11508:
case 11509:
case 11510:
return true;
}
return false;
}