《使用MUDCORE框架从零开发LPMUD游戏》系列内容,通过教程既能熟悉 MUDCORE 框架的使用,也能学习LPCMUD游戏的开发,版权所有 mud.ren。
游戏环境除了普通房间模式和上一节介绍的区域模式外,还有利用虚拟对象特性的自动环境模式和迷宫模式,适合打造荒野地型和地牢环境。
虚拟环境模式
虚拟环境模块和普通房间模式类似,只是使用坐标来处理不***间,world/start_room.c
已经做了演示,我们明明只有一个文件代码,却生成了无尽的环境地区。
目前项目中world/dq9
下面各编号的荒野地图也都是使用这种方式实现,代码示例:
#include <ansi.h>
inherit STD_WILD_9;
varargs void create(int x, int y, int z)
{
::create();
set("short", "贝伦海岸");
set("long", "这里是等待冒险者征服的地区,无数的魔物等待清理。");
set("exits", ([
"north" : __DIR__ "wild/" + x + "," + (y + 1) + "," + z,
"south" : __DIR__ "wild/" + x + "," + (y - 1) + "," + z,
"west" : __DIR__ "wild/" + (x - 1) + "," + y + "," + z,
"east" : __DIR__ "wild/" + (x + 1) + "," + y + "," + z,
]));
setArea(13, x, y, z);
setMob(random(3), random(4), random(7));
}
这里我们没有使用复杂的代码,但也实现了魔物的自动生成,我们进不同地区会发现有不同的魔物生成,关键代码为:
setMob(random(3), random(4), random(7));
具体功能在房间模块inherit/room.c
实现,主要是把部分设置简化:
// 设置环境区域怪物种类、每种数量上限、等级范围(0~7)
varargs void setMob(int mob, int max, int range)
{
set("mob", mob);
set("mob_max", max);
set("mob_range", range);
}
关键代码是在标准地牢对象STD_DUNGEON
所在文件std/room/dungeon.c
的init()
方法:
/*****************************************************************************
Copyright: 2019, Mud.Ren
File name: dungeon.c
Description: 游戏地牢环境(危险区)继承对象 STD_DUNGEON
Author: xuefeng
Version: v1.0
Date: 2019-03-12
History:
*****************************************************************************/
#include <status.h>
inherit STD_ROOM;
void create()
{
::create();
set("short", "地牢");
set("long", "这里是废弃地牢,四周雾蒙蒙一片,什么也看不清。");
set("no_fight", 0);
}
/**
* 游戏刷新魔物设置
*/
void init()
{
object me = this_player();
object ob = next_inventory(me);
if ( interactive(me) && !me->query_temp(STA_INVISIBLE)
&& query("area") && query("mob")
&& random(me->query_charm()) < random(200)
&& (!objectp(ob) || !living(ob)) )
{
set("objects", AREA_D->mob(query("dq"), query("area"),
query("mob"), query("mob_max"), query("mob_range")));
setup();
}
// 毒气陷阱
if (query("pitfall"))
{
me->start_condition(CD_POISON);
}
}
当玩家进入环境时触发init
方法,调用地区守护进程ATEA_D
加载魔物,代码如下:
/*****************************************************************************
Copyright: 2019, Mud.Ren
File name: area_d.c
Description: 游戏区域怪物守护进程
Author: xuefeng
Version: v1.0 Date: 2019-03-12
*****************************************************************************/
int *slice(int *mob, int range);
nosave mixed area_mob = ({
({}),
({1, 2, 3, 4, 5, 6, 7}),
({1, 6, 7, 8, 9, 10, 11}),
({12, 13, 14, 15, 16, 17, 21, 23}),
({5, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}),
({20, 21, 22, 24, 25, 26, 27, 28}),
({27, 28, 29, 30, 31, 32}),
({30, 33, 34, 35, 36, 37, 38, 39}),
({29, 34, 35, 36, 37, 38, 39, 40, 41, 42, 101}),
({42, 43, 44, 45, 46}),
({43, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56}),
({48, 50, 51, 53, 54, 55, 56, 57, 204}),
({41, 52, 58, 59, 60, 61, 62}),
({58, 59, 60, 62, 63, 64, 65, 66, 67, 107}),
({57, 63, 64, 66, 67, 68, 69, 74}),
({68, 69, 70, 71, 72, 74}),
({71, 73, 75, 76, 77, 78}),
({72, 78, 79, 80, 81, 82, 86, 90, 93}),
({83, 84, 85, 86, 87, 88, 89, 204}),
({77, 81, 89, 91, 95, 102, 119, 137, 138, 154, 161, 169}),
({76, 92, 93, 94, 95, 96, 97, 98, 108}),
({98, 99, 100, 101, 102, 103, 111}),
({103, 104, 105, 106}),
({104, 106, 107, 108, 109, 110, 111}),
({110, 112, 113, 114, 115, 116, 117, 151}),
({112, 113, 114, 115, 116, 117, 118}),
({119, 124}),
({120, 121, 122, 123, 124}),
({125, 126, 127, 128, 129, 130, 132}),
({131, 133, 134, 135, 136}),
({139, 140, 141, 142, 143, 144}),
({139, 141, 143, 144, 145, 147}),
({145, 146, 147, 148, 149, 150, 151, 152, 153, 205}),
({138, 149, 150, 152, 154, 155, 156, 157, 158, 159, 160, 161, 163, 168, 169, 170}),
({89, 160, 164, 165, 166, 167, 168, 169}),
({170, 171, 172,173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 205}),
({185, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203}),
({202, 220, 230, 231, 232, 233, 235, 236, 237}),
({206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218}),
({207, 208, 214, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229}),
({209, 214, 238, 239, 240, 241, 242, 243, 244, 245, 246}),
({214, 221, 226, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256}),
({46, 87, 90, 105, 109, 137, 172}),
({88, 91, 92, 138, 162, 184})
});
/**
* @brief 返回魔物列表
*
* @param dq 指定所属世界,现在暂未用到,仅支持9,query("dq")
* @param area 指定所属地区,确定魔物列表,query("area")
* @param kind 指定加载的魔物种类上限,query("mob")
* @param max 指定加载种类魔物数量上限,总数最大值为kind*max,query("mob_max")
* @param range 指定魔物分组范围,query("mob_range")
* @return varargs
*/
varargs mapping mob(int dq, int area, int kind, int max, int range)
{
int *mob, i;
mapping mob_list = ([]);
if (!dq)
{
dq = 9;
}
if (area < 1 || kind < 1 ||
sizeof(area_mob) <= area ||
!sizeof(mob = area_mob[area]))
{
return mob_list;
}
if (range)
mob = slice(mob, range);
if (max < 1)
max = 1;
for (i = 0; i < kind; i++)
{
mob_list += ([MOB_DIR + dq + "/" + element_of(mob):1 + random(max),]);
}
return mob_list;
}
void create()
{
// debug_message();
}
// 数组切分3部分,方便控制地区怪物范围
// 0 0 0 : 高4 中2 初1
int *slice(int *mob, int range)
{
int i;
int *mob1, *mob2, *mob3;
if (!range || range > 6)
return mob;
i = sizeof(mob) / 3;
mob1 = mob[0..i];
mob2 = mob[i..i * 2];
mob3 = mob[i * 2..];
return (range & 1 ? mob1 : ({})) + (range & 2 ? mob2 : ({})) + (range & 4 ? mob3 : ({}));
}
varargs int *mob_list(int area, int range)
{
if (area < 1 || area >= sizeof(area_mob))
{
area = 1 + random(sizeof(area_mob) - 1);
}
return slice(area_mob[area], range);
}
守护进程统一管理了所有地区可以生成哪些魔物,这样我们不需要复杂的代码,就能满足多变的需求。
迷宫环境
虚拟环境模式可以用一个文件生成无尽的地图,但有时我们需要地图不大,但线路复杂,mudcore提供的迷宫模式则很好的满足了此需求。
我们看看world/dq9/2/maze1.c
的代码:
// 迷宫
#include <ansi.h>
inherit CORE_VRM;
void create()
{
//迷宫房间所继承的对象的档案名称
set_inherit_room( STD_DUNGEON_9 );
//迷宫房间里的怪物
// set_maze_npcs(({MOB_DIR "9/11", MOB_DIR "9/28", MOB_DIR "9/38", MOB_DIR "9/44", MOB_DIR "9/55"}));
//迷宫的单边长
set_maze_long(10);
//入口方向(出口在对面)
set_entry_dir("south");
//入口与区域的连接方向
set_link_entry_dir("out");
//入口与区域的连接档案名
set_link_entry_room(__DIR__"entrance");
//出口与区域的连接方向
set_link_exit_dir("enter");
//出口与区域的连接档案名
set_link_exit_room(__DIR__"dungeon/-55,-5,6");
//入口房间短描述
set_entry_short(HIC "基萨格纳遗迹" NOR);
//入口房间描述
set_entry_desc(HIB @LONG
这里是基萨格纳遗迹,到处都是断壁残垣,魔物潜藏在里面等待着猎物,这里有离开遗迹的唯一出口,如果要深入探索千万不要迷路。
LONG NOR);
//出口房间短描述
set_exit_short(HIC "基萨格纳遗迹" NOR);
//出口房间描述
set_exit_desc(HIB @LONG
这里是基萨格纳遗迹,到处都是断壁残垣,向北方向的建筑风格很特殊,而且灯火通明,好像有谁住在里面。
LONG NOR);
//迷宫房间的短描述
set_maze_room_short(HIB "基萨格纳遗迹" NOR);
//迷宫房间的描述,如果有多条描述,制造每个房间的时候会从中随机选择一个。
set_maze_room_desc(HIB @LONG
这里是基萨格纳遗迹,到处都是断壁残垣,魔物潜藏在里面等待着猎物。
LONG NOR);
// 迷宫房间是否为户外房间?
// set_outdoors(1);
// 是否绘制迷宫地图?
set_maze_map(1);
// 迷宫的额外参数
set_extra_info(([
"area" : 2,
"zone/z" : 6,
"mob" : 3,
"mob_max" : 3,
"mob_range" : 3,
]));
}
直接继承了mudcore框架提供的CORE_VRM
模块,通过固定的配置生成动态的迷宫,具体功能可进入游戏中基萨格纳遗迹体验吧。