def Trigger(players, conditions=[], actions=[]): conditions = ut.FlattenList(conditions) actions = ut.FlattenList(actions) ut.ep_assert(type(players) is list) ut.ep_assert(type(conditions) is list) ut.ep_assert(type(actions) is list) ut.ep_assert(len(conditions) <= 16) ut.ep_assert(len(actions) <= 64) peff = bytearray(28) for p in players: peff[EncodePlayer(p)] = 1 b = b''.join(conditions + [bytes(20 * (16 - len(conditions)))] + actions + [bytes(32 * (64 - len(actions)))] + [b'\x04\0\0\0'] + [bytes(peff)]) ut.ep_assert(len(b) == 2400) return b
def f_dbstr_print(dst, *args): """Print multiple string / number to dst. :param dst: Destination address (Not EPD player) :param args: Things to print """ if ut.isUnproxyInstance(dst, DBString): dst = dst.GetStringMemoryAddr() args = ut.FlattenList(args) for arg in args: if ut.isUnproxyInstance(arg, bytes): dst = f_dbstr_addstr(dst, c.Db(arg + b'\0')) elif ut.isUnproxyInstance(arg, str): dst = f_dbstr_addstr(dst, c.Db(ut.u2b(arg) + b'\0')) elif ut.isUnproxyInstance(arg, DBString): dst = f_dbstr_addstr(dst, arg.GetStringMemoryAddr()) elif ut.isUnproxyInstance(arg, int): # int and c.EUDVariable should act the same if possible. # EUDVariable has a value of 32bit unsigned integer. # So we adjust arg to be in the same range. dst = f_dbstr_addstr(dst, c.Db( ut.u2b(str(arg & 0xFFFFFFFF)) + b'\0')) elif ut.isUnproxyInstance(arg, c.EUDVariable): dst = f_dbstr_adddw(dst, arg) elif c.IsConstExpr(arg): dst = f_dbstr_adddw(dst, arg) elif ut.isUnproxyInstance(arg, hptr): dst = f_dbstr_addptr(dst, arg._value) else: raise ut.EPError( 'Object wit unknown parameter type %s given to f_eudprint.' % type(arg) ) return dst
def EUDBranch(conditions, ontrue, onfalse): """Branch by whether conditions is satisfied or not. :param conditions: Nested list of conditions. :param ontrue: When all conditions are true, this branch is taken. :param onfalse: When any of the conditions are false, this branch is taken. """ conditions = ut.FlattenList(conditions) conditions = list(map(PatchCondition, conditions)) if len(conditions) == 0: c.RawTrigger(nextptr=ontrue) # Just jump return # Check all conditions for i in range(0, len(conditions), 16): subontrue = c.Forward() subonfalse = onfalse _EUDBranchSub(conditions[i:i + 16], subontrue, subonfalse) if i + 16 < len(conditions): subontrue << c.NextTrigger() else: subontrue << ontrue
def Trigger(conditions=None, actions=None, preserved=True): """General easy-to-use trigger :param conditions: List of conditions. If there are none, trigger will always execute. :param actions: List of actions. If there are none, trigger will have no actions. :param preserved: Is trigger preserved? True by default. .. note:: This is 'extended' trigger. All conditions and variables can contain `EUDVariable` object, and there may be more than 16 conditions and 64 actions. Trigger internally uses `RawTrigger`. """ ut.ep_assert(isinstance(preserved, bool), 'preserved should be bool') if conditions is None: conditions = [] if actions is None: actions = None conditions = ut.FlattenList(conditions) actions = ut.FlattenList(actions) # Normal if len(conditions) <= 16 and len(actions) <= 64: patched_conds = [] for cond in conditions: patched_conds.append(PatchCondition(cond)) patched_actions = [] for act in actions: patched_actions.append(PatchAction(act)) c.RawTrigger(conditions=patched_conds, actions=patched_actions, preserved=preserved) else: # Extended trigger condts = [] cend = c.Forward() # Check conditions for i in range(0, len(conditions), 16): conds = conditions[i:i + 16] cts = c.Forward() patched_conds = [] for cond in conds: patched_conds.append(PatchCondition(cond)) nextcond = c.Forward() cts << c.RawTrigger(nextptr=cend, conditions=patched_conds, actions=c.SetNextPtr(cts, nextcond)) nextcond << c.NextTrigger() condts.append(cts) skipt = c.Forward() if not preserved: a = c.RawTrigger() c.RawTrigger(actions=c.SetNextPtr(a, skipt)) # Execute actions for i in range(0, len(actions), 64): acts = actions[i:i + 64] patched_actions = [] for act in acts: patched_actions.append(PatchAction(act)) c.RawTrigger(actions=patched_actions) if not preserved: skipt << c.NextTrigger() # Revert conditions cend << c.NextTrigger() for i in range(0, len(condts), 64): c.RawTrigger( actions=[c.SetNextPtr(cts, cend) for cts in condts[i:i + 64]])
def __init__(self, prevptr=None, nextptr=None, conditions=None, actions=None, *args, preserved=True, trigSection=None): super().__init__() # Register trigger to global table global _trgCounter _trgCounter += 1 _RegisterTrigger(self) # This should be called before (1) # Set linked list pointers if prevptr is None: prevptr = 0 if nextptr is None: nextptr = NextTrigger() # (1) self._prevptr = prevptr self._nextptr = nextptr # Uses normal condition/action initialization if trigSection is None: # Normalize conditions/actions if conditions is None: conditions = [] conditions = ut.FlattenList(conditions) conditions = list(map(_bool2Cond, conditions)) if actions is None: actions = [] actions = ut.FlattenList(actions) ut.ep_assert(len(conditions) <= 16, 'Too many conditions') ut.ep_assert(len(actions) <= 64, 'Too many actions') # Register condition/actions to trigger for i, cond in enumerate(conditions): cond.CheckArgs(i) cond.SetParentTrigger(self, i) for i, act in enumerate(actions): act.CheckArgs(i) act.SetParentTrigger(self, i) self._conditions = conditions self._actions = actions self.preserved = preserved # Uses trigger segment for initialization # NOTE : player information is lost inside eudplib. else: self._conditions = [ Db(trigSection[i * 20:i * 20 + 20]) for i in range(16) ] self._actions = [ Db(trigSection[320 + i * 32:320 + i * 32 + 32]) for i in range(64) ] self.preserved = bool(trigSection[320 + 2048] & 4)
def PTrigger(players, conditions=None, actions=None): """Execute trigger by player basis :param players: Players the trigger should execute with. When Current Player specifies any of the players, trigger will execute. :param conditions: List of conditions. If all conditions are met, then actions will be executed. :param actions: List of actions. """ InitPTrigger() players = ut.FlattenList(players) effp = [False] * 8 # Trigger is never executed if it has no effplayers. if len(players) == 0: return # Check whose the player is executed to. for player in players: player = c.EncodePlayer(player) if 0 <= player <= 7: effp[player] = True elif 0x12 <= player <= 0x15: # Force 1 ~ 4 forceIndex = player - 0x12 for p in range(8): if _pinfos[p].force == forceIndex: effp[p] = True elif player == 0x11: # All players for p in range(8): effp[p] = True break # Create player table! dbb = b''.join([b'\0\0\0\0' if eff is False else b'aaaa' for eff in effp]) if dbb in _pdbtable: pdb = _pdbtable[dbb] else: pdb = c.Db(dbb) _pdbtable[dbb] = pdb # effplayer[p] is True -> Memory(EPD(pdb) + p) == b'aaaa' # effplayer[p] is False -> Memory(EPD(pdb) + p) == b'\0\0\0\0' # Create triggers offset_curpl = 0x6509B0 t1, t2, tc, t3 = c.Forward(), c.Forward(), c.Forward(), c.Forward() t1 << c.RawTrigger(nextptr=t3, conditions=c.Memory(offset_curpl, c.AtMost, 7), actions=[ c.SetNextPtr(t1, t2), c.SetMemory(offset_curpl, c.Add, ut.EPD(pdb)) ]) t2 << c.RawTrigger(nextptr=t3, conditions=c.Deaths(c.CurrentPlayer, c.Exactly, ut.b2i4(b'aaaa'), 0), actions=[ c.SetNextPtr(t2, tc), c.SetMemory(offset_curpl, c.Subtract, ut.EPD(pdb)), ]) tc << c.NextTrigger() Trigger(conditions, actions) c.RawTrigger(actions=[ c.SetNextPtr(t2, t3), c.SetMemory(offset_curpl, c.Add, ut.EPD(pdb)) ]) t3 << c.RawTrigger(actions=[ c.SetNextPtr(t1, t3), c.SetMemory(offset_curpl, c.Subtract, ut.EPD(pdb)) ])
def DoActions(actions, preserved=True): tg.Trigger(actions=ut.FlattenList(actions), preserved=preserved)