LPC和C对比(2) 函数

函数默认值

2023.12之后添加的新用法(还在更新啊)

void test(string str : (: "你好,中国" :), int i : (: 100 :), object ob : (: this_object() :))
{
    printf("str = %s; i = %d; ob = %O\n", str, i, ob);
}

int main(object me, string arg)
{
    // 请在此实现你的代码
    test();
    test("test");
    test(arg, 520, me);

    return 1;
}

可变参数

void test(mixed *x...)
{
    printf("x = %O\n", x);
}

库函数

efun

在LPC语言中有各种可以直接使用的库函数,专业术语为 外部函数(external function),
通常简称为 efun,在 fluffos 中一共有近300个 efun,这些函数都可以直接使用,
而且不需要和C语言一样要引入头文件,如:printf、allocate、this_object
efun列表

模拟库函数sefun

可以类比为自己写的efun,类似于头文件+cpp实现的方法

局部函数lfun

local func 除了 efun 和 sefun,我们正常开发中会大量的自定义函数,这些函数被称为 局部函数(local function),
简称 lfun。因为LPC是面向对象编程,所有 lfun 都是写在蓝图对象中,而且和对象直接相关,
不像 efun 和 sefun 可以随意调用。在现在面向对象编程中,对这些函数的称呼是 方法,我个人也习惯这种称呼,
在本教程中对自定义函数全部统一称呼为 方法,代表和对象相关的自定义函数。

系统方法apply

方法列表

请注意:有的 apply 方法必须实现,否则游戏不能正常运行,如:connect方法、logon方法。而有的 apply 方法可以不实现,这样相关的行为就不会被处理。

简单示例

// 示例:5.1.1
// apply 方法,对象加载时自动执行
void create()
{
    // 发送信息给当前玩家
    write("create 5.1.1!\n");
}

// apply 方法,设置心跳后自动执行
void heart_beat()
{
    // 记录日志,请在driver界面或 debug.log 文件中查看
    debug_message(file_name(this_object()) + ": " + time());
}

int main(object me, string arg)
{
    if (query_heart_beat())
    {
        write("停止心跳!\n");
        set_heart_beat(0);
    }
    else
    {
        write("开始心跳!\n");
        set_heart_beat(1);
    }

    return 1;
}

在本示例中,包括 efun、lfun 和 apply,
debug_message、file_name、this_object、time、query_heart_beat、set_heart_beat、write是 efun,
create、heart_beat是 apply,
main是 lfun

环境(environment)和内容物(inventory)

在 LPC 的世界里,大多数对象均有一个环境,而该环境的内容物即包含在环境中的对象。
举一个简单的例子,玩家 player A、player B 目前站在一个房间 room A ,
而此房间放置了一个物品 item A ,那么 player A、player B 及 item A 均为 room A 的内容物,
相对的 room A 为 player A、player B 及 item A 的环境。实际状况如图所示

任何对象均能被当作其它对象的环境, 我们可以将任何对象视为一个容器,如 player A 将 item A 捡起,实际情形如下:

此时,我们可以执行外部函数 environment(player A 或 player B) 来得到环境对象 room A,
可以执行 environment(item A) 得到 player A,而透过执行 all_inventory(room A),可以得到 player A 及 player B 的对象数组,
要注意的是,这样无法取得 item A,除非执行了 all_inventory(player A) 或 deep_inventory(room A)

也就是说all_inventory()无法递归的去调用,deep_inventory()可以

相关函数

this_object()

object this_object( void );//返回当前对象的指针。

environment()

返回包含对象 `ob` 的对象(环境),如果没有指定参数 `ob`,默认是 this_object()。如果对象 `ob` 不在任何环境里,返回 0。
object environment( void );
object environment( object ob );

all_inventory()

//返回在指定对象 `ob` 中的所有对象组成的数组。如果没有指定参数 `ob`,默认是 this_object()。
object *all_inventory( void );
object *all_inventory( object ob );

deep_inventory()

//返回对象 `ob` 中的所有对象及对象中的所有对象(层层递进查找,直到传回所有对象为止)的数组。如果没有指定参数 `ob`,默认是 this_object()。
object *deep_inventory( void );
object *deep_inventory( object ob );

first_inventory()

//返回对象 `ob` 内容物品中的第一个物品,参数 `ob` 既可以是对象类型也可以是字符串类型(对象的文件名),如果没有指定参数 `ob`,默认是 this_object()。
object first_inventory( void );
object first_inventory( mixed ob );

next_inventory()

//返回和对象 `ob` 环境相同的后一个对象。如果没有指定参数 `ob`,默认是 this_object()。

//先进入环境的对象顺序靠后,所以 next_inventory() 取得的是比指定对象先进入环境的对象,如果指定对象是第一个进入环境,哪怕环境中有其它对象进入返回值也是 0。

object next_inventory( void );
object next_inventory( object ob );

move_object()

void move_object( mixed dest );
//移动当前对象到环境 `dest`,移动后会触发当前对象和目标环境及其中对象的 init() 方法。

任何 .c 文件在游戏中都是一个对象,而任何对象都可以做为环境,不管这个对象的功能是什么,
哪怕一个文件的作用只是一个指令,甚至是一个没有任何代码的空的 .c 文件。在游戏开发中,我们需要限制对象的移动,不能进入不是环境的对象。

输入输出函数

输出

write()对当前玩家送出信息

//对当前玩家显示 'str' 信息。 'str' 如果是数字会自动转换成字符串。对象类型也可以正常显示,
//但其它类型比如数组、映射、函数指针或缓冲区类型会显示为<ARRAY>、<MAPPING>、<FUNCTION>和<BUFFER>。
void write(mixed str);

say() - 把信息发送给在相同环境中的所有用户

//把信息发送给发送者所在环境中的所有对象及所在环境是发送者的所有对象。
//发送者只能是 `this_player()` 或者 `this_player() == 0` 的 `this_object()`。
//第二个参数是可选的,如果指定第二个参数 `obj`,信息不会发给 `obj`,`obj` 可以是一个对象或者是对象数组。
void say( string str );
void say( string str, object obj );
void say( string str, object *obj );

shout() - 对所有活着的(living)对象发送信息

//对 this_player() 以外的所有活着的对象发送信息 `str`。
void shout( string str );

和say不同的是,say只有当前环境的其他玩家能看到消息,相当于频道发言
shout是大喇叭,全部玩家都能看到

tell_object() - 向一个对象发送消息

//向 `ob` 对象发送消息 `str`,如果对象是玩家,消息会显示给对方,否则会被此对象中的 apply 方法 `catch_tell()` 捕获。
void tell_object( object ob, string str );

私聊功能

tell_room() - 对一个房间中的所有对象发送消息

//向房间 `ob` 中的所有对象发送消息 `str`,`ob` 既可以是房间对象,也可以是房间文件名字符串。如果指定 `exclude` 参数,所有在此数组中的对象不会收到消息。
void tell_room( mixed ob, string str );
void tell_room( mixed ob, string str, object *exclude );

输入函数

input_to把玩家接下来输入的内容传递给指定的函数

//把玩家接下来输入的内容做为参数传给局部函数 `fun`。驱动程序不会解析(parse)输入的字符。

//请注意: input_to() 是非阻塞式监听,也就是说呼叫 input_to() 的对象不会暂停下来等待用户输入,而是继续执行后续程序。

//如果在同一次执行时多次调用 input_to(),仅第一次呼叫有效。

//如果可选参数 `flag` 非零,用户输入的字符不会回显,在被窃听(snoop)时也不会显示(这在输入密码时很有用)。

//函数 `fun` 执行时用户输入的字符会做为第一个参数(字符串类型),input_to() 函数 `flag` 之后的参数会做为额外参数传递给 `fun`。

//说明:这个外部函数的用法和 get_char() 外部函数及其类似,只是获取的输入从单个字符改为字符串。

varargs void input_to( string | function fun, int flag, ... );

get_char() - 把玩家接下来输入的内容的第一个字符传递给指定的函数

其余和input_to()相同

posted @ 2024-01-24 17:15  LiviaYu  阅读(92)  评论(0)    收藏  举报