id Tech Games: Customizable ammo capacity (#3565)

* Doom, Doom 2, Heretic: customizable ammo capacity

* Do not progression balance capacity up items

* Prog fill still doesn't agree, just go with our original idea

* Clean up the new options a bit

- Gave all options a consistent and easily readable naming scheme
  (`max_ammo_<type>` and `added_ammo_<type>`)
- Don't show the new options in the spoiler log,
  as they do not affect logic
- Fix the Doom games' Split Backpack option accidentally referring to
  Heretic's Bag of Holding

The logging change across all three games is incidental, as at some
point I did run into that condition by happenstance and it turns out
that it throws an exception due to bad formatting if it's reached

* Do the visibility change for Heretic as well

* Update required client version

* Remove spoiler log restriction on options

* Remove Visibility import now made redundant
This commit is contained in:
Kaito Sinclaire
2025-03-08 07:37:54 -08:00
committed by GitHub
parent 00a6ac3a52
commit b5269e9aa4
10 changed files with 469 additions and 19 deletions

View File

@@ -41,7 +41,7 @@ class HereticWorld(World):
options: HereticOptions
game = "Heretic"
web = HereticWeb()
required_client_version = (0, 3, 9)
required_client_version = (0, 5, 0) # 1.2.0-prerelease or higher
item_name_to_id = {data["name"]: item_id for item_id, data in Items.item_table.items()}
item_name_groups = Items.item_name_groups
@@ -206,6 +206,17 @@ class HereticWorld(World):
count = item["count"] if item["name"] not in self.starting_level_for_episode else item["count"] - 1
itempool += [self.create_item(item["name"]) for _ in range(count)]
# Bag(s) of Holding based on options
if self.options.split_bag_of_holding.value:
itempool += [self.create_item("Crystal Capacity") for _ in range(self.options.bag_of_holding_count.value)]
itempool += [self.create_item("Ethereal Arrow Capacity") for _ in range(self.options.bag_of_holding_count.value)]
itempool += [self.create_item("Claw Orb Capacity") for _ in range(self.options.bag_of_holding_count.value)]
itempool += [self.create_item("Rune Capacity") for _ in range(self.options.bag_of_holding_count.value)]
itempool += [self.create_item("Flame Orb Capacity") for _ in range(self.options.bag_of_holding_count.value)]
itempool += [self.create_item("Mace Sphere Capacity") for _ in range(self.options.bag_of_holding_count.value)]
else:
itempool += [self.create_item("Bag of Holding") for _ in range(self.options.bag_of_holding_count.value)]
# Place end level items in locked locations
for map_name in Maps.map_names:
loc_name = map_name + " - Exit"
@@ -274,7 +285,7 @@ class HereticWorld(World):
episode_count = self.get_episode_count()
count = min(remaining_loc, max(1, self.items_ratio[item_name] * episode_count))
if count == 0:
logger.warning("Warning, no " + item_name + " will be placed.")
logger.warning(f"Warning, no {item_name} will be placed.")
return
for i in range(count):
@@ -290,4 +301,18 @@ class HereticWorld(World):
slot_data["episode4"] = self.included_episodes[3]
slot_data["episode5"] = self.included_episodes[4]
# Send slot data for ammo capacity values; this must be generic because Doom uses it too
slot_data["ammo1start"] = self.options.max_ammo_crystals.value
slot_data["ammo2start"] = self.options.max_ammo_arrows.value
slot_data["ammo3start"] = self.options.max_ammo_claw_orbs.value
slot_data["ammo4start"] = self.options.max_ammo_runes.value
slot_data["ammo5start"] = self.options.max_ammo_flame_orbs.value
slot_data["ammo6start"] = self.options.max_ammo_spheres.value
slot_data["ammo1add"] = self.options.added_ammo_crystals.value
slot_data["ammo2add"] = self.options.added_ammo_arrows.value
slot_data["ammo3add"] = self.options.added_ammo_claw_orbs.value
slot_data["ammo4add"] = self.options.added_ammo_runes.value
slot_data["ammo5add"] = self.options.added_ammo_flame_orbs.value
slot_data["ammo6add"] = self.options.added_ammo_spheres.value
return slot_data