Compare commits

..

2 Commits

Author SHA1 Message Date
e98680d123 Add dynamic statement 2024-03-27 00:26:23 +01:00
8e80555393 Add decorator 2024-03-27 00:26:14 +01:00

View File

@ -1,3 +1,59 @@
python early hide:
import inspect
__register_params = frozenset(inspect.signature(renpy.register_statement).parameters).difference({"name", "parse"})
def register_decorator(cls):
"""
A class decorator which registers a new statement.
The name of the statement will be the class name unless a `name` class attribute is present, which should be a string.
The `parse` method should be a static method that returns an object which will be passed to the other methods as `self`.
Returning an instance of the class is disabled for now.
"""
# security
def raiser(*args, **kwargs):
raise NotImplementedError("Returning an instance of the class is disabled")
cls.__init__ = raiser
name = getattr(cls, "name", cls.__name__)
parse = getattr(cls, "parse", cls) # left in
renpy.register_statement(name,
parse=parse,
**{k:getattr(cls, k) for k in __register_params.intersection(vars(cls))})
return cls
@register_decorator
class dynamic:
block = "possible"
@staticmethod
def parse(l):
rv = {}
def parse_simple(ll):
target = ll.require(ll.name, "variable name")
if target in rv:
ll.error(f"Variable {target} already set in the same dynamic block")
ll.require("=", "equals sign")
expression = ll.simple_expression()
ll.expect_eol()
rv[target] = expression
if l.match(":"):
l.expect_block("dynamic block")
l.expect_eol()
ll = l.subblock_lexer()
while ll.advance():
parse_simple(ll)
else:
parse_simple(l)
return rv
def execute(self):
evaled = {n: eval(e) for n, e in self.items()}
renpy.dynamic(**evaled)
python early: python early:
def parse_chibi(l): def parse_chibi(l):
who = l.simple_expression() who = l.simple_expression()
@ -72,11 +128,11 @@ python early:
return {"blocks": blocks} return {"blocks": blocks}
def next_random(p): def next_random(p):
blocks = [(block, weight, condition) for block, weight, condition in p["blocks"] if eval(condition)] blocks = [(block, weight) for block, weight, condition in p["blocks"] if eval(condition)]
total_weight = sum(weight for _, weight, _ in blocks) total_weight = sum(weight for _, weight in blocks)
n = renpy.random.random() * total_weight n = renpy.random.random() * total_weight
for block, weight, _ in blocks: for block, weight in blocks:
if n <= weight: if n <= weight:
break break
else: else: