Skip to content

Commit eaeef91

Browse files
authored
Merge pull request #46 from ManualForArchipelago/deathlink
Deathlink button!
2 parents c7b29fb + 4546c16 commit eaeef91

File tree

6 files changed

+71
-7
lines changed

6 files changed

+71
-7
lines changed

docs/making/game.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Game.json contains the most fundamental details about your Manual Game, the details about the game itself.
44

55
At its most basic, it needs the name of the game, and name of the creator (you).
6-
It also contains the name of the auto-generated filler item, and details about Starting Inventory (see below for more details)
6+
It also contains the name of the auto-generated filler item, and details about [Starting Inventory](#starting-inventory) and whether [Deathlink](#death-link) is enabled.
77

88
```json
99
{
@@ -84,5 +84,19 @@ This works like the first one, except with categories instead of items. There's
8484
```
8585
Lastly, this gives you three completely random items.
8686

87+
## Death Link
88+
89+
Enabling Deathlink is very simple. Just add `"death_link": true` to your game.json, and you'll get a yaml setting and fancy button in the client.
90+
91+
```json
92+
{
93+
"game": "Snolf",
94+
"creator": "YourNameHere",
95+
"filler_item_name": "Gold Rings",
96+
"death_link": true
97+
}
98+
```
99+
100+
If you turn this on, make sure you have a clear (and documented) understanding of what a death is, when players should send one, and what it means to receive it.
87101

88102
Next: Add your [items](/docs/making/items.md)

schemas/Manual.game.schema.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
"$ref": "#/definitions/Sitems"
2929
}
3030
},
31+
"death_link": {
32+
"description": "(Optional) Does your game support Deathlink?",
33+
"type": "boolean"
34+
},
3135
"_comment": {"$ref": "#/definitions/comment"}
3236
},
3337
"required":["game", "filler_item_name"],

src/ManualClient.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
2+
import time
23
from typing import Any
4+
import typing
35
from worlds import AutoWorldRegister, network_data_package
46
import json
57

@@ -45,6 +47,10 @@ class ManualContext(SuperContext):
4547
tracker_reachable_locations = []
4648
tracker_reachable_events = []
4749

50+
set_deathlink = False
51+
last_death_link = 0
52+
deathlink_out = False
53+
4854
def __init__(self, server_address, password, game, player_name) -> None:
4955
super(ManualContext, self).__init__(server_address, password)
5056

@@ -55,7 +61,6 @@ def __init__(self, server_address, password, game, player_name) -> None:
5561

5662
self.send_index: int = 0
5763
self.syncing = False
58-
self.awaiting_bridge = False
5964
self.game = game
6065
self.username = player_name
6166

@@ -145,6 +150,10 @@ def on_package(self, cmd: str, args: dict):
145150
goal = args["slot_data"].get("goal")
146151
if goal and goal < len(self.victory_names):
147152
self.goal_location = self.get_location_by_name(self.victory_names[goal])
153+
if args['slot_data'].get('death_link'):
154+
self.ui.enable_death_link()
155+
self.set_deathlink = True
156+
self.last_death_link = 0
148157
logger.info(f"Slot data: {args['slot_data']}")
149158

150159
self.ui.build_tracker_and_locations_table()
@@ -154,6 +163,12 @@ def on_package(self, cmd: str, args: dict):
154163
elif cmd in {"RoomUpdate"}:
155164
self.ui.update_tracker_and_locations_table(update_highlights=False)
156165

166+
def on_deathlink(self, data: typing.Dict[str, typing.Any]) -> None:
167+
super().on_deathlink(data)
168+
self.ui.death_link_button.text = f"Death Link: {data['source']}"
169+
self.ui.death_link_button.background_color = [1, 0, 0, 1]
170+
171+
157172
def on_tracker_updated(self, reachable_locations: list[str]):
158173
self.tracker_reachable_locations = reachable_locations
159174
self.ui.update_tracker_and_locations_table(update_highlights=True)
@@ -265,6 +280,23 @@ def set_active_location_accordion(self, instance):
265280

266281
index += 1
267282

283+
def enable_death_link(self):
284+
if not hasattr(self, "death_link_button"):
285+
self.death_link_button = Button(text="Death Link: Primed",
286+
size_hint_x=None, width=150)
287+
self.connect_layout.add_widget(self.death_link_button)
288+
self.death_link_button.bind(on_press=self.send_death_link)
289+
290+
def send_death_link(self, *args):
291+
if self.ctx.last_death_link:
292+
self.ctx.last_death_link = 0
293+
self.death_link_button.text = "Death Link: Primed"
294+
self.death_link_button.background_color = [1, 1, 1, 1]
295+
else:
296+
self.ctx.deathlink_out = True
297+
self.death_link_button.text = "Death Link: Sent"
298+
self.death_link_button.background_color = [0, 1, 0, 1]
299+
268300
def update_hints(self):
269301
super().update_hints()
270302
rebuild = False
@@ -599,6 +631,15 @@ async def game_watcher_manual(ctx: ManualContext):
599631
sync_msg.append({"cmd": "LocationChecks", "locations": list(ctx.locations_checked)})
600632
await ctx.send_msgs(sync_msg)
601633
ctx.syncing = False
634+
635+
if ctx.set_deathlink:
636+
ctx.set_deathlink = False
637+
await ctx.update_death_link(True)
638+
639+
if ctx.deathlink_out:
640+
ctx.deathlink_out = False
641+
await ctx.send_death()
642+
602643
sending = []
603644
victory = ("__Victory__" in ctx.items_received)
604645
ctx.locations_checked = sending

src/Options.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from Options import FreeText, NumericOption, Toggle, DefaultOnToggle, Choice, TextChoice, Range, NamedRange, PerGameCommonOptions
1+
from Options import FreeText, NumericOption, Toggle, DefaultOnToggle, Choice, TextChoice, Range, NamedRange, PerGameCommonOptions, DeathLink
22
from dataclasses import make_dataclass
33
from .hooks.Options import before_options_defined, after_options_defined
4-
from .Data import category_table
4+
from .Data import category_table, game_table
55
from .Locations import victory_names
66
from .Items import item_table
77

@@ -20,6 +20,9 @@ class FillerTrapPercent(Range):
2020
if any(item.get('trap') for item in item_table):
2121
manual_options["filler_traps"] = FillerTrapPercent
2222

23+
if game_table.get("death_link"):
24+
manual_options["death_link"] = DeathLink
25+
2326
for category in category_table:
2427
for option_name in category_table[category].get("yaml_option", []):
2528
if option_name[0] == "!":

src/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ def __init__(self, display_name: str, script_name: Optional[str] = None, func: O
409409
self.version = version
410410

411411
def add_client_to_launcher() -> None:
412-
version = 2024_04_10 # YYYYMMDD
412+
version = 2024_04_23 # YYYYMMDD
413413
found = False
414414
for c in components:
415415
if c.display_name == "Manual Client":

src/data/game.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"$schema": "https://github.com/ManualForArchipelago/Manual/raw/main/schemas/Manual.game.schema.json",
23
"game": "UltimateMarvelVsCapcom3",
34
"creator": "ManualTeam",
45

@@ -22,5 +23,6 @@
2223
{
2324
"random": 3
2425
}
25-
]
26-
}
26+
],
27+
"death_link": false
28+
}

0 commit comments

Comments
 (0)