mud_sanc 板


LINE

为了避免自己再忘记後不晓得怎麽使用,所以写这个手册。 /std/new_ob/instance_room.c 副本区域房间样本档 /std/new_ob/instance/ 主目录 /std/new_ob/instance/satin.c 单纯的 npc,里面备注了日後的星际传送门 npc /open/cmds/cmd_instance.o 指令 instance 的储存档 /std/new_ob/instance/laechan/ 我所写的所有副本(包含一些范例) // instance_ob.c // 副本物件继承用样本档 // instance.c // 副本区域房间样本档 // instance_rooms.c // 副本房间暂存处,本物件不 update 上面三个都不用看,因为 simul_efun questing("instance" 已写好 // _instance.c // 副本管理指令 只需要看这个指令,以及 laechan/ 目录下的 005.c 副本范例。 /open/cmds/cmd_instance.o 资料结构 "副本所在房间" : ([ "归类/副本" : ({ ({"开放的难度":0=单/1=多人,}), ({"开放的难度":0=单/1=多人,}), ... }), . . ]), instance(副本管理指令)说明: ============================================================ instance -list 列出副本管理员所在地的副本情报 instance -enter [副本编号] 进入所选择的副本 也就是说在 instance 指令内就包含了如何从副本 A 跳去副本 B 的程式码。 1.部分副本进入前设有等级种族职业等限制。 2.部分副本进入前须通过防机测试。 这些都可以在跳过去之前写在 questing 之外。 管理者指令区 instance -export 汇出目前设定总表 instance -export here/房间完整路径档名 汇出指定资料设定 instance -add 房间完整路径档名 = 副本识别id 难度 单人/多人 instance -del 房间完整路径档名 = 副本识别id 难度 单人/多人 范例 instance -add /d/wiz/room/disc = laechan/001 normal single instance -del /d/wiz/room/disc = laechan/001 normal single instance -add /d/wiz/room/disc = justinj/002 hard1 multi ============================================================ > instance -export 副本设定总表: 副本所在房间 归类 副本名 难度 单/多人 instance -add /d/ppl/map/n6e4 = ppl_area/ina_tiger hard1 single instance -add /d/ppl/map/n6e4 = ppl_area/ina_tiger hard1 multi instance -add /d/ppl/map/n6e4 = ppl_area/ina_tiger normal single . . 指令内容,enter 的部份: 单人副本 questing("instance","create",tmps[n3*2-2],({files,({me}), tmps[n3*2-1][0],tmps[n3*2-1][1]})); 多人副本 questing("instance","create",tmps[n3*2-2],({files, tmps2, tmps[n3*2-1][0],tmps[n3*2-1][1]})); 亦即进入副本只需呼叫 questing("instance","create", tmps 资料结构即 ({"难度",0/1,"难度",0/1,...}) 所以玩家假设选第一个,tmps[n3*2-2] = tmps[1*2-2] = tmps[0] = "归类/副本" tmps[n3*2-1] = tmps[1*2-1] = tmps[1] = ({"难度",0/1}) files = 副本所在房间,即主 key 也就是说,如果要从我的工作室直接进入副本: > l [/u/l/laechan/workroom ] = 天上界 = 明显出口有: 无 Lv255.副本管理员─绫儿(Instance manager, Satin) > instance -list 绫儿: 这里可 enter 的副本如下: ========================================== 1.白瓦镇黑熊讨伐任务副本(普通单人模式) 2.测试串接副本(普通单人模式) 3.测试串接副本(普通多人模式) ========================================== > instance -export 副本设定总表: instance -add /u/l/laechan/workroom = laechan/001 normal single instance -add /u/l/laechan/workroom = laechan/006 normal single instance -add /u/l/laechan/workroom = laechan/006 normal multi 则 running code 可以这样写 questing("instance", // 呼叫副本处理 "create", // 呼叫创建(进入)副本 "laechan/001", // 副本名称 ({ "/u/l/laechan/workroom", // 副本所在房间 ({me}), // 传自己进去 "normal", // 难度 0, // 单人 })); me->force_me("look"); ========== 程式执行区 ========== 副本载入中......ok! [/std/new_ob/instance_room#652352 ] [副本]山林小径 你拨开草丛, 隐约地可以看见埋在杂草堆里面的道路, 由此可以 想见这条小径平时应该没有什麽人在走动. 据说小径可以通往这 座山的深处, 可是蛮危险的. 明显出口有: north. ========== 程式执行区 ========== 这样就可以实现从副本 A 跳到副本 B 的设计,不过这是以後的 事,重点是接了某任务,在解任务过程中需要把玩家传进副本, 这时候 files 的部份就很微妙,关键在於有些副本是不允许玩 家任意进入,只有在解任务解到某一步骤时才能进去。 == 分隔线 == 再来需要副本的房间循环判断部份 :::::::::::::: /std/new_ob/instance/laechan/005.c :::::::::::::: // 005.c // Laechan@Sanc add in 2014/04/26 // 模拟幻想○域的地狱裂痕副本 instance_data=([ "002":(["instance_check":1, "cant_go":(["north":1]), ]), 即需要循环判断就增设 instance_data 并给 instance_check = 1 int instance_check(string files,object room) { int flags,t; object ob; flags=(int)room->query("instance_flags"); t=time(); 这个 flags 并不需要事前设定,最初值都是 0(即无) switch(files) { // 西尔克交待任务 case "002": switch(flags) { case 0: birth_npcs(room,INSTANCE_NPC,"sealker"); instance_set(room, ({ "instance_data/enter_msgs", ({HIW"西尔克:你就是...来帮助我的人吧!"NOR"\n", HIW"西尔克:请帮助我打倒矿坑内的魔物吧!"NOR"\n",}), "instance_next_times",12+t,"instance_flags",1, })); break; case 1: if(t>room->query("instance_next_times")) { instance_del(room,({"cant_go/north"})); instance_set(room,({"instance_flags",2,"already_ended",1})); } break; } break; // end of 002 采双层 switch 设计,针对不同的房间、不同的 flags 阶段, 来产生不同的结果。 刚进入房间时,它会产生 西尔克 这只 npc: instance_set(room, ({ "instance_data/enter_msgs", ({HIW"西尔克:你就是...来帮助我的人吧!"NOR"\n", HIW"西尔克:请帮助我打倒矿坑内的魔物吧!"NOR"\n",}), "instance_next_times",12+t,"instance_flags",1, })); 并跑出对话,同时设定触发下一 flags 阶段所需的时间 12 秒, 并把阶段参数 flags 改成 1。 则 12 秒过後 case 1: if(t>room->query("instance_next_times")) { instance_del(room,({"cant_go/north"})); instance_set(room,({"instance_flags",2,"already_ended",1})); } 移除不能往北走的设定,并把 flags 改成 2(实际上无 case 2), 并加上 already_ended 参数,则 times_check 看到该参数就不会 做动作。 嘛,这样就没问题。我刚在从头看了一次,重点在於 1.副本档要先写好 2.然後决定要把它设定在哪个房间 3.然後就能让玩家进去玩了 我最近若有空,会拿毒竹城区域(即影子传说区域)来测试,测试若 成功,毒城城会改为副本区域,好处是 1.这会是一个在其它 mud 没看过的新设计 2.它可以模拟任天堂的影子传说,设定难度关卡 3.如果这个能成功放出来,那吞食天地二也可以具现化 ==== 分隔线 ==== 副本档案的 instance_check 函数无作用,原因不明。 检查 /open/cmds/quest/quest_data/quest_data.c 690 行起 if(s>=4) ob->create_instance(vars[0],vars[1],vars[2],vars[3]); else if(s==3) ob->create_instance(vars[0],vars[1],vars[2]); else ob->create_instance(vars[0],vars[1]); 参数给足四个,因此会呼叫副本档案的 create_instance 函数 检查 /std/new_ob/instance/instance_ob.c 它会呼叫底下 // 最後再把房间资料设到 /std/new_ob/instance/instance_rooms.c ob->ppl_instance("set",ppl_name,setting_data); 检查 /std/new_ob/instance/instance_rooms.c 的 ppl_instance 函数 case "set": ppl_instance[ppl_name]=setting_data; tmps=keys(ppl_instance[ppl_name]); heart_beat_obs-=({0}); foreach(tmp in tmps) if(tmp[0..0]!="#" && ob=ppl_instance[ppl_name][tmp]) heart_beat_obs+=({ob}); break; 我刚检查的结果,副本房间都有被丢进 heart_beat_obs 里头 int heart_beat() { int i,j; object ob; j=sizeof(heart_beat_obs); for(i=0;i<j;i++) { if(!ob=heart_beat_obs[i]) continue; else if(!ob->query("already_init")) continue; else if(ob->query("already_ended")) { heart_beat_obs[i]=0; continue; } // 有 instance_check 才做 check_instance // if(ob->query("instance_check")) ob->check_instance(); } 所以我搞错了,必须要有 already_init 但是不能有 already_ended ,一但出现 already_ended,instance_rooms 就会将其移除。 这时一种可行的方法,就是只要重新把它加回去即可,即 // 确定 room 有 already_init INSTANCE_ROOMS->heart_beat_obs_func("add",room); 但基本上还是没用,因为不明原因 already_ended 都会被加上去, 以 grep 搜寻的结果,这东西出现在以下几个地方 /std/new_ob/instance_room.c int init() { if(!query("already_init")) { string instance_ob,msg; if(instance_ob=query("instance_ob")) { set("already_init",1); // laechan add in 2015/02/22 // 没有 instance_check 的情况直接加上 instance_ended if(undefinedp(query("instance_data")) || undefinedp(query("instance_data/instance_check"))) set("already_ended",1); if(msg=catch(call_other(instance_ob,"init_instance",this_object(),ppl))) write(msg+"\n"); } } 这意思是,虽然一开始全部房间都被加进 heart_beat_ob,但是 进入某房间後,如果该房间没有 instance_data 资料或是没有 instance_data/instance_check 资料,那就设定 instance_ended ,接着 heart_beat 发现它有 instance_ended 时就会将其移出 心跳判断。 对 instance_room.c 除错的结果: > instance -enter 2 副本载入中......ok! debug: already_init=0 already_ended=0 instance_data=UNDEFINED <= 这里是有问题的 ppl=玩家(laechan /std/user) 将 init 内 catch 的段落挪到前面: debug: already_init=1 already_ended=0 instance_data=([ "instance_check" : 1 ]) ppl=玩家(laechan /std/user) 已可正常识别出资料,bug fixed。 Laechan --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 59.126.145.135 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/mud_sanc/M.1665627510.A.BCE.html ※ 编辑: laechan (59.126.145.135 台湾), 10/13/2022 17:31:05







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:iOS站内搜寻

TOP