马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本帖最后由 忘忧北萱草 于 2021-6-24 13:17 编辑
有的时候,我们需要改变内置行为的动作,比如在保存之前进行一些判断与操作。
行为钩子是一种实现方式,它通过替换内置行为的定义,拦截行为的执行。
这是我写的行为钩子的实现,为了便于使用,我使用了装饰器的写法。以下是装饰器的定义:
[RenPy] 纯文本查看 复制代码 init -10 python:
class ActionHook(Action):
alt = None
def __init__(self, action, func):
self.action = action
self.func = func
self.alt = action.alt
def get_sensitive(self):
return self.action.get_sensitive()
def get_selected(self):
return self.action.get_selected()
def get_tooltip(self):
return self.action.get_tooltip()
def periodic(self, st):
return self.action.periodic(st)
def predict(self):
return self.action.predict()
def __call__(self):
return self.func(self.action)
def __eq__(self, other):
if isinstance(other, ActionHook):
return self.action == other.action
elif isinstance(other, Action):
return self.action == other
return False
def action_hook(action_name):
'''行为钩子装饰器,用于拦截并改变行为的执行。
用法举例:
```
@action_hook('FileSave')
def file_save_hook(do_action, *args, **kwargs):
if renpy.random.random() > 0.5:
return do_action() # 执行正常的保存
else:
renpy.notify('A mysterious power has stopped you from saving...')
return
```
参数:
action_name: 所拦截的行为的名称
被装饰函数需要有一个固定参数`do_action`,这是一个无参数的`callable`,表示执行原本的`action`。
被装饰函数其余的参数与所拦截行为的参数一致。
'''
def wrapper(func):
variables = globals()
action_old = variables[action_name]
if not action_old:
raise NameError('{} is not an action!'.format(action_name))
def action_new(*args, **kwargs):
action_instance = action_old(*args, **kwargs)
def exec_action(action):
return func(action, *args, **kwargs)
return ActionHook(action_instance, exec_action)
print(action_name)
variables[action_name] = action_new
return func
return wrapper
用法可以看 action_hook 的 docstring。
以下是一个应用实例:
[RenPy] 纯文本查看 复制代码 define y = Character("Yiri")
default forbid_saving = False
default forbid_loading = False
label start:
y "接下来是存档测试。"
$ forbid_saving = True
y "现在,存档被禁止了。"
y "这很有趣,不是吗?"
$ forbid_saving = False
y "好了,你现在可以存档了。"
$ forbid_loading = True
y "不过,不能读档。"
$ forbid_saving = True
y "现在,试试一起被禁用的感觉。"
$ forbid_saving = False
$ forbid_loading = False
y "很好,玩笑开够了。你可以继续了。"
return
init -5 python:
@action_hook('FileAction')
def file_action_hook(action, *args, **kwargs):
if forbid_saving and renpy.current_screen().screen_name[0] == "save":
renpy.notify("不,你现在不可以存档。")
elif forbid_loading and renpy.current_screen().screen_name[0] == "load":
renpy.notify("不,你现在不可以读档。")
else:
return action()
注意:由于行为钩子采用了是覆盖全局变量中原本的行为的方法,所以可能存在一些尚不确定的问题,请谨慎使用。
|