?? npc_scheduleman.c
字號:
#include "version.h"
#include <time.h>
#include "char.h"
#include "object.h"
#include "lssproto_serv.h"
#include "npcutil.h"
#include "handletime.h"
#include "npc_scheduleman.h"
#include "family.h"
/*
* 家族 PK 登記員
*
* 這個 npc 顯示并且登記家族 pk 排程
* pk 排程以一小時一場 pk 為原則排定 pk 場的賽程, 這個賽程由登記員
* 登記與設(shè)定,主要的設(shè)定事項在 FamilyPKSchedule
*
* 這個登記員同時會將這個 schedule 寫入磁碟,如果 Game Server 重新
* 啟動的話,會先讀入這一份對戰(zhàn)排程表,同時進行排程。
* 排程只排從現(xiàn)在開始的 24 小時之內(nèi)的賽程
* 排程表檔案的格式為:
*
* time|host_index|host_name|guest_index|guest_name|prepare_time|max_player|flag|win
*
* 檔案的命名: 登記員樓層號碼_登記員X座標(biāo)_登記員Y座標(biāo)
*
*/
// 全部的家族 pk 賽程
FamilyPKSchedule fmpks[MAX_SCHEDULE*MAX_SCHEDULEMAN];
extern int familyNumTotal;
enum {
NPC_WORK_ID = CHAR_NPCWORKINT1, // 登記員 ID, 從 0 開始
NPC_WORK_CHALLENGETIMEOUT = CHAR_NPCWORKINT2, // 同意挑戰(zhàn)的 timeout
NPC_WORK_SETTINGTIMEOUT = CHAR_NPCWORKINT3, // 設(shè)定挑戰(zhàn)的 timeout
NPC_WORK_PREVIOUSCHECKTIME = CHAR_NPCWORKINT4, // 上一次檢查的時間
NPC_WORK_FIGHTINTERVAL = CHAR_NPCWORKINT5, // PK 場次的間隔 (單位: 分)
};
enum {
CHAR_WORK_PAGE = CHAR_WORKSHOPRELEVANT, // 換頁用
CHAR_WORK_DUELTIME = CHAR_WORKSHOPRELEVANTSEC, // 所選擇的 pk 時間
};
#define SCHEDULEFILEDIR "./Schedule/"
void NPC_LoadPKSchedule(int meindex); // Load schedule from disk
void NPC_SavePKSchedule(int meindex); // save schedule to disk
void NPC_RemoveExpiredBattle(int meindex); // 移除過期的戰(zhàn)斗
void NPC_ProcessTimeout(int meindex); // 處理 timeout
BOOL NPC_AlreadyScheduled(int meindex, int talkerindex); // 檢查, 一個家族只能安排一場
// 產(chǎn)生排程表的 data
void NPC_LIST_gendata(int meindex, int talkerindex, int page, char *buf, int size);
// 產(chǎn)生選擇家族的 data
void NPC_SELECT_gendata(int meindex, int talkerindex, int page, char *buf, int size);
// 產(chǎn)生排程詳細(xì)的 data
void NPC_DETAIL_gendata(int meindex, char *buf, int size, int dueltime);
BOOL NPC_SchedulemanInit( int meindex )
{
char argstr[NPC_UTIL_GETARGSTR_BUFSIZE];
int meid;
int interval;
CHAR_setInt( meindex, CHAR_WHICHTYPE, CHAR_TYPEFMSCHEDULEMAN );
CHAR_setWorkInt ( meindex, NPC_WORK_PREVIOUSCHECKTIME, -1);
// 參數(shù)
NPC_Util_GetArgStr(meindex, argstr, sizeof(argstr));
meid = NPC_Util_GetNumFromStrWithDelim(argstr, "id" );
if ((meid<0) || (meid>=MAX_SCHEDULEMAN)) {
print("SCHEDULEMAN init error: invalid ID(%d)\n",meid);
meid=0;
}
CHAR_setWorkInt(meindex, NPC_WORK_ID, meid);
interval = NPC_Util_GetNumFromStrWithDelim(argstr, "loopinterval" );
if ((interval<100) || (interval>10000)) interval=1000;
CHAR_setInt(meindex, CHAR_LOOPINTERVAL, interval);
interval = NPC_Util_GetNumFromStrWithDelim(argstr, "challengetimeout");
if ((interval<60) || (interval>60*60)) interval=20*60;
CHAR_setWorkInt(meindex, NPC_WORK_CHALLENGETIMEOUT, interval);
interval = NPC_Util_GetNumFromStrWithDelim(argstr, "settingtimeout");
if ((interval<10) || (interval>60*60)) interval=60;
CHAR_setWorkInt(meindex, NPC_WORK_SETTINGTIMEOUT, interval);
interval = NPC_Util_GetNumFromStrWithDelim(argstr, "fightinterval");
if ((interval<5) || (interval>60)) interval = 50;
CHAR_setWorkInt(meindex, NPC_WORK_FIGHTINTERVAL, interval);
NPC_LoadPKSchedule(meindex);
return TRUE;
}
void NPC_SchedulemanTalked(int meindex, int talkerindex, char *msg, int color)
{
char buf[4096];
int fd;
if (NPC_Util_CharDistance(meindex, talkerindex) > 2) return;
if (!NPC_Util_isFaceToFace(meindex, talkerindex, 2)) return;
fd = getfdFromCharaIndex(talkerindex);
if (fd == -1) return;
CHAR_setWorkInt(talkerindex, CHAR_WORK_PAGE, 0);
NPC_LIST_gendata(meindex, talkerindex, 0, buf, sizeof(buf));
lssproto_WN_send(fd, WINDOW_MESSAGETYPE_PKSCHEDULELIST,
WINDOW_BUTTONTYPE_NEXT | WINDOW_BUTTONTYPE_CANCEL,
CHAR_WINDOWTYPE_SCHEDULEMAN_START,
CHAR_getWorkInt(meindex, CHAR_WORKOBJINDEX),
buf);
}
void NPC_SchedulemanWindowTalked(int meindex, int talkerindex,
int seqno, int select, char *data)
{
int page;
int buttontype;
char buf[4096],token[256];
int fd,i,dt,a;
int fmpks_pos;
if (NPC_Util_CharDistance(meindex,talkerindex) > 2) return;
if (!NPC_Util_isFaceToFace(meindex, talkerindex, 2)) return;
fd = getfdFromCharaIndex(talkerindex);
if (fd == -1) return;
fmpks_pos = CHAR_getWorkInt(meindex, NPC_WORK_ID)*MAX_SCHEDULE;
// print("seqno=%d select=%d data=%s\n", seqno,select,data);
switch (seqno) {
case CHAR_WINDOWTYPE_SCHEDULEMAN_START:
switch (select) {
case WINDOW_BUTTONTYPE_NEXT:
case WINDOW_BUTTONTYPE_PREV:
page=CHAR_getWorkInt(talkerindex, CHAR_WORK_PAGE)
+ MAXSCHEDULEINONEWINDOW
* (( select == WINDOW_BUTTONTYPE_NEXT) ? 1 : -1);
buttontype=WINDOW_BUTTONTYPE_NEXT | WINDOW_BUTTONTYPE_PREV | WINDOW_BUTTONTYPE_CANCEL;
if (page<0) {
page=0;
buttontype=WINDOW_BUTTONTYPE_NEXT | WINDOW_BUTTONTYPE_CANCEL;
}
if (page>MAX_SCHEDULE-MAXSCHEDULEINONEWINDOW) {
page=MAX_SCHEDULE-MAXSCHEDULEINONEWINDOW;
buttontype=WINDOW_BUTTONTYPE_PREV | WINDOW_BUTTONTYPE_CANCEL;
}
CHAR_setWorkInt(talkerindex, CHAR_WORK_PAGE, page);
// Send WN
NPC_LIST_gendata(meindex, talkerindex, page, buf, sizeof(buf));
lssproto_WN_send(fd, WINDOW_MESSAGETYPE_PKSCHEDULELIST,
buttontype,
CHAR_WINDOWTYPE_SCHEDULEMAN_START,
CHAR_getWorkInt(meindex, CHAR_WORKOBJINDEX),
buf);
break;
case WINDOW_BUTTONTYPE_OK:
#ifdef _DEATH_FAMILY_CANT_SCHEDULE // WON ADD 家族戰(zhàn)玩家不能自行約戰(zhàn)
CHAR_talkToCli(talkerindex, meindex, "此星球無法約戰(zhàn)", CHAR_COLORWHITE);
break;
#endif
#ifdef _FMVER21
if ((CHAR_getInt(talkerindex,CHAR_FMLEADERFLAG)==FMMEMBER_LEADER) &&
#else
if ((CHAR_getInt(talkerindex,CHAR_FMLEADERFLAG)==1) &&
#endif
(CHAR_getWorkInt(talkerindex, CHAR_WORKFMSETUPFLAG)==1)) {
// 只有已成立家族的族長可以使用進一步的功能 (設(shè)定、更改、同意)
// decide: send family list or detail or accept
dt=atoi(data);
for (i=0; i<MAX_SCHEDULE; i++) {
if (fmpks[fmpks_pos+i].dueltime==dt) {
if (i==0) {
CHAR_talkToCli(talkerindex, meindex,
"這個時間無法進行預(yù)約。", CHAR_COLORWHITE);
break;
}
switch (fmpks[fmpks_pos+i].flag) {
case FMPKS_FLAG_NONE:
if (NPC_AlreadyScheduled(meindex, talkerindex)) {
// 同一個家族只能有一次排程
CHAR_talkToCli(talkerindex, meindex,
"你已經(jīng)安排過戰(zhàn)斗,將機會留給其他家族吧。", CHAR_COLORWHITE);
} else {
fmpks[fmpks_pos+i].host_index=CHAR_getWorkInt(talkerindex, CHAR_WORKFMINDEXI);
strcpy(fmpks[fmpks_pos+i].host_name,makeStringFromEscaped(CHAR_getChar(talkerindex, CHAR_FMNAME)));
// print("CHAR_FMNAME: %s\n",fmpks[fmpks_pos+i].host_name);
fmpks[fmpks_pos+i].guest_index=-1;
strcpy(fmpks[fmpks_pos+i].guest_name,"");
fmpks[fmpks_pos+i].prepare_time=5; // default
fmpks[fmpks_pos+i].max_player=50; // default
fmpks[fmpks_pos+i].win=0; // default
fmpks[fmpks_pos+i].flag=FMPKS_FLAG_SETTING;
fmpks[fmpks_pos+i].setting_timeout=
CHAR_getWorkInt(meindex, NPC_WORK_SETTINGTIMEOUT);
// 送出選擇家族的列表
CHAR_setWorkInt(talkerindex, CHAR_WORK_PAGE, 1); // page 1
CHAR_setWorkInt(talkerindex, CHAR_WORK_DUELTIME, dt);
NPC_SELECT_gendata(meindex, talkerindex, 1, buf, sizeof(buf));
buttontype=0;
if (familyNumTotal>MAXFAMILYINONEWINDOW)
buttontype |= WINDOW_BUTTONTYPE_NEXT;
lssproto_WN_send(fd, WINDOW_MESSAGETYPE_PKSCHEDULESELECTFAMILY,
buttontype,
CHAR_WINDOWTYPE_SCHEDULEMAN_SELECT,
CHAR_getWorkInt(meindex, CHAR_WORKOBJINDEX),
buf);
}
break;
case FMPKS_FLAG_CHALLENGE:
{ // 主隊族長可以重設(shè)條件,客隊則是同意 pk,其他人滾蛋
int tkfmindex=CHAR_getWorkInt(talkerindex, CHAR_WORKFMINDEXI);
if (tkfmindex==fmpks[fmpks_pos+i].host_index) {
fmpks[fmpks_pos+i].flag=FMPKS_FLAG_SETTING;
fmpks[fmpks_pos+i].setting_timeout=
CHAR_getWorkInt(meindex, NPC_WORK_SETTINGTIMEOUT);
// 送出細(xì)部調(diào)整的列表
CHAR_setWorkInt(talkerindex, CHAR_WORK_DUELTIME, dt);
NPC_DETAIL_gendata(meindex, buf, sizeof(buf), dt);
lssproto_WN_send(fd, WINDOW_MESSAGETYPE_PKSCHEDULEDETAIL,
WINDOW_BUTTONTYPE_OK | WINDOW_BUTTONTYPE_CANCEL,
CHAR_WINDOWTYPE_SCHEDULEMAN_DETAIL,
CHAR_getWorkInt(meindex, CHAR_WORKOBJINDEX),
buf);
} else if (tkfmindex==fmpks[fmpks_pos+i].guest_index) {
fmpks[fmpks_pos+i].flag=FMPKS_FLAG_SCHEDULED;
page=CHAR_getWorkInt(talkerindex, CHAR_WORK_PAGE);
buttontype=WINDOW_BUTTONTYPE_NEXT | WINDOW_BUTTONTYPE_PREV | WINDOW_BUTTONTYPE_OK;
if (page<0) {
page=0;
buttontype=WINDOW_BUTTONTYPE_NEXT | WINDOW_BUTTONTYPE_OK;
}
if (page>MAX_SCHEDULE-MAXSCHEDULEINONEWINDOW) {
page=MAX_SCHEDULE-MAXSCHEDULEINONEWINDOW;
buttontype=WINDOW_BUTTONTYPE_PREV | WINDOW_BUTTONTYPE_OK;
}
CHAR_talkToCli(talkerindex, meindex,
"你的家族已經(jīng)接受挑戰(zhàn)。", CHAR_COLORWHITE);
// 重新送出 list
NPC_LIST_gendata(meindex, talkerindex, page, buf, sizeof(buf));
lssproto_WN_send(fd, WINDOW_MESSAGETYPE_PKSCHEDULELIST,
buttontype,
CHAR_WINDOWTYPE_SCHEDULEMAN_START,
CHAR_getWorkInt(meindex, CHAR_WORKOBJINDEX),
buf);
}
}
break;
case FMPKS_FLAG_SETTING:
{ // 主隊族長可以重設(shè)條件
int tkfmindex=CHAR_getWorkInt(talkerindex, CHAR_WORKFMINDEXI);
if (tkfmindex==fmpks[fmpks_pos+i].host_index) {
fmpks[fmpks_pos+i].flag=FMPKS_FLAG_SETTING;
fmpks[fmpks_pos+i].setting_timeout=
CHAR_getWorkInt(meindex, NPC_WORK_SETTINGTIMEOUT);
// 送出細(xì)部調(diào)整的列表
CHAR_setWorkInt(talkerindex, CHAR_WORK_DUELTIME, dt);
NPC_DETAIL_gendata(meindex, buf, sizeof(buf), dt);
lssproto_WN_send(fd, WINDOW_MESSAGETYPE_PKSCHEDULEDETAIL,
WINDOW_BUTTONTYPE_OK | WINDOW_BUTTONTYPE_CANCEL,
CHAR_WINDOWTYPE_SCHEDULEMAN_DETAIL,
CHAR_getWorkInt(meindex, CHAR_WORKOBJINDEX),
buf);
}
}
// WON ADD 修正家族pk場的約戰(zhàn)問題
break;
}
}
}
NPC_SavePKSchedule(meindex);
} else {
#ifdef _FMVER21
if (CHAR_getInt(talkerindex,CHAR_FMLEADERFLAG)!=FMMEMBER_LEADER) {
#else
if (CHAR_getInt(talkerindex,CHAR_FMLEADERFLAG)!=1) {
#endif
CHAR_talkToCli(talkerindex, meindex,
"只有族長才能預(yù)約家族PK喔。", CHAR_COLORWHITE);
}else if (CHAR_getWorkInt(talkerindex, CHAR_WORKFMSETUPFLAG)!=1) {
CHAR_talkToCli(talkerindex, meindex,
"你的家族還沒有正式成立喔。", CHAR_COLORWHITE);
}
}
break;
}
break;
case CHAR_WINDOWTYPE_SCHEDULEMAN_SELECT:
switch (select) {
case WINDOW_BUTTONTYPE_PREV:
case WINDOW_BUTTONTYPE_NEXT:
page=CHAR_getWorkInt(talkerindex, CHAR_WORK_PAGE)
+ MAXFAMILYINONEWINDOW
* (( select == WINDOW_BUTTONTYPE_NEXT) ? 1 : -1);
buttontype=WINDOW_BUTTONTYPE_NEXT | WINDOW_BUTTONTYPE_PREV;
if (page<1) {
page=1;
buttontype=WINDOW_BUTTONTYPE_NEXT;
}
if (page>familyNumTotal-MAXFAMILYINONEWINDOW+1) {
page=familyNumTotal-MAXFAMILYINONEWINDOW+1;
buttontype=WINDOW_BUTTONTYPE_PREV;
}
CHAR_setWorkInt(talkerindex, CHAR_WORK_PAGE, page);
// Send WN
NPC_SELECT_gendata(meindex, talkerindex, page, buf, sizeof(buf));
lssproto_WN_send(fd, WINDOW_MESSAGETYPE_PKSCHEDULESELECTFAMILY,
buttontype,
CHAR_WINDOWTYPE_SCHEDULEMAN_SELECT,
CHAR_getWorkInt(meindex, CHAR_WORKOBJINDEX),
buf);
break;
case WINDOW_BUTTONTYPE_OK:
#ifdef _FMVER21
if ((CHAR_getInt(talkerindex,CHAR_FMLEADERFLAG)==FMMEMBER_LEADER) &&
#else
if ((CHAR_getInt(talkerindex,CHAR_FMLEADERFLAG)==1) &&
#endif
(CHAR_getWorkInt(talkerindex, CHAR_WORKFMSETUPFLAG)==1)) {
dt=CHAR_getWorkInt(talkerindex, CHAR_WORK_DUELTIME);
for (i=0; i<MAX_SCHEDULE; i++) {
if (fmpks[fmpks_pos+i].dueltime==dt) {
print("host_index: %d %d\n",fmpks[fmpks_pos+i].host_index,CHAR_getWorkInt(talkerindex, CHAR_WORKFMINDEXI));
if (fmpks[fmpks_pos+i].host_index==CHAR_getWorkInt(talkerindex, CHAR_WORKFMINDEXI)) {
print("data:%s\n",data);
if (getStringFromIndexWithDelim(data,"|",1,token,sizeof(token))) {
a=atoi(token);
if (a!=fmpks[fmpks_pos+i].host_index) {
fmpks[fmpks_pos+i].guest_index=a;
// 必須要再檢查是否有這個客隊家族 /**/
if (getStringFromIndexWithDelim(data,"|",2,token,sizeof(token))) {
strcpy(fmpks[fmpks_pos+i].guest_name, makeStringFromEscaped(token));
// 送出 detail 編輯窗
NPC_DETAIL_gendata(meindex, buf, sizeof(buf), dt);
lssproto_WN_send(fd, WINDOW_MESSAGETYPE_PKSCHEDULEDETAIL,
WINDOW_BUTTONTYPE_OK | WINDOW_BUTTONTYPE_CANCEL,
CHAR_WINDOWTYPE_SCHEDULEMAN_DETAIL,
CHAR_getWorkInt(meindex, CHAR_WORKOBJINDEX),
buf);
} else fmpks[fmpks_pos+i].flag=FMPKS_FLAG_NONE;
} else fmpks[fmpks_pos+i].flag=FMPKS_FLAG_NONE;
} else fmpks[fmpks_pos+i].flag=FMPKS_FLAG_NONE;
}
}
}
}
break;
}
break;
case CHAR_WINDOWTYPE_SCHEDULEMAN_DETAIL:
#ifdef _FMVER21
if ((CHAR_getInt(talkerindex,CHAR_FMLEADERFLAG)==FMMEMBER_LEADER) &&
#else
if ((CHAR_getInt(talkerindex,CHAR_FMLEADERFLAG)==1) &&
#endif
(CHAR_getWorkInt(talkerindex, CHAR_WORKFMSETUPFLAG)==1)) {
dt=CHAR_getWorkInt(talkerindex, CHAR_WORK_DUELTIME);
for (i=0; i<MAX_SCHEDULE; i++) {
if (fmpks[fmpks_pos+i].dueltime==dt) {
if (fmpks[fmpks_pos+i].host_index==CHAR_getWorkInt(talkerindex, CHAR_WORKFMINDEXI)) {
switch (select) {
case WINDOW_BUTTONTYPE_OK:
{
// 準(zhǔn)備時間
if (getStringFromIndexWithDelim(data,"|",4,token,sizeof(token))) {
a=atoi(token);
if ((a>0) && (a<=40)) fmpks[fmpks_pos+i].prepare_time=a;
}
// 最大人數(shù)
if (getStringFromIndexWithDelim(data,"|",5,token,sizeof(token))) {
a=atoi(token);
if ((a>0) && (a<=50)) fmpks[fmpks_pos+i].max_player=a;
}
// 勝利條件
if (getStringFromIndexWithDelim(data,"|",6,token,sizeof(token))) {
a=atoi(token);
if ((a>=0) && (a<=1)) fmpks[fmpks_pos+i].win = a;
}
fmpks[fmpks_pos+i].flag=FMPKS_FLAG_CHALLENGE;
fmpks[fmpks_pos+i].challenge_timeout=
CHAR_getWorkInt(meindex, NPC_WORK_CHALLENGETIMEOUT);
CHAR_talkToCli(talkerindex, meindex,
"家族挑戰(zhàn)設(shè)定完成。", CHAR_COLORWHITE);
}
break;
case WINDOW_BUTTONTYPE_CANCEL:
fmpks[fmpks_pos+i].flag=FMPKS_FLAG_NONE;
fmpks[fmpks_pos+i].host_index=-1;
strcpy(fmpks[fmpks_pos+i].host_name,"");
fmpks[fmpks_pos+i].guest_index=-1;
strcpy(fmpks[fmpks_pos+i].guest_name,"");
CHAR_talkToCli(talkerindex, meindex,
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -