Co-authored-by: Alchav <59858495+Alchav@users.noreply.github.com> Co-authored-by: Aaron Wagener <mmmcheese158@gmail.com> Co-authored-by: Doug Hoskisson <beauxq@yahoo.com> Co-authored-by: Fabian Dill <Berserker66@users.noreply.github.com>
		
			
				
	
	
		
			96 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import struct
 | 
						|
import typing
 | 
						|
from BaseClasses import Region, ItemClassification
 | 
						|
 | 
						|
if typing.TYPE_CHECKING:
 | 
						|
    from .Rom import RomData
 | 
						|
 | 
						|
animal_map = {
 | 
						|
    "Rick Spawn": 0,
 | 
						|
    "Kine Spawn": 1,
 | 
						|
    "Coo Spawn": 2,
 | 
						|
    "Nago Spawn": 3,
 | 
						|
    "ChuChu Spawn": 4,
 | 
						|
    "Pitch Spawn": 5
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
class KDL3Room(Region):
 | 
						|
    pointer: int = 0
 | 
						|
    level: int = 0
 | 
						|
    stage: int = 0
 | 
						|
    room: int = 0
 | 
						|
    music: int = 0
 | 
						|
    default_exits: typing.List[typing.Dict[str, typing.Union[int, typing.List[str]]]]
 | 
						|
    animal_pointers: typing.List[int]
 | 
						|
    enemies: typing.List[str]
 | 
						|
    entity_load: typing.List[typing.List[int]]
 | 
						|
    consumables: typing.List[typing.Dict[str, typing.Union[int, str]]]
 | 
						|
 | 
						|
    def __init__(self, name, player, multiworld, hint, level, stage, room, pointer, music, default_exits,
 | 
						|
                 animal_pointers, enemies, entity_load, consumables, consumable_pointer):
 | 
						|
        super().__init__(name, player, multiworld, hint)
 | 
						|
        self.level = level
 | 
						|
        self.stage = stage
 | 
						|
        self.room = room
 | 
						|
        self.pointer = pointer
 | 
						|
        self.music = music
 | 
						|
        self.default_exits = default_exits
 | 
						|
        self.animal_pointers = animal_pointers
 | 
						|
        self.enemies = enemies
 | 
						|
        self.entity_load = entity_load
 | 
						|
        self.consumables = consumables
 | 
						|
        self.consumable_pointer = consumable_pointer
 | 
						|
 | 
						|
    def patch(self, rom: "RomData"):
 | 
						|
        rom.write_byte(self.pointer + 2, self.music)
 | 
						|
        animals = [x.item.name for x in self.locations if "Animal" in x.name]
 | 
						|
        if len(animals) > 0:
 | 
						|
            for current_animal, address in zip(animals, self.animal_pointers):
 | 
						|
                rom.write_byte(self.pointer + address + 7, animal_map[current_animal])
 | 
						|
        if self.multiworld.worlds[self.player].options.consumables:
 | 
						|
            load_len = len(self.entity_load)
 | 
						|
            for consumable in self.consumables:
 | 
						|
                location = next(x for x in self.locations if x.name == consumable["name"])
 | 
						|
                assert location.item
 | 
						|
                is_progression = location.item.classification & ItemClassification.progression
 | 
						|
                if load_len == 8:
 | 
						|
                    # edge case, there is exactly 1 room with 8 entities and only 1 consumable among them
 | 
						|
                    if not (any(x in self.entity_load for x in [[0, 22], [1, 22]])
 | 
						|
                            and any(x in self.entity_load for x in [[2, 22], [3, 22]])):
 | 
						|
                        replacement_target = self.entity_load.index(
 | 
						|
                            next(x for x in self.entity_load if x in [[0, 22], [1, 22], [2, 22], [3, 22]]))
 | 
						|
                        if is_progression:
 | 
						|
                            vtype = 0
 | 
						|
                        else:
 | 
						|
                            vtype = 2
 | 
						|
                        rom.write_byte(self.pointer + 88 + (replacement_target * 2), vtype)
 | 
						|
                        self.entity_load[replacement_target] = [vtype, 22]
 | 
						|
                else:
 | 
						|
                    if is_progression:
 | 
						|
                        # we need to see if 1-ups are in our load list
 | 
						|
                        if any(x not in self.entity_load for x in [[0, 22], [1, 22]]):
 | 
						|
                            self.entity_load.append([0, 22])
 | 
						|
                    else:
 | 
						|
                        if any(x not in self.entity_load for x in [[2, 22], [3, 22]]):
 | 
						|
                            # edge case: if (1, 22) is in, we need to load (3, 22) instead
 | 
						|
                            if [1, 22] in self.entity_load:
 | 
						|
                                self.entity_load.append([3, 22])
 | 
						|
                            else:
 | 
						|
                                self.entity_load.append([2, 22])
 | 
						|
                if load_len < len(self.entity_load):
 | 
						|
                    rom.write_bytes(self.pointer + 88 + (load_len * 2), bytes(self.entity_load[load_len]))
 | 
						|
                    rom.write_bytes(self.pointer + 104 + (load_len * 2),
 | 
						|
                                    bytes(struct.pack("H", self.consumable_pointer)))
 | 
						|
                if is_progression:
 | 
						|
                    if [1, 22] in self.entity_load:
 | 
						|
                        vtype = 1
 | 
						|
                    else:
 | 
						|
                        vtype = 0
 | 
						|
                else:
 | 
						|
                    if [3, 22] in self.entity_load:
 | 
						|
                        vtype = 3
 | 
						|
                    else:
 | 
						|
                        vtype = 2
 | 
						|
                rom.write_byte(self.pointer + consumable["pointer"] + 7, vtype)
 |