回精華區
作者itoc.bbs@processor.tfcis.org (核心動力) 看板: plan
標題[功能] RPG 架構
時間動力核心 (2004/08/23 Mon 23:15:43) Updated: 2004/10/09
  新增此功能以後
  舊使用者要先 (A)pply RPG申請,才會有 RPG 帳號
  新使用者則是在註冊時就會順便填 RPG 帳號

: maple.p

+ /* rpg.c */
+ int rpg_load(RPG *rpg, char *userid);
+ void rpg_save(RPG *rpg, char *userid);
+ void rpg_apply(RPG *u, char *userid);
+ int r_info(void);
+ int r_query(void);
+ int r_apply(void);

: bbsd.c:u_exit()

  /* 寫回 .ACCT */

  if (!HAS_STATUS(STATUS_DATALOCK))
  {
    ...
    ...
      close(fd);
    }
+   rpg_save(&crpg, cuser.userid);
  }
}

: bbsd.c:acct_apply()

+ rpg_apply(&crpg, userid);

+ usr_fpath(buf, userid, FN_RPG);
+ fd = open(buf, O_WRONLY | O_CREAT, 0600);
+ write(fd, &crpg, sizeof(crpg));
+ close(fd);

  sprintf(buf, "%d", try);
  blog("APPLY", buf);

: bbsd.c:login_user()

+ rpg_load(&crpg, uid);

  return multi;
}

: menu.c:menu_rpg[] 新增在 menu_tool[] 上面

  /* --------------------------------------------------- */
  /* rpg menu                                            */
  /* --------------------------------------------------- */

static MENU menu_rpg[] =
{
  r_query, 0, M_QUERY,
  "Query    RPG查詢",

  r_info, PERM_BASIC, M_XMODE,
  "Info     RPG資訊",

  r_apply, PERM_BASIC, M_XMODE,
  "Apply    RPG申請",

  menu_tool, PERM_MENU + 'Q', M_XMENU,
  "冒險進取"
};

: menu.c:menu_tool[]

+ menu_rpg, 0, M_XMENU,
+ "RPG        【 遊戲人間 】",

  menu_tool, PERM_MENU + Ctrl('A'), M_XMENU,
  "其他功\能"

: bbs.h

#include "struct.h"             /* data structure */
+ #include "rpg.h"              /* rule play game */
#include "global.h"             /* global variable & definition */

: global.h

/* ----------------------------------------------------- */
/* 個人目錄檔名設定                                      */
/* ----------------------------------------------------- */

+ #define FN_RPG          ".RPG"          /* User rpg account */
#define FN_ACCT         ".ACCT"         /* User account */

  ...
  ...

/* ----------------------------------------------------- */
/* GLOBAL VARIABLE                                       */
/* ----------------------------------------------------- */

+ VAR RPG crpg;                       /* current user structure */
VAR int bbsmode;                /* bbs operating mode, see modes.h */

: src/maple/Makefile

SRC =   acct.c bbsd.c bmw.c board.c cache.c edit.c favor.c \
        gem.c mail.c menu.c more.c pal.c post.c talk.c visio.c \
-       window.c xover.c xpost.c
+       window.c xover.c xpost.c rpg.c

OBJ =   acct.o bbsd.o bmw.o board.o cache.o edit.o favor.o \
        gem.o mail.o menu.o more.o pal.o post.o talk.o visio.o \
-       window.o xover.o xpost.o
+       window.o xover.o xpost.o rpg.o


: ─────────────────────────────────────

: src/include/rpg.h 新增此程式
: 其中 struct RPG 只是個範例,可以隨自己的遊戲設定修改

/*-------------------------------------------------------*/
/* rpg.h     ( NTHU CS MapleBBS Ver 3.10 )               */
/*-------------------------------------------------------*/
/* target : rpg games                                    */
/* create : 00/03/16                                     */
/* update :   /  /                                       */
/* author : itoc.bbs@bbs.tnfsh.tn.edu.tw                 */
/*-------------------------------------------------------*/


#ifndef _RPG_H_
#define _RPG_H_


/*-------------------------------------------------------*/
/* 參考 struct.h                                         */
/* ----------------------------------------------------- */
/* 使用者遊戲記錄 .RPG struct : 512 bytes                */
/* ----------------------------------------------------- */


typedef struct
{
  char usertitle[12];       /* 頭銜 */
  char username[24];        /* 暱稱 */

  int level;                /* 等級(絕對值) (+)轉職後的等級 (-)轉職前的等級 */
  int alliance;             /* 陣營(絕對值) (+)善良 (-)邪惡 */
  int exp;                  /* 經驗值 */

                            /* 能量(用2char縮寫) */
  int hp;                   /* 體力 health point */
  int mp;                   /* 靈力 mana point   */
  int mv;                   /* 動力 moving point */
  int po;                   /* 內力 power point  */

                            /* 能量上限 */
  int maxhp;                /*  血  */
  int maxmp;                /* 靈力 */
  int maxmv;                /* 動力 */
  int maxpo;                /* 內力 */

                            /* 屬性(用3char縮寫) */
  int str;                  /* 力量 strength */
  int inl;                  /* 智力 intelligence */
  int wis;                  /* 智慧 wisdom */
  int dex;                  /* 敏捷 dexterity */
  int con;                  /* 體格 constitution */
  int luc;                  /* 運氣 luck */
  int cha;                  /* 魅力 charisma */

                            /* 隱藏特質(用4char縮寫) */
  int calm;                 /* 冷靜 calm */
  int cour;                 /* 勇氣 courage */
  int heal;                 /* 健康 health */
  int lern;                 /* 學習 learn */
  int mood;                 /* 心情 mood */

                            /* 五大資源(用單數) */
  int money;                /* 銀幣 */
  int gold;                 /* 黃金 */
  int gem;                  /* 寶石 */
  int wood;                 /* 木材 */
  int iron;                 /* 礦石 */

                            /* 十大裝備(用單數) */
  int weapon;               /* 武器 */
  int helm;                 /* 頭盔、帽、冠 */
  int amulet;               /* 護身符、項鍊 */
  int armor;                /* 盔甲 */
  int glove;                /* 手套 */
  int ring;                 /* 戒指 */
  int bracer;               /* 臂章 */
  int belt;                 /* 皮帶 */
  int pant;                 /* 褲子 */
  int shoe;                 /* 鞋子 */

}      RPG;
#endif          /* _RPG_H_ */


: ─────────────────────────────────────

: src/maple/rpg.c 新增此程式

/*-------------------------------------------------------*/
/* rpg.c        ( NTHU CS MapleBBS Ver 3.00 )            */
/*-------------------------------------------------------*/
/* target : rpg routines                                 */
/* create : 01/03/16                                     */
/* update :   /  /                                       */
/* author : itoc.bbs@bbs.tnfsh.tn.edu.tw                 */
/*-------------------------------------------------------*/


#include "bbs.h"


/* ----------------------------------------------------- */
/* (.RPG) 冒險者帳號 (account) I/O                       */
/* ----------------------------------------------------- */


int
rpg_load(rpg, userid)
  RPG *rpg;
  char *userid;
{
  int fd;

  usr_fpath((char *) rpg, userid, FN_RPG);
  fd = open((char *) rpg, O_RDONLY);
  if (fd >= 0)
  {
    /* Thor.990416: 特別注意, 有時 .RPG的長度會是0 */
    read(fd, rpg, sizeof(RPG));
    close(fd);
  }
  return fd;
}


void
rpg_save(rpg, userid)
  RPG *rpg;
  char *userid;
{
  int fd;
  char fpath[64];

  usr_fpath(fpath, userid, FN_RPG);
  fd = open(fpath, O_WRONLY | O_CREAT, 0600);
  if (fd >= 0)
  {
    write(fd, rpg, sizeof(RPG));
    close(fd);
  }
}


/* ----------------------------------------------------- */
/* (.RPG) 冒險者帳號 (account) subroutine                */
/* ----------------------------------------------------- */


void
rpg_apply(u, userid)
  RPG *u;
  char *userid;
{
  strcpy(u->usertitle, "新冒險者");
  strcpy(u->username, userid);

  u->level = -1;
  u->alliance = u->exp = 0;
  u->hp = u->mp = u->mv = u->po =
    u->maxhp = u->maxmp = u->maxmv = u->maxpo = 100;
  u->str = u->inl = u->wis = u->dex = u->con = u->luc = u->cha = 10;
  u->calm = u->cour = u->heal = u->lern = u->mood = 0;
  u->money = u->gold = u->gem = u->wood = u->iron = 0;
  u->weapon = u->helm = u->amulet = u->armor = u->glove = 0;
  u->ring = u->bracer = u->belt = u->pant = u->shoe = 0;
}


static int
rpg_get(msg, rpg, userid)
  char *msg;
  RPG *rpg;
  char *userid;
{
  outz("★ 輸入首字母後, 可以按空白鍵自動搜尋");

  /* --------------------------------------------------- */
  /* name complete for user ID                           */
  /* --------------------------------------------------- */
  /* return value :                                      */
  /*  0: 使用直接按 enter ==> cancel                     */
  /* -1: bad user id                                     */
  /*  1: current user id                                 */
  /* --------------------------------------------------- */

  if (!vget(1, 0, msg, userid, IDLEN + 1, GET_USER))
    return 0;

  if (rpg_load(rpg, userid) >= 0)
    return 1;

  vmsg(err_uid);
  return -1;
}


static void
rpg_show(u, adm)
  RPG *u;
  int adm;                      /* 0: user info/query  1: admin */
{
  int alli;
  char *camp;

  clrtobot();

  outs("\n        \033[30;41m┬┴┬┴┬┴\033[m  \033[45m╰╦╦╮╭╦═╮"
    "╔╦═╮╭╦═╮\033[m  \033[30;41m┬┴┬┴┬┴\033[m\n"
    "        \033[30;41m┴┬┴┬┴┬\033[m  \033[1;37;45m  ╠╣  ╠╣"
    "  ║╠╬╣  ╠╣  ║\033[m  \033[30;41m┴┬┴┬┴┬\033[m\n"
    "        \033[30;41m┬┴┬┴┬┴\033[m  \033[45m  ╠╣  ╠╣  ║"
    "╠╣╯  ╠╣  ║\033[m  \033[30;41m┬┴┬┴┬┴\033[m\n"
    "        \033[30;41m┴┬┴┬┴┬\033[m  \033[1;30;45m╰╩╩╮╚╝"
    "  ╰╚╝    ╰╩═╯\033[m  \033[30;41m┴┬┴┬┴┬\033[m\n");


  alli = u->alliance;
  if (alli > 100)
  {
    if (alli > 700)
      camp = "\033[41m大好人\033[m";
    else if (alli > 400)
      camp = "\033[1;31m好人\033[m";
    else
      camp = "\033[31m有一點點善良\033[m";
  }
  else if (alli < -100)
  {
    if (alli < -700)
      camp = "\033[45m你實在太壞了\033[m";
    else if (alli < -400)
      camp = "\033[1;35m蠻賤的\033[m";
    else
      camp = "\033[35m有一點點邪惡\033[m";
  }
  else
    camp = "中立無比";

  prints("\n能量:體力 %5d/%5d  靈力 %5d/%5d  動力 %5d/%5d  內力 %5d/%5d\n",
    u->hp, u->maxhp, u->mp, u->maxmp, u->mv, u->maxmv, u->po, u->maxpo);

  prints("\n\033[1;33m[%s] \033[36m%s\033[m",
    u->usertitle, u->username);

  prints("\n考核:等級 %5d  經驗 %5d  陣營 %s  %s轉職",
    abs(u->level), u->exp, camp, u->level > 0 ? "已" : "未");

  prints("\n屬性:力量 [%3d]  智力 [%3d]  智慧 [%3d]  敏捷 [%3d]",
    u->str, u->inl, u->wis, u->dex);

  prints("\n屬性:體格 [%3d]  運氣 [%3d]  魅力 [%3d]",
    u->con, u->luc, u->cha);

  prints("\n資源:銀幣 %5d  黃金 %5d", u->money, u->gold);

  prints("\n資源:寶石 %5d  木材 %5d  礦石 %5d", u->gem, u->wood, u->iron);

  if (adm)
  {
    prints("\n特質:冷靜 %5d  勇氣 %5d  健康 %5d  學習 %5d  心情 %5d",
      u->calm, u->cour, u->heal, u->lern, u->mood);

    prints("\n裝備:武器 %5d  頭盔 %5d  項鍊 %5d  盔甲 %5d  手套 %5d",
      u->weapon, u->helm, u->amulet, u->armor, u->glove);

    prints("\n裝備:戒指 %5d  臂章 %5d  皮帶 %5d  褲子 %5d  鞋子 %5d",
      u->ring, u->bracer, u->belt, u->pant, u->shoe);
  }

  outs("\n\n        \033[30;41m┴┬┴┬┴┬┴┬┴┬┴┬┴┬┴┬┴┬"
    "┴┬┴┬┴┬┴┬┴┬┴┬\033[m");
}


static void
rpg_setup(u, userid, adm)
  RPG *u;
  char *userid;
  int adm;
{
  RPG x;
  int i, num;
  char *str, buf[80];

  rpg_show(u, adm);
  memcpy(&x, u, sizeof(RPG));

  if (vans("設定 1)資料 Q)取消 [Q] ") != '1')
    return;

  move(i = 3, 0);
  clrtobot();

  str = x.usertitle;
  while (1)
  {
    if (vget(i, 0, "頭    銜:", str, sizeof(x.usertitle), GCARRY))
      break;
  }

  i++;
  str = x.username;
  while (1)
  {
    if (vget(i, 0, "暱    稱:", str, sizeof(x.username), GCARRY))
      break;
  }

  if (adm)
  {
    for (;;)
    {
      /* 還有改別的欄位的話,自己改寫程式 */
      adm = vans("1)等級 2)陣營 3)上限 [Q] ");

      if (adm == '1')
      {
        sprintf(buf, "%d", u->level);
        vget(i, 0, "等級:", buf, 6, GCARRY);
        x.level = atoi(buf);
      }
      else if (adm == '2')
      {
        sprintf(buf, "%d", u->alliance);
        vget(i, 0, "陣營:", buf, 6, GCARRY);
        x.alliance = atoi(buf);
      }
      else if (adm == '3')
      {
        for (;;)
        {
          num = vans("[上限] s)力量 i)智力 w)智慧 d)敏捷 "
            "c)體格 l)運氣 a)魅力 [Q] ");

          if (num == 's')
          {
            sprintf(buf, "%d", u->str);
            vget(i, 0, "力量:", buf, 6, GCARRY);
            if (num = atoi(buf) > 0)
              x.str = num;
          }
          else if (num == 'i')
          {
            sprintf(buf, "%d", u->inl);
            vget(i, 0, "智力:", buf, 6, GCARRY);
            if (num = atoi(buf) > 0)
              x.inl = num;
          }
          else if (num == 'w')
          {
            sprintf(buf, "%d", u->wis);
            vget(i, 0, "智慧:", buf, 6, GCARRY);
            if (num = atoi(buf) > 0)
              x.wis = num;
          }
          else if (num == 'd')
          {
            sprintf(buf, "%d", u->dex);
            vget(i, 0, "敏捷:", buf, 6, GCARRY);
            if (num = atoi(buf) > 0)
              x.dex = num;
          }
          else if (num == 'c')
          {
            sprintf(buf, "%d", u->con);
            vget(i, 0, "體格:", buf, 6, GCARRY);
            if (num = atoi(buf) > 0)
              x.con = num;
          }
          else if (num == 'l')
          {
            sprintf(buf, "%d", u->luc);
            vget(i, 0, "運氣:", buf, 6, GCARRY);
            if (num = atoi(buf) > 0)
              x.luc = num;
          }
          else if (num == 'a')
          {
            sprintf(buf, "%d", u->cha);
            vget(i, 0, "魅力:", buf, 6, GCARRY);
            if (num = atoi(buf) > 0)
              x.cha = num;
          }
          else
          {
            break;
          }
        }
      }
      else
      {
        break;
      }
    }
  }

  if (vans(msg_sure_ny) != 'y')
    return;

  memcpy(u, &x, sizeof(x));
  rpg_save(u, userid);
  utmp_admset(acct_userno(userid), STATUS_DATALOCK);
}


/* ----------------------------------------------------- */
/* 選單指令                                              */
/* ----------------------------------------------------- */


int
r_info()
{
  move(1, 0);
  rpg_setup(&crpg, cuser.userid, 0);
  return 0;
}


int
r_query()
{
  int ans;
  char userid[IDLEN + 1];
  RPG rpg;

  move(1, 0);
  clrtobot();

  if (HAS_PERM(PERM_ALLACCT))
  {
    while (ans = rpg_get(msg_uid, &rpg, userid))
    {
      if (ans > 0)
        rpg_setup(&rpg, userid, 1);
    }
  }
  else
  {
    while (ans = rpg_get(msg_uid, &rpg, userid))
    {
      if (ans > 0)
        rpg_show(&rpg, 0);
    }
  }

  return 0;
}


int
r_apply()               /* 自殺重來 */
{
  if (vans("您將重新開始一段新的旅途(Y/N)?[N] ") != 'y')
    return XEASY;

  rpg_apply(&crpg, cuser.userid);
  rpg_save(&crpg, cuser.userid);
  return 0;
}

: ─────────────────────────────────────

  這只是 RPG 的架構,細節並沒有寫
  遊戲的細部玩法則是要讓站長自行規劃,例如:

  一、發表文章,依字數加木材、依時間加礦石
    : post.c:do_post()
      mode = BMIN(wordsnum, spendtime) / 10;    /* 每十字/秒 一元 */
      prints("這是您的第 %d 篇文章,得 %d 銀。", ++cuser.numposts, mode);
      addmoney(mode);
    + crpg.wood += wordsnum;
    + crpg.iron += spendtime;

  二、發表文章,若字數超過時間,陣營變善良;反之變邪惡
    : post.c:do_post()
      mode = BMIN(wordsnum, spendtime) / 10;    /* 每十字/秒 一元 */
      prints("這是您的第 %d 篇文章,得 %d 銀。", ++cuser.numposts, mode);
      addmoney(mode);
    + crpg.alliance += wordsnum - spendtime;

  三、在水球列表丟水球,加力量
    : bmw.c:bmw_write()
      if (up = utmp_find(userno))
    + {
        do_write(up);
    +   crpg.str++;
    + }

  四、在使用者列表丟水球,加智力
    : ulist.c:ulist_write()
      if (up = ulist_pool[xo->pos])
    + {
        do_write(up);
    +   crpg.inl++;
    + }

  五、離站時,每一分鐘加經驗值 1 點,集滿 10000 分鐘升一級
    : bbsd.c:u_exit()
      diff = (time(&cuser.lastlogin) - ap_start) / 60;
    + crpg.exp += diff;
    + if (crpg.exp >= 10000)
    + {
    +   crpg.exp -= 10000;
    +   crpg.level++;
    + }

  反正都是 crpg.xxx 怎樣怎樣
  至於 xxx 是什麼,你只要看 rpg.h 就可以知道了

--
  Origin:  Maple-itoc˙動力核心  processor.tfcis.org 
  Author: itoc itoc.dorm11.nctu.edu.tw 發表
精華選讀←離開[主題上]主題下(k)上篇(j)下篇S/a搜尋 G串列 TAB精華 ↑↓捲 Pg/Space翻