mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3aaf625282 | ||
![]() |
9df2360b8b | ||
![]() |
d61ac9a135 | ||
![]() |
c8fc56d7c4 | ||
![]() |
51aad167cc | ||
![]() |
e2def66522 | ||
![]() |
73e9d9d577 | ||
![]() |
a5d7ff65c1 | ||
![]() |
05bf60abf7 | ||
![]() |
7f627e2c07 | ||
![]() |
19e0fe1286 | ||
![]() |
b390974019 | ||
![]() |
9da65fab09 | ||
![]() |
02d2eab5a4 | ||
![]() |
985c8b681b | ||
![]() |
cf5a4012c0 | ||
![]() |
c59e75ef7b | ||
![]() |
2dbe344348 |
@@ -1,3 +1,4 @@
|
|||||||
|
import time
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
import asyncio
|
import asyncio
|
||||||
import NetUtils
|
import NetUtils
|
||||||
@@ -78,6 +79,9 @@ class GrinchClient(BizHawkClient):
|
|||||||
self.loc_unlimited_eggs = bool(ctx.slot_data["give_unlimited_eggs"])
|
self.loc_unlimited_eggs = bool(ctx.slot_data["give_unlimited_eggs"])
|
||||||
logger.info("You are now connected to the client. "+
|
logger.info("You are now connected to the client. "+
|
||||||
"There may be a slight delay to check you are not in demo mode before locations start to send.")
|
"There may be a slight delay to check you are not in demo mode before locations start to send.")
|
||||||
|
# tags = args.get("tags", [])
|
||||||
|
# if "RingLink" in tags:
|
||||||
|
# ring_link_input(self, args["data"])
|
||||||
|
|
||||||
async def set_auth(self, ctx: "BizHawkClientContext") -> None:
|
async def set_auth(self, ctx: "BizHawkClientContext") -> None:
|
||||||
await ctx.get_username()
|
await ctx.get_username()
|
||||||
@@ -85,7 +89,7 @@ class GrinchClient(BizHawkClient):
|
|||||||
async def game_watcher(self, ctx: "BizHawkClientContext") -> None:
|
async def game_watcher(self, ctx: "BizHawkClientContext") -> None:
|
||||||
from CommonClient import logger
|
from CommonClient import logger
|
||||||
#If the player is not connected to an AP Server, or their connection was disconnected.
|
#If the player is not connected to an AP Server, or their connection was disconnected.
|
||||||
if ctx.server is None or ctx.server.socket.closed or ctx.slot_data is None:
|
if not ctx.slot:
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -97,11 +101,17 @@ class GrinchClient(BizHawkClient):
|
|||||||
await self.goal_checker(ctx)
|
await self.goal_checker(ctx)
|
||||||
await self.option_handler(ctx)
|
await self.option_handler(ctx)
|
||||||
await self.constant_address_update(ctx)
|
await self.constant_address_update(ctx)
|
||||||
|
# await self.ring_link_input(args["args"])
|
||||||
|
|
||||||
except bizhawk.RequestFailedError as ex:
|
except bizhawk.RequestFailedError as ex:
|
||||||
# The connector didn't respond. Exit handler and return to main loop to reconnect
|
# The connector didn't respond. Exit handler and return to main loop to reconnect
|
||||||
logger.error("Failure to connect / authenticate the grinch. Error details: " + str(ex))
|
logger.error("Failure to connect / authenticate the grinch. Error details: " + str(ex))
|
||||||
pass
|
pass
|
||||||
|
except Exception as genericEx:
|
||||||
|
# For all other errors, catch this and let the client gracefully disconnect
|
||||||
|
logger.error("Unknown error occurred while playing the grinch. Error details: " + str(genericEx))
|
||||||
|
await ctx.disconnect(False)
|
||||||
|
pass
|
||||||
|
|
||||||
async def location_checker(self, ctx: "BizHawkClientContext"):
|
async def location_checker(self, ctx: "BizHawkClientContext"):
|
||||||
from CommonClient import logger
|
from CommonClient import logger
|
||||||
@@ -221,19 +231,25 @@ class GrinchClient(BizHawkClient):
|
|||||||
|
|
||||||
for (item_name, item_data) in items_to_check.items():
|
for (item_name, item_data) in items_to_check.items():
|
||||||
# If item is an event or already been received, ignore.
|
# If item is an event or already been received, ignore.
|
||||||
if item_data.id is None or GrinchLocation.get_apid(item_data.id) in list_recv_itemids:
|
if item_data.id is None: # or GrinchLocation.get_apid(item_data.id) in list_recv_itemids:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# This assumes we don't have the item so we must set all the data to 0
|
# This will either constantly update the item to ensure you still have it or take it away if you don't deserve it
|
||||||
for addr_to_update in item_data.update_ram_addr:
|
for addr_to_update in item_data.update_ram_addr:
|
||||||
is_binary = True if not addr_to_update.binary_bit_pos is None else False
|
is_binary = True if not addr_to_update.binary_bit_pos is None else False
|
||||||
if is_binary:
|
if is_binary:
|
||||||
current_bin_value = int.from_bytes((await bizhawk.read(ctx.bizhawk_ctx, [(
|
current_bin_value = int.from_bytes((await bizhawk.read(ctx.bizhawk_ctx, [(
|
||||||
addr_to_update.ram_address, addr_to_update.bit_size, "MainRAM")]))[0], "little")
|
addr_to_update.ram_address, addr_to_update.bit_size, "MainRAM")]))[0], "little")
|
||||||
current_bin_value &= ~(1 << addr_to_update.binary_bit_pos)
|
if GrinchLocation.get_apid(item_data.id) in list_recv_itemids:
|
||||||
|
current_bin_value |= (1 << addr_to_update.binary_bit_pos)
|
||||||
|
else:
|
||||||
|
current_bin_value &= ~(1 << addr_to_update.binary_bit_pos)
|
||||||
await self.update_and_validate_address(ctx, addr_to_update.ram_address, current_bin_value, 1)
|
await self.update_and_validate_address(ctx, addr_to_update.ram_address, current_bin_value, 1)
|
||||||
else:
|
else:
|
||||||
await self.update_and_validate_address(ctx, addr_to_update.ram_address, 0, 1)
|
if GrinchLocation.get_apid(item_data.id) in list_recv_itemids:
|
||||||
|
await self.update_and_validate_address(ctx, addr_to_update.ram_address, addr_to_update.value, 1)
|
||||||
|
else:
|
||||||
|
await self.update_and_validate_address(ctx, addr_to_update.ram_address, 0, 1)
|
||||||
|
|
||||||
async def ingame_checker(self, ctx: "BizHawkClientContext"):
|
async def ingame_checker(self, ctx: "BizHawkClientContext"):
|
||||||
from CommonClient import logger
|
from CommonClient import logger
|
||||||
@@ -284,4 +300,40 @@ class GrinchClient(BizHawkClient):
|
|||||||
if not current_value == expected_value:
|
if not current_value == expected_value:
|
||||||
if address_to_validate == 0x010000 or address_to_validate == 0x08FB94: # TODO Temporairly skips teleportation addresses; to be changed later on.
|
if address_to_validate == 0x010000 or address_to_validate == 0x08FB94: # TODO Temporairly skips teleportation addresses; to be changed later on.
|
||||||
return
|
return
|
||||||
raise Exception("Unable to update address as expected. Address: "+ str(address_to_validate)+"; Expected Value: "+str(expected_value))
|
raise Exception("Unable to update address as expected. Address: "+ str(address_to_validate)+"; Expected Value: "+str(expected_value))
|
||||||
|
|
||||||
|
# async def ring_link_output(self, ctx: "BizHawkClientContext", byte_size: int):
|
||||||
|
# bizhawk.seek(0x010058)
|
||||||
|
# byte_size = 2
|
||||||
|
# current_eggs = int.from_bytes(byte_size=2, byteorder="little")
|
||||||
|
# difference = current_eggs - ctx.previous_eggs
|
||||||
|
# ctx.previous_eggs = current_eggs + ctx.ring_link_eggs
|
||||||
|
#
|
||||||
|
# if difference != 0:
|
||||||
|
# # logger.info("got here with a difference of " + str(difference))
|
||||||
|
# msg = {
|
||||||
|
# "cmd": "Bounce",
|
||||||
|
# "slots": [ctx.slot],
|
||||||
|
# "data": {
|
||||||
|
# "time": time.time(),
|
||||||
|
# "source": ctx.slot,
|
||||||
|
# "amount": difference
|
||||||
|
# },
|
||||||
|
# "tags": ["RingLink"]
|
||||||
|
# }
|
||||||
|
# await ctx.send_msgs([msg])
|
||||||
|
#
|
||||||
|
# # here write new ring value back into file
|
||||||
|
# bizhawk.seek(0x010058)
|
||||||
|
# if current_eggs + ctx.ring_link_eggs < 0:
|
||||||
|
# ctx.ring_link_eggs = -current_eggs
|
||||||
|
# bizhawk.write(int(current_eggs + ctx.ring_link_eggs).to_bytes(byte_size=2, byteorder="little"))
|
||||||
|
# ctx.ring_link_eggs = 0
|
||||||
|
#
|
||||||
|
# async def ring_link_input(self, data):
|
||||||
|
# amount = data["amount"]
|
||||||
|
# source = data["source"]
|
||||||
|
# if source == self.slot:
|
||||||
|
# return
|
||||||
|
# else:
|
||||||
|
# self.ring_link_eggs += amount
|
||||||
|
@@ -203,6 +203,7 @@ TRAPS_TABLE: dict[str, GrinchItemData] = {
|
|||||||
# "No Vac Trap": GrinchItemData("Traps", 610, IC.trap, [GrinchRamData(0x0102DA, value=0]),
|
# "No Vac Trap": GrinchItemData("Traps", 610, IC.trap, [GrinchRamData(0x0102DA, value=0]),
|
||||||
# "Invisible Trap": GrinchItemData("Traps", 611, IC.trap, [GrinchRamData(0x0102DA, value=0, bit_size=4)])
|
# "Invisible Trap": GrinchItemData("Traps", 611, IC.trap, [GrinchRamData(0x0102DA, value=0, bit_size=4)])
|
||||||
# "Child Trap": GrinchItemData("Traps", 612, IC.trap,[GrinchRamData()])
|
# "Child Trap": GrinchItemData("Traps", 612, IC.trap,[GrinchRamData()])
|
||||||
|
# "Disable Jump Trap": GrinchItemData("Traps", 613, IC.trap,[GrinchRamData(0x010026, binary_bit_pos=6)])
|
||||||
}
|
}
|
||||||
|
|
||||||
#Movesets
|
#Movesets
|
||||||
@@ -228,12 +229,15 @@ ALL_ITEMS_TABLE: dict[str, GrinchItemData] = {
|
|||||||
# Psuedocoding traplink table
|
# Psuedocoding traplink table
|
||||||
# BEE_TRAP_EQUIV = ["Army Trap", "Buyon Trap", "Ghost", "Gooey Bag", "OmoTrap", "Police Trap"]
|
# BEE_TRAP_EQUIV = ["Army Trap", "Buyon Trap", "Ghost", "Gooey Bag", "OmoTrap", "Police Trap"]
|
||||||
# ICE_TRAP_EQUIV = ["Chaos Control Trap", "Freeze Trap", "Frozen Trap", "Honey Trap", "Paralyze Trap", "Stun Trap", "Bubble Trap"]
|
# ICE_TRAP_EQUIV = ["Chaos Control Trap", "Freeze Trap", "Frozen Trap", "Honey Trap", "Paralyze Trap", "Stun Trap", "Bubble Trap"]
|
||||||
# DAMAGE_TRAP_EQUIV = ["Banana Trap", "Bomb", "Bonk Trap", "Fire Trap", "Laughter Trap", "Nut Trap", "Push Trap", "Squash Trap", "Thwimp Trap", "TNT Barrel Trap", "Meteor Trap"]
|
# DAMAGE_TRAP_EQUIV = ["Banana Trap", "Bomb", "Bonk Trap", "Fire Trap", "Laughter Trap", "Nut Trap", "Push Trap",
|
||||||
|
# "Squash Trap", "Thwimp Trap", "TNT Barrel Trap", "Meteor Trap", "Double Damage", "Spike Ball Trap"]
|
||||||
|
|
||||||
# SPRING_TRAP_EQUIV = ["Eject Ability", "Hiccup Trap", "Jump Trap", "Jumping Jacks Trap", "Whoops! Trap"]
|
# SPRING_TRAP_EQUIV = ["Eject Ability", "Hiccup Trap", "Jump Trap", "Jumping Jacks Trap", "Whoops! Trap"]
|
||||||
# HOME_TRAP_EQUIV = ["Blue Balls Curse", "Instant Death Trap"]
|
# HOME_TRAP_EQUIV = ["Blue Balls Curse", "Instant Death Trap", "Get Out Trap"]
|
||||||
# SLOWNESS_TRAP_EQUIV = ["Iron Boots Trap", "Slow Trap", "Sticky Floor Trap"]
|
# SLOWNESS_TRAP_EQUIV = ["Iron Boots Trap", "Slow Trap", "Sticky Floor Trap"]
|
||||||
# CUTSCENE_TRAP_EQUIV = ["Phone Trap"]
|
# CUTSCENE_TRAP_EQUIV = ["Phone Trap"]
|
||||||
# ELEC_TRAP_EQUIV = []
|
# ELEC_TRAP_EQUIV = []
|
||||||
|
# DEPL_TRAP_EQUIV = ["Dry Trap"]
|
||||||
|
|
||||||
def grinch_items_to_id() -> dict[str, int]:
|
def grinch_items_to_id() -> dict[str, int]:
|
||||||
item_mappings: dict[str, int] = {}
|
item_mappings: dict[str, int] = {}
|
||||||
|
@@ -182,6 +182,12 @@ grinch_locations = {
|
|||||||
"Tires in Who Dump": GrinchLocationData("Sleigh Room", "Sleigh Ride", 1602, [GrinchRamData(0x0101FB, binary_bit_pos=4)]),
|
"Tires in Who Dump": GrinchLocationData("Sleigh Room", "Sleigh Ride", 1602, [GrinchRamData(0x0101FB, binary_bit_pos=4)]),
|
||||||
"Twin-End Tuba in Submarine World": GrinchLocationData("Sleigh Room", "Sleigh Ride", 1603, [GrinchRamData(0x0101FB, binary_bit_pos=6)]),
|
"Twin-End Tuba in Submarine World": GrinchLocationData("Sleigh Room", "Sleigh Ride", 1603, [GrinchRamData(0x0101FB, binary_bit_pos=6)]),
|
||||||
"GPS in Who Lake": GrinchLocationData("Sleigh Room", "Sleigh Ride", 1604, [GrinchRamData(0x0101FB, binary_bit_pos=5)]),
|
"GPS in Who Lake": GrinchLocationData("Sleigh Room", "Sleigh Ride", 1604, [GrinchRamData(0x0101FB, binary_bit_pos=5)]),
|
||||||
|
# Mount Crumpit Locations
|
||||||
|
# "1st Crate Squashed": GrinchLocationData("Mount Crumpit", "Mount Crumpit", 1700, [GrinchRamData(0x095343, value=1)]),
|
||||||
|
# "2nd Crate Squashed": GrinchLocationData("Mount Crumpit", "Mount Crumpit", 1701, [GrinchRamData(0x095343, value=2)]),
|
||||||
|
# "3rd Crate Squashed": GrinchLocationData("Mount Crumpit", "Mount Crumpit", 1702, [GrinchRamData(0x095343, value=3)]),
|
||||||
|
# "4th Crate Squashed": GrinchLocationData("Mount Crumpit", "Mount Crumpit", 1703, [GrinchRamData(0x095343, value=4)]),
|
||||||
|
# "5th Crate Squashed": GrinchLocationData("Mount Crumpit", "Mount Crumpit", 1704, [GrinchRamData(0x095343, value=5)]),
|
||||||
}
|
}
|
||||||
|
|
||||||
def grinch_locations_to_id() -> dict[str,int]:
|
def grinch_locations_to_id() -> dict[str,int]:
|
||||||
|
@@ -80,7 +80,6 @@ class GrinchOptions(PerGameCommonOptions):#DeathLinkMixin
|
|||||||
progressive_vacuum: ProgressiveVacuum
|
progressive_vacuum: ProgressiveVacuum
|
||||||
missionsanity: Missionsanity
|
missionsanity: Missionsanity
|
||||||
annoying_locations: AnnoyingLocations
|
annoying_locations: AnnoyingLocations
|
||||||
minigamesanity: Supadow
|
|
||||||
progressive_gadget: ProgressiveGadget
|
progressive_gadget: ProgressiveGadget
|
||||||
supadow_minigames: Supadow
|
supadow_minigames: Supadow
|
||||||
giftsanity: Gifts
|
giftsanity: Gifts
|
||||||
|
@@ -295,7 +295,7 @@ rules_dict: dict[str,list[list[str]]] = {
|
|||||||
# ["Max"]
|
# ["Max"]
|
||||||
],
|
],
|
||||||
"OCD Blueprint - Guardian's House - Right Side": [
|
"OCD Blueprint - Guardian's House - Right Side": [
|
||||||
["Rotten Egg Launcher", "Grinch Copter"],
|
["Grinch Copter"],
|
||||||
["Slime Shooter", "Rocket Spring"]
|
["Slime Shooter", "Rocket Spring"]
|
||||||
],
|
],
|
||||||
"OCD Blueprint - Inside Guardian's House": [
|
"OCD Blueprint - Inside Guardian's House": [
|
||||||
@@ -494,7 +494,22 @@ rules_dict: dict[str,list[list[str]]] = {
|
|||||||
],
|
],
|
||||||
"GPS in Who Lake": [
|
"GPS in Who Lake": [
|
||||||
["Who Lake Vacuum Access", "Rotten Egg Launcher"]
|
["Who Lake Vacuum Access", "Rotten Egg Launcher"]
|
||||||
],
|
# ],
|
||||||
|
# "1st Crate Squashed": [
|
||||||
|
# []
|
||||||
|
# ],
|
||||||
|
# "2nd Crate Squashed": [
|
||||||
|
# []
|
||||||
|
# ],
|
||||||
|
# "3rd Crate Squashed": [
|
||||||
|
# []
|
||||||
|
# ],
|
||||||
|
# "4th Crate Squashed": [
|
||||||
|
# []
|
||||||
|
# ],
|
||||||
|
# "5th Crate Squashed": [
|
||||||
|
# []
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -560,19 +575,23 @@ access_rules_dict: dict[str,list[list[str]]] = {
|
|||||||
["Sleigh Room Key"]
|
["Sleigh Room Key"]
|
||||||
],
|
],
|
||||||
"Spin N' Win Supadow": [
|
"Spin N' Win Supadow": [
|
||||||
["Spin N' Win Door Unlock"],
|
[]
|
||||||
|
# ["Spin N' Win Door Unlock"],
|
||||||
# ["Progressive Supadow Door Unlock"]
|
# ["Progressive Supadow Door Unlock"]
|
||||||
],
|
],
|
||||||
"Dankamania Supadow": [
|
"Dankamania Supadow": [
|
||||||
["Dankamania Door Unlock"],
|
[]
|
||||||
|
# ["Dankamania Door Unlock"],
|
||||||
# ["Progressive Supadow Door Unlock: 2"]
|
# ["Progressive Supadow Door Unlock: 2"]
|
||||||
],
|
],
|
||||||
"The Copter Race Contest Supadow": [
|
"The Copter Race Contest Supadow": [
|
||||||
["The Copter Race Contest Door Unlock"],
|
[]
|
||||||
|
# ["The Copter Race Contest Door Unlock"],
|
||||||
# ["Progressive Supadow Door Unlock: 3"]
|
# ["Progressive Supadow Door Unlock: 3"]
|
||||||
],
|
],
|
||||||
"Bike Race": [
|
"Bike Race": [
|
||||||
["Bike Race Access"],
|
[]
|
||||||
|
# ["Bike Race Access"],
|
||||||
# ["Progressive Supadow Door Unlock: 4"]
|
# ["Progressive Supadow Door Unlock: 4"]
|
||||||
]
|
]
|
||||||
}
|
}
|
@@ -16,7 +16,7 @@ from .Rules import access_rules_dict
|
|||||||
class GrinchWorld(World):
|
class GrinchWorld(World):
|
||||||
game: ClassVar[str] = "The Grinch"
|
game: ClassVar[str] = "The Grinch"
|
||||||
options_dataclass = Options.GrinchOptions
|
options_dataclass = Options.GrinchOptions
|
||||||
options = Options.GrinchOptions
|
options: Options.GrinchOptions
|
||||||
topology_present = True #not an open world game, very linear
|
topology_present = True #not an open world game, very linear
|
||||||
item_name_to_id: ClassVar[dict[str,int]] = grinch_items_to_id()
|
item_name_to_id: ClassVar[dict[str,int]] = grinch_items_to_id()
|
||||||
location_name_to_id: ClassVar[dict[str,int]] = grinch_locations_to_id()
|
location_name_to_id: ClassVar[dict[str,int]] = grinch_locations_to_id()
|
||||||
|
Reference in New Issue
Block a user