def AddString(self, string): string = ut.u2b(string) # Starcraft uses multibyte encoding. if not isinstance(string, bytes): raise ut.EPError('Invalid type for string') stringindex = len(self._dataindextb) # If duplicate text exist -> just proxy it try: repr_stringid = self._stringmap[string] dataindex = self._dataindextb[repr_stringid] self._dataindextb.append(dataindex) self._capacity += 2 # just string offset # Else -> Create new entry except KeyError: dataindex = len(self._datatb) self._stringmap[string] = stringindex self._datatb.append(string) self._dataindextb.append(dataindex) # string + b'\0' + string offset self._capacity += len(string) + 1 + 2 ut.ep_assert(self._capacity < 65536, 'String table overflow') return stringindex
def ConstructPayload(): global phase phase = PHASE_WRITING lprint("[Stage 3/3] ConstructPayload", flush=True) objn = len(_found_objects) pbuf = pbuffer.PayloadBuffer(_payload_size) for i, obj in enumerate(_found_objects): objaddr, objsize = _alloctable[obj], obj.GetDataSize() pbuf.StartWrite(objaddr) obj.WritePayload(pbuf) written_bytes = pbuf.EndWrite() ut.ep_assert( written_bytes == objsize, 'obj.GetDataSize()(%d) != Real payload size(%d) for object %s' % (objsize, written_bytes, obj) ) lprint(" - Written %d / %d objects" % (i + 1, objn)) lprint(" - Written %d / %d objects" % (objn, objn), flush=True) phase = None return pbuf.CreatePayload()
def ConstructPayload(): global phase phase = PHASE_WRITING lprint("[Stage 3/3] ConstructPayload", flush=True) objn = len(_found_objects) pbuf = pbuffer.PayloadBuffer(_payload_size) for i, obj in enumerate(_found_objects): objaddr, objsize = _alloctable[obj], obj.GetDataSize() pbuf.StartWrite(objaddr) obj.WritePayload(pbuf) written_bytes = pbuf.EndWrite() ut.ep_assert( written_bytes == objsize, 'obj.GetDataSize()(%d) != Real payload size(%d) for object %s' % (objsize, written_bytes, obj)) lprint(" - Written %d / %d objects" % (i + 1, objn)) lprint(" - Written %d / %d objects" % (objn, objn), flush=True) phase = None return pbuf.CreatePayload()
def AddString(self, string): string = ut.u2b(string) # Starcraft uses multibyte encoding. if not isinstance(string, bytes): raise ut.EPError('Invalid type for string') stringindex = len(self._dataindextb) # If duplicate text exist -> just proxy it try: repr_stringid = self._stringmap[string] dataindex = self._dataindextb[repr_stringid] self._dataindextb.append(dataindex) self._capacity += 2 # just string offset # Else -> Create new entry except KeyError: dataindex = len(self._datatb) self._stringmap[string] = stringindex self._datatb.append(string) self._dataindextb.append(dataindex) # string + b'\0' + string offset self._capacity += len(string) + 1 + 2 ut.ep_assert(self._capacity < 65536, 'String table overflow') return stringindex
def __mul__(self, other): if isinstance(other, RlocInt_C): ut.ep_assert(other.rlocmode == 0, 'Cannot divide RlocInt with non-const') other = other.offset return RlocInt_C((self.offset * other) & 0xFFFFFFFF, self.rlocmode * other)
def _footer(): lb = ut.EUDGetLastBlock() ut.ep_assert(lb[0] == 'swblock', 'Block start/end mismatch') block = lb[1] ut.ep_assert(not block['defaultbr'].IsSet(), 'Duplicate default') block['defaultbr'] << c.NextTrigger() return True
def _footer(): lb = ut.EUDGetLastBlock() ut.ep_assert(lb[0] == 'swblock', 'Block start/end mismatch') block = lb[1] ut.ep_assert(not block['defaultbr'].IsSet(), 'Duplicate default') block['defaultbr'] << c.NextTrigger() return True
def _header(): block = ut.EUDPeekBlock('ifblock')[1] ut.ep_assert(block['next_elseif'] is not None, 'Cannot have EUDElseIf after EUDElse') # Finish previous if/elseif block EUDJump(block['ifend']) block['next_elseif'] << c.NextTrigger() block['next_elseif'] = c.Forward()
def _footer(): block = ut.EUDPeekBlock('ifblock')[1] ut.ep_assert(block['next_elseif'] is not None, 'Cannot have EUDElse after EUDElse') # Finish previous if/elseif block EUDJump(block['ifend']) block['next_elseif'] << c.NextTrigger() block['next_elseif'] = None return True
def _footer(): block = ut.EUDPeekBlock('ifblock')[1] ut.ep_assert( block['next_elseif'] is not None, 'Cannot have EUDElse after EUDElse' ) # Finish previous if/elseif block EUDJump(block['ifend']) block['next_elseif'] << c.NextTrigger() block['next_elseif'] = None return True
def __mul__(self, other): if isinstance(other, RlocInt_C): ut.ep_assert( other.rlocmode == 0, 'Cannot divide RlocInt with non-const' ) other = other.offset return RlocInt_C( (self.offset * other) & 0xFFFFFFFF, self.rlocmode * other )
def _header(): block = ut.EUDPeekBlock('ifblock')[1] ut.ep_assert( block['next_elseif'] is not None, 'Cannot have EUDElseIf after EUDElse' ) # Finish previous if/elseif block EUDJump(block['ifend']) block['next_elseif'] << c.NextTrigger() block['next_elseif'] = c.Forward()
def EncodeAIScript(ais, issueError=False): ais = ut.unProxy(ais) if type(ais) is str: ais = ut.u2b(ais) if type(ais) is bytes: ut.ep_assert(len(ais) >= 4, 'AIScript name too short') if len(ais) > 4: return ut.b2i4(DefAIScriptDict[ais]) elif len(ais) == 4: return ut.b2i4(ais) else: return ais
def EncodeAIScript(ais, issueError=False): ais = ut.unProxy(ais) if type(ais) is str: ais = ut.u2b(ais) if type(ais) is bytes: ut.ep_assert(len(ais) >= 4, 'AIScript name too short') if len(ais) > 4: return ut.b2i4(DefAIScriptDict[ais]) elif len(ais) == 4: return ut.b2i4(ais) else: return ais
def GetPropertyIndex(prop): ut.ep_assert(isinstance(prop, UnitProperty) or isinstance(prop, bytes), 'Invalid property type') prop = bytes(prop) try: return _uprpdict[prop] + 1 # SC counts unit properties from 1. Sucks except KeyError: for uprpindex in range(64): if _uprptable[uprpindex] is None: break ut.ep_assert(uprpindex < 64, 'Unit property table overflow') _uprptable[uprpindex] = prop _uprpdict[prop] = uprpindex return uprpindex + 1 # SC counts unit properties from 1. Sucks
def EUDLoopList(header_offset, break_offset=None): blockname = 'listloop' ut.EUDCreateBlock(blockname, header_offset) ptr, epd = f_dwepdread_epd(ut.EPD(header_offset)) if break_offset is not None: cs.EUDWhileNot()(ptr == break_offset) else: cs.EUDWhile()([ptr > 0, ptr <= 0x7FFFFFFF]) yield ptr, epd cs.EUDSetContinuePoint() c.SetVariables([ptr, epd], f_dwepdread_epd(epd + 1)) cs.EUDEndWhile() ut.ep_assert( ut.EUDPopBlock(blockname)[1] is header_offset, 'listloop mismatch' )
def WriteDword(self, number): number = constexpr.Evaluate(number) if number.rlocmode: ut.ep_assert( self._datacur % 4 == 0, 'Non-const dwords must be aligned to 4byte' ) if number.rlocmode == 1: self._prttable.append(self._datacur) elif number.rlocmode == 4: self._orttable.append(self._datacur) else: raise ut.EPError('rlocmode should be 1 or 4') offset = number.offset self._data[self._datacur + 0] = offset & 0xFF self._data[self._datacur + 1] = (offset >> 8) & 0xFF self._data[self._datacur + 2] = (offset >> 16) & 0xFF self._data[self._datacur + 3] = (offset >> 24) & 0xFF self._datacur += 4
def SetParentTrigger(self, trg, index): ut.ep_assert(self.parenttrg is None, 'Condition cannot be shared by two triggers. ') ut.ep_assert(trg is not None, 'Trigger should not be null.') ut.ep_assert(0 <= index < 16, 'WTF') self.parenttrg = trg self.condindex = index
def _StructPacker(sizelist, buf, arglist): dpos = buf._datacur data = buf._data prttb = buf._prttable orttb = buf._orttable for i, arg in enumerate(arglist): argsize = sizelist[i] ri = constexpr.Evaluate(arg) ut.ep_assert( ri.rlocmode == 0 or (sizelist[i] == 4 and dpos % 4 == 0), 'Cannot write non-const in byte/word/nonalligned dword.' ) if ri.rlocmode == 1: prttb.append(dpos) elif ri.rlocmode == 4: orttb.append(dpos) if sizelist[i] == 1: data[dpos] = ri.offset & 0xFF elif sizelist[i] == 2: data[dpos] = ri.offset & 0xFF data[dpos + 1] = (ri.offset >> 8) & 0xFF else: data[dpos] = ri.offset & 0xFF data[dpos + 1] = (ri.offset >> 8) & 0xFF data[dpos + 2] = (ri.offset >> 16) & 0xFF data[dpos + 3] = (ri.offset >> 24) & 0xFF dpos += sizelist[i] buf._datacur = dpos
def SetParentTrigger(self, trg, index): ut.ep_assert(self.parenttrg is None, 'Actions cannot be shared by two triggers.') ut.ep_assert(trg is not None, 'Trigger should not be null.') ut.ep_assert(0 <= index < 64, 'Triggers out of range') self.parenttrg = trg self.actindex = index
def SetParentTrigger(self, trg, index): ut.ep_assert( self.parenttrg is None, 'Actions cannot be shared by two triggers.' ) ut.ep_assert(trg is not None, 'Trigger should not be null.') ut.ep_assert(0 <= index < 64, 'Triggers out of range') self.parenttrg = trg self.actindex = index
def SetParentTrigger(self, trg, index): ut.ep_assert( self.parenttrg is None, 'Condition cannot be shared by two triggers. ' ) ut.ep_assert(trg is not None, 'Trigger should not be null.') ut.ep_assert(0 <= index < 16, 'WTF') self.parenttrg = trg self.condindex = index
def __floordiv__(self, other): if isinstance(other, RlocInt_C): ut.ep_assert(other.rlocmode == 0, 'Cannot divide RlocInt with non-const') other = other.offset ut.ep_assert(other != 0, 'Divide by zero') ut.ep_assert( (self.rlocmode == 0) or (self.rlocmode % other == 0 and self.offset % other == 0), 'RlocInt not divisible by %d' % other) return RlocInt_C((self.offset // other) & 0xFFFFFFFF, self.rlocmode // other)
def _footer(*numbers): for number in numbers: ut.ep_assert( isinstance(number, int) or isinstance(number, c.ConstExpr), 'Invalid selector start for EUDSwitch') lb = ut.EUDGetLastBlock() ut.ep_assert(lb[0] == 'swblock', 'Block start/end mismatch') block = lb[1] for number in numbers: ut.ep_assert(number not in block['casebrlist'], 'Duplicate cases') block['casebrlist'][number] = c.NextTrigger() return True
def _footer(*numbers): for number in numbers: ut.ep_assert( isinstance(number, int) or isinstance(number, c.ConstExpr), 'Invalid selector start for EUDSwitch' ) lb = ut.EUDGetLastBlock() ut.ep_assert(lb[0] == 'swblock', 'Block start/end mismatch') block = lb[1] for number in numbers: ut.ep_assert(number not in block['casebrlist'], 'Duplicate cases') block['casebrlist'][number] = c.NextTrigger() return True
def __floordiv__(self, other): if isinstance(other, RlocInt_C): ut.ep_assert( other.rlocmode == 0, 'Cannot divide RlocInt with non-const' ) other = other.offset ut.ep_assert(other != 0, 'Divide by zero') ut.ep_assert( (self.rlocmode == 0) or (self.rlocmode % other == 0 and self.offset % other == 0), 'RlocInt not divisible by %d' % other ) return RlocInt_C( (self.offset // other) & 0xFFFFFFFF, self.rlocmode // other )
def EUDEndExecuteOnce(): lb = ut.EUDPopBlock('executeonceblock') ut.ep_assert(lb[0] == 'executeonceblock', 'Block start/end mismatch') block = lb[1] block['blockend'] << c.NextTrigger()
def __init__( self, hitpoint=None, shield=None, energy=None, resource=None, hanger=None, cloaked=None, burrowed=None, intransit=None, hallucinated=None, invincible=None ): ''' Properties : Value/None (Don't care) - hitpoint : 0~100(%) if) When unit's hitpoint is greater than 167772, - shield : 0~100(%) you should give hitpoint None to make 100%% HP. - energy : 0~100(%) - resource : 0~4294967295 - hanger : 0~65536 (Count) Special properties : True(Enabled)/False(Disabled)/None(Don't care) - clocked : Unit is clocked. - burrowed : Unit is burrowed. - intransit : Unit is lifted. (In transit) - hallucinated : Unit is hallucination. - invincible : Unit is invincible. >>> UnitProperty(hitpoint = 50, burrowed = True) # HP 50%, burrowed ''' ut.ep_assert(hitpoint is None or 0 <= hitpoint <= 100) ut.ep_assert(shield is None or 0 <= shield <= 100) ut.ep_assert(energy is None or 0 <= energy <= 100) ut.ep_assert(resource is None or 0 <= resource) ut.ep_assert(hanger is None or 0 <= hanger <= 255) ut.ep_assert(cloaked in [None, True, False]) ut.ep_assert(burrowed in [None, True, False]) ut.ep_assert(intransit in [None, True, False]) ut.ep_assert(hallucinated in [None, True, False]) ut.ep_assert(invincible in [None, True, False]) def prop2int(p): if p is None: return 0 else: return p def prop2valid(p, v): if p is None: return 0 else: return v def prop2flag(p, v): if p: return v else: return 0 self.player = 0 # Set properties self.hitpoint = prop2int(hitpoint) self.shield = prop2int(shield) self.energy = prop2int(energy) self.resource = prop2int(resource) self.hanger = prop2int(hanger) self.prpvalid = ( prop2valid(hitpoint, 1 << 1) | prop2valid(shield, 1 << 2) | prop2valid(energy, 1 << 3) | prop2valid(resource, 1 << 4) | prop2valid(hanger, 1 << 5) ) # Set special properties self.sprpvalid = ( prop2valid(cloaked, 1 << 0) | prop2valid(burrowed, 1 << 1) | prop2valid(intransit, 1 << 2) | prop2valid(hallucinated, 1 << 3) | prop2valid(invincible, 1 << 4) ) self.sprpflag = ( prop2flag(cloaked, 1 << 0) | prop2flag(burrowed, 1 << 1) | prop2flag(intransit, 1 << 2) | prop2flag(hallucinated, 1 << 3) | prop2flag(invincible, 1 << 4) )
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 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 __init__(self, hitpoint=None, shield=None, energy=None, resource=None, hanger=None, cloaked=None, burrowed=None, intransit=None, hallucinated=None, invincible=None): ''' Properties : Value/None (Don't care) - hitpoint : 0~100(%) if) When unit's hitpoint is greater than 167772, - shield : 0~100(%) you should give hitpoint None to make 100%% HP. - energy : 0~100(%) - resource : 0~4294967295 - hanger : 0~65536 (Count) Special properties : True(Enabled)/False(Disabled)/None(Don't care) - clocked : Unit is clocked. - burrowed : Unit is burrowed. - intransit : Unit is lifted. (In transit) - hallucinated : Unit is hallucination. - invincible : Unit is invincible. >>> UnitProperty(hitpoint = 50, burrowed = True) # HP 50%, burrowed ''' ut.ep_assert(hitpoint is None or 0 <= hitpoint <= 100) ut.ep_assert(shield is None or 0 <= shield <= 100) ut.ep_assert(energy is None or 0 <= energy <= 100) ut.ep_assert(resource is None or 0 <= resource) ut.ep_assert(hanger is None or 0 <= hanger <= 255) ut.ep_assert(cloaked in [None, True, False]) ut.ep_assert(burrowed in [None, True, False]) ut.ep_assert(intransit in [None, True, False]) ut.ep_assert(hallucinated in [None, True, False]) ut.ep_assert(invincible in [None, True, False]) def prop2int(p): if p is None: return 0 else: return p def prop2valid(p, v): if p is None: return 0 else: return v def prop2flag(p, v): if p: return v else: return 0 self.player = 0 # Set properties self.hitpoint = prop2int(hitpoint) self.shield = prop2int(shield) self.energy = prop2int(energy) self.resource = prop2int(resource) self.hanger = prop2int(hanger) self.prpvalid = (prop2valid(hitpoint, 1 << 1) | prop2valid(shield, 1 << 2) | prop2valid(energy, 1 << 3) | prop2valid(resource, 1 << 4) | prop2valid(hanger, 1 << 5)) # Set special properties self.sprpvalid = (prop2valid(cloaked, 1 << 0) | prop2valid(burrowed, 1 << 1) | prop2valid(intransit, 1 << 2) | prop2valid(hallucinated, 1 << 3) | prop2valid(invincible, 1 << 4)) self.sprpflag = (prop2flag(cloaked, 1 << 0) | prop2flag(burrowed, 1 << 1) | prop2flag(intransit, 1 << 2) | prop2flag(hallucinated, 1 << 3) | prop2flag(invincible, 1 << 4))
def CheckArgs(self, i): ut.ep_assert( self.fields[0] is None or IsConstExpr(self.fields[0]), 'Invalid locid1 "%s" in trigger index %d' % (self.fields[0], i) ) ut.ep_assert( self.fields[1] is None or IsConstExpr(self.fields[1]), 'Invalid strid "%s" in trigger index %d' % (self.fields[1], i) ) ut.ep_assert( self.fields[2] is None or IsConstExpr(self.fields[2]), 'Invalid wavid "%s" in trigger index %d' % (self.fields[2], i) ) ut.ep_assert( self.fields[3] is None or IsConstExpr(self.fields[3]), 'Invalid time "%s" in trigger index %d' % (self.fields[3], i) ) ut.ep_assert( self.fields[4] is None or IsConstExpr(self.fields[4]), 'Invalid player1 "%s" in trigger index %d' % (self.fields[4], i) ) ut.ep_assert( self.fields[5] is None or IsConstExpr(self.fields[5]), 'Invalid player2 "%s" in trigger index %d' % (self.fields[5], i) ) ut.ep_assert( self.fields[6] is None or IsConstExpr(self.fields[6]), 'Invalid unitid "%s" in trigger index %d' % (self.fields[6], i) ) ut.ep_assert( self.fields[7] is None or IsConstExpr(self.fields[7]), 'Invalid acttype "%s" in trigger index %d' % (self.fields[7], i) ) ut.ep_assert( self.fields[8] is None or IsConstExpr(self.fields[8]), 'Invalid amount "%s" in trigger index %d' % (self.fields[8], i) ) ut.ep_assert( self.fields[9] is None or IsConstExpr(self.fields[9]), 'Invalid flags "%s" in trigger index %d' % (self.fields[9], i) ) return True
def CheckArgs(self, i): ut.ep_assert( self.fields[0] is None or IsConstExpr(self.fields[0]), 'Invalid locid1 "%s" in trigger index %d' % (self.fields[0], i)) ut.ep_assert( self.fields[1] is None or IsConstExpr(self.fields[1]), 'Invalid strid "%s" in trigger index %d' % (self.fields[1], i)) ut.ep_assert( self.fields[2] is None or IsConstExpr(self.fields[2]), 'Invalid wavid "%s" in trigger index %d' % (self.fields[2], i)) ut.ep_assert( self.fields[3] is None or IsConstExpr(self.fields[3]), 'Invalid time "%s" in trigger index %d' % (self.fields[3], i)) ut.ep_assert( self.fields[4] is None or IsConstExpr(self.fields[4]), 'Invalid player1 "%s" in trigger index %d' % (self.fields[4], i)) ut.ep_assert( self.fields[5] is None or IsConstExpr(self.fields[5]), 'Invalid player2 "%s" in trigger index %d' % (self.fields[5], i)) ut.ep_assert( self.fields[6] is None or IsConstExpr(self.fields[6]), 'Invalid unitid "%s" in trigger index %d' % (self.fields[6], i)) ut.ep_assert( self.fields[7] is None or IsConstExpr(self.fields[7]), 'Invalid acttype "%s" in trigger index %d' % (self.fields[7], i)) ut.ep_assert( self.fields[8] is None or IsConstExpr(self.fields[8]), 'Invalid amount "%s" in trigger index %d' % (self.fields[8], i)) ut.ep_assert( self.fields[9] is None or IsConstExpr(self.fields[9]), 'Invalid flags "%s" in trigger index %d' % (self.fields[9], i)) return True
def Evaluate(self): ut.ep_assert( self.parenttrg is not None, 'Orphan condition. This often happens when you try to do ' + 'arithmetics with conditions.') return self.parenttrg.Evaluate() + 8 + self.condindex * 20
def CheckArgs(self, i): ut.ep_assert( self.fields[0] is None or IsConstExpr(self.fields[0]), 'Invalid locid "%s" in trigger index %d' % (self.fields[0], i) ) ut.ep_assert( self.fields[1] is None or IsConstExpr(self.fields[1]), 'Invalid player "%s" in trigger index %d' % (self.fields[1], i) ) ut.ep_assert( self.fields[2] is None or IsConstExpr(self.fields[2]), 'Invalid amount "%s" in trigger index %d' % (self.fields[2], i) ) ut.ep_assert( self.fields[3] is None or IsConstExpr(self.fields[3]), 'Invalid unitid "%s" in trigger index %d' % (self.fields[3], i) ) ut.ep_assert( self.fields[4] is None or IsConstExpr(self.fields[4]), 'Invalid comparison "%s" in trigger index %d' % (self.fields[4], i) ) ut.ep_assert( self.fields[5] is None or IsConstExpr(self.fields[5]), 'Invalid condtype "%s" in trigger index %d' % (self.fields[5], i) ) ut.ep_assert( self.fields[6] is None or IsConstExpr(self.fields[6]), 'Invalid restype "%s" in trigger index %d' % (self.fields[6], i) ) ut.ep_assert( self.fields[7] is None or IsConstExpr(self.fields[7]), 'Invalid flags "%s" in trigger index %d' % (self.fields[7], i) ) return True
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 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 __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 EUDEndExecuteOnce(): lb = ut.EUDPopBlock('executeonceblock') ut.ep_assert(lb[0] == 'executeonceblock', 'Block start/end mismatch') block = lb[1] block['blockend'] << c.NextTrigger()