Pokemon R/B: Bug fixes and add trap weights (#1319)

* [Pokemon R/B] Move type chart rando to generate_early and add trap weights

* [Pokemon R/B] Update patching process on client to verify hash
This commit is contained in:
Alchav
2022-12-11 14:51:28 -05:00
committed by GitHub
parent 6173bc6e03
commit 32820ba653
4 changed files with 127 additions and 76 deletions

View File

@@ -1,6 +1,7 @@
from typing import TextIO
import os
import logging
from copy import deepcopy
from BaseClasses import Item, MultiWorld, Tutorial, ItemClassification
from Fill import fill_restrictive, FillError, sweep_from_pool
@@ -62,6 +63,8 @@ class PokemonRedBlueWorld(World):
self.learnsets = None
self.trainer_name = None
self.rival_name = None
self.type_chart = None
self.traps = None
@classmethod
def stage_assert_generate(cls, world):
@@ -108,6 +111,69 @@ class PokemonRedBlueWorld(World):
process_pokemon_data(self)
if self.multiworld.randomize_type_chart[self.player] == "vanilla":
chart = deepcopy(poke_data.type_chart)
elif self.multiworld.randomize_type_chart[self.player] == "randomize":
types = poke_data.type_names.values()
matchups = []
for type1 in types:
for type2 in types:
matchups.append([type1, type2])
self.multiworld.random.shuffle(matchups)
immunities = self.multiworld.immunity_matchups[self.player].value
super_effectives = self.multiworld.super_effective_matchups[self.player].value
not_very_effectives = self.multiworld.not_very_effective_matchups[self.player].value
normals = self.multiworld.normal_matchups[self.player].value
while super_effectives + not_very_effectives + normals < 225 - immunities:
super_effectives += self.multiworld.super_effective_matchups[self.player].value
not_very_effectives += self.multiworld.not_very_effective_matchups[self.player].value
normals += self.multiworld.normal_matchups[self.player].value
if super_effectives + not_very_effectives + normals > 225 - immunities:
total = super_effectives + not_very_effectives + normals
excess = total - (225 - immunities)
subtract_amounts = (
int((excess / (super_effectives + not_very_effectives + normals)) * super_effectives),
int((excess / (super_effectives + not_very_effectives + normals)) * not_very_effectives),
int((excess / (super_effectives + not_very_effectives + normals)) * normals))
super_effectives -= subtract_amounts[0]
not_very_effectives -= subtract_amounts[1]
normals -= subtract_amounts[2]
while super_effectives + not_very_effectives + normals > 225 - immunities:
r = self.multiworld.random.randint(0, 2)
if r == 0:
super_effectives -= 1
elif r == 1:
not_very_effectives -= 1
else:
normals -= 1
chart = []
for matchup_list, matchup_value in zip([immunities, normals, super_effectives, not_very_effectives],
[0, 10, 20, 5]):
for _ in range(matchup_list):
matchup = matchups.pop()
matchup.append(matchup_value)
chart.append(matchup)
elif self.multiworld.randomize_type_chart[self.player] == "chaos":
types = poke_data.type_names.values()
matchups = []
for type1 in types:
for type2 in types:
matchups.append([type1, type2])
chart = []
values = list(range(21))
self.multiworld.random.shuffle(matchups)
self.multiworld.random.shuffle(values)
for matchup in matchups:
value = values.pop(0)
values.append(value)
matchup.append(value)
chart.append(matchup)
# sort so that super-effective matchups occur first, to prevent dual "not very effective" / "super effective"
# matchups from leading to damage being ultimately divided by 2 and then multiplied by 2, which can lead to
# damage being reduced by 1 which leads to a "not very effective" message appearing due to my changes
# to the way effectiveness messages are generated.
self.type_chart = sorted(chart, key=lambda matchup: -matchup[2])
def create_items(self) -> None:
start_inventory = self.multiworld.start_inventory[self.player].value.copy()
if self.multiworld.randomize_pokedex[self.player] == "start_with":
@@ -128,8 +194,7 @@ class PokemonRedBlueWorld(World):
item = self.create_item(location.original_item)
if (item.classification == ItemClassification.filler and self.multiworld.random.randint(1, 100)
<= self.multiworld.trap_percentage[self.player].value):
item = self.create_item(self.multiworld.random.choice([item for item in item_table if
item_table[item].classification == ItemClassification.trap]))
item = self.create_item(self.select_trap())
if location.event:
self.multiworld.get_location(location.name, self.player).place_locked_item(item)
elif "Badge" not in item.name or self.multiworld.badgesanity[self.player].value:
@@ -255,13 +320,21 @@ class PokemonRedBlueWorld(World):
def get_filler_item_name(self) -> str:
if self.multiworld.random.randint(1, 100) <= self.multiworld.trap_percentage[self.player].value:
return self.multiworld.random.choice([item for item in item_table if
item_table[item].classification == ItemClassification.trap])
return self.select_trap()
return self.multiworld.random.choice([item for item in item_table if item_table[
item].classification == ItemClassification.filler and item not in item_groups["Vending Machine Drinks"] +
item_groups["Unique"]])
def select_trap(self):
if self.traps is None:
self.traps = []
self.traps += ["Poison Trap"] * self.multiworld.poison_trap_weight[self.player].value
self.traps += ["Fire Trap"] * self.multiworld.fire_trap_weight[self.player].value
self.traps += ["Paralyze Trap"] * self.multiworld.paralyze_trap_weight[self.player].value
self.traps += ["Ice Trap"] * self.multiworld.ice_trap_weight[self.player].value
return self.multiworld.random.choice(self.traps)
def fill_slot_data(self) -> dict:
return {
"second_fossil_check_condition": self.multiworld.second_fossil_check_condition[self.player].value,