mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-13 16:04:58 +00:00
update 6.7
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class SecretBase
|
||||
attr_reader :outside_map_id #Id of the map where the secret base is
|
||||
attr_reader :inside_map_id #Id of the secret base's map itself
|
||||
|
||||
attr_reader :location_name #Name of the Route where the secret base is in plain text
|
||||
|
||||
|
||||
attr_reader :outside_entrance_position #Fly coordinates
|
||||
attr_reader :inside_entrance_position #Where the player gets warped
|
||||
|
||||
attr_reader :biome_type #:CAVE, :TREE,
|
||||
attr_reader :base_layout_type
|
||||
attr_accessor :base_name
|
||||
attr_accessor :base_message
|
||||
|
||||
attr_accessor :layout
|
||||
attr_accessor :is_visitor
|
||||
|
||||
|
||||
def initialize(biome:,outside_map_id:,outside_entrance_position:, inside_map_id:, base_layout_type:, is_visitor:, layout: nil, visitor_message:nil)
|
||||
@biome_type = biome
|
||||
@outside_map_id = outside_map_id
|
||||
@inside_map_id = inside_map_id
|
||||
|
||||
@outside_entrance_position = outside_entrance_position
|
||||
@base_layout_type = base_layout_type.to_sym
|
||||
|
||||
@inside_entrance_position = SecretBasesData::SECRET_BASE_ENTRANCES[@base_layout_type][:position]
|
||||
|
||||
@base_name=initializeBaseName
|
||||
@base_message=visitor_message
|
||||
initialize_base_message unless @base_message #Message that people see when visiting the secret base
|
||||
@is_visitor=is_visitor
|
||||
@layout = layout
|
||||
initializeLayout unless @layout
|
||||
end
|
||||
|
||||
def initializeBaseName
|
||||
return _INTL("{1}'s secret base",$Trainer.name)
|
||||
end
|
||||
|
||||
def initialize_base_message
|
||||
return _INTL("Welcome to my secret base!")
|
||||
end
|
||||
def initializeLayout
|
||||
@layout = SecretBaseLayout.new(@base_layout_type,!@is_visitor)
|
||||
entrance_x = @inside_entrance_position[0]
|
||||
entrance_y = @inside_entrance_position[1]
|
||||
|
||||
@layout.add_item(:PC,[entrance_x,entrance_y-3])
|
||||
end
|
||||
|
||||
def load_furniture
|
||||
@layout.items.each do |item_instance|
|
||||
next unless item_instance.is_a?(SecretBaseItemInstance)
|
||||
next unless SecretBasesData::SECRET_BASE_ITEMS[item_instance.itemId]
|
||||
|
||||
item_instance.direction = DIRECTION_DOWN
|
||||
|
||||
|
||||
template = item_instance.itemTemplate
|
||||
echoln template
|
||||
|
||||
|
||||
item_instance.create_events
|
||||
|
||||
# event = $PokemonTemp.createTempEvent(TEMPLATE_EVENT_SECRET_BASE_FURNITURE, $game_map.map_id, item_instance.position, DIRECTION_DOWN)
|
||||
# event.character_name = "player/SecretBases/#{template.graphics}"
|
||||
# event.through = template.pass_through
|
||||
# event.under_player = template.under_player
|
||||
# event.direction = item_instance.direction
|
||||
|
||||
|
||||
if item_instance.itemTemplate.id == :MANNEQUIN && @is_visitor
|
||||
setEventAppearance(item_instance.main_event.id, @trainer_appearance) if @trainer_appearance
|
||||
end
|
||||
# item_instance.setMainEventId(event.id)
|
||||
item_instance.refresh_events
|
||||
#event.refresh
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,172 @@
|
||||
# frozen_string_literal: true
|
||||
class SecretBaseItemInstance
|
||||
attr_reader :itemId
|
||||
attr_reader :instanceId
|
||||
attr_accessor :position
|
||||
attr_accessor :direction
|
||||
attr_accessor :itemTemplate
|
||||
attr_accessor :main_event_id
|
||||
attr_reader :disposed
|
||||
attr_reader :main_event
|
||||
|
||||
RANDOM_ID_LENGTH = 6
|
||||
|
||||
def initialize(itemId, position = [0, 0], direction = DIRECTION_DOWN)
|
||||
@itemId = itemId
|
||||
@instanceId = generate_new_instance_id()
|
||||
@direction = direction
|
||||
@position = position
|
||||
@main_event = nil # Objects that are wider or taller than 1 tile work by duplicating the object, but making only the middle instance visible. This contains the id of the middle instance
|
||||
end
|
||||
|
||||
def create_events()
|
||||
template = get_item_template
|
||||
@volume_events = []
|
||||
main_event = $PokemonTemp.createTempEvent(TEMPLATE_EVENT_SECRET_BASE_FURNITURE, $game_map.map_id, @position, @direction)
|
||||
main_event.character_name = "player/SecretBases/#{template.graphics}"
|
||||
main_event.through = template.pass_through
|
||||
main_event.under_player = template.under_player
|
||||
|
||||
main_event.trigger = template.trigger
|
||||
@main_event = main_event
|
||||
occupied_positions = calculate_occupied_volume_positions(@position)
|
||||
occupied_positions.each do |position|
|
||||
event = $PokemonTemp.createTempEvent(TEMPLATE_EVENT_SECRET_BASE_FURNITURE, $game_map.map_id, position)
|
||||
event.character_name = "player/SecretBases/empty" # Game will consider it passable if we don't put anything here
|
||||
event.through = template.pass_through
|
||||
event.trigger = template.trigger
|
||||
|
||||
@volume_events << event
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Use this - can't save it into the object because of proc
|
||||
def get_item_template
|
||||
return SecretBasesData::SECRET_BASE_ITEMS[@itemId]
|
||||
end
|
||||
|
||||
# fake accessor
|
||||
def itemTemplate
|
||||
return get_item_template
|
||||
end
|
||||
|
||||
def get_occupied_positions()
|
||||
occupied_positions = []
|
||||
occupied_positions << [@main_event.x, @main_event.y]
|
||||
@volume_events.each do |event|
|
||||
occupied_positions << [event.x, event.y]
|
||||
end
|
||||
return occupied_positions
|
||||
end
|
||||
|
||||
def interactable?(position = [0,0])
|
||||
return get_interactable_positions.include?(position)
|
||||
end
|
||||
|
||||
def get_interactable_positions()
|
||||
all_positions = get_occupied_positions
|
||||
uninteractable_positions = get_item_template.uninteractable_positions
|
||||
main_x, main_y = @main_event.x, @main_event.y
|
||||
|
||||
uninteractable_absolute_positions = uninteractable_positions.map do |dx, dy|
|
||||
[main_x + dx, main_y + dy]
|
||||
end
|
||||
interactable_positions = all_positions.reject do |pos|
|
||||
uninteractable_absolute_positions.include?(pos)
|
||||
end
|
||||
return interactable_positions
|
||||
end
|
||||
|
||||
def calculate_occupied_volume_positions(main_event_position)
|
||||
template = get_item_template
|
||||
|
||||
item_x, item_y = main_event_position
|
||||
item_height = template.height || 1
|
||||
item_width = template.width || 1
|
||||
direction = @direction
|
||||
|
||||
# Flip width/height if rotated sideways
|
||||
if direction == DIRECTION_LEFT || direction == DIRECTION_RIGHT
|
||||
item_width, item_height = item_height, item_width
|
||||
end
|
||||
|
||||
half_width = (item_width - 1) / 2
|
||||
half_height = (item_height - 1) / 2
|
||||
|
||||
occupied_positions = []
|
||||
|
||||
x_range = (item_x - half_width..item_x + half_width)
|
||||
y_range = (item_y - half_height..item_y + half_height)
|
||||
x_range.each do |x|
|
||||
y_range.each do |y|
|
||||
is_main_event = (x == item_x && y == item_y)
|
||||
next if is_main_event
|
||||
|
||||
occupied_positions << [x, y]
|
||||
end
|
||||
end
|
||||
return occupied_positions
|
||||
|
||||
end
|
||||
|
||||
def refresh_events
|
||||
@main_event.refresh
|
||||
@volume_events.each do |event|
|
||||
event.refresh
|
||||
end
|
||||
end
|
||||
|
||||
def name
|
||||
return itemTemplate&.real_name
|
||||
end
|
||||
|
||||
def getGraphics()
|
||||
return itemTemplate.graphics
|
||||
end
|
||||
|
||||
def height
|
||||
return itemTemplate.height
|
||||
end
|
||||
|
||||
def width
|
||||
return itemTemplate.width
|
||||
end
|
||||
|
||||
def generate_new_instance_id()
|
||||
randomId = rand(36 ** RANDOM_ID_LENGTH).to_s(36)
|
||||
return "#{@itemId}_#{randomId}"
|
||||
end
|
||||
|
||||
def getMainEvent()
|
||||
return @main_event
|
||||
end
|
||||
|
||||
def disposed?
|
||||
return @disposed
|
||||
end
|
||||
|
||||
def dispose
|
||||
@itemId = nil
|
||||
@position = nil
|
||||
@direction = nil
|
||||
@main_event_id = nil
|
||||
@itemTemplate = nil
|
||||
@disposed = true
|
||||
|
||||
@main_event.erase
|
||||
@main_event = nil
|
||||
@volume_events.each do |event|
|
||||
event.erase
|
||||
end
|
||||
@volume_events = nil
|
||||
end
|
||||
|
||||
def connect_to_other_instance(instance_id)
|
||||
@volume_events << instance_id
|
||||
end
|
||||
|
||||
def set_main_instance(instance_id)
|
||||
@main_event = instance_id
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,52 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# wrapper for secret base items
|
||||
|
||||
class SecretBaseItem
|
||||
attr_reader :id # Symbol. Used for manipulating in other classes (trainer.unlockedBaseItems is an array of these, etc.)
|
||||
attr_reader :graphics # File path to the item's graphics
|
||||
attr_reader :real_name # Name displayed in-game
|
||||
attr_reader :price
|
||||
|
||||
# Event attributes
|
||||
attr_reader :pass_through # for carpets, etc.
|
||||
attr_reader :under_player # for carpets, etc.
|
||||
|
||||
attr_reader :height
|
||||
attr_reader :width
|
||||
#todo: instead of this, have a 2d array that represents the layout visually and shows which tiles are interactable and which aren't
|
||||
# ex:
|
||||
# [
|
||||
# [[x],[x],[x]],
|
||||
# [[i],[i],[i]
|
||||
# ]
|
||||
# -> 2 rows, only interactable from the bottom
|
||||
|
||||
# Secret base object attributes
|
||||
attr_reader :deletable
|
||||
attr_reader :behavior # Lambda function that's defined when initializing the items. Some secret bases can have special effects when you interact with them (ex: a berry pot to grow berries, a bed, etc.)
|
||||
# -> This is the function that will be called when the player interacts with the item in the base.
|
||||
# Should just display flavor text for most basic items.
|
||||
attr_reader :uninteractable_positions #Positions at which the behavior won't trigger (relative to the center) ex: [[-1,0],[1,0]] in a 3x1 object will trigger in the center, but not on the sides
|
||||
attr_reader :trigger #Can define a different event trigger (Action Button by default)
|
||||
|
||||
def initialize(id:, graphics:, real_name:, price:, deletable: true, pass_through: false, under_player: false, behavior: nil, height:1, width:1, uninteractable_positions:[], trigger:TRIGGER_ACTION_BUTTON)
|
||||
@id = id
|
||||
@graphics = graphics
|
||||
@real_name = real_name
|
||||
@price = price
|
||||
@deletable = deletable
|
||||
@pass_through = pass_through
|
||||
@under_player = under_player
|
||||
|
||||
#Parts of the item that the player shouldn't be able to pass through
|
||||
@height = height
|
||||
@width = width
|
||||
|
||||
# Default behavior just shows text if none provided
|
||||
@behavior = behavior
|
||||
@uninteractable_positions = uninteractable_positions
|
||||
@trigger = trigger
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,81 @@
|
||||
class SecretBaseLayout
|
||||
attr_accessor :items #SecretBaseItemInstance
|
||||
attr_accessor :tileset #todo Reuse the same layouts map for all bases and change the tileset depending on the type
|
||||
attr_accessor :biome_type #:TREES, :CLIFF, :CLIFF_BEACH, :BUSH, etc. -> Determines which tiles are used in the base
|
||||
attr_accessor :is_player_base
|
||||
def initialize(layout_biome,is_player_base=false)
|
||||
@biome_type = layout_biome
|
||||
@items = []
|
||||
@is_player_base = is_player_base
|
||||
end
|
||||
|
||||
def add_item(itemId, position = [0, 0])
|
||||
new_item = SecretBaseItemInstance.new(itemId, position)
|
||||
@items << new_item
|
||||
return new_item.instanceId
|
||||
end
|
||||
|
||||
def get_item_at_position(position = [0,0])
|
||||
@items.each do |item|
|
||||
return item if item.get_occupied_positions.include?(position)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
def get_item_by_id(instanceId)
|
||||
@items.each do |item|
|
||||
return item if item.instanceId == instanceId
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
def remove_item_by_instance(instanceId)
|
||||
@items.each do |item|
|
||||
if item.instanceId == instanceId
|
||||
@items.delete(item)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
def remove_item_at_position(position = [0, 0])
|
||||
@items.each do |item|
|
||||
if item.position == position
|
||||
@items.delete(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# returns a list of ids of the items that are currently in the base's layout
|
||||
def list_items_instances()
|
||||
list = []
|
||||
@items.each do |item|
|
||||
list << item.instanceId
|
||||
end
|
||||
end
|
||||
|
||||
def get_all_occupied_positions()
|
||||
occupied_positions = []
|
||||
@items.each do |item|
|
||||
occupied_positions << get_occupied_positions_for_item(item)
|
||||
end
|
||||
return occupied_positions
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
def check_position_available_for_item(itemInstance,position)
|
||||
#placed_item_positions = get_all_occupied_positions
|
||||
item_occupied_positions = itemInstance.calculate_occupied_volume_positions(position)
|
||||
item_occupied_positions.each do |position|
|
||||
x, y = position
|
||||
#return false if placed_item_positions.include?(position)
|
||||
return false if !$game_map.passableStrict?(x, y, DIRECTION_ALL)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
class SecretBaseTrainer
|
||||
attr_accessor :name
|
||||
attr_accessor :nb_badges
|
||||
attr_accessor :game_mode
|
||||
attr_accessor :appearance #TrainerAppearance
|
||||
attr_accessor :team #Array of Pokemon
|
||||
|
||||
def initialize(name, nb_badges, game_mode, appearance, team)
|
||||
@name = name
|
||||
@nb_badges = nb_badges
|
||||
@game_mode = game_mode
|
||||
@appearance = appearance
|
||||
@team = team
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,52 @@
|
||||
class VisitorSecretBase < SecretBase
|
||||
attr_reader :trainer_name, :trainer_badges, :trainer_game_mode
|
||||
attr_reader :trainer_appearance, :trainer_team
|
||||
|
||||
def initialize(biome:, outside_map_id:, outside_entrance_position:, inside_map_id:, layout:, base_layout_type:, base_message:, trainer_data:)
|
||||
super(biome: biome,
|
||||
outside_map_id: outside_map_id,
|
||||
outside_entrance_position: outside_entrance_position,
|
||||
inside_map_id: inside_map_id,
|
||||
layout: layout,
|
||||
base_layout_type: base_layout_type,
|
||||
visitor_message: base_message,
|
||||
is_visitor: true,)
|
||||
|
||||
@trainer_name = trainer_data.name
|
||||
@trainer_badges = trainer_data.nb_badges || 0
|
||||
@trainer_game_mode = trainer_data.game_mode || 0
|
||||
@trainer_appearance = trainer_data.appearance
|
||||
@trainer_team = trainer_data.team
|
||||
end
|
||||
|
||||
def dump_info
|
||||
echoln "=== Visitor Secret Base ==="
|
||||
echoln "Biome: #{@biome_type}"
|
||||
echoln "Outside Map ID: #{@outside_map_id}"
|
||||
echoln "Inside Map ID: #{@inside_map_id}"
|
||||
echoln "Outside Entrance Position: #{@outside_entrance_position.inspect}"
|
||||
echoln "Inside Entrance Position: #{@inside_entrance_position.inspect}"
|
||||
echoln "Layout Type: #{@base_layout_type}"
|
||||
echoln "Base Name: #{@base_name}"
|
||||
echoln "Base Message: #{@base_message}"
|
||||
echoln "Visitor?: #{@is_visitor}"
|
||||
|
||||
echoln "--- Trainer Info ---"
|
||||
echoln "Name: #{@trainer_name}"
|
||||
echoln "Badges: #{@trainer_badges}"
|
||||
echoln "Game Mode: #{@trainer_game_mode}"
|
||||
echoln "Appearance: #{@trainer_appearance.inspect}"
|
||||
|
||||
echoln "--- Trainer Team ---"
|
||||
if @trainer_team && !@trainer_team.empty?
|
||||
@trainer_team.each_with_index do |pokemon, i|
|
||||
echoln " #{i + 1}. #{pokemon.name} (#{pokemon.species}, Lv#{pokemon.level})"
|
||||
end
|
||||
else
|
||||
echoln " (No Pokémon)"
|
||||
end
|
||||
|
||||
echoln "============================="
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user