📄 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 场的赛程, 这个赛程由登记员 * 登记与设定,主要的设定事项在 FamilyPKSchedule * * 这个登记员同时会将这个 schedule 写入磁碟,如果 Game Server 重新 * 启动的话,会先读入这一份对战排程表,同时进行排程。 * 排程只排从现在开始的 24 小时之内的赛程 * 排程表档案的格式为: * * time|host_index|host_name|guest_index|guest_name|prepare_time|max_player|flag|win * * 档案的命名: 登记员楼层号码_登记员X座标_登记员Y座标 * */// 全部的家族 pk 赛程FamilyPKSchedule fmpks[MAX_SCHEDULE*MAX_SCHEDULEMAN];extern int familyNumTotal;enum { NPC_WORK_ID = CHAR_NPCWORKINT1, // 登记员 ID, 从 0 开始 NPC_WORK_CHALLENGETIMEOUT = CHAR_NPCWORKINT2, // 同意挑战的 timeout NPC_WORK_SETTINGTIMEOUT = CHAR_NPCWORKINT3, // 设定挑战的 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 diskvoid NPC_SavePKSchedule(int meindex); // save schedule to diskvoid NPC_RemoveExpiredBattle(int meindex); // 移除过期的战斗void NPC_ProcessTimeout(int meindex); // 处理 timeoutBOOL NPC_AlreadyScheduled(int meindex, int talkerindex); // 检查, 一个家族只能安排一场// 产生排程表的 datavoid NPC_LIST_gendata(int meindex, int talkerindex, int page, char *buf, int size);// 产生选择家族的 datavoid NPC_SELECT_gendata(int meindex, int talkerindex, int page, char *buf, int size);// 产生排程详细的 datavoid 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); // 参数 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 _FMVER21 if ((CHAR_getInt(talkerindex,CHAR_FMLEADERFLAG)==FMMEMBER_LEADER) &&#else if ((CHAR_getInt(talkerindex,CHAR_FMLEADERFLAG)==1) &&#endif (CHAR_getWorkInt(talkerindex, CHAR_WORKFMSETUPFLAG)==1)) { // 只有已成立家族的族长可以使用进一步的功能 (设定、更改、同意) // 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, "这个时间无法进行预约。", CHAR_COLORWHITE); break; } switch (fmpks[fmpks_pos+i].flag) { case FMPKS_FLAG_NONE: if (NPC_AlreadyScheduled(meindex, talkerindex)) { // 同一个家族只能有一次排程 CHAR_talkToCli(talkerindex, meindex, "你已经安排过战斗,将机会留给其他家族吧。", 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: { // 主队族长可以重设条件,客队则是同意 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); // 送出细部调整的列表 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, "你的家族已经接受挑战。", 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: { // 主队族长可以重设条件 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); // 送出细部调整的列表 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场的约战问题 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, "只有族长才能预约家族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: { // 准备时间 if (getStringFromIndexWithDelim(data,"|",4,token,sizeof(token))) { a=atoi(token); if ((a>0) && (a<=40)) fmpks[fmpks_pos+i].prepare_time=a; } // 最大人数 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, "家族挑战设定完成。", 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, "清除家族挑战。", CHAR_COLORWHITE); break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -