⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 npc_scheduleman.c

📁 石器时代8.0服务端完整源代码。可以直接编译
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 disk
void NPC_SavePKSchedule(int meindex);	// save schedule to disk
void NPC_RemoveExpiredBattle(int meindex);	// 移除过期的战斗
void NPC_ProcessTimeout(int meindex);	// 处理 timeout
BOOL NPC_AlreadyScheduled(int meindex, int talkerindex);	// 检查, 一个家族只能安排一场
// 产生排程表的 data
void NPC_LIST_gendata(int meindex, int talkerindex, int page, char *buf, int size);
// 产生选择家族的 data
void NPC_SELECT_gendata(int meindex, int talkerindex, int page, char *buf, int size);
// 产生排程详细的 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);

  // 参数
  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 家族战玩家不能自行约战
	  CHAR_talkToCli(talkerindex, meindex, "此星球无法约战", 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)) {
        // 只有已成立家族的族长可以使用进一步的功能 (设定、更改、同意)

        // 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,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -