【求救】请教present用法及room地址的赋值问题
mud吧
全部回复
仅看楼主
level 8
xiuliinlove 楼主
dtsl的mudlib终于快要修补完毕了,目前差的最大一个模块就是公共武功的quest解密测试及修复。但第一个公共武功云帅轻功解密那里就卡壳了,原版dtsl代码有问题导致不能正常解密。我想出了方案但代码写不明白了,需要涉及到present和对非当前room的判断,排列组合折腾了好久写出的代码都编译出错[心碎]
请教问题:
1、present能否查询非当前房间的物件?
2、如果能查询,代码应该怎么写?
问题详述:
当前房间:/d/job/cisha/chunzailou里有个npc xiang,然后通过询问xiang触发对房间
/d/quest/yunshuai-dodge/migong8的查询,判断/d/quest/yunshuai-dodge/migong8里是否已经存在lian rou(档案名lianrou.c)和ren fanzi(档案名killer.c)的id,代码应该怎么写?
我已经试过的有:
(1)present("lian rou",/d/quest/yunshuai-dodge/migong8)、present("lian rou","/d/quest/yunshuai-dodge/migong8"),编译均出错。
(2)前面没通过,猜想可能需要赋值,于是随便写了个变量名place,语句换成了present("lian rou",place).但无论是object place 还是string place,搭配写法place=/d/quest/yunshuai-dodge/migong8或者place="/d/quest/yunshuai-dodge/migong8"均报错,不知道这种room地点怎么赋值[不高兴]
没辙了,求代码正确写法或者能达成我目的的方法。
2014年09月24日 06点09分 1
level 8
xiuliinlove 楼主
附上相关代码及背景详述:
npc xiang的部分先关代码:
void create()
{
set_name("香玉山",({ "xiang yushan","xiang","yushan" }) );
//省略
set("inquiry",([
"贩卖人口":(:give_job:),
"放弃":(:cancel_job:),
"救人":(:do_action1:),
]));
set("target_id","####");//防止别人用 ansha 等命令杀他。
setup();
carry_object(__DIR__"chouyi")->wear();
}
……
//中间无关代码省略
……
int accept_object(object ob,object obj)
{
object target,killer;
if(obj->query("daughter")!="lianrou")
return 0;
if(ob->query("dtsl_quest_ysdodge_help_ok"))
return 0;
command("grin");
command("say 你可真行啊,找来这么漂亮的女人!\n");
message_vision("$N一挥手,出来一个手下,把莲柔带走了!\n",this_object());
target=new("/d/quest/yunshuai-dodge/lianrou");
killer=new(__DIR__"killer");
copy_object(target,obj);
target->move("/d/quest/yunshuai-dodge/migong8");
killer->set_status(ob);//[灯泡]这里有问题[灯泡]
killer->move("/d/quest/yunshuai-dodge/migong8");
ob->set("dtsl_quest_ysdodge_help_ok",1);
return 1;
}
int do_action1()
{
object ob;
ob=this_player();
if(ob->query_skill("jiuying-dodge",1)){
command("say 你甭想打这个歪主意了!\n");
return 1;
}
command("say 好,敢来我这里救人,有胆量,就怕你是有去无回!");
ob->move("/d/quest/yunshuai-dodge/migong1");
return 1;
}
背景详述:解密要求一个协助player把莲柔(lian rou)打昏交给香玉山,然后解密player去问香玉山“救人”触发解密流程。
但关键是killer->set_status(ob);这句代码存在问题:第一个问题是它复制的状态是协助player的,按道理应该复制解密player的状态才对;第二个问题是dt的系统有任务人物专属设定,复制了协助player的状态后这个killer就只有协助player能kill了,其他人kill会返回“xxx根本不理会你的战斗请求”。完全背离了谜题设计初衷。
于是我就想把killer的出现和复制代码转到ask 救人那里(do_action1部分),这样就解决了上述的问题。但是带来了新问题:每有player ask 一下就会产生一个killer,所以需要对migong8的room来检查判断,如果里面没有莲柔或者已经有killer了就不再产生killer。
但是判断代码没搞定啊……
2014年09月24日 06点09分 2
level 5
亲,不要修改代码。把原代码放回去,把原代码和报的错误贴出来,然后发个贴,然后你的问题就搞定了。至于复制错误只是你传参的错误。
2014年09月24日 12点09分 3
额……问题是不改代码的话是不报错的……但是会导致我2楼说的解密id无法叫杀解密npc的问题……至于我后来改的代码,编译报错倒是大概是present参数错误的意思。所以我才想知道那个room参数应该怎么写……sign
2014年09月24日 13点09分
琢磨了半天又想到一条路,先move过去判断然后再move回来不知道能不能行得通……先去折腾代码了……
2014年09月24日 14点09分
回复 xiuliinlove :经测试,move过去判断貌似行得通。但是不足的是会有场景穿越,没找到屏蔽场景信息的办法(从sleep指令里找到个block_msg/all,但貌似无法屏蔽场景描述信息)。
2014年09月24日 15点09分
回复 xiuliinlove :既然是这个问题不是更好解决?传参错误,你只需要把你要复制的物件传给set_status()就OK了。而原参数ob是由 accept_object(object ob,object obj)调用进来来,呼叫这个函数的时候传给它accept_object(解密player,lianrou);
2014年09月25日 14点09分
level 15
一,present可以判断任何物件内是否存在指定物件(或指定id的物件),首先你要理解这个efun的用法。如果present没有经过simul_efun中重载的话,那么present这个efun是这样定义的:
object present( mixed str, object ob )
这个efun会判断在ob的inventory内是否有str这个物件,这里有两种情况:
1,str是一个物件,则直接看ob的inventory内是否有这个物件,如果有,直接返回该物件。
2,str是一个string,也就是一个物件的id,那么会看ob的inventory内是否有id为str的物件,如果有,直接返回该物件。
如果没有给定ob,则将搜索调用该efun的当前物件的inventory和当前该物件environment物件的inventory。
ps.某物件的inventory可以理解为某物件内(比如房间物件内的物品人物或人物物件内的携带物),某物件的environment就是指该物件的所在环境物件。
所以说,对于你的问题1,答案是肯定的,可以。
你的错误在于,place的赋值方式有误,下面例子中会告诉你如何
正确的
做。
至于问题2,该怎么写,我给你一个简单地写法作参考:
object qstroom;
if ( !( qstroom = find_object("d/quest/yunshuai-dodge/migong8") ) )
qstroom = load_object("d/quest/yunshuai-dodge/migong8");
// 上面这种写法十分常见
if( objectp( present( "lian rou", qstroom ) && objectp( present( "ren fanzi", qstroom ) )
{
ooxx.....//如果在的话,你要做什么。。。放在这里
}
二、你所说的set_status()函数存在问题,这个函数不是efun,至于他为什么会出问题,出了什么问题,如何修正,那要看代码才知道了。
2014年09月25日 02点09分 4
非常感谢!那个set函数本身是没问题的不需要修改也不好改。我所说的问题是它复制的对象有问题导致解密ID无法叫杀,属于逻辑问题。room赋值问题终于有方向了。之前我无奈下move ob到目标房间判断present("lian rou",envirenment(ob))
2014年09月25日 07点09分
回复 xiuliinlove : (之前没加环境函数直接ob功能不通过)之前没辙时我才用move ob到目标房间判断present("lian rou",environment(ob))(直接ob不加环境函数貌似无效)判断完再move回来也基本实现了功能(场景穿越没法避免--)
2014年09月25日 07点09分
回复 xiuliinlove :想再请教的是我move方法的判断代码是否有错误或隐患?还有就是if objectp(present(xxx)) 前面的objectp是否可以省略?
2014年09月25日 07点09分
level 15
1,仔细看下我说的present的定义,你会发现直接present("lian rou", ob) 其实是判断ob的inventory中是否有lianrou,肯定是不行的。同样的,objectp不可省略,这是判断你是否找到了目标物件。
2,我提供的方式是可用的,可以不必move过去。。。- -!
3,你的这个move方法么。。。怎么说呢。。。场景穿越之类的都以避免,比如直接用efun:move_object(),或者修改move()函数的定义增加个flag,判断下什么时候不执行look。不过这种方式真是很不正常,倒不是绝对不行,但基本没人会这样弄。。。相当于是绕了一个不靠谱的大弯。。。- -!是否有错误和隐患的话,思路应该是没太大问题,但是具体还要看你的代码实现。我个人感觉,完全没必要去纠结这种没意义不靠谱的方式。。。- -!
2014年09月25日 09点09分 5
非常感谢,测试通过了。之前少了半个),折腾了半天才找出来问题。经常改着改着一不注意就缺个)或者}神马的……
2014年09月25日 15点09分
level 3
前面的大神太高深,我给个更简单的建议。如果你每次判断的另一个地点固定,直接给那个地点加一个函数,进行本地判断后返回一个int。任务中直接调用那个房间的那个函数即可。注意要先判定那个房间存在。
2014年09月25日 15点09分 6
谢谢。不过你这个对我来说也很高深……代码小白伤不起啊- -
2014年09月25日 15点09分
回复 xiuliinlove :这个很简单的
2014年09月25日 15点09分
level 3
我就分享一段我自己写的代码吧。我做了一个解谜任务,玩家拿着名为“聚风幡”的法宝,对着二郎神摇动,成功则会把二郎神连同自己抓到一个独立空间去谋害他。在摇旗的时候先要做个判定,就是那个空间内是否有人。我在独立空间里做了个函数:
int is_clear() {
object *inv=all_inventory();
for (int i=0;i<sizeof(inv);i++)
if (userp(inv[i])) return 0;
return 1;
}
聚风幡这个item有个函数是对应摇旗动作的,里面定义了一条:
object fan_room=find_object("/d/public/leibu/inside_fan");
当摇旗的时候,swing flag,会调用一个判断:
if(fan_room && fan_room->is_clear()==0)
return notify_fail("你催动"+me->name()+",却没有反应,好像有其他人刚刚用过。\n");
也就是如果这个房间是存在的,且其中有人在,就不能使用了。
对照你的情况,你只要在前面的is_clear()函数中,把我写的判定物品改成present("xxx xxx",this_object())即可
是不是很简单
2014年09月25日 15点09分 7
嗯,有点理解了,不过我认为对于我这样的菜鸟来说,zero9k的方法更适合一些,他那个方法只用写一个文件的代码,你这个我没理解错的话还需要去修改目标房间的代码(确切地说是需要在目标房间添加函数代码)。在我看来添加函数的难度要比直接写if 判断语句大。
2014年09月25日 15点09分
回复 xiuliinlove :其实再回头看一下你的方法和zero9k的也差不多。我原来主要是卡在不知道用find_object()来给room赋值这里……
2014年09月25日 15点09分
回复 xiuliinlove :嗯,殊途同归
2014年09月25日 16点09分
level 5
但关键是killer->set_status(ob);这句代码存在问题:第一个问题是它复制的状态是协助player的,按道理应该复制解密player的状态才对;第二个问题是dt的系统有任务人物专属设定,复制了协助player的状态后这个killer就只有协助player能kill了,其他人kill会返回“xxx根本不理会你的战斗请求”。完全背离了谜题设计初衷。
按你意思这是两个玩家合作完成的任务?如果是这样,那么协助player和解密player必定在某个地方有关联,比如说协助player身上标记着协助对象的物件,那么在它身上找到这个物件传给killer->set_status();(比如ob2=ob->query("assit_ob"),killer->set_status(ob2));如果你找不到关联,你必须自己标记一个关联,让程序知道你这个是在协助谁(比如在开始任务的时候:协助player->set("assit_ob",解密player))
关于第二个问题,你可以找到killer的文件,里面应该有个函数void intit(){add_action("do_kill","kill");修改do_kill函数可以让你想怎么杀它就怎么杀它。
第三个问题:函数的参数数据类型不对,不报错才怪!present函数:object present( mixed str, object ob );你把,/d/quest/yunshuai-dodge/migong8(未定义的标识)和“,/d/quest/yunshuai-dodge/migong8“(字符窜)当成ojbect传给present,能不出错吗?把一个object 传到第二个参数,present才能检查那个object里面是否有叫作str的这个物件。
第四个问题:还是数据类型与函数的问题:/d/quest/yunshuai-dodge/migong8这一串字符是什么?它跟a,b,c或hello,kill,have,place,....是一样的,是一个未定义类型的数据!
2014年09月25日 16点09分 8
1、协助问题。这点只能说dtsl的lib比较另类,它的协助是没有标记的,另外因为player的不确定问题,在代码中添加关联标记我感觉不太现实。这个lib里有状态标记,但player to player属于双动态,所以没考虑过补加标记的方式。
2014年09月25日 16点09分
回复 xiuliinlove :2、killer文件。这个应该说也是“特色”,它的里面没定义kill,是通过killer文件里的set_status()语句来控制:
2014年09月25日 16点09分
回复 xiuliinlove : 代码楼中楼发不出来- -,请见楼下。
2014年09月25日 16点09分
回复 xiuliinlove :3、赋值。这个是问题症结所在,之前我就是不了解怎么把room赋值所以才没办法处理。通过zero9k的解答,已经了解了room的复制方法。之前也看过lpc的教程,也知道有find_object这个东西,但是我看的那个教程里没有像zero9k那样列举具体room赋值的例子……
2014年09月25日 16点09分
level 8
xiuliinlove 楼主
killer部分代码
int set_status(object ob)
{
object guard;
guard=this_object();
guard->set("last",time());
guard->set("target_id",ob->query("id"));//这个控制
//后面省略
}
2014年09月25日 16点09分 9
guard->set("target_id",ob->query("id"));这句控制可以叫杀killer的ob,后面省略的部分是复制ob状态语句。
2014年09月25日 16点09分
level 15
@hcc01 说的是都是正确的,特别是关于第三个问题一阵见血,我上面没有如此明确的指出你代码发生错无的原因。其实是这样,对于无论efun,simul_efun,lfun来说,都需要弄明白这些函数的用法,输入变量,处理过程,返回值或变量的类型,意义等等。
另外就是对于一些任务、想法等等一切要用代码实现的东东来说,可以说能找到n中实现的方式,无论@一叶之林 还是@hcc01 所说的方式或者我说的方式都是可以的。只不过有些方式方法经过多年的编码已经成了一种约定俗成的习惯,当然也未必都是最佳方式,但只要多读代码,多写东西,逐渐就会融会贯通了,到时候会发现(注意:我的经典语录再次出现了!!哈哈哈哈):技术编码永远不是瓶颈,难的是游戏世界的整体规划和平衡设定。[吐舌]
2014年09月25日 23点09分 10
level 5
回复 xiuliinlove :你知道set("target_id")是干什么用的吗?它只是在KILLER上增加了一个数据,要让这人数据有意义,就得在某地方使用它,这个数据要在哪里使用?没有加kill的action的话,kill里面一般会有一个accept_kill()的判断。自己去找。还有,没什么特色不特色,整个游戏都是基于前人改的,根本就不会有特色!!你对函数和变量太不理解了。告诉你怎么做:在每个使用变量的地方,你都要找出这个变量在哪里定义,用来干什么;在每个调用函数的地方,也都要找出这个函数在哪里定义,怎么定义;在每个赋值的地方,你要懂得赋这个值的作用!函数或变量除了EFUN只能是本物件中定义过(找不到就去找inherit),而->这个符号可以让你调用别的物件中的函数。记住:函数名只是让你容易了解这个函数的作用,而不是你说英语计算机就听懂,所有的函数都是人工设定的用来执行一些动作的。PS:你知道set()在哪里定义了吗?你知道set()的数据是怎么保存的吗?
2014年09月26日 01点09分 11
set函数包括其他一些比较常用的lib函数我在feature/dabase.c里看到过,只能理解个大概。至于函数具体执行和保存方式虽然很重要,但对我这样对代码不精通的人来说能够略过过程直接明白结果就已经很不容易了……
2014年09月26日 02点09分
level 8
xiuliinlove 楼主
if(stringp(obj->query("target_id"))&&obj->query("target_id")!=me->query("id"))
return notify_fail(obj->name()+"根本不理会你的战斗请求。\n");
if(arrayp(obj->query("target_id"))&&
member_array(me->query("id"),obj->query("target_id"))==-1)
return notify_fail(obj->name()+"根本不理会你的战斗请求。\n");
这个是kill里相关控制的代码。
能够找到这段代码的确更容易理解。但因为我对代码结构不熟,很多时候找不到源头,但结合函数名字和自己测试对一些函数功能还是能猜个大概的,之前我就是从killer->set_status(ob);和实际测试不让叫杀猜到set_status(ob);里的ob决定set的状态和能叫杀的id,这样我只要把ob弄正常了就好了。这样的确是不求甚解,但只要能达到目的就好了。对于代码盲来说纠结中间的问题过于高深。当然再解决了问题的基础上能再理解下原理也是非常不错的。其实对于我的问题,只要大家直接告诉我room赋值和判断是
object qstroom;
if ( !( qstroom = find_object("d/quest/yunshuai-dodge/migong8") ) )
qstroom = load_object("d/quest/yunshuai-dodge/migong8")
if( objectp( present( "lian rou", qstroom ) && objectp( present( "ren fanzi", qstroom ) )
这样写就可以了。其余的都算是各位超值附送的相关知识,非常感谢!
对待同一个问题,高手可能要弄明白原理,但菜鸟一般只要最后结果也就知足了。对待业余人士就不要从专业的角度提要求了,压力山大[汗]
2014年09月26日 03点09分 12
另外贴吧也是刚刚开始深入接触。之前不知道楼中楼发代码很难发出来。然后又为了能给人回复提示特意在楼中楼回复了下,现在才反应过来还可以直接帖子下面回复然后@呼人
2014年09月26日 03点09分
回复 xiuliinlove :不用压力大,都是这么过来的[吐舌]慢慢来,毕竟都是爱好驱动,加油!
2014年09月26日 04点09分
1