def SaveEntrances(self): """ Saves the entrances back to block 7 """ offset = 0 entstruct = struct.Struct('>HHxxxxBBBBxBBBHxB') buffer = bytearray(len(self.entrances) * 20) zonelist = self.zones for entrance in self.entrances: zoneID = SLib.MapPositionToZoneID(zonelist, entrance.objx, entrance.objy) if zoneID == -1: # No zone was found in the level. # Pretend the entrance belongs to zone 0, even though this zone # does not exist. The level won't work in-game anyway, because # there are no zones. This default allows users to save areas # without zones, so it adds greater flexibility. zoneID = 0 entstruct.pack_into(buffer, offset, int(entrance.objx), int(entrance.objy), int(entrance.entid), int(entrance.destarea), int(entrance.destentrance), int(entrance.enttype), zoneID, int(entrance.entlayer), int(entrance.entpath), int(entrance.entsettings), int(entrance.cpdirection)) offset += 20 self.blocks[6] = bytes(buffer)
def SaveSprites(self): """ Saves the sprites back to block 8 """ offset = 0 sprstruct = struct.Struct('>HHHHLLBx2sxxxx') buffer = bytearray((len(self.sprites) * 24) + 4) f_int = int for sprite in self.sprites: zoneID = SLib.MapPositionToZoneID(self.zones, sprite.objx, sprite.objy, True) try: sprstruct.pack_into(buffer, offset, f_int(sprite.type), f_int(sprite.objx), f_int(sprite.objy), struct.unpack(">H", sprite.spritedata[:2])[0], struct.unpack(">I", sprite.spritedata[2:6])[0], struct.unpack(">I", sprite.spritedata[6:10])[0], zoneID, sprite.spritedata[10:]) except struct.error: # Hopefully this will solve the mysterious bug, and will # soon no longer be necessary. if zoneID < 0: raise ValueError('Sprite %d at (%d, %d) is too far from any zone\'s boundaries!\nPlease place it near a zone.' % (sprite.type, sprite.objx, sprite.objy)) from None else: raise ValueError('SaveSprites struct.error. Current sprite data dump:\n' + \ str(offset) + '\n' + \ str(sprite.type) + '\n' + \ str(sprite.objx) + '\n' + \ str(sprite.objy) + '\n' + \ str(sprite.spritedata[:10]) + '\n' + \ str(zoneID) + '\n' + \ str(sprite.spritedata[10:]) + '\n', ) offset += 24 buffer[offset] = 0xFF buffer[offset + 1] = 0xFF buffer[offset + 2] = 0xFF buffer[offset + 3] = 0xFF self.blocks[7] = bytes(buffer)
def SaveEntrances(self): """ Saves the entrances back to block 7 """ offset = 0 entstruct = struct.Struct('>HHhhBBBBBBxBHBBBBBx') buffer = bytearray(len(self.entrances) * 24) zonelist = self.zones for entrance in self.entrances: zoneID = SLib.MapPositionToZoneID(zonelist, entrance.objx, entrance.objy) entstruct.pack_into(buffer, offset, int(entrance.objx), int(entrance.objy), int(entrance.camerax), int(entrance.cameray), int(entrance.entid), int(entrance.destarea), int(entrance.destentrance), int(entrance.enttype), int(entrance.players), int(entrance.entzone), int(entrance.playerDistance), int(entrance.entsettings), int(entrance.otherID), int(entrance.coinOrder), int(entrance.pathID), int(entrance.pathnodeindex), int(entrance.transition)) offset += 24 self.blocks[6] = bytes(buffer)
def EntranceTooCloseToZoneEdge(self, mode='f'): """ Checks if the main entrance is too close to the left zone edge """ # global Area offset = 24 * 8 # 8 blocks away from the left zone edge if len(globals_.Area.zones) == 0: return False # if the ent isn't even in the zone, return if self.EntranceOutsideOfZone('c'): return False start = None for ent in globals_.Area.entrances: if ent.entid == globals_.Area.startEntrance: start = ent if start is None: return False firstzoneid = SLib.MapPositionToZoneID(globals_.Area.zones, start.objx, start.objy, True) firstzone = None for z in globals_.Area.zones: if z.id == firstzoneid: firstzone = z if firstzone is None: return False problem = start.objx < firstzone.objx + offset if mode == 'c': return problem elif problem: start.setPos((firstzone.objx + offset) * 1.5, start.objy * 1.5)
def SaveSprites(self): """ Saves the sprites back to block 8 """ offset = 0 sprstruct = struct.Struct('>HHH10sBB3sxxx') buffer = bytearray((len(self.sprites) * 24) + 4) f_int = int for sprite in self.sprites: try: sprstruct.pack_into( buffer, offset, f_int(sprite.type), f_int(sprite.objx), f_int(sprite.objy), sprite.spritedata[:10], SLib.MapPositionToZoneID(self.zones, sprite.objx, sprite.objy, True), 0, sprite.spritedata[10:] + to_bytes(0, 1)) except struct.error: # Hopefully this will solve the mysterious bug, and will # soon no longer be necessary. raise ValueError('SaveSprites struct.error. Current sprite data dump:\n' + \ str(offset) + '\n' + \ str(sprite.type) + '\n' + \ str(sprite.objx) + '\n' + \ str(sprite.objy) + '\n' + \ str(sprite.spritedata[:6]) + '\n' + \ str(sprite.zoneID) + '\n' + \ str(bytes([sprite.spritedata[7], ])) + '\n', ) offset += 24 buffer[offset] = 0xFF buffer[offset + 1] = 0xFF buffer[offset + 2] = 0xFF buffer[offset + 3] = 0xFF self.blocks[7] = bytes(buffer)
def EntranceOutsideOfZone(self, mode='f'): """ Checks if any entrances are not inside of a zone """ # global Area left_offset = 24 * 8 # 8 blocks away from the left zone edge if len(globals_.Area.zones) == 0: return False for ent in globals_.Area.entrances: x = ent.objx y = ent.objy zoneID = SLib.MapPositionToZoneID(globals_.Area.zones, x, y, True) zone = None for z in globals_.Area.zones: if z.id == zoneID: zone = z if zone is None: return False if x < zone.objx: problem = True elif x > zone.objx + zone.width: problem = True elif y < zone.objy - 64: problem = True elif y > zone.objy + zone.height + 192: problem = True else: problem = False if problem and mode == 'c': return True elif problem: if x < zone.objx: newx = zone.objx + left_offset elif x > zone.objx + zone.width: newx = zone.objx + zone.width - 16 else: newx = ent.objx if y < (zone.objy - 64): newy = zone.objy - 64 # entrances can be placed a few blocks above the top zone border elif y > zone.objy + zone.height: newy = zone.objy + zone.height - 32 else: newy = ent.objy ent.objx = newx ent.objy = newy ent.setPos(int(newx * 1.5), int(newy * 1.5)) globals_.mainWindow.scene.update() return False
def SaveEntrances(self): """ Saves the entrances back to block 7 """ offset = 0 entstruct = struct.Struct('>HHhhBBBBBBxBHBBBBBx') buffer = bytearray(len(self.entrances) * 24) zonelist = self.zones for entrance in self.entrances: zoneID = SLib.MapPositionToZoneID(zonelist, entrance.objx, entrance.objy) try: entstruct.pack_into(buffer, offset, int(entrance.objx), int(entrance.objy), int(entrance.camerax), int(entrance.cameray), int(entrance.entid), int(entrance.destarea), int(entrance.destentrance), int(entrance.enttype), int(entrance.players), zoneID, int(entrance.playerDistance), int(entrance.entsettings), int(entrance.otherID), int(entrance.coinOrder), int(entrance.pathID), int(entrance.pathnodeindex), int(entrance.transition)) except struct.error: if zoneID < 0: raise ValueError('Entrance %d at (%d, %d) is too far from any zone\'s boundaries!\nPlease place it near a zone.' % (entrance.entid, int(entrance.objx), int(entrance.objy))) from None else: raise ValueError('SaveEntrances struct.error.') offset += 24 self.blocks[6] = bytes(buffer)
def SaveEntrances(self): """ Saves the entrances back to block 7 """ offset = 0 entstruct = struct.Struct('>HHxBxxBBBBBBxBxBBBBBBx') buffer = bytearray(len(self.entrances) * 24) zonelist = self.zones for entrance in self.entrances: zoneID = SLib.MapPositionToZoneID(zonelist, entrance.objx, entrance.objy) entstruct.pack_into(buffer, offset, int(entrance.objx), int(entrance.objy), int(entrance.unk05), int(entrance.entid), int(entrance.destarea), int(entrance.destentrance), int(entrance.enttype), int(entrance.unk0C), zoneID, int(entrance.unk0F), int(entrance.entsettings), int(entrance.unk12), int(entrance.camera), int(entrance.pathID), int(entrance.pathnodeindex), int(entrance.unk16)) offset += 24 self.blocks[6] = bytes(buffer)
def compKey(zonelist, sprite): id = SLib.MapPositionToZoneID(zonelist, sprite.objx, sprite.objy) sprite.zoneID = zonelist[id].id if id != -1 else -1 return id