mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-11 15:15:00 +00:00
274 lines
9.0 KiB
Ruby
274 lines
9.0 KiB
Ruby
|
|
TRAINER_CLASS_FAVORITE_TYPES =
|
|
{
|
|
AROMALADY: [:GRASS, :FAIRY],
|
|
BEAUTY: [:FAIRY, :WATER, :NORMAL, :GRASS],
|
|
BIKER: [:POISON, :DARK],
|
|
BIRDKEEPER: [:FLYING, :NORMAL],
|
|
BUGCATCHER: [:BUG],
|
|
BURGLAR: [:FIRE, :DARK],
|
|
CHANNELER: [:GHOST, :PSYCHIC],
|
|
CUEBALL: [:FIGHTING, :STEEL],
|
|
ENGINEER: [:ELECTRIC, :STEEL],
|
|
FISHERMAN: [:WATER],
|
|
GAMBLER: [:NORMAL, :PSYCHIC],
|
|
GENTLEMAN: [:NORMAL, :STEEL],
|
|
HIKER: [:ROCK, :GROUND],
|
|
JUGGLER: [:PSYCHIC, :GHOST, :NORMAL, :POISON],
|
|
LADY: [:FAIRY, :NORMAL],
|
|
PAINTER: [:NORMAL, :PSYCHIC, :GRASS],
|
|
POKEMANIAC: [:DRAGON, :GROUND],
|
|
POKEMONBREEDER: [:NORMAL, :GRASS],
|
|
PROFESSOR: [:NORMAL, :PSYCHIC],
|
|
ROCKER: [:ELECTRIC, :FIRE],
|
|
RUINMANIAC: [:GROUND, :ROCK, :PSYCHIC],
|
|
SAILOR: [:WATER, :FIGHTING],
|
|
SCIENTIST: [:ELECTRIC, :STEEL, :POISON],
|
|
SUPERNERD: [:ELECTRIC, :PSYCHIC, :STEEL],
|
|
TAMER: [:NORMAL, :DARK],
|
|
BLACKBELT: [:FIGHTING],
|
|
CRUSHGIRL: [:FIGHTING],
|
|
CAMPER: [:BUG, :NORMAL, :GRASS],
|
|
PICNICKER: [:GRASS, :NORMAL],
|
|
COOLTRAINER_M: [:DRAGON, :STEEL, :FIRE],
|
|
COOLTRAINER_F: [:ICE, :PSYCHIC, :FAIRY],
|
|
YOUNGSTER: [:NORMAL, :BUG, :GRASS, :FLYING],
|
|
LASS: [:NORMAL, :FAIRY],
|
|
POKEMONRANGER_M: [:GRASS, :GROUND],
|
|
POKEMONRANGER_F: [:GRASS, :WATER],
|
|
PSYCHIC_M: [:PSYCHIC, :GHOST],
|
|
PSYCHIC_F: [:PSYCHIC, :FAIRY],
|
|
SWIMMER_M: [:WATER, :ICE],
|
|
SWIMMER_F: [:WATER, :ICE],
|
|
SWIMMER2_M: [:WATER],
|
|
SWIMMER2_F: [:WATER],
|
|
TUBER_M: [:WATER],
|
|
TUBER_F: [:WATER],
|
|
TUBER2_M: [:WATER],
|
|
TUBER2_F: [:WATER],
|
|
COOLCOUPLE: [:FIRE, :ICE],
|
|
CRUSHKIN: [:FIGHTING],
|
|
SISANDBRO: [:WATER, :GROUND],
|
|
TWINS: [:FAIRY, :NORMAL],
|
|
YOUNGCOUPLE: [:NORMAL, :PSYCHIC],
|
|
SOCIALITE: [:FAIRY, :NORMAL],
|
|
BUGCATCHER_F: [:BUG],
|
|
ROUGHNECK: [:DARK, :FIGHTING],
|
|
TEACHER: [:PSYCHIC, :NORMAL],
|
|
PRESCHOOLER_M: [:NORMAL, :BUG],
|
|
PRESCHOOLER_F: [:FAIRY, :NORMAL],
|
|
HAUNTEDGIRL_YOUNG: [:GHOST],
|
|
HAUNTEDGIRL: [:GHOST, :DARK],
|
|
CLOWN: [:PSYCHIC, :FAIRY],
|
|
NURSE: [:NORMAL, :FAIRY],
|
|
WORKER: [:STEEL, :GROUND],
|
|
COOLTRAINER_M2: [:FIGHTING, :STEEL],
|
|
COOLTRAINER_F2: [:PSYCHIC, :ICE],
|
|
FARMER: [:GRASS, :GROUND, :NORMAL],
|
|
PYROMANIAC: [:FIRE],
|
|
KIMONOGIRL: [:FAIRY, :PSYCHIC, :GHOST],
|
|
SAGE: [:PSYCHIC, :GHOST],
|
|
PLAYER: [:ICE, :FIGHTING],
|
|
POLICE: [:DARK, :FIGHTING],
|
|
SKIER_F: [:ICE],
|
|
DELIVERYMAN: [:NORMAL],
|
|
}
|
|
|
|
#Higher values: pickier
|
|
TRAINER_CLASS_PICKINESS = {
|
|
AROMALADY: 1.8,
|
|
BEAUTY: 2.2,
|
|
BIKER: 1.2,
|
|
BIRDKEEPER: 1.4,
|
|
BUGCATCHER: 1.1,
|
|
BURGLAR: 1.3,
|
|
CHANNELER: 1.7,
|
|
CUEBALL: 1.3,
|
|
ENGINEER: 2.0,
|
|
FISHERMAN: 1.4,
|
|
GAMBLER: 1.5,
|
|
GENTLEMAN: 2.3,
|
|
HIKER: 1.5,
|
|
JUGGLER: 1.8,
|
|
LADY: 2.4,
|
|
PAINTER: 2.0,
|
|
POKEMANIAC: 1.6,
|
|
POKEMONBREEDER: 1.9,
|
|
PROFESSOR: 2.5,
|
|
ROCKER: 1.4,
|
|
RUINMANIAC: 1.5,
|
|
SAILOR: 1.3,
|
|
SCIENTIST: 2.0,
|
|
SUPERNERD: 1.9,
|
|
TAMER: 1.5,
|
|
BLACKBELT: 1.7,
|
|
CRUSHGIRL: 1.6,
|
|
CAMPER: 1.2,
|
|
PICNICKER: 1.2,
|
|
COOLTRAINER_M: 2.4,
|
|
COOLTRAINER_F: 2.4,
|
|
YOUNGSTER: 0.9,
|
|
LASS: 1.0,
|
|
POKEMONRANGER_M: 2.0,
|
|
POKEMONRANGER_F: 2.0,
|
|
PSYCHIC_M: 2.0,
|
|
PSYCHIC_F: 2.0,
|
|
SWIMMER_M: 1.0,
|
|
SWIMMER_F: 1.0,
|
|
SWIMMER2_M: 1.0,
|
|
SWIMMER2_F: 1.0,
|
|
TUBER_M: 0.8,
|
|
TUBER_F: 0.8,
|
|
TUBER2_M: 0.8,
|
|
TUBER2_F: 0.8,
|
|
COOLCOUPLE: 2.1,
|
|
CRUSHKIN: 1.7,
|
|
SISANDBRO: 1.3,
|
|
TWINS: 1.0,
|
|
YOUNGCOUPLE: 1.6,
|
|
SOCIALITE: 2.3,
|
|
BUGCATCHER_F: 1.1,
|
|
ROUGHNECK: 1.4,
|
|
TEACHER: 2.0,
|
|
PRESCHOOLER_M: 0.6,
|
|
PRESCHOOLER_F: 0.6,
|
|
HAUNTEDGIRL_YOUNG: 1.3,
|
|
HAUNTEDGIRL: 1.7,
|
|
CLOWN: 1.5,
|
|
NURSE: 2.0,
|
|
WORKER: 1.6,
|
|
COOLTRAINER_M2: 2.4,
|
|
COOLTRAINER_F2: 2.4,
|
|
FARMER: 1.5,
|
|
PYROMANIAC: 1.6,
|
|
KIMONOGIRL: 2.2,
|
|
SAGE: 2.1,
|
|
PLAYER: 1.0,
|
|
POLICE: 1.8,
|
|
SKIER_F: 1.6,
|
|
DELIVERYMAN: 1.3
|
|
}
|
|
|
|
|
|
def evaluate_pokemon_worth(pkmn, compare_level: nil)
|
|
species_data = pkmn.species_data
|
|
return 0 unless species_data
|
|
|
|
level = pkmn.level
|
|
level_diff = compare_level ? (level - compare_level) : 0
|
|
level_score = level * 2 + [level_diff, 0].max * 1.5 # bonus if player's level is higher
|
|
|
|
base_stats_score = species_data.base_stats.values.sum / 10.0
|
|
rarity_score = (255 - species_data.catch_rate) / 5.0
|
|
iv_score = (pkmn.iv&.values&.sum || 0) / 4.0
|
|
shiny_score = pkmn.shiny? ? 50 : 0
|
|
fusion_bonus = pkmn.isFusion? ? 40 : 0
|
|
|
|
score = level_score +
|
|
base_stats_score +
|
|
rarity_score +
|
|
iv_score +
|
|
shiny_score +
|
|
fusion_bonus
|
|
|
|
echoln("#{pkmn.name} - Score : #{score}")
|
|
return score
|
|
end
|
|
|
|
|
|
|
|
def offerPokemonForTrade(player_pokemon, npc_party, trainer_class)
|
|
player_score = evaluate_pokemon_worth(player_pokemon)
|
|
pickiness = TRAINER_CLASS_PICKINESS[trainer_class] || 1.0
|
|
|
|
# Evaluate all NPC Pokémon scores
|
|
npc_scores = npc_party.map do |npc_pkmn|
|
|
[npc_pkmn, evaluate_pokemon_worth(npc_pkmn, compare_level: player_pokemon.level)]
|
|
end
|
|
best_npc_pokemon, best_score = npc_scores.max_by { |_, score| score }
|
|
return best_npc_pokemon if player_score > best_score
|
|
|
|
max_difference = [player_score, 100].min * pickiness
|
|
candidates = npc_scores.select do |npc_pkmn, npc_score|
|
|
(npc_score - player_score).abs <= max_difference
|
|
end
|
|
|
|
return nil if candidates.empty?
|
|
candidates.min_by do |_, npc_score|
|
|
(npc_score - player_score).abs
|
|
end.first
|
|
end
|
|
|
|
def doNPCTrainerTrade(trainer)
|
|
echoln trainer.getTimeSinceLastTrade
|
|
if trainer.isNextTradeReady?
|
|
pbMessage(_INTL("The trainer is not ready to trade yet. Wait a little bit before you make your offer."))
|
|
return trainer
|
|
end
|
|
return generateTrainerTradeOffer(trainer)
|
|
end
|
|
|
|
#prefered type depends on the trainer class
|
|
#
|
|
def generateTrainerTradeOffer(trainer)
|
|
bg_image_id=20
|
|
wanted_type = trainer.favorite_type
|
|
wanted_type = :NORMAL if !wanted_type
|
|
|
|
wanted_type_name = GameData::Type.get(wanted_type).real_name
|
|
trainerClassName = GameData::TrainerType.get(trainer.trainerType).real_name
|
|
pbMessage(_INTL("#{trainerClassName} #{trainer.trainerName} is looking for \\C[1]#{wanted_type_name}-type Pokémon\\C[0]. Which Pokémon do you want to trade?."),)
|
|
pbChoosePokemon(1,2,
|
|
proc {|pokemon|
|
|
pokemon.hasType?(wanted_type)
|
|
})
|
|
|
|
chosen_index = pbGet(1)
|
|
echoln pbGet(1)
|
|
if chosen_index && chosen_index >= 0
|
|
chosen_pokemon = $Trainer.party[chosen_index]
|
|
offered_pokemon = offerPokemonForTrade(chosen_pokemon,trainer.currentTeam,trainer.trainerType)
|
|
if !offered_pokemon
|
|
pbMessage(_INTL("#{trainerClassName} #{trainer.trainerName} does not want to trade..."))
|
|
return trainer
|
|
end
|
|
|
|
pif_sprite = BattleSpriteLoader.new.get_pif_sprite_from_species(offered_pokemon.species)
|
|
pif_sprite.dump_info()
|
|
|
|
message = _INTL("#{trainerClassName} #{trainer.trainerName} is offering #{offered_pokemon.name} (Level #{offered_pokemon.level}) for your #{chosen_pokemon.name}.")
|
|
showPokemonInPokeballWithMessage(pif_sprite, message)
|
|
|
|
if pbConfirmMessage(_INTL("Trade away #{chosen_pokemon.name} for #{trainerClassName} #{trainer.trainerName}'s #{offered_pokemon.name}?"))
|
|
pbStartTrade(chosen_index, offered_pokemon,offered_pokemon.name,trainer.trainerName,0)
|
|
updated_party = trainer.currentTeam
|
|
updated_party.delete(offered_pokemon)
|
|
updated_party << chosen_pokemon.clone
|
|
trainer.previous_trade_timestamp= Time.now
|
|
trainer.increase_friendship(20)
|
|
return trainer
|
|
end
|
|
end
|
|
return trainer
|
|
|
|
#todo
|
|
#
|
|
# NPC says "I'm looking for X or Y tyflpe Pokemon (prefered Pokemon can be determined when initializing from a pool of types that depends on the trainer class)
|
|
# Also possible to pass a list of specific Pokemon in trainers.txt that the trainer will ask for instead if it's defined
|
|
#
|
|
# you select one of your Pokemon and he gives you one for it
|
|
# prioritize recently caught pokemon
|
|
# prioritive weaker Pokemon
|
|
#
|
|
#Assign a score to each Pokemon in trainer's team. calculate the same score for trainer's pokemon - select which
|
|
# one is closer
|
|
#
|
|
# NPC says "I can offer A in exchange for your B.
|
|
# -Yes -> Trade, update trainer team to put the player's pokemon in there
|
|
# Cannot trade again with the same trainer for 5 minutes
|
|
# "You just traded with this trainer. Wait a bit before you make another offer
|
|
# -No
|
|
trainer.set_pending_action(false) if trainer
|
|
return trainer
|
|
end
|