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
|
||||
import asyncio
|
||||
import NetUtils
|
||||
@@ -78,6 +79,9 @@ class GrinchClient(BizHawkClient):
|
||||
self.loc_unlimited_eggs = bool(ctx.slot_data["give_unlimited_eggs"])
|
||||
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.")
|
||||
# tags = args.get("tags", [])
|
||||
# if "RingLink" in tags:
|
||||
# ring_link_input(self, args["data"])
|
||||
|
||||
async def set_auth(self, ctx: "BizHawkClientContext") -> None:
|
||||
await ctx.get_username()
|
||||
@@ -85,7 +89,7 @@ class GrinchClient(BizHawkClient):
|
||||
async def game_watcher(self, ctx: "BizHawkClientContext") -> None:
|
||||
from CommonClient import logger
|
||||
#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
|
||||
|
||||
try:
|
||||
@@ -97,11 +101,17 @@ class GrinchClient(BizHawkClient):
|
||||
await self.goal_checker(ctx)
|
||||
await self.option_handler(ctx)
|
||||
await self.constant_address_update(ctx)
|
||||
# await self.ring_link_input(args["args"])
|
||||
|
||||
except bizhawk.RequestFailedError as ex:
|
||||
# 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))
|
||||
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"):
|
||||
from CommonClient import logger
|
||||
@@ -221,17 +231,23 @@ class GrinchClient(BizHawkClient):
|
||||
|
||||
for (item_name, item_data) in items_to_check.items():
|
||||
# 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
|
||||
|
||||
# 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:
|
||||
is_binary = True if not addr_to_update.binary_bit_pos is None else False
|
||||
if is_binary:
|
||||
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")
|
||||
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)
|
||||
else:
|
||||
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)
|
||||
|
||||
@@ -285,3 +301,39 @@ class GrinchClient(BizHawkClient):
|
||||
if address_to_validate == 0x010000 or address_to_validate == 0x08FB94: # TODO Temporairly skips teleportation addresses; to be changed later on.
|
||||
return
|
||||
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]),
|
||||
# "Invisible Trap": GrinchItemData("Traps", 611, IC.trap, [GrinchRamData(0x0102DA, value=0, bit_size=4)])
|
||||
# "Child Trap": GrinchItemData("Traps", 612, IC.trap,[GrinchRamData()])
|
||||
# "Disable Jump Trap": GrinchItemData("Traps", 613, IC.trap,[GrinchRamData(0x010026, binary_bit_pos=6)])
|
||||
}
|
||||
|
||||
#Movesets
|
||||
@@ -228,12 +229,15 @@ ALL_ITEMS_TABLE: dict[str, GrinchItemData] = {
|
||||
# Psuedocoding traplink table
|
||||
# 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"]
|
||||
# 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"]
|
||||
# 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"]
|
||||
# CUTSCENE_TRAP_EQUIV = ["Phone Trap"]
|
||||
# ELEC_TRAP_EQUIV = []
|
||||
# DEPL_TRAP_EQUIV = ["Dry Trap"]
|
||||
|
||||
def grinch_items_to_id() -> 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)]),
|
||||
"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)]),
|
||||
# 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]:
|
||||
|
@@ -80,7 +80,6 @@ class GrinchOptions(PerGameCommonOptions):#DeathLinkMixin
|
||||
progressive_vacuum: ProgressiveVacuum
|
||||
missionsanity: Missionsanity
|
||||
annoying_locations: AnnoyingLocations
|
||||
minigamesanity: Supadow
|
||||
progressive_gadget: ProgressiveGadget
|
||||
supadow_minigames: Supadow
|
||||
giftsanity: Gifts
|
||||
|
@@ -295,7 +295,7 @@ rules_dict: dict[str,list[list[str]]] = {
|
||||
# ["Max"]
|
||||
],
|
||||
"OCD Blueprint - Guardian's House - Right Side": [
|
||||
["Rotten Egg Launcher", "Grinch Copter"],
|
||||
["Grinch Copter"],
|
||||
["Slime Shooter", "Rocket Spring"]
|
||||
],
|
||||
"OCD Blueprint - Inside Guardian's House": [
|
||||
@@ -494,7 +494,22 @@ rules_dict: dict[str,list[list[str]]] = {
|
||||
],
|
||||
"GPS in Who Lake": [
|
||||
["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"]
|
||||
],
|
||||
"Spin N' Win Supadow": [
|
||||
["Spin N' Win Door Unlock"],
|
||||
[]
|
||||
# ["Spin N' Win Door Unlock"],
|
||||
# ["Progressive Supadow Door Unlock"]
|
||||
],
|
||||
"Dankamania Supadow": [
|
||||
["Dankamania Door Unlock"],
|
||||
[]
|
||||
# ["Dankamania Door Unlock"],
|
||||
# ["Progressive Supadow Door Unlock: 2"]
|
||||
],
|
||||
"The Copter Race Contest Supadow": [
|
||||
["The Copter Race Contest Door Unlock"],
|
||||
[]
|
||||
# ["The Copter Race Contest Door Unlock"],
|
||||
# ["Progressive Supadow Door Unlock: 3"]
|
||||
],
|
||||
"Bike Race": [
|
||||
["Bike Race Access"],
|
||||
[]
|
||||
# ["Bike Race Access"],
|
||||
# ["Progressive Supadow Door Unlock: 4"]
|
||||
]
|
||||
}
|
@@ -16,7 +16,7 @@ from .Rules import access_rules_dict
|
||||
class GrinchWorld(World):
|
||||
game: ClassVar[str] = "The Grinch"
|
||||
options_dataclass = Options.GrinchOptions
|
||||
options = Options.GrinchOptions
|
||||
options: Options.GrinchOptions
|
||||
topology_present = True #not an open world game, very linear
|
||||
item_name_to_id: ClassVar[dict[str,int]] = grinch_items_to_id()
|
||||
location_name_to_id: ClassVar[dict[str,int]] = grinch_locations_to_id()
|
||||
|
Reference in New Issue
Block a user