Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ##=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- # CARDGAME SKILL/BATTLE SYSTEM
- # Author: pencilcase27
- # Version: v1.09
- #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- # v1.00 - Script released
- # v1.01 - Added stack, skills now can't revive themself.
- # - Added CardHelp_Window, normal help window is no longer used to draw cards
- # - Item Window is back to normal
- # v1.02 - reworked card effects
- # - added deck count and toggle actor to deck build scene
- # - simplified scriptcalls to add and remove cards from collection
- # - Added max_card limit exception
- # v1.03 - reworked card effects (again)
- # - added card cost effects
- # - added custom images
- # v1.04 - added more script calls
- # - changed card costs slightly
- # - bugfixes
- # v1.05 - bugfixes
- # v1.06 - added initial decks for actors
- # v1.07 - fixed a bug with item canceling
- # - fixed a bug with the draw card effect
- # v1.08 - added Attack and Guard command
- # - added two notetags for equip
- # v1.09 - fixed an issue with attack and guard
- # - added limitations on how many cards can be played each turn
- # - added a feature to instantly empty your deck
- #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- #
- # Description
- #
- # This script changes the way actors aquire and use skills. Instead of each
- # actor having an own set of skills, the party now has a card collection of
- # different cards, each card representing a skill. Out of this collection, each
- # actor can now create a custom deck.
- # In battle, actors will act in turns. They draw cards and, while an actor is
- # active, he can play as many cards and items as he wants, as long as he has
- # the recources to do so. Once he is done, he can end his turn and the next
- # actor becomes active. When every actor finished his or her turn, the enemys
- # use their skills normal.
- #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- #
- # Script Calls
- #
- # add_card_to_coll(id1, id2, id3, ...)
- # Adds cards of the given skill ids to your collection
- #
- # remove_card?(id)
- # Tries to remove a single card of the given skill id from your collection.
- # Returns true if successfull and false otherwise.
- #
- # remove_all_cards(id1, id2, ...)
- # Removes all cards of the given skill ids from both the players decks and
- # from the collection
- #
- # has_card?(id)
- # Checks if the player has a specific card in his collection or in his deck
- #
- # has_card_in_deck?(id)
- # Checks if the player has a specific card in his deck
- #
- # has_card_in_grave?(id)
- # Checks if the player has a specific card in his graveyard
- #
- # has_x_cards_in_grave?(id, count)
- # Checks if the player has a specific cards in his graveyard
- #
- # has_card_in_banish?(id)
- # Checks if the player has a specific card in his banish
- #
- # has_x_cards_in_banish?(id, count)
- # Checks if the player has a specific cards in his banish
- #
- # has_card_in_hand?(id)
- # Checks if the player has a specific card in his hand
- #
- # add_card_deck(id1, id2, id3, ...)
- # Adds cards of the given skill ids to the designed actor deck
- #
- # remove_card_deck(id1, id2, id3, ...)
- # Remove cards of the given skill ids to the designed actor deck
- #
- # add_card_hand(id1, id2, id3, ...)
- # Adds cards of the given skill ids to the designed actor hand
- #
- # remove_card_hand(id1, id2, id3, ...)
- # Remove cards of the given skill ids to the designed actor hand
- #
- # count_actor_deck(id)
- # Returns the amount of cards in this actors deck
- #
- # count_all_decks
- # Returns the combined deck size of all actors
- #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- #
- # Skill Notetags
- #
- # <card id: x>
- # The card id of the skill. Each card must have a unique id.
- # Important: Every time this script uses the word id, it refers to the skills
- # id, not the card id! The card id is only used to sort cards.
- #
- # <card type: x>
- # The type of the card. Different types can be defined below.
- #
- # <card rarity: x>
- # The rarity of the card. Different raritys can be defined below.
- #
- # <card cost: effect_name>
- # Adds the given cost effect to the card. Please read about card effects
- # down below.
- #
- # <card impact: effect_name>
- # Adds the given impact effect to the card. Please read about card effects
- # down below.
- #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- #
- # Armor/Weapon Notetags
- #
- # <extra start cards: x>
- # Draws x extra cards at the begin of each battle
- #
- # <extra turn cards: x>
- # Draws x extra cards at the begin of each turn
- #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- #
- # Damage Formula
- #
- # Those commands can be used for a skills damage formula. Make sure they
- # always target an actor, since they won't have any effect on enemys. Minor
- # scripting knowlegde is required to make the most out of those methods.
- #
- # a/b.revive_grave(true/false)
- # Shuffles your grave in your deck without penalty. If the argumet is true,
- # a message will be shown.
- #
- # a/b.revive_penalty
- # Causes the revive penalty to happen.
- #
- # a/b.shuffle_deck(true/false)
- # Shuffles the actors deck. If the argument is true, a sound will be played.
- #
- # a/b.card_to_grave?(skill_id)
- # Tries to throw the skill with the given ID to the grave. Returns true, if it's
- # successfull and false otherwise.
- #
- # a/b.throw_cards(n)
- # Throws n random cards to the grave. If n = 0, the actor will loose all cards.
- # Returns how many cards were thrown away.
- #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- #
- # Card Effects
- #
- # Card effects are special, card related effects like "draw x cards" or
- # "discard a fire spell to play this card" or "look at the top 5 cards of your
- # deck and put them back in any order". Every card effect can be played both as
- # a card cost or as a card impact. Costs are handled before the player plays the
- # cards, impacts after.
- # To set up a card effect, scroll to the end of Options where you will find an
- # option called CARD_EFFECT. There you can add a effect name and the effects
- # arguments. Then add the effect either as cost or as impact via note tag to
- # a skill.
- # Each skill can have one cost effect and one impact effect.
- # Each item can have one impact effect.
- # WARNING: This is not trivial. Read carefully!
- #
- # Type: Draw
- # Simply draws cards
- # "effect_name" => [:draw, a, b, c]
- # a -> how many cards do you want to draw?
- # b -> chance the effect is successfull (between 0 and 100)
- # c -> :self to make only the user draw a card, :target to apply the effect to
- # each target.
- # Example:
- # "draw2" => [:draw, 2, 100, :self]
- # -> The user of this skill will draw 2 cards.
- #
- # Type: View (impact only)
- # Looks at a certain number of cards taken from location a, and then puts them
- # back to location b. Locations can be :deck, :hand and :grave.
- # "effect_name" => [ :view, a, b, c]
- # a -> how many cards do you want to view? 0 for the entire location.
- # b -> from where do you want to take those cards?
- # c -> where do you want to put them when you're done?
- # Example:
- # "view_effect" => [:view, 10, :deck, :deck]
- # -> look at the top 10 cards of your deck.
- #
- # Type: Sort
- # Same as view but allows to sort the cards.
- # Example:
- # "stupid_effect" => [:sort, 0, :hand, :deck]
- # -> Put your entire hand ontop of your deck in any order.
- #
- # Type: Take
- # This one is a little bit harder. It allows to take some of the viewed cards
- # from one location to another.
- # "effect_name" => [:take, a, b, c, d, e, f]
- # a, b, c -> same as above
- # d -> filter that determines which cards can be choosen,
- # [element_id, type_id, rarity_id], 0 for all id's allowed.
- # e -> the location to put the choosen cards.
- # f -> how many cards can be choosen.
- # Example:
- # "search_for_element2" => [:take, 0, :deck, :deck, [2,0,0], :hand, 1]
- # -> Search your deck for one card of element 2 and take it to your hand.
- # Another Example:
- # "discard_cost" => [:take, 0, :hand, :hand, [0,0,0], :grave, 2]
- # -> If this is added as a cost effect, the player has to discard two cards
- # from his or her hand to play this card.
- #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- module PC27
- module CG
- #-------------------------------------------------------------------------------
- #
- # Options
- #
- #-------------------------------------------------------------------------------
- #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- # Vocab
- #------------------------------------------------------------------------------
- # DECK - Name of the actors Deck
- # GRAVE - Name of the actors Grave
- # COLLECTION - Name of the Card Collection
- # END_TURN - Name of the command that will end a players turn
- # DRAW_MESSAGE - Text that appears when an actor draws a card. Displayed
- # as "Actor Name" + DRAW_MESSAGE + "Skill Name"
- # REVIVE_MSG - Text that appears when you revive your grave
- # CARD_HELP_WINDOW - Help text shown in the deck scene (Use \n to break line)
- # FILTER_TEXT - First part of the text inside of the filter window
- # F_... - Second part of the text inside of the filter window
- # EMPTY_DECK - Text in filter window that allows to empty the entire deck
- # CONFIRM - Confirmation for EMPTY_DECK
- # CARD_EFF_TEXT - Text displayed when a card effect is evaluated.
- #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- DECK = "Deck"
- GRAVE = "Grave"
- BANISH = "Banish"
- EXTRA = "Extra"
- FIELD = "Field"
- COLLECTION = "Collection"
- END_TURN = "End"
- DRAW_MESSAGE = "draws:"
- REVIVE_MSG = "'s deck was restored!"
- CARD_HELP_WINDOW = "(Z): Move card\n(A): Open filter\n(Shift): Change between\nMain/Extra Deck"
- FILTER_TEXT = "Filter by "
- F_ELEMENT = "Attribute: "
- F_TYPE = "Type: "
- F_RARITY = "Rarity: "
- F_SUBTYPE = "Sub Type: "
- F_LEVEL = "Level: "
- EMPTY_DECK = "Clean Deck"
- CONFIRM = "Are you sure?"
- CARD_EFF_TEXT = "Choose the cards:"
- #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- # Gameplay
- #------------------------------------------------------------------------------
- # USE_ATTACK - Enables the regular attack command in battle.
- # USE_GUARD - Enables the regular guard command in battle.
- # USE_ITEMS - Are items in battle enabeld?
- # START_CARDS - Cards drawn in Turn 1
- # MAX_DECK_SIZE - Maximum size of a players deck
- # MAX_SAME_CARDS - Maximum amount of same cards in each deck
- # MAX_ACTIONS - Maximum amount of cards an actor can use each turn
- # DECK_EMPTY - What happens if an actor tries to draw a card but has an
- # empty deck?
- # 1 -> The actor dies
- # 2 -> The actor dies if his grave is empty, too. If it
- # isn't, he revives his grave, meaning he shuffles his
- # grave back into his deck. Revive penalty is applied
- # 3 -> Like 2, but the actor won't die if the grave is empty
- # REVIVE_PENALTY - The revive penalty. Types are :hp, :mhp, :mp and :mmp.
- # The actor will lose either hp or mp, based on its current
- # or maximum value
- # MAX_SAME_EXCEP - Exceptions to MAX_SAME_CARDS
- #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- USE_ATTACK = true
- USE_GUARD = true
- USE_ITEMS = true
- START_CARDS = 5
- MONSTER_ZONE_COUNT = 3
- SPELL_TRAP_ZONE_COUNT = 3
- MAX_DECK_SIZE = 60
- MIN_DECK_SIZE = 39
- MAX_EXTRA_SIZE = 15
- MAX_SAME_CARDS = 3
- MAX_ACTIONS = 0 # if this is 0, an actor can play infinite cards
- # (until he's out of mana or cards)
- DECK_EMPTY = 1
- # [percent, type]
- REVIVE_PENALTY = [ 50, :hp]
- MAX_SAME_EXCEP = {
- # skill id => max. amount,
- 67 => 1,
- 45 => 1,
- #7 => 1,
- } # do not remove this
- #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- # Icons and Sound
- #------------------------------------------------------------------------------
- # DRAW_SOUND - Sound that will play when you draw a card
- # PENALTY_SOUND - Sound that will play when the revive penalty is applied
- # DECK_ICON - Icon that displays an actors deck size in battle
- #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- # ["filename", volume, pitch] -> ["", 0, 0] means no sound
- DRAW_SOUND = [ "draw", 100, 150]
- PENALTY_SOUND = [ "Attack1", 100, 50]
- DECK_ICON = 804
- #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- # Cards
- #------------------------------------------------------------------------------
- # To add custom card images, add an image with the name Card + skill id to your
- # graphics folder (example: Card2). The script will use every picture it can
- # find. Card0 is used when no card is selected. If you choose to do this, most
- # of those options are irrelevant.
- #
- # CUSTOM_CARD_BG - Name of the windowskin used for cards (in Graphics/System)
- # CARD_BACK_OP - Background opacity of cards (0-255)
- # CARD_NAME_UP - If true, card names will be written in capital letters
- # MP_COLOR - Textcolor the mana costs are drawn in
- # TP_COLOR - Textcolor the tp costs are drawn in
- # RARITY - Name and icon index of the raritys your cards have
- # TYPES - Different types your cards can have
- # ELEMENT_COLOR - Background color of your cards based on their element ID
- #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- CUSTOM_CARD_BG = "Window" # RPG Maker default is "Window"
- CARD_BACK_OP = 255
- CARD_NAME_UP = true
- MP_COLOR = 4
- TP_COLOR = 3
- RARITY = {
- # ID => [ icon, "name"]
- 1 => [ 798, "Normal"],
- 2 => [ 797, "Rare"],
- 3 => [ 796, "Super Rare"],
- 4 => [ 795, "Ultra Rare"],
- } # do not remove this
- SUBTYPE = {
- # ID => [ icon, "name"]
- 1 => [ 896, "Dragon"],
- 2 => [ 897, "Zombie"],
- 3 => [ 898, "Fiend"],
- 4 => [ 899, "Pyro"],
- 5 => [ 900, "Sea-Serpent"],
- 6 => [ 901, "Rock"],
- 7 => [ 902, "Machine"],
- 8 => [ 903, "Fish"],
- 9 => [ 904, "Dinosaur"],
- 10 => [ 905, "Insect"],
- 11 => [ 906, "Beast"],
- 12 => [ 907, "Beast-Warrior"],
- 13 => [ 908, "Plant"],
- 14 => [ 909, "Aqua"],
- 15 => [ 910, "Warrior"],
- 16 => [ 911, "Winged-Beast"],
- 17 => [ 912, "Fairy"],
- 18 => [ 913, "Spellcaster"],
- 19 => [ 914, "Thunder"],
- 20 => [ 915, "Reptile"],
- 21 => [ 916, "Psychic"],
- 22 => [ 917, "Wyrm"],
- 23 => [ 918, "Divine-Beast"],
- 24 => [ 913, "Normal Spell"],
- 25 => [ 914, "Quick-Play Spell"],
- 26 => [ 915, "Continuous Spell"],
- 27 => [ 916, "Field Spell"],
- 28 => [ 917, "Equip Spell"],
- 29 => [ 918, "Normal Trap"],
- 30 => [ 917, "Continuous Trap"],
- 31 => [ 918, "Counter Trap"],
- } # do not remove this
- LEVEL = {
- # ID => [ icon, "name"]
- 1 => [ 803, "Level 1"],
- 2 => [ 803, "Level 2"],
- 3 => [ 803, "Level 3"],
- 4 => [ 803, "Level 4"],
- 5 => [ 803, "Level 5"],
- 6 => [ 803, "Level 6"],
- 7 => [ 803, "Level 7"],
- 8 => [ 803, "Level 8"],
- 9 => [ 803, "Level 9"],
- 10 => [ 803, "Level 10"],
- 11 => [ 803, "Level 11"],
- 12 => [ 803, "Level 12"],
- } # do not remove this
- NORMEFF = {
- # ID => [ icon, "name"]
- 1 => [ 803, "None"],
- 2 => [ 803, "Effect"],
- 3 => [ 803, "Normal"],
- } # do not remove this
- FRAME = {
- # ID => [ icon, "name"]
- 1 => [ 803, "Fusion"],
- 2 => [ 803, "Synchro"],
- 3 => [ 803, "Ritual"],
- 4 => [ 803, "Tuner"],
- 5 => [ 803, "Token"],
- 6 => [ 803, "Normal"],
- 7 => [ 803, "Effect"],
- } # do not remove this
- ARCHETYPE = {
- # ID => [ icon, "name"]
- 1 => [ 803, "X-Saber"],
- 2 => [ 803, "Ice Barrier"],
- 3 => [ 803, "Mist Valley"],
- 4 => [ 803, "Flamvell"],
- 5 => [ 803, "Dragunity"],
- 6 => [ 803, "Gishki"],
- 7 => [ 803, "Dragunity"],
- 8 => [ 803, "Jurrac"],
- 9 => [ 803, "Worm"],
- 10 => [ 803, "Fabled"],
- 11 => [ 803, "Polymerization"],
- 12 => [ 803, "Kuriboh"],
- 13 => [ 803, "Dark World"],
- 14 => [ 803, "Jurassic World"],
- 15 => [ 803, "Evolution Pill"],
- } # do not remove this
- SPECIAL = {
- # ID => [ icon, "name"]
- 1 => [ 782, "Exodia"],
- 2 => [ 782, "Thunder Dragon"],
- 3 => [ 782, "Consonance"],
- 4 => [ 782, "exceptjarofavarice"],
- 5 => [ 782, "non-Effect"],
- 6 => [ 782, "Normal"],
- 7 => [ 782, "knowledge"],
- } # do not remove this
- TYPE = {
- # ID => "name"
- 1 => "Spell",
- 2 => "Trap",
- 3 => "Monster",
- 4 => "Extra",
- } # do not remove this
- ELEMENT_COLOR = {
- # ID => [red, grn, blu]
- 0 => [ 0, 0, 0], # 0 is used for skills without an element
- 1 => [200, 0, 100],
- 2 => [200, 0, 0],
- 3 => [200, 200, 0],
- 4 => [ 0, 0, 200],
- 5 => [ 0, 0, 200],
- 6 => [ 0, 0, 200],
- 7 => [ 0, 0, 200],
- 8 => [ 0, 0, 200],
- 9 => [ 0, 0, 200],
- } # do not remove this
- #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- # Start Decks
- #------------------------------------------------------------------------------
- # Those are the initial decks for each actor. If an actors id is not listed
- # below, his initial deck will be empty.
- #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- START_DECKS = {
- 1 => [],
- 22 => [72,72,72,68,68,68,56,56,56,38,38,38,51,51,51,28,28,28,30,30,30,36,36,36,114,114,114,254,254,254,256,256,256,255,255,255,257,257,257,258,258,258,259,259,259,260,260,260,262,262,262,263,263,264,264,264],
- 12 => [29,29,29,26,26,26,27,27,114,114,114,254,254,254,256,256,256,255,255,255,257,257,257,258,258,258,259,259,259,260,260,260,262,262,262,263,263,264,264,264],
- 14 => [29,29,29,26,26,26,27,27,114,114,114,254,254,254,256,256,256,255,255,255,257,257,257,258,258,258,259,259,259,260,260,260,262,262,262,263,263,264,264,264],
- 6 => [29,29,29,26,26,26,27,27,114,114,114,254,254,254,256,256,256,255,255,255,257,257,257,258,258,258,259,259,259,260,260,260,262,262,262,263,263,264,264,264],
- 15 => [21,21,21,205,205,205,195,195,195,193,193,193,188,189,190,191,192],
- 16 => [186,186,186,186,186,186,186,186,186,186,186,101,101,101,112,189,190,191,192,74,74,74,193,193,193],
- 17 => [186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,188,189,190,191,192,74,74,74,193,193,193],
- 18 => [186,186,186,186,186,186,186,186,186,186,186,186,186,186,193,193,193,74,74,74],
- 19 => [21,21,21,205,205,205,195,195,195,193,193,193,188,189,190,191,192],
- 20 => [186,186,186,186,186,186,186,186,186,186,186,101,101,101,112,189,190,191,192,74,74,74,193,193,193],
- 21 => [186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,188,189,190,191,192,74,74,74,193,193,193],
- 23 => [186,186,186,186,186,186,186,186,186,186,186,186,186,186,193,193,193,74,74,74],
- 24 => [21,21,21,205,205,205,195,195,195,193,193,193,188,189,190,191,192],
- 25 => [186,186,186,186,186,186,186,186,186,186,186,101,101,101,112,189,190,191,192,74,74,74,193,193,193],
- } # do not remove this
- #------------------------------------------------------------------------------
- # The first effect called "grave" is available as a command in battle and
- # usually used to view your grave. You can change this effect if you wish, but
- # keep in mind that the player can use this effect as many times as he wants.
- # Please add all other effects below. Do not forget that every effect needs its
- # own name. You can name them however you want, as long as you dont use the
- # same name twice.
- #[Attritube, Type, Rarity, Subtype, Level, Normal/Effect, Frame, Archetype, ATK, DEF, Special]
- #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- CARD_EFFECT = {
- "grave" => [:view, 0, :grave, :grave], # Grave command effect
- "banish" => [:view, 0, :banish, :banish], # Banish command effect
- "extra" => [:view, 0, :extra, :extra], # Extra command effect
- "field" => [:view, 0, :field, :field], # Extra command effect
- "senditself" => [:cost, 1, :none, :none, nil, :grave],
- "none" => [:none],
- "draw1" => [:draw, 1, 100, :self],
- "draw2" => [:draw, 2, 100, :self],
- "draw3" => [:draw, 3, 100, :self],
- "draw4" => [:draw, 4, 100, :self],
- "draw5" => [:draw, 5, 100, :self],
- "draw6" => [:draw, 6, 100, :self],
- "destroyitself" => [:destroy_active_card],
- "exodia" => [:take, 0, :hand, :hand, [0,0,0,0,0,0,0,0,0,0,1], :grave, 4],
- "discard1" => [:takem, 0, :hand, :hand, [0,0,0,0,0,0,0,0,0,0,0], :grave, 1],
- "discard2" => [:takem, 0, :hand, :hand, [0,0,0,0,0,0,0,0,0,0,0], :grave, 2],
- "discard5" => [:take, 0, :hand, :hand, [0,0,0,0,0,0,0,0,0,0,0], :grave, 5],
- "kujikuri" => [:take, 0, :hand_or_field, :hand_or_field, [0,0,0,0,9,0,0,0,0,0,0], :grave, 1],
- "discardhand" => [:takem, 0, :hand, :hand, [0,0,0,0,0,0,0,0,0,0,0], :grave, 0],
- "disc1monst" => [:take, 0, :hand, :hand, [0,3,0,0,0,0,0,0,0,0,0], :grave, 1],
- "disc3monst" => [:take, 0, :hand, :hand, [0,3,0,0,0,0,0,0,0,0,0], :grave, 3],
- "dealings" => [:draw, 1, 100, :self, "discard1"],
- "beginning" => [:takem, 0, :grave,:grave, [5,0,0,0,0,0,0,0,0,0,0], :banish, 5],
- "allure" => [:takem, 0, :hand, :hand, [5,3,0,0,0,0,0,0,0,0,0], :banish, 1],
- "avarice" => [:takem, 0, :grave, :grave, [0,3,0,0,0,0,0,0,0,0,0], :deck, 5],
- "shuffle1" => [:take, 0, :hand, :hand, [0,0,0,0,0,0,0,0,0,0,0], :deck, 1],
- "jaravarice" => [:take, 0, :grave, :grave, [0,0,0,0,0,0,0,0,0,0,0, :exclude_active], :deck, 5],
- "moray" => [:take, 0, :hand, :hand, [4,3,0,0,0,0,0,0,0,0,0], :deck, 2],
- "duality" => [:takem, 3, :deck, :deck, [0,0,0,0,0,0,0,0,0,0,0], :hand, 1],
- "prosperity" => [:takem, 6, :deck, :deck, [0,0,0,0,0,0,0,0,0,0,0], :hand, 1],
- "discardlv8" => [:take, 0, :hand, :hand, [0,0,0,0,8,0,0,0,0,0,0], :grave, 1],
- "consonance" => [:take, 0, :hand, :hand, [0,0,0,1,0,0,4,0,0..1000,0,0], :grave, 1],
- "cardsky" => [:takem, 0, :hand, :hand, [6,3,0,17,0,0,0,0,0,0,0], :banish, 1],
- "addlv1" => [:takem, 0, :deck, :deck, [0,3,0,0,1,0,0,0,0,0,0], :hand, 1],
- "teleport" => [:take, 0, :deck, :deck, [0,3,0,21,1..3,0,0,0,0,0,0], :field, 1],
- "desires" => [:auto, 10, :deck, :deck, [0,0,0,0,0,0,0,0,0,0,0], :banish, :face_down, 10],
- "acqui" => [:take, 0, :banish, :banish, [0,3,0,0,0,0,0,0,0,0,0], :deck, 3],
- "7sword" => [:take, 0, :hand_or_field, :hand_or_field, [0,3,0,0,7,0,0,0,0,0,0], :banish, 1],
- "elephant" => [:take, 0, :hand, :hand, [0,3,0,0,0,3,0,0,0,0,0], :grave, 1],
- "banish1normal" => [:take, 0, :hand, :hand, [0,3,0,0,0,3,0,0,0,0,0], :banish, 1],
- "knowledge" => [:take, 0, :hand, :hand, [0,3,0,18,0,0,0,0,0,0,0], :grave, 1],
- "brightf" => [:take, 0, :banish, :banish, [0,0,3,21,0,0,0,0,0,0,0], :grave, 2],
- "overload" => [:take, 0, :grave, :grave, [0,0,0,21,0,0,0,0,0,0,0], :deck, 3],
- "backup" => [:take, 0, :grave, :grave, [0,0,0,0,0,3,0,0,0,0,0], :hand, 3],
- "addpoly" => [:take, 0, :deck, :deck, [0,0,0,0,0,0,0,11,0,0,0], :hand, 1],
- "miracledig" => [:take, 0, :banish, :banish, [0,3,0,0,0,0,0,0,0,0,0], :grave, 3],
- "kuriboh" => [:take, 0, :hand, :hand, [0,3,0,0,0,0,0,12,0,0,0], :grave, 1],
- "release" => [:takem, 0, :grave, :grave, [0,0,0,0,0,0,0,0,0,0,0], :banish, 5],
- "fossildig" => [:takem, 0, :deck, :deck, [0,0,0,9,1..6,0,0,0,0,0,0], :hand, 1],
- "lightload" => [:takem, 0, :hand, :hand, [0,3,0,0,7..12,0,0,0,0,0,0], :deck, 1],
- "foolishburial" => [:take, 0, :deck, :deck, [0,3,0,0,0,0,0,0,0,0,0], :grave, 1],
- "banish1wb" => [:take, 0, :deck, :deck, [0,3,0,11,0,0,0,0,0,0,0], :banish, 1],
- "banish1b" => [:take, 0, :deck, :deck, [0,3,0,16,0,0,0,0,0,0,0], :banish, 1],
- "rota" => [:take, 0, :deck, :deck, [0,3,0,15,1..4,0,0,0,0,0,0], :hand, 1],
- "reincarnation" => [:take, 0, :grave, :grave, [0,3,0,0,0,0,0,0,0,0,0], :hand, 1],
- "throwextra" => [:take, 0, :extra, :extra, [0,0,0,0,0,0,0,0,0,0,0], :grave, 1],
- "prosp3" => [:take, 0, :extra, :extra, [0,0,0,0,0,0,0,0,0,0,0], :banish, 3],
- "prosp6" => [:take, 0, :extra, :extra, [0,0,0,0,0,0,0,0,0,0,0], :banish, 6],
- "bombardment" => [:take, 0, :deck, :deck, [0,3,0,6,0,0,0,0,0,0,0], :grave, 1],
- "genta" => [:take, 0, :deck, :deck, [0,0,0,27,0,0,0,13,0,0,0], :hand, 1],
- "costgatesdw" => [:take, 0, :grave, :grave, [0,0,0,3,0,0,0,0,0,0,0], :banish, 1],
- "effgatesdw" => [:takem, 0, :hand, :hand, [0,0,0,3,0,0,0,0,0,0,0], :grave, 1],
- "jurassicworld" => [:take, 0, :deck, :deck, [0,0,0,27,0,0,0,14,0,0,0], :hand, 1],
- "ovisummon" => [:takem, 0, :deck, :deck, [0,0,0,9,0,0,0,0,0,0,0], :choice_hand_grave, 1],
- "ovi_destroy" => [:take, 0, :field, :field, [0,3,0,9,1..4,0,0,0,0,0,0, :exclude_itself, :face_up], :destroy_and_chain, "ovi_revive"],
- "ovi_revive" => [:takem, 0, :grave, :grave, [0,3,0,9,0,0,0,0,0,0,0], :special_summon_def, 1],
- "babycera" => [:takem, 0, :deck, :deck, [0,3,0,9,1..4,0,0,0,0,0,0], :special_summon, 1],
- "UCT" => [:take, 0, :grave, :grave, [0,3,0,9,0,0,0,0,0,0,0], :inherent_landing, 2],
- "endofline" => [:none],
- "miscellahand" => [:none],
- "miscellagrave" => [:take, 0, :grave, :grave, [0,3,0,9,0,0,0,0,0,0,0], :inherent_landing, 2],
- "archo_destroy" => [:takem, 0, :hand_or_field, :hand_or_field, [0,0,0,9,0,0,0,0,0,0,0, :exclude_active, :face_up], :destroy_and_chain, 1, "archo_add"],
- "archo_add" => [:takem, 0, :deck, :deck,
- [
- [0,0,0,12, :destroyed_level,0,0,0,0,0,0],
- [0,0,0,5, :destroyed_level,0,0,0,0,0,0],
- [0,0,0,20, :destroyed_level,0,0,0,0,0,0],
- [0,0,0,0,0,0,0,15,0,0,0]
- ], :hand, 1],
- "double_pill_cost1" => [:takem, 0, :hand_or_grave, :hand_or_grave, [0,3,0,9,0,0,0,0,0,0,0], :banish_and_chain, 1, "double_pill_cost2"],
- "double_pill_cost2" => [:takem, 0, :hand_or_grave, :hand_or_grave, [0,3,0,"!9",0,0,0,0,0,0,0], :banish, 1, ],
- "double_pill_resolve" => [:takem, 0, :hand_or_deck, :hand_or_deck, [0,3,0,9,7..12,0,0,0,0,0,0], :special_summon_ignore, 1],
- "giantrex" => [:impact, 1, :self_banished, :none, nil, :special_summon_self],
- "draining_shield" => [:quick_reactive, :negate_attack, :heal_atk],
- "enchantedjavelin" => [:quick_reactive, :heal_atk],
- "numinous_healer" => [:quick_reactive, :heal_1000, :heal_500_x_29_grave],
- "rainbowlife" => [:add_state, 0, :user, 66],
- "heal700" => [:quick_reactive, :heal_700],
- "heal2000" => [:quick_reactive, :heal_2000],
- "heal3000" => [:quick_reactive, :heal_3000],
- "heal4000" => [:quick_reactive, :heal_4000],
- } # do not remove this
- #-------------------------------------------------------------------------------
- #
- # End Options
- #
- #-------------------------------------------------------------------------------
- end #CG
- end #PC27
- ################################################################################
- # Start of script #
- ################################################################################
- $imported = {} if $imported.nil?
- $imported["PC27: CardGame System"] = true
- #===============================================================================
- # Flow trace helper (DEBUG)
- #===============================================================================
- module FlowTrace
- def trace_call(name)
- puts "[FLOW] #{name}"
- end
- end
- #===============================================================================
- # Load notetags
- #===============================================================================
- module DataManager
- class <<self; alias load_database_pc27_cardgame load_database; end
- def self.load_database
- load_database_pc27_cardgame
- load_notetags_pc27_cardgame
- end
- def self.load_notetags_effect
- for skill in $data_skills
- next if skill.nil?
- skill.load_notetags_effect
- end
- end
- def self.load_notetags_pc27_cardgame
- for skill in $data_skills
- next if skill.nil?
- skill.load_notetags_pc27_cardgame_skill
- end
- for item in $data_items
- next if item.nil?
- item.load_notetags_pc27_cardgame_item
- end
- for state in $data_states
- next if state.nil?
- state.load_notetags_pc27_cardgame_states
- end
- for equip_type in [$data_weapons, $data_armors]
- for obj in equip_type
- next if obj.nil?
- obj.load_notetags_pc27_cardgame_equip
- end
- end
- end
- end
- #===============================================================================
- # Usable Item
- #===============================================================================
- class RPG::UsableItem < RPG::BaseItem
- attr_accessor :card_id
- attr_accessor :attribute
- attr_accessor :type
- attr_accessor :rarity
- attr_accessor :subtype
- attr_accessor :level
- attr_accessor :normeff
- attr_accessor :frame
- attr_accessor :archetype
- attr_accessor :atk
- attr_accessor :def
- attr_accessor :special
- attr_accessor :cost
- attr_accessor :impact
- attr_accessor :impact2
- attr_accessor :fieldeff
- attr_accessor :graveeff
- attr_accessor :handeff
- attr_accessor :hand_impact
- attr_accessor :grave_impact
- attr_accessor :field_impact
- attr_accessor :summon_impact
- attr_accessor :properly_summoned
- #-----------------------------------------------------------------------------
- # Add card attributes
- #-----------------------------------------------------------------------------
- def load_notetags_pc27_cardgame_skill
- @description = wordwrap(@description)
- @card_id = 0
- @attribute = 0
- @type = 1
- @rarity = 1
- @subtype = 1
- @level = 1
- @normeff = 1
- @frame = 1
- @archetype = 1
- @atk = 1
- @def = 1
- @special = 1
- @cost = false
- @impact = false
- @fieldeff = 0
- @graveeff = 0
- @hand_impact = false
- @grave_impact = false
- @field_impact = false
- @summon_impact = false
- self.note.split(/[\r\n]+/).each { |line|
- if /<card[ -_]id: +(?<inr>\d+)>/i =~ line
- @card_id = inr.to_i
- elsif /<card[ -_]attribute: +(?<attrnr>\d+)>/i =~ line
- @attribute = attrnr.to_i
- elsif /<card[ -_]type: +(?<tnr>\d+)>/i =~ line
- @type = tnr.to_i
- elsif /<card[ -_]rarity: +(?<rnr>\d+)>/i =~ line
- @rarity = rnr.to_i
- elsif /<card[ -_]subtype: +(?<stnr>\d+)>/i =~ line
- @subtype = stnr.to_i
- elsif /<card[ -_]level: +(?<lvnr>\d+)>/i =~ line
- @level = lvnr.to_i
- elsif /<card[ -_]normeff: +(?<nenr>\d+)>/i =~ line
- @normeff = nenr.to_i
- elsif /<card[ -_]frame: +(?<frnr>\d+)>/i =~ line
- @frame = frnr.to_i
- elsif /<card[ -_]archetype: +(?<arnr>\d+)>/i =~ line
- @archetype = arnr.to_i
- elsif /<card[ -_]atk: +(?<atnr>\d+)>/i =~ line
- @atk = atnr.to_i
- elsif /<card[ -_]def: +(?<dfnr>\d+)>/i =~ line
- @def = dfnr.to_i
- elsif /<card[ -_]special: +(?<spnr>\d+)>/i =~ line
- @special = spnr.to_i
- elsif /<card[ -_]cost: +(?<cst>.+)>/i =~ line
- @cost = cst
- elsif /<card[ -_]impact: +(?<imp>.+)>/i =~ line
- @impact = imp
- elsif /<card[ -_]impact2: +(?<imp2>.+)>/i =~ line
- @impact2 = imp2
- elsif /<(?:field)[ ](\d+)>/i =~ line
- @fieldeff = $1.to_i
- elsif /<(?:grave)[ ](\d+)>/i =~ line
- @graveeff = $1.to_i
- elsif /<(?:hand)[ ](\d+)>/i =~ line
- @handeff = $1.to_i
- elsif /<hand[-_ ]impact:\s*(.+?)>/i =~ line
- @hand_impact = $1.to_s.strip
- elsif /<grave[-_ ]impact:\s*(.+?)>/i =~ line
- @grave_impact = $1.to_s.strip
- elsif /<field[-_ ]impact:\s*(.+?)>/i =~ line
- @field_impact = $1.to_s.strip
- elsif /<summon[-_ ]impact:\s*(.+?)>/i =~ line
- @summon_impact = $1.to_s.strip
- end
- }
- end
- def load_notetags_pc27_cardgame_item
- @impact = false
- @impact2 = false
- @fieldeff = 0
- @graveeff = 0
- @handeff = 0
- self.note.split(/[\r\n]+/).each { |line|
- if /<card[ -_]impact: +(?<imp>.+)>/i =~ line
- @impact = imp
- elsif /<card[ -_]impact2: +(?<imp2>.+)>/i =~ line
- @impact2 = imp2
- elsif /<(?:field)[ ](\d+)>/i =~ line
- @fieldeff = $1.to_i
- elsif /<(?:grave)[ ](\d+)>/i =~ line
- @graveeff = $1.to_i
- elsif /<(?:hand)[ ](\d+)>/i =~ line
- @handeff = $1.to_i
- end
- }
- end
- #-----------------------------------------------------------------------------
- # Method to rearange text so it fits inside a window
- #-----------------------------------------------------------------------------
- def wordwrap(desc_text, window = nil, default_max_chars = 16)
- max_chars = (window ? (window.width - 2 * window.padding) / 10 : default_max_chars)
- text, line= "", ""
- desc_text.split(/[\r\n ]+/).each { |word|
- if word.size + line.size > max_chars
- text += line+"\n"
- line = word
- else
- line += word
- end
- line += " "
- }
- text += line
- return text
- end
- def match_filter?(filter)
- return true if filter.nil?
- return false if filter[0] != 0 && self.type != filter[0]
- return false if filter[1] != 0 && self.subtype != filter[1]
- return false if filter[2] != 0 && self.rarity != filter[2]
- return false if filter[3] != 0 && self.archetype != filter[3]
- if filter[4].is_a?(Range)
- return false unless filter[4].include?(self.level)
- elsif filter[4] != 0
- return false if self.level != filter[4]
- end
- return true
- end
- end
- #===============================================================================
- # Equip Item
- #===============================================================================
- class RPG::EquipItem < RPG::BaseItem
- attr_accessor :extra_turn_cards
- attr_accessor :extra_start_cards
- def load_notetags_pc27_cardgame_equip
- @extra_turn_cards = 0
- @extra_start_cards = 0
- self.note.split(/[\r\n]+/).each { |line|
- if /<extra[ -_]turn[ -_]cards: +(?<tnr>\d+)>/i =~ line
- @extra_turn_cards = tnr.to_i
- elsif /<extra[ -_]start[ -_]cards: +(?<snr>\d+)>/i =~ line
- @extra_start_cards = snr.to_i
- end
- }
- end
- end
- #===============================================================================
- # State
- #===============================================================================
- class RPG::State < RPG::BaseItem
- attr_reader :limited_actions
- def load_notetags_pc27_cardgame_states
- @limited_actions = 0
- self.note.split(/[\r\n]+/).each { |line|
- if /<limited[ -_]actions: +(?<lnr>\d+)>/i =~ line
- @limited_actions = lnr.to_i
- end
- }
- end
- end
- #===============================================================================
- # Game_Interpreter
- #===============================================================================
- class Game_Interpreter
- def add_card_to_coll(*args)
- for id in args
- $game_party.coll.push($data_skills[id])
- end
- end
- def remove_card?(id)
- for i in (0...$game_party.coll.length)
- if $game_party.coll[i].id == id
- $game_party.coll.delete_at(i)
- return true
- end
- end
- return false
- end
- def remove_all_cards(*args)
- for id in args
- $game_party.coll -= [$data_skills[id]]
- for actor in $game_party.members
- actor.deck -= [$data_skills[id]]
- end
- end
- end
- def has_card?(id)
- for card in $game_party.coll
- return true if card.id == id
- end
- for actor in $game_party.members
- for card in actor.deck
- return true if card.id == id
- end
- end
- return false
- end
- def atributes_in_grave(id, count)
- if self.grave.count { |card| skill.attribute == id} <= count
- return true
- else
- return false
- end
- end
- def has_card_in_deck?(id)
- for card in self.deck
- return true if card.id == id
- end
- return false
- end
- def has_card_in_field?(id)
- for card in self.field
- return true if card.id == id
- end
- return false
- end
- def has_many_card_in_deck?(count)
- return self.deck.count { |card| } >= count
- end
- def has_x_cards?(id, count)
- return self.deck.count { |card| card.id == id } >= count
- end
- def has_card_in_hand?(id)
- for card in self.hand
- return true if card.id == id
- end
- return false
- end
- def has_card_in_grave?(id)
- actor = $game_actors[$game_variables[27]]
- for card in actor.grave
- return true if card.id == id
- end
- return false
- end
- def has_x_cards_in_grave?(id, count)
- actor = $game_actors[$game_variables[27]]
- return actor.grave.count { |card| card.id == id } >= count
- end
- def numinous_in_grave
- nr = 0
- for actor in $game_party.members
- nr += actor.grave.count { |card| card.id == 29 }
- end
- return nr
- end
- def has_card_in_banish?(id)
- actor = $game_actors[$game_variables[27]]
- for card in actor.banish
- return true if card.id == id
- end
- return false
- end
- def has_x_cards_in_banish?(id, count)
- actor = $game_actors[$game_variables[27]]
- return actor.banish.count { |card| card.id == id } >= count
- end
- def add_card_deck(*args)
- for id in args
- actor = $game_actors[$game_variables[27]]
- actor.deck += [$data_skills[id]]
- end
- end
- def remove_card_deck(*args)
- for id in args
- actor = $game_actors[$game_variables[27]]
- actor.deck -= [$data_skills[id]]
- end
- end
- def add_card_hand(*args)
- for id in args
- self.hand += [$data_skills[id]]
- end
- end
- def summon_token(*args)
- for id in args
- self.field += [$data_skills[id]]
- end
- end
- def add_card_hand_2(*args)
- for id in args
- actor = $game_actors[$game_variables[27]]
- actor.hand += [$data_skills[id]]
- end
- end
- def remove_card_hand(*args)
- for id in args
- self.hand -= [$data_skills[id]]
- end
- end
- def send_card_from_hand_to_grave(*args)
- for id in args
- actor = $game_actors[$game_variables[42]]
- actor.hand -= [$data_skills[id]]
- actor.grave += [$data_skills[id]]
- end
- end
- def send_card_from_hand_to_grave_2(id)
- actor = $game_actors[$game_variables[42]]
- for i in (0...actor.hand.length)
- if actor.hand[i].id == id
- actor.grave.push(@hand[i])
- actor.hand.delete_at(i)
- return true
- end
- end
- return false
- end
- def count_actor_deck(id)
- return $game_actors[id].deck.size
- end
- def count_all_decks
- nr = 0
- for actor in $game_party.members
- nr += actor.deck.size
- end
- return nr
- end
- end
- #===============================================================================
- # Game_Battler
- #===============================================================================
- class Game_Battler < Game_BattlerBase
- #-----------------------------------------------------------------------------
- # defines card actions for non actors, in case the user messes up
- #-----------------------------------------------------------------------------
- def revive_grave(show = true) ;end
- def revive_penalty ;end
- def shuffle_deck(sound = true);end
- def card_to_grave?(id) ;end
- def throw_cards(n) ;end
- def draw_cards(n) ;end
- end
- #===============================================================================
- # Game_Actor
- #===============================================================================
- class Game_Actor < Game_Battler
- #-----------------------------------------------------------------------------
- # Attributes
- #-----------------------------------------------------------------------------
- attr_accessor :deck
- attr_accessor :grave
- attr_accessor :banish
- attr_accessor :extra
- attr_accessor :hand
- attr_accessor :field
- attr_accessor :monster_zones
- attr_accessor :st_zones
- attr_accessor :field_zone
- attr_accessor :stack
- attr_accessor :turn_actions
- attr_accessor :current_zone
- attr_accessor :used_turn_effects
- attr_accessor :is_official_shuffle
- attr_accessor :monster_zones_state
- attr_accessor :st_zones_state
- attr_accessor :field_zone_state
- def init_card_zones
- @monster_zones ||= Array.new(5)
- @monster_zones_state ||= Array.new(5) { { position: :attack, face_down: false } }
- @spell_zones ||= Array.new(5)
- @field_zone ||= nil
- end
- def card_in_zone(zone, index)
- case zone
- when :monster
- @monster_zones[index]
- when :spell
- @st_zones[index]
- when :fieldspell
- @field_zone
- else
- nil
- end
- end
- def free_monster_zone_available?
- init_card_zones
- @monster_zones.any? { |z| z.nil? }
- end
- def st_zone_available?
- init_card_zones
- @st_zones.include?(nil)
- end
- def st_zones_state
- @st_zones_state ||= Array.new(5) { { face_down: false, set_this_turn: false } }
- end
- def field_zone_state
- @field_zone_state ||= { face_down: false, set_this_turn: false }
- end
- def public_banish
- self.banish.reject { |c| c.instance_variable_get(:@banished_face_down) }
- end
- def private_banish
- self.banish.select { |c| c.instance_variable_get(:@banished_face_down) }
- end
- def card_counters
- @card_counters ||= {}
- end
- def add_card_counter(card_obj_id, type, amount = 1)
- card_counters[card_obj_id] ||= {}
- card_counters[card_obj_id][type] ||= 0
- card_counters[card_obj_id][type] += amount
- end
- def get_card_counters(card_obj_id, type)
- return 0 unless card_counters[card_obj_id]
- card_counters[card_obj_id][type] || 0
- end
- def clear_card_counters(card_obj_id)
- card_counters.delete(card_obj_id) if card_counters.key?(card_obj_id)
- end
- def leads_to_special_summon?(effect_name, history = [])
- return false if effect_name.nil? || history.include?(effect_name)
- history << effect_name
- effect_data = PC27::CG::CARD_EFFECT[effect_name]
- return false unless effect_data
- destination = effect_data[5]
- sp_summons = [:special_summon, :special_summon_def, :special_summon_atk,
- :special_summon_ignore, :special_summon_self, :inherent_landing]
- return true if sp_summons.include?(destination)
- next_effect = effect_data[7] || effect_data[6]
- if next_effect.is_a?(String)
- if [:destroy_and_chain, :banish_and_chain].include?(destination) || effect_data[0] == :cost
- return leads_to_special_summon?(next_effect, history)
- end
- end
- return false
- end
- def can_activate_impact?(impact_name)
- return false unless impact_name
- if self.state?(18) && leads_to_special_summon?(impact_name)
- return false
- end
- card = nil
- if SceneManager.scene_is?(Scene_Battle)
- card = SceneManager.scene.instance_variable_get(:@selected_card) ||
- SceneManager.scene.instance_variable_get(:@active_effect_card) ||
- $temp_active_card
- end
- if card
- card.note.split(/[\r\n]+/).each do |line|
- if line =~ /<block_if_state:\s*(.+?)\s*,\s*(\d+)>/i
- effect_to_block = $1.to_s.strip.downcase
- state_id = $2.to_i
- if effect_to_block == impact_name.to_s.downcase && self.state?(state_id)
- return false
- end
- end
- end
- end
- effect_data = PC27::CG::CARD_EFFECT[impact_name]
- return true unless effect_data
- target_zone = effect_data[2]
- filter = effect_data[4]
- cards_to_check = case target_zone
- when :deck then self.deck
- when :grave then self.grave
- when :hand then self.hand
- when :banish then self.banish
- when :extra then self.extra
- when :field then self.field
- else nil
- end
- if cards_to_check && filter && filter.is_a?(Array)
- valid_targets = cards_to_check.count do |card_target|
- ok = true
- ok = false if filter[0] != 0 && card_target.attribute != filter[0]
- ok = false if filter[1] != 0 && card_target.type != filter[1]
- ok = false if filter[2] != 0 && card_target.rarity != filter[2]
- ok = false if filter[3] != 0 && card_target.subtype != filter[3]
- if filter[4].is_a?(Range)
- ok = false unless filter[4].include?(card_target.level)
- elsif filter[4] != 0
- ok = false if card_target.level != filter[4]
- end
- ok = false if filter[5] != 0 && card_target.normeff != filter[5]
- ok = false if filter[6] != 0 && card_target.frame != filter[6]
- ok = false if filter[7] != 0 && card_target.archetype != filter[7]
- ok = false if filter[8] != 0 && card_target.atk != filter[8]
- ok = false if filter[9] != 0 && card_target.def != filter[9]
- ok = false if filter[10] && filter[10] != 0 && card_target.special != filter[10]
- ok
- end
- req_amount = effect_data[1].to_i > 0 ? effect_data[1].to_i : 1
- return valid_targets >= req_amount
- elsif cards_to_check
- return cards_to_check.size > 0
- end
- return true
- end
- def is_face_up?(card)
- if self.respond_to?(:monster_zones) && self.monster_zones.include?(card)
- idx = self.monster_zones.index(card)
- state = self.monster_zones_state[idx]
- return state ? !state[:face_down] : true
- end
- if self.respond_to?(:st_zones) && self.st_zones.include?(card)
- idx = self.st_zones.index(card)
- state = self.st_zones_state[idx] rescue nil
- return state ? !state[:face_down] : true
- end
- if self.respond_to?(:field_zone) && self.field_zone == card
- state = self.field_zone_state rescue nil
- return state ? !state[:face_down] : true
- end
- return true
- end
- def active_continuous_effects
- effects = []
- return effects unless self.respond_to?(:field)
- self.field.each do |card|
- next if card.nil?
- next unless is_face_up?(card)
- regex = /<(on_[a-z_]+)_(at_[a-z_]+):\s*([a-z_]+)\.(\d+)\s*(=[+-])\s*([a-z_]+)\.(\d+)>/i
- card.note.scan(regex) do |trigger, target_loc, f_type, f_val, op, stat, stat_val|
- effects << {
- source_card: card,
- trigger: trigger.downcase, # Ej: "on_field"
- target_loc: target_loc.downcase, # Ej: "at_field" o "at_hand"
- filter_type: f_type.downcase, # Ej: "subtype" o "type"
- filter_val: f_val.to_i, # Ej: 9 o 3
- operation: op, # Ej: "=+" o "=-"
- stat: stat.downcase, # Ej: "atk", "def" o "level"
- amount: stat_val.to_i # Ej: 300 o 1
- }
- end
- end
- effects
- end
- def calculate_continuous_stat(card, base_stat, stat_name, current_location)
- return base_stat if card.nil?
- total_stat = base_stat
- active_continuous_effects.each do |eff|
- next unless eff[:target_loc] == current_location
- match = false
- case eff[:filter_type]
- when "subtype"
- sub = card.respond_to?(:subtype) ? card.subtype : nil
- if sub.is_a?(Array)
- match = sub.map(&:to_i).include?(eff[:filter_val])
- else
- match = (sub.to_i == eff[:filter_val])
- end
- when "type"
- match = (card.respond_to?(:type) && card.type == eff[:filter_val])
- when "element", "attribute"
- match = (card.respond_to?(:damage) && card.attribute == eff[:filter_val])
- end
- next unless match
- next unless eff[:stat] == stat_name
- if eff[:operation] == "=+"
- total_stat += eff[:amount]
- elsif eff[:operation] == "=-"
- total_stat -= eff[:amount]
- total_stat = 0 if total_stat < 0
- end
- end
- return total_stat
- end
- def current_monster_atk(card, location = "at_field")
- base = card.atk rescue 0
- personal_buff = 0
- if location == "at_field" && self.respond_to?(:monster_zones)
- idx = self.monster_zones.index { |c| c && c.equal?(card) }
- if idx
- state = self.monster_zones_state[idx]
- personal_buff = state[:personal_atk_buff].to_i if state && !state[:face_down]
- end
- end
- calculate_continuous_stat(card, base, "atk", location) + personal_buff
- end
- def current_monster_def(card, location = "at_field")
- base = card.def rescue 0
- personal_buff = 0
- if location == "at_field" && self.respond_to?(:monster_zones)
- idx = self.monster_zones.index { |c| c && c.equal?(card) }
- if idx
- state = self.monster_zones_state[idx]
- personal_buff = state[:personal_def_buff].to_i if state && !state[:face_down]
- end
- end
- calculate_continuous_stat(card, base, "def", location) + personal_buff
- end
- def current_monster_level(card, location = "at_field")
- base = card.level rescue 0
- personal_buff = 0
- if location == "at_field" && self.respond_to?(:monster_zones)
- idx = self.monster_zones.index { |c| c && c.equal?(card) }
- if idx
- state = self.monster_zones_state[idx]
- personal_buff = state[:personal_level_buff].to_i if state && !state[:face_down]
- end
- end
- calculate_continuous_stat(card, base, "level", location) + personal_buff
- end
- alias pc27_param_plus_ygo param_plus unless method_defined?(:pc27_param_plus_ygo)
- def param_plus(param_id)
- total = pc27_param_plus_ygo(param_id)
- if param_id == 2 || param_id == 3
- if self.respond_to?(:monster_zones) && self.monster_zones
- self.monster_zones.each_with_index do |card, idx|
- next if card.nil?
- state = self.monster_zones_state[idx]
- next if state.nil? || state[:face_down]
- if param_id == 2 && state[:position] == :attack
- total += current_monster_atk(card, "at_field")
- elsif param_id == 3 && state[:position] == :defense
- total += current_monster_def(card, "at_field")
- end
- end
- end
- end
- return total
- end
- def hopt_blocked?(card, effect_name)
- return false unless card && card.note
- return false if effect_name.nil? || effect_name == ""
- self.used_turn_effects ||= []
- if card.note =~ /<hopt:\s*(.+?)>/i
- hopt_groups = $1.to_s.split(",").map { |s| s.strip }
- hopt_groups.each do |group|
- sub_effs = group.split(/\s*\|\|\s*|\s+or\s+/i).map { |s| s.strip }
- if sub_effs.include?(effect_name.to_s)
- return true if sub_effs.any? { |id| self.used_turn_effects.include?(id) }
- end
- end
- end
- return false
- end
- def can_activate_summon_effect?(card)
- return false unless card
- return false if card.summon_impact.nil? || card.summon_impact == false || card.summon_impact == ""
- self.used_turn_effects ||= []
- return false if hopt_blocked?(card, card.summon_impact)
- if card.note =~ /<shared_opt:\s*(.+?)>/i
- shared_name = $1.to_s.strip
- return false if self.used_turn_effects.include?(shared_name)
- end
- return meets_activation_requirements?(card, card.summon_impact)
- end
- def can_activate_field_effect?(card)
- return false unless card
- return false if card.field_impact && self.state?(18) && leads_to_special_summon?(card.field_impact)
- return false if card.field_impact.nil? || card.field_impact == false || card.field_impact == ""
- self.used_turn_effects ||= []
- eff_str = card.field_impact.to_s
- return false if hopt_blocked?(card, eff_str)
- if card.note =~ /<shared_opt:\s*(.+?)>/i
- shared_name = $1.to_s.strip
- return false if self.used_turn_effects.include?(shared_name)
- end
- return meets_activation_requirements?(card, eff_str)
- end
- def used_turn_effects
- @used_turn_effects ||= []
- end
- def custom_req_met?(card)
- return true unless card
- if card.note =~ /<custom_req>\s*(.*?)\s*<\/custom_req>/im
- begin
- return !!eval($1.to_s)
- rescue => e
- p "[ERROR CUSTOM REQ] Carta: #{card.name} | Fallo: #{e.message}"
- return false
- end
- end
- return true
- end
- def meets_activation_requirements?(card, effect_name)
- return false unless card && effect_name
- eff_str = effect_name.to_s
- if card.note =~ /<req_field_counters:\s*#{eff_str}\s*,\s*([^,>]+)\s*,\s*(\d+)>/i
- c_type = $1.to_s.strip.downcase.to_sym
- c_amount = $2.to_i
- return false unless self.get_card_counters(card.object_id, c_type) >= c_amount
- end
- if card.note =~ /<req_ss_grave:\s*#{eff_str}\s*,\s*(\d+)(?:\s*,\s*(\d+))?>/i
- return false unless self.count_legal_ss_targets($1.to_i) >= ($2 ? $2.to_i : 1)
- end
- if card.note =~ /<req_deck_subtype:\s*#{eff_str}\s*,\s*(\d+)(?:\s*,\s*(\d+))?>/i
- return false unless self.deck.count { |c| c && c.subtype == $1.to_i } >= ($2 ? $2.to_i : 1)
- end
- if card.note =~ /<req_grave_subtype:\s*#{eff_str}\s*,\s*(\d+)(?:\s*,\s*(\d+))?>/i
- return false unless self.count_legal_ss_targets($1.to_i) >= ($2 ? $2.to_i : 1)
- end
- if card.note =~ /<req_field_other_subtype:\s*#{eff_str}\s*,\s*(\d+)(?:\s*,\s*(\d+))?>/i
- valid_count = self.monster_zones.compact.count { |c| c.subtype == $1.to_i }
- req_total = (card.subtype == $1.to_i) ? ($2.to_i + 1) : $2.to_i
- return false unless valid_count >= req_total
- end
- if card.note =~ /<req_dry_run:\s*([^,>]+)\s*,\s*([^,>]+)(?:\s*,\s*([^>]+))?>/i
- e1, e2, e3 = $1.strip, $2.strip, ($3 ? $3.strip : nil)
- d1, d2 = PC27::CG::CARD_EFFECT[e1], PC27::CG::CARD_EFFECT[e2]
- return false unless d1 && d2
- get_clean_pool = lambda do |zone_sym|
- pool = []
- pool += self.hand if [:hand, :hand_or_field, :hand_or_grave, :hand_or_deck].include?(zone_sym)
- pool += self.grave if [:grave, :hand_or_grave].include?(zone_sym)
- pool += self.deck if [:deck, :hand_or_deck].include?(zone_sym)
- pool += self.monster_zones.compact if [:field, :hand_or_field].include?(zone_sym)
- pool.delete_if { |c| c.id == card.id }
- pool
- end
- p1, p2 = get_clean_pool.call(d1[2]), get_clean_pool.call(d2[2])
- p1.each do |t1|
- if match_complex_filter?(t1, d1[4], card, nil)
- lvl = t1.respond_to?(:level) ? t1.level : nil
- p2.each do |t2|
- next if t1 == t2
- if match_complex_filter?(t2, d2[4], card, lvl)
- if e3
- d3 = PC27::CG::CARD_EFFECT[e3]
- return true if get_clean_pool.call(d3[2]).any? { |t3|
- t3 != t1 && t3 != t2 && match_complex_filter?(t3, d3[4], card, lvl)
- }
- else
- return true
- end
- end
- end
- end
- end
- return false
- end
- return true
- end
- def match_complex_filter?(item, filter, active_card = nil, simulated_level = nil, zone_index = nil, source_zone = nil)
- return true if filter.nil? || filter.empty?
- if filter[0].is_a?(Array)
- return filter.any? { |f| match_single_complex_filter?(item, f, active_card, simulated_level, zone_index, source_zone) }
- else
- return match_single_complex_filter?(item, filter, active_card, simulated_level, zone_index, source_zone)
- end
- end
- def match_single_complex_filter?(item, f, active_card = nil, simulated_level = nil, zone_index = nil, source_zone = nil)
- begin
- f = [] if f.nil?
- f_str = f.map(&:to_s)
- if f_str.include?("face_up") || f_str.include?("face_down")
- is_face_up = true
- has_position = false
- if source_zone == :hand || source_zone == :deck || source_zone == :grave || source_zone == :banish || source_zone == :extra
- else
- if zone_index != nil
- state = self.monster_zones_state[zone_index]
- is_face_up = state ? !state[:face_down] : true
- has_position = true
- else
- ($game_party.battle_members + $game_troop.members).each do |battler|
- next unless battler.respond_to?(:monster_zones)
- if battler.monster_zones.include?(item)
- idx = battler.monster_zones.index(item)
- state = battler.monster_zones_state[idx]
- is_face_up = state ? !state[:face_down] : true
- has_position = true
- break
- end
- end
- end
- end
- if has_position
- return false if f_str.include?("face_up") && !is_face_up
- return false if f_str.include?("face_down") && is_face_up
- end
- end
- return false unless (f[0] || 0).to_s == "0" || (item.attribute rescue 0).to_s == f[0].to_s
- return false unless (f[1] || 0).to_s == "0" || (item.type rescue 0).to_s == f[1].to_s
- return false unless (f[2] || 0).to_s == "0" || (item.rarity rescue 0).to_s == f[2].to_s
- if (f[3] || 0).to_s != "0" || f[3].is_a?(String)
- item_sub = item.respond_to?(:subtype) ? item.subtype : nil
- item_sub = 0 if item_sub.nil?
- f3_str = f[3].to_s
- is_not = f3_str.start_with?("!")
- target_val = is_not ? f3_str[1..-1] : f3_str
- if item_sub.is_a?(Array)
- res = item_sub.map(&:to_s).include?(target_val)
- else
- res = item_sub.to_s == target_val
- end
- return false if is_not && res
- return false if !is_not && !res
- end
- f4 = f[4] || 0
- if f4.to_s != "0"
- target_lvl = simulated_level || ($chain_memory_card ? $chain_memory_card.level : 0)
- check_val = (f4 == :destroyed_level) ? target_lvl : f4
- if check_val.is_a?(Range)
- return false unless item.respond_to?(:level) && check_val.include?(item.level.to_i)
- elsif check_val.to_s != "0"
- return false unless item.respond_to?(:level) && item.level.to_s == check_val.to_s
- end
- end
- return false unless (f[5] || 0).to_s == "0" || (item.normeff rescue 0).to_s == f[5].to_s
- return false unless (f[6] || 0).to_s == "0" || (item.frame rescue 0).to_s == f[6].to_s
- if (f[7] || 0).to_s != "0"
- item_arch = item.respond_to?(:archetype) ? item.archetype : nil
- return false if item_arch.nil?
- if item_arch.is_a?(Array)
- return false unless item_arch.map(&:to_s).include?(f[7].to_s)
- else
- return false unless item_arch.to_s == f[7].to_s
- end
- end
- return false unless (f[8] || 0).to_s == "0" || (item.atk rescue 0).to_s == f[8].to_s
- return false unless (f[9] || 0).to_s == "0" || (item.def rescue 0).to_s == f[9].to_s
- return false unless (f[10]|| 0).to_s == "0" || (item.special rescue 0).to_s == f[10].to_s
- if f[11] == :exclude_active
- ref = active_card || $temp_active_card
- return false if ref && item.id == ref.id
- end
- return true
- rescue => e
- p "[ERROR EN FILTRO] Carta: #{item.name} | Fallo: #{e.message}"
- return false
- end
- end
- #--------------------------------------------------------------------------
- # Verifica si hay blancos legales para Special Summon en una zona
- #--------------------------------------------------------------------------
- def has_legal_spec_summon_target?(zone_type, subtype)
- cards_to_check = case zone_type
- when :grave then self.grave
- when :hand then self.hand
- when :banish then self.banish
- when :deck then self.deck
- when :extra then self.extra
- else []
- end
- cards_to_check.any? do |card|
- next false unless card && card.subtype == subtype
- is_nomi = (card.note =~ /<special_only:/i)
- if is_nomi
- card.properly_summoned == true
- else
- true
- end
- end
- end
- def count_legal_ss_targets(subtype)
- targets = self.grave.select do |card|
- next false unless card && card.subtype == subtype
- if card.note =~ /<special_only:/i
- card.properly_summoned == true
- else
- true
- end
- end
- return targets.size
- end
- #-----------------------------------------------------------------------------
- # Adds Hand, Deck, Grave, Banish, Extra, Field and Stack to an Actor (alias)
- #-----------------------------------------------------------------------------
- alias pc27_cardgame_gameactor_setup setup
- def setup(actor_id)
- pc27_cardgame_gameactor_setup(actor_id)
- @current_zone = :hand
- setup_start_deck(actor_id)
- @hand = []
- @grave = []
- @banish = []
- @extra = []
- @field = []
- @stack = []
- @monster_zones = Array.new(5, nil)
- @monster_zones_state = Array.new(5) { { position: :attack, face_down: false } }
- @st_zones = Array.new(5, nil)
- @field_zone = nil
- @turn_actions = { :can_attack => true,
- :can_guard => true,
- :actions => 0, }
- end
- #-----------------------------------------------------------------------------
- # Setup for the initial deck (new)
- #-----------------------------------------------------------------------------
- def setup_start_deck(actor_id)
- @deck = []
- if PC27::CG::START_DECKS.has_key?(actor_id)
- PC27::CG::START_DECKS[actor_id].each { |card| @deck.push($data_skills[card]) }
- end
- end
- #-----------------------------------------------------------------------------
- # Setup for the initial extra (new)
- #-----------------------------------------------------------------------------
- def setup_start_extra(actor_id)
- @extra = []
- if PC27::CG::START_EXTRA.has_key?(actor_id)
- PC27::CG::START_EXTRA[actor_id].each { |card| @extra.push($data_skills[card]) }
- end
- end
- #-----------------------------------------------------------------------------
- # Draws n cards from the deck (new)
- #-----------------------------------------------------------------------------
- def draw_cards(n, show = true, sound = true)
- is_interrupt = false
- if $game_party && $game_party.in_battle && SceneManager.scene_is?(Scene_Battle)
- if SceneManager.scene.instance_variable_get(:@is_interrupt_effect)
- show = false
- is_interrupt = true
- end
- end
- drawn_cards = []
- begin
- n.times do
- if @deck.length == 0
- add_state(1) if PC27::CG::DECK_EMPTY == 1
- return if PC27::CG::DECK_EMPTY == 1
- if @grave.length == 0
- add_state(1) if PC27::CG::DECK_EMPTY == 2
- return
- else
- revive_grave
- revive_penalty if PC27::CG::REVIVE_PENALTY[0] > 0
- end
- end
- skill = @deck.shift
- @hand.push(skill)
- drawn_cards << skill
- end
- if $game_party.in_battle && SceneManager.scene_is?(Scene_Battle)
- scene = SceneManager.scene
- scene.instance_variable_get(:@status_window).refresh rescue nil
- end
- if $game_party && $game_party.in_battle && SceneManager.scene_is?(Scene_Battle) && drawn_cards.size > 0
- scene = SceneManager.scene
- sprites = []
- center_x = Graphics.width / 2
- center_y = Graphics.height / 2
- total_cards = drawn_cards.size
- spacing = [80, 400 / total_cards].min
- start_x = center_x - ((total_cards - 1) * spacing) / 2
- drawn_cards.each_with_index do |skill, i|
- sprite = Sprite.new
- begin
- sprite.bitmap = Cache.picture("Card#{skill.id}")
- rescue
- sprite.bitmap = Bitmap.new(100, 140)
- sprite.bitmap.fill_rect(0, 0, 100, 140, Color.new(255, 255, 255))
- end
- sprite.ox = sprite.bitmap.width / 2 rescue 0
- sprite.oy = sprite.bitmap.height / 2 rescue 0
- sprite.z = 10050 + i
- dest_x = start_x + (i * spacing)
- dest_y = center_y
- sprite.x = dest_x
- sprite.y = -150 - (i * 150)
- sprites << { sprite: sprite, dest_x: dest_x, dest_y: dest_y, skill: skill }
- end
- falling = true
- while falling
- falling = false
- sprites.each do |data|
- s = data[:sprite]
- if s.y < data[:dest_y]
- s.y += [(data[:dest_y] - s.y) * 0.25, 15].max
- s.y = data[:dest_y] if s.y > data[:dest_y]
- falling = true if s.y < data[:dest_y]
- end
- end
- scene.update_basic if falling
- end
- 45.times { scene.update_basic }
- if self.actor?
- target_x = self.screen_x rescue center_x
- target_y = self.screen_y rescue Graphics.height
- else
- target_x = self.screen_x rescue center_x
- target_y = (self.screen_y - 50) rescue -50
- end
- sprites.reverse.each do |data|
- s = data[:sprite]
- RPG::SE.new(*PC27::CG::DRAW_SOUND).play if sound
- 15.times do |frame|
- progress = (frame + 1) / 15.0
- s.x = data[:dest_x] + (target_x - data[:dest_x]) * progress
- s.y = data[:dest_y] + (target_y - data[:dest_y]) * progress
- s.zoom_x = 1.0 - progress
- s.zoom_y = 1.0 - progress
- s.opacity = 255 * (1.0 - progress)
- scene.update_basic
- end
- end
- sprites.each do |data|
- data[:sprite].bitmap.dispose if data[:sprite].bitmap
- data[:sprite].dispose
- end
- end
- if show
- drawn_cards.each do |skill|
- text = @name + " " + PC27::CG::DRAW_MESSAGE + " " + skill.name
- if $game_party && $game_party.in_battle && SceneManager.scene_is?(Scene_Battle)
- begin
- SceneManager.scene.log_window.add_text(text)
- rescue
- end
- else
- $game_message.background = 1
- $game_message.position = 1
- $game_message.add(text)
- end
- end
- end
- ensure
- if is_interrupt && SceneManager.scene_is?(Scene_Battle)
- SceneManager.scene.instance_variable_set(:@is_interrupt_effect, false)
- end
- end
- end
- #-----------------------------------------------------------------------------
- # Puts all cards from your grave back into your deck (new)
- #-----------------------------------------------------------------------------
- def revive_grave(show = true)
- @deck += @grave
- @grave = []
- shuffle_deck(false)
- if show
- $game_message.background = 1
- $game_message.position = 1
- text = @name + PC27::CG::REVIVE_MSG
- $game_message.add(text)
- end
- end
- #-----------------------------------------------------------------------------
- # Revive penalty (new)
- #-----------------------------------------------------------------------------
- def revive_penalty
- percent = PC27::CG::REVIVE_PENALTY[0] * 0.01
- case PC27::CG::REVIVE_PENALTY[1]
- when :hp
- @hp -= (@hp * percent).round
- when :mhp
- @hp -= (@mhp * percent).round
- when :mp
- @mp -= (@mp * percent).round
- when :mmp
- @mp -= (@mmp * percent).round
- end
- RPG::SE.new(*PC27::CG::PENALTY_SOUND).play
- end
- #-----------------------------------------------------------------------------
- # Shuffles the deck (Ahora con soporte Visual)
- #-----------------------------------------------------------------------------
- def shuffle_deck(sound = true)
- if sound
- if SceneManager.scene_is?(Scene_Battle)
- if SceneManager.scene.instance_variable_get(:@deck_was_searched) && !@is_official_shuffle
- @deck = @deck.shuffle
- return
- end
- SceneManager.scene.show_deck_shuffle_visuals
- else
- 5.times do
- RPG::SE.new(PC27::CG::DRAW_SOUND[0], 100, 150).play rescue nil
- 20.times { Graphics.update; Input.update }
- RPG::SE.new(PC27::CG::DRAW_SOUND[0], 100, 100).play rescue nil
- 10.times { Graphics.update; Input.update }
- end
- end
- end
- @deck = @deck.shuffle
- end
- #-----------------------------------------------------------------------------
- # Sorts Hand, Deck or Grave (new)
- #-----------------------------------------------------------------------------
- def sort_cards(location)
- case location
- when :deck
- @deck.sort!{|a,b| a.card_id <=> b.card_id}
- when :hand
- @hand.sort!{|a,b| a.card_id <=> b.card_id}
- when :grave
- @grave.sort!{|a,b| a.card_id <=> b.card_id}
- when :banish
- @banish.sort!{|a,b| a.card_id <=> b.card_id}
- when :extra
- @extra.sort!{|a,b| a.card_id <=> b.card_id}
- when :field
- @field.sort!{|a,b| a.card_id <=> b.card_id}
- end
- end
- #-----------------------------------------------------------------------------
- # Tries to put a specific card from your hand to your grave (new)
- #-----------------------------------------------------------------------------
- def card_to_grave?(id)
- for i in (0...@hand.length)
- if @hand[i].id == id
- @grave.push(@hand[i])
- @hand.delete_at(i)
- return true
- end
- end
- return false
- end
- #-----------------------------------------------------------------------------
- # Tries to put a specific card from your deck to your grave (new)
- #-----------------------------------------------------------------------------
- def card_from_deck_to_grave?(id)
- for i in (0...@deck.length)
- if @deck[i].id == id
- @grave.push(@deck[i])
- @deck.delete_at(i)
- return true
- end
- end
- return false
- end
- #-----------------------------------------------------------------------------
- # Tries to put a specific card from your hand to your banish (new)
- #-----------------------------------------------------------------------------
- def card_to_banish?(id)
- for i in (0...@hand.length)
- if @hand[i].id == id
- @banish.push(@hand[i])
- @hand.delete_at(i)
- return true
- end
- end
- return false
- end
- #-----------------------------------------------------------------------------
- # Tries to put a specific card from your hand to your stack (new)
- #-----------------------------------------------------------------------------
- def card_to_stack?(id)
- for i in (0...@hand.length)
- if @hand[i].id == id
- @stack.push(@hand[i])
- @hand.delete_at(i)
- return true
- end
- end
- return false
- end
- #-----------------------------------------------------------------------------
- # Tries to put a specific card from your field to your stack (new)
- #-----------------------------------------------------------------------------
- def card_to_field?(id)
- init_card_zones
- index_hand = @hand.index { |c| c.id == id }
- return false unless index_hand
- card = @hand[index_hand]
- index_field = @monster_zones.index(nil)
- return false unless index_field
- @monster_zones[index_field] = card
- @hand.delete_at(index_hand)
- return index_field
- end
- def card_face_down?(card)
- index = @monster_zones.index(card)
- return false unless index
- state = @monster_zones_state[index]
- return state ? state[:face_down] : false
- end
- def card_face_up?(card)
- index = @monster_zones.index(card)
- return false unless index
- state = @monster_zones_state[index]
- return state ? !state[:face_down] : true
- end
- #-----------------------------------------------------------------------------
- # Tries to put a specific spell/trap from hand to field (new)
- #-----------------------------------------------------------------------------
- def PRUEBAspell_to_field?(card)
- init_card_zones
- index_hand = @hand.index { |c| c.equal?(card) }
- return false unless index_hand
- if card.subtype == 27
- if @field_zone != nil
- @grave.push(@field_zone)
- @field.delete(@field_zone)
- end
- @field_zone = card
- @field.push(card)
- @hand.delete_at(index_hand)
- @field_zone_state ||= {}
- @field_zone_state[:face_down] = false
- @field_zone_state[:set_this_turn] = false
- return :field
- else
- index_field = @st_zones.index(nil)
- return false unless index_field
- @st_zones[index_field] = card
- @field.push(card)
- @hand.delete_at(index_hand)
- @st_zones_state ||= []
- @st_zones_state[index_field] ||= {}
- @st_zones_state[index_field][:face_down] = false
- @st_zones_state[index_field][:set_this_turn] = false
- return index_field
- end
- end
- def spell_to_field?(card)
- if card.subtype == 27
- idx_hand = self.hand.index { |c| c && c.equal?(card) }
- if self.field_zone != nil
- self.grave.push(self.field_zone)
- self.field.delete(self.field_zone)
- end
- self.hand.delete_at(idx_hand) if idx_hand
- self.field_zone = card
- self.field.push(card)
- self.field_zone_state = { face_down: false, set_this_turn: false }
- return :field
- else
- idx = self.st_zones.index(nil)
- idx_hand = self.hand.index { |c| c && c.equal?(card) }
- if idx && idx_hand
- self.hand.delete_at(idx_hand)
- self.st_zones[idx] = card
- self.field.push(card)
- self.st_zones_state ||= []
- self.st_zones_state[idx] = { face_down: false, set_this_turn: false }
- return idx
- end
- end
- return nil
- end
- #-----------------------------------------------------------------------------
- # Tries to put a specific card from your field to your graveyard (new)
- #-----------------------------------------------------------------------------
- def field_to_grave?(id)
- for i in (0...@field.length)
- if @field[i].id == id
- @grave.push(@field[i])
- @field.delete_at(i)
- return true
- end
- end
- return false
- end
- #-----------------------------------------------------------------------------
- # Puts n random cards from your field to your grave (new)
- #-----------------------------------------------------------------------------
- def send_field(n)
- amount_send_field = 0
- if n == 0
- amount_send_field += @field.size
- @grave += @field
- @field = []
- else
- n.times do
- break if @field.size == 0
- @grave.push(@field.slice!(rand(@field.size-1)))
- amount_send_field += 1
- end
- end
- end
- #-----------------------------------------------------------------------------
- # Puts n random card(s) TYPE from your field to your grave (new)
- #-----------------------------------------------------------------------------
- def send_card_from_field(n)
- for i in (0...@field.length)
- if @field[i].type == n
- @grave.push(@field[i])
- @field.delete_at(i)
- return true
- end
- end
- return false
- end
- #-----------------------------------------------------------------------------
- # Puts n random cards from your hand to your grave (new)
- #-----------------------------------------------------------------------------
- def throw_cards(n)
- amount_thrown_cards = 0
- if n == 0
- amount_thrown_cards += @hand.size
- @grave += @hand
- @hand = []
- else
- n.times do
- break if @hand.size == 0
- @grave.push(@hand.slice!(rand(@hand.size-1)))
- amount_thrown_cards += 1
- end
- end
- $game_variables[46] = amount_thrown_cards
- return amount_thrown_cards
- end
- #-----------------------------------------------------------------------------
- # Mill n random cards from your deck to your grave (new)
- #-----------------------------------------------------------------------------
- def mill_cards(n)
- amount_mill_cards = 0
- if n == 0
- amount_mill_cards += @deck.size
- @grave += @deck
- @deck = []
- else
- n.times do
- break if @deck.size == 0
- @grave.push(@deck.slice!(rand(@deck.size-1)))
- amount_mill_cards += 1
- end
- end
- end
- #-----------------------------------------------------------------------------
- # Puts n random cards from your hand to your banish (new)
- #-----------------------------------------------------------------------------
- def banish_cards(n)
- amount_banish_cards = 0
- if n == 0
- amount_banish_cards += @hand.size
- @banish += @hand
- @hand = []
- else
- n.times do
- break if @hand.size == 0
- @banish.push(@hand.slice!(rand(@hand.size-1)))
- amount_banish_cards += 1
- end
- end
- $game_variables[51] = amount_banish_cards
- return amount_banish_cards
- end
- #-----------------------------------------------------------------------------
- # Mill n random cards from your deck to your banish (new)
- #-----------------------------------------------------------------------------
- def mill_banish_cards(n)
- amount_mill_banish_cards = 0
- if n == 0
- amount_mill_banish_cards += @deck.size
- @banish += @deck
- @deck = []
- else
- n.times do
- break if @deck.size == 0
- @banish.push(@deck.slice!(rand(@deck.size-1)))
- amount_mill_banish_cards += 1
- end
- end
- end
- #-----------------------------------------------------------------------------
- # Banish n random cards from your extra (new)
- #-----------------------------------------------------------------------------
- def banish_extra_cards(n)
- amount_banish_extra_cards = 0
- if n == 0
- amount_banish_extra_cards += @extra.size
- @banish += @extra
- @extra = []
- else
- n.times do
- break if @extra.size == 0
- @banish.push(@extra.slice!(rand(@extra.size-1)))
- amount_banish_extra_cards += 1
- end
- end
- end
- #-----------------------------------------------------------------------------
- # Replace Field Spell
- #-----------------------------------------------------------------------------
- def replace_field_spell(id)
- for i in (0...@field.length)
- if @field[i].subtype == id
- @grave.push(@field[i])
- @field.delete_at(i)
- return true
- end
- end
- return false
- end
- #-----------------------------------------------------------------------------
- # Shuffles Deck and draws cards at the begin of each battle (new)
- #-----------------------------------------------------------------------------
- def on_battle_start
- super()
- shuffle_deck(false)
- draw_cards(starting_cards, false, false)
- @turn_actions[:can_attack] = true
- @turn_actions[:can_guard] = true
- @turn_actions[:actions] = available_actions
- end
- #-----------------------------------------------------------------------------
- # Starting Cards (new)
- #-----------------------------------------------------------------------------
- def starting_cards
- x = PC27::CG::START_CARDS
- @equips.each { |equip|
- next unless equip
- next unless equip.object
- x += equip.object.extra_start_cards
- }
- return x
- end
- #-----------------------------------------------------------------------------
- # Draws a card at the end of each turn (new)
- #-----------------------------------------------------------------------------
- def on_turn_end
- super()
- if self.respond_to?(:used_turn_effects) && self.used_turn_effects
- self.used_turn_effects.clear
- puts "[SISTEMA] Memoria de turnos limpiada para #{self.name} (on_turn_end)"
- end
- if self.monster_zones_state
- self.monster_zones_state.each do |state|
- state[:changed_this_turn] = false if state
- end
- end
- if self.respond_to?(:st_zones_state) && self.st_zones_state
- self.st_zones_state.each do |state|
- state[:set_this_turn] = false if state
- end
- end
- if $game_party.in_battle && !death_state?
- cannot_draw_state = self.states.any? { |state| state.note =~ /<cannot_draw>/i }
- unless cannot_draw_state
- draw_cards(turn_cards, true, false)
- valid_field_cards = []
- if self.respond_to?(:st_zones) && self.st_zones
- self.st_zones.each_with_index do |card, i|
- if card
- st_state = self.st_zones_state[i] rescue nil
- is_fd = st_state ? st_state[:face_down] : false
- valid_field_cards << card unless is_fd
- end
- end
- end
- if self.respond_to?(:field_zone) && self.field_zone
- f_state = self.field_zone_state rescue nil
- f_is_fd = f_state ? f_state[:face_down] : false
- valid_field_cards << self.field_zone unless f_is_fd
- end
- if valid_field_cards.any?
- PC27::LunaticCards.run_effects(valid_field_cards, self, :field, :ondrawphase, true)
- end
- end
- @turn_actions[:can_attack] = true
- @turn_actions[:can_guard] = true
- @turn_actions[:actions] = available_actions
- end
- end
- #-----------------------------------------------------------------------------
- # Determines the amount of actions an actor can make (new)
- #-----------------------------------------------------------------------------
- def available_actions
- for id in @states
- state = $data_states[id]
- if state.limited_actions != 0
- x = state.limited_actions if x.nil? || x > state.limited_actions
- end
- end
- if PC27::CG::MAX_ACTIONS <= 0
- return (x ? x : -1)
- else
- return (x ? [x, PC27::CG::MAX_ACTIONS].min : PC27::CG::MAX_ACTIONS)
- end
- end
- #-----------------------------------------------------------------------------
- # Turn Cards(new)
- #-----------------------------------------------------------------------------
- def turn_cards
- x = 1
- @equips.each { |equip|
- next unless equip
- next unless equip.object
- x += equip.object.extra_turn_cards
- if state?(82)
- x = 0
- end
- }
- return x
- end
- #-----------------------------------------------------------------------------
- # Restore deck at the end of battle (new)
- #-----------------------------------------------------------------------------
- def on_battle_end
- actual_field_cards = []
- actual_field_cards += @monster_zones.compact if @monster_zones
- actual_field_cards += @st_zones.compact if @st_zones
- if self.respond_to?(:card_in_zone)
- f_card = self.card_in_zone(:fieldspell, 0) rescue nil
- actual_field_cards << f_card if f_card
- end
- all_field_cards = (actual_field_cards + (@field || [])).uniq
- @deck += @hand + @grave + @banish + all_field_cards
- @deck.select! { |card| card.frame != 5 }
- @deck.select! { |card| card.type != 4 }
- @extra += @hand + @grave + @banish + all_field_cards
- @extra.select! { |card| card.type == 4 }
- @hand, @grave, @banish, @field = [], [], [], []
- @monster_zones = Array.new(5, nil) if @monster_zones
- @st_zones = Array.new(5, nil) if @st_zones
- if @monster_zones_state
- @monster_zones_state = Array.new(5) { { face_down: false, position: :attack, changed_this_turn: false } }
- end
- if @st_zones_state
- @st_zones_state = Array.new(5) { { face_down: false, set_this_turn: false } }
- end
- if @field_zone_state
- @field_zone_state = { face_down: false, set_this_turn: false }
- end
- @field_zone = nil if defined?(@field_zone)
- @field_spell = nil if defined?(@field_spell)
- super()
- end
- #--------------------------------------------------------------------------
- # * Determine Usability of Attack
- #--------------------------------------------------------------------------
- def attack_usable?
- super && @turn_actions[:can_attack]
- end
- #--------------------------------------------------------------------------
- # * Determine Usability of Guard
- #--------------------------------------------------------------------------
- def guard_usable?
- super && @turn_actions[:can_guard]
- end
- end
- #===============================================================================
- # Game_Party
- #===============================================================================
- class Game_Party < Game_Unit
- #-----------------------------------------------------------------------------
- # Attributes
- #-----------------------------------------------------------------------------
- attr_accessor :coll
- #-----------------------------------------------------------------------------
- # Adds a card collection to the party (alias)
- #-----------------------------------------------------------------------------
- alias pc27_gameparty_initialize initialize
- def initialize
- pc27_gameparty_initialize
- @coll = []
- end
- end
- #==============================================================================
- # Window_CardZoneLabel
- #==============================================================================
- class Window_CardZoneLabel < Window_Base
- def initialize(x, y)
- super(x, y, window_width, window_height)
- @text = ""
- refresh
- @icon_index = nil
- end
- def window_width
- 120
- end
- def window_height
- fitting_height(1)
- end
- def set_text(text, icon_index = nil)
- return if @text == text && @icon_index == icon_index
- @text = text
- @icon_index = icon_index
- refresh
- end
- def standard_padding
- 6
- end
- def refresh
- contents.clear
- contents.font.size = 22
- contents.font.bold = false
- icon_w = @icon_index ? 24 : 0
- text_w = text_size(@text).width
- w = icon_w + text_w + standard_padding * 2 + 8
- h = line_height + standard_padding * 2
- self.width = w
- self.height = h
- create_contents
- x = 0
- if @icon_index
- draw_icon(@icon_index, x, 0)
- x += 24 + 4
- end
- contents.font.italic = false
- contents.font.color = text_color(0)
- draw_text(x, 0, contents.width - x, line_height, @text)
- end
- end
- #===============================================================================
- # Window_SkillList
- #===============================================================================
- class Window_SkillList < Window_Selectable
- attr_accessor :cursor_opacity
- def initialize(x, y, width, height)
- super(x, y, Graphics.width, 300)
- @data = []
- @last_selected_index = nil
- @highlight_counter = 0
- make_item_list
- refresh
- end
- def create_contents
- self.contents.dispose if self.contents
- self.contents = Bitmap.new(
- width - padding * 2,
- height - padding * 2
- )
- end
- def make_item_list
- @actor ||= $game_party.battle_members[0]
- return @data = [] if @actor.nil?
- case @actor.current_zone
- when :hand
- @actor.sort_cards(:hand)
- @data = @actor.hand || []
- when :field
- @data = @actor.field || []
- when :graveyard
- @data = @actor.grave || []
- when :banish
- @data = @actor.banish || []
- when :extra
- @data = @actor.extra || []
- when :deck
- @data = @actor.deck || []
- else
- @data = @actor.hand || []
- end
- if @data.empty?
- self.index = -1 if respond_to?(:index=)
- else
- self.index = 0 if respond_to?(:index=) && (self.index.nil? || self.index < 0 || self.index >= @data.size)
- end
- end
- def refresh
- contents.clear if contents
- return if @data.nil? || @data.empty?
- selected_index = self.index
- selected_index = nil if selected_index.nil? || selected_index < 0 || selected_index >= @data.size
- unless selected_index
- (0...@data.size).to_a.reverse.each do |index|
- draw_item(index)
- end
- return
- end
- left_count = selected_index
- right_count = @data.size - selected_index - 1
- max_steps = [left_count, right_count].max
- (0..max_steps).each do |step|
- left_index = step
- draw_item(left_index) if left_index < selected_index
- right_index = @data.size - step - 1
- draw_item(right_index) if right_index > selected_index
- end
- draw_item(selected_index)
- draw_highlight(selected_index) if selected_index
- @last_selected_index = selected_index
- end
- def draw_item(index)
- card = @data[index]
- return unless card
- rect = item_rect(index)
- draw_card_illustration(card, rect.x, rect.y)
- is_grave_or_banish = false
- if self.is_a?(Window_CardSelect) && @zone_tags && @zone_tags[index]
- src = @zone_tags[index]
- is_grave_or_banish = true if src == :grave || src == :banish
- elsif @actor && [:graveyard, :grave, :banish].include?(@actor.current_zone)
- is_grave_or_banish = true
- end
- if is_grave_or_banish
- is_nomi = (card.note =~ /<special_only:/i)
- if is_nomi && !card.properly_summoned
- draw_icon(809, rect.x + 8, rect.y + 8)
- end
- end
- end
- def draw_card_illustration(card, x, y)
- bitmap = Cache.picture("Card" + card.id.to_s)
- return unless bitmap
- rect = Rect.new(0, 0, 190, 264)
- contents.blt(x, y, bitmap, rect)
- if card.instance_variable_get(:@banished_face_down)
- back_bitmap = Cache.picture("BackCard")
- contents.blt(x, y, back_bitmap, rect, 120) if back_bitmap
- end
- end
- def draw_highlight(index)
- return if index < 0 || index >= @data.size
- rect = item_rect(index)
- overlay = Cache.picture("blank_rectangle")
- return unless overlay
- opacity = 30 + (Math.sin(@highlight_counter / 20.0) * 64).abs
- overlay_opacity = opacity
- contents.blt(rect.x, rect.y, overlay, Rect.new(0, 0, overlay.width, overlay.height), overlay_opacity)
- end
- def item_rect(index)
- return Rect.new(0, 0, 0, 0) unless @data && !@data.empty?
- total_cards = @data.size
- card_width = 190
- card_height = 264
- usable_width = width - standard_padding * 2
- if total_cards > 1
- overlap = [(card_width * total_cards - usable_width) / (total_cards - 1), card_width].min
- overlap = [overlap, 0].max
- else
- overlap = 0
- end
- x = index * (card_width - overlap)
- y = 12
- Rect.new(x, y, card_width, card_height)
- end
- def item_height
- 276
- end
- def row_max
- 1
- end
- def contents_height
- height - standard_padding * 2
- end
- def ensure_cursor_visible
- end
- def cursor_visible?
- active && open? && !@cursor_all && @index >= 0
- end
- def update_cursor
- if @cursor_all
- cursor_rect.set(rect.x, rect.y, contents.width, contents.height)
- self.cursor_opacity = 255
- elsif @index < 0
- cursor_rect.empty
- self.cursor_opacity = 0
- else
- rect = item_rect(@index)
- cursor_rect.set(rect.x, rect.y, rect.width, rect.height)
- self.cursor_opacity = cursor_visible? ? 255 : 0
- end
- end
- def update
- super
- if @last_index != self.index
- @last_index = self.index
- refresh
- end
- @highlight_counter += 1
- refresh if @highlight_counter % 1 == 0
- end
- def cursor_down(wrap = false); end
- def cursor_up(wrap = false); end
- def cursor_right(wrap = false)
- return if item_max <= 0
- self.index = (self.index + 1) % item_max
- end
- def cursor_left(wrap = false)
- return if item_max <= 0
- self.index = (self.index - 1) % item_max
- end
- alias pc27_process_ok_graveblock process_ok
- def process_ok
- actor = BattleManager.actor
- return pc27_process_ok_graveblock unless actor
- if actor.current_zone == :graveyard
- skill = item
- if skill.nil?
- Sound.play_buzzer
- return
- end
- unless card_has_grave_effect?(skill)
- Sound.play_buzzer
- return
- end
- end
- pc27_process_ok_graveblock
- end
- def card_has_grave_effect?(skill)
- skill.note =~ /<grave[-_ ]?effect/i || skill.note =~ /<grave/i
- end
- def monster_has_hand_effect?(skill)
- skill.note =~ /<hand[-_ ]?effect>/i || skill.note =~ /<hand/i
- end
- end
- #===============================================================================
- # Window_ActorCommand
- #===============================================================================
- class Window_ActorCommand < Window_Command
- #--------------------------------------------------------------------------
- # Add "End Turn" command (new)
- #--------------------------------------------------------------------------
- def add_turn_end_command
- add_command(PC27::CG::END_TURN, :end_turn)
- end
- #--------------------------------------------------------------------------
- # Add "Grave" command (new)
- #--------------------------------------------------------------------------
- def add_look_at_grave_command
- add_command(PC27::CG::GRAVE, :look_grave)
- end
- #--------------------------------------------------------------------------
- # Add "Banish" command (new)
- #--------------------------------------------------------------------------
- def add_look_at_banish_command
- add_command(PC27::CG::BANISH, :look_banish)
- end
- #--------------------------------------------------------------------------
- # Add "Extra" command (new)
- #--------------------------------------------------------------------------
- def add_look_at_extra_command
- add_command(PC27::CG::EXTRA, :look_extra)
- end
- #--------------------------------------------------------------------------
- # Add "Field" command (new)
- #--------------------------------------------------------------------------
- def add_look_at_field_command
- add_command(PC27::CG::FIELD, :look_field)
- end
- #--------------------------------------------------------------------------
- # Make new command List (overwrite)
- #--------------------------------------------------------------------------
- def make_command_list
- return unless @actor
- add_attack_command if PC27::CG::USE_ATTACK
- add_guard_command if PC27::CG::USE_GUARD
- add_skill_commands
- add_item_command if PC27::CG::USE_ITEMS
- add_look_at_grave_command
- add_look_at_banish_command
- add_look_at_extra_command
- add_look_at_field_command
- add_turn_end_command
- end
- end
- #===============================================================================
- # Window_BattleStatus
- #===============================================================================
- class Window_BattleStatus < Window_Selectable
- #--------------------------------------------------------------------------
- # Add deck to Draw Item (alias)
- #--------------------------------------------------------------------------
- alias pc27_cardgame_wndbttlstat_draw_item draw_item
- def draw_item(index)
- pc27_cardgame_wndbttlstat_draw_item(index)
- actor = $game_party.battle_members[index]
- draw_deck_area(deck_area_rect(index), actor)
- end
- #--------------------------------------------------------------------------
- # Shrink basic rect (overwrite)
- #--------------------------------------------------------------------------
- def basic_area_rect(index)
- rect = item_rect_for_text(index)
- rect.width -= gauge_area_width + deck_area_width + 10
- rect
- end
- #--------------------------------------------------------------------------
- # Get Deck rect (new)
- #--------------------------------------------------------------------------
- def deck_area_rect(index)
- rect = item_rect_for_text(index)
- rect.x += rect.width - gauge_area_width - deck_area_width
- rect.width = deck_area_width
- rect
- end
- #--------------------------------------------------------------------------
- # Get Deck Area Width (new)
- #--------------------------------------------------------------------------
- def deck_area_width
- return 48
- end
- #--------------------------------------------------------------------------
- # Draw Deck Area (new)
- #--------------------------------------------------------------------------
- def draw_deck_area(rect, actor)
- draw_icon(PC27::CG::DECK_ICON, rect.x + 246, rect.y + 43)
- draw_text(rect.x + 248, rect.y + 12, 80, rect.height, actor.deck.size.to_s)
- end
- end
- #===============================================================================
- # Window_SkillList
- #===============================================================================
- class Window_BattleSkill < Window_SkillList
- #-----------------------------------------------------------------------------
- # changes the BattleSkillList Window layout (overwrite)
- #-----------------------------------------------------------------------------
- def initialize(help_window, info_viewport)
- y = 0
- super(0, 0, (Graphics.width - 210) * 0.7, info_viewport.rect.y)
- self.visible = false
- @help_window = help_window
- @info_viewport = info_viewport
- end
- #--------------------------------------------------------------------------
- # * Display Skill in Active State?
- #--------------------------------------------------------------------------
- def enable?(item)
- return false unless item
- return true if @actor && @actor.current_zone == :hand
- return false unless @actor.skill_cost_payable?(item)
- return false unless @actor.custom_req_met?(item)
- if item.note =~ /<card_id:\s*(\d+)>/i
- impact_name = PC27::CG::SKILL_IMPACT[item.id]
- if impact_name
- return false unless @actor.can_activate_impact?(impact_name)
- end
- end
- return true
- end
- end
- #===============================================================================
- # Window CardHelp (new)
- #===============================================================================
- class Window_CardHelp < Window_Base
- include PC27::CG
- def initialize()
- super(Graphics.width - 200, 10, 190, 264)
- self.windowskin = Cache.system(PC27::CG::CUSTOM_CARD_BG) if PC27::CG::CUSTOM_CARD_BG
- @card = nil
- refresh
- end
- def set_text(card)
- if card != @card
- @card = card
- refresh
- end
- end
- def set_item(item)
- set_text(item)
- end
- def refresh
- contents.clear
- draw_card_pic(@card)
- end
- def draw_card_pic(item)
- if item
- draw_card_illustration(item) rescue draw_card_text(item)
- else
- draw_card_illustration_no_card rescue nil
- end
- end
- def draw_card_illustration_no_card
- contents.dispose
- self.contents = Bitmap.new(190, 264)
- bitmap = Cache.picture("BackCard")
- self.padding = 0
- rect = Rect.new(0, 0, 190, 264)
- contents.blt(0, 0, bitmap, rect, 255)
- bitmap.dispose
- end
- def draw_card_illustration(item)
- contents.dispose
- self.contents = Bitmap.new(190, 264)
- bitmap = Cache.picture("Card" + item.id.to_s)
- self.padding = 0
- rect = Rect.new(0, 0, 190, 264)
- contents.blt(0, 0, bitmap, rect, 255)
- bitmap.dispose
- end
- def draw_card_text(item)
- create_contents
- self.padding = standard_padding
- draw_text_ex(0, 0, item.name)
- end
- def update_tone; end
- def update_padding; end
- end
- #===============================================================================
- # Window_CardSelect (new)
- #===============================================================================
- class Window_CardSelect < Window_SkillList
- attr_accessor :actor
- attr_accessor :cards
- attr_accessor :sort_index
- attr_accessor :filter
- attr_accessor :dry_run_eff2
- attr_accessor :zone_tags
- def initialize(help_window, info_viewport)
- super(0, 0, (Graphics.width - 210) * 0.7, info_viewport.rect.y)
- self.visible = false
- @help_window = help_window
- @info_viewport = info_viewport
- @filter = [0,0,0,0,0,0,0,0,0,0]
- @cards = []
- @zone_tags = []
- @sort_index = -1
- end
- def make_item_list
- @data = @cards ? @cards.dup : []
- if SceneManager.scene.is_a?(Scene_Battle)
- scene = SceneManager.scene
- effect_data = scene.instance_variable_get(:@temp_effect_data)
- if effect_data && effect_data[1] && PC27::CG::CARD_EFFECT[effect_data[1]]
- destination = PC27::CG::CARD_EFFECT[effect_data[1]][5]
- if [:special_summon, :special_summon_def, :special_summon_atk].include?(destination)
- @data.reject! do |card|
- is_nomi = (card.note =~ /<special_only:/i)
- is_nomi && !card.properly_summoned
- end
- end
- end
- end
- end
- def enable?(item)
- return false unless item
- return false if @actor.nil?
- active_c = nil
- scene = SceneManager.scene
- if scene.is_a?(Scene_Battle)
- active_c = scene.instance_variable_get(:@active_effect_card)
- end
- sim_lvl = $chain_memory_card ? $chain_memory_card.level : nil
- return false unless @actor.match_complex_filter?(item, @filter, active_c, sim_lvl)
- if @dry_run_eff2
- eff2_data = PC27::CG::CARD_EFFECT[@dry_run_eff2]
- if eff2_data
- eff2_filter = eff2_data[4]
- eff2_zone = eff2_data[2]
- sim_lvl2 = item.level
- has_target = false
- if [:deck, :hand_or_deck].include?(eff2_zone)
- has_target ||= @actor.deck.any? { |c| @actor.match_complex_filter?(c, eff2_filter, active_c, sim_lvl2) }
- end
- if [:hand, :hand_or_deck, :hand_or_grave, :hand_or_field].include?(eff2_zone)
- has_target ||= @actor.hand.any? { |c| c != item && @actor.match_complex_filter?(c, eff2_filter, active_c, sim_lvl2) }
- end
- if [:grave, :hand_or_grave].include?(eff2_zone)
- has_target ||= @actor.grave.any? { |c| c != item && @actor.match_complex_filter?(c, eff2_filter, active_c, sim_lvl2) }
- end
- return false unless has_target
- end
- end
- return true
- end
- def match_single_filter?(item, f)
- return false unless item.attribute == f[0] || f[0] == 0
- return false unless item.type == f[1] || f[1] == 0
- return false unless item.rarity == f[2] || f[2] == 0
- return false unless item.subtype == f[3] || f[3] == 0
- lvl_check = f[4]
- if lvl_check == :destroyed_level
- scene = SceneManager.scene
- if scene.is_a?(Scene_Battle)
- temp_data = scene.instance_variable_get(:@temp_effect_data)
- lvl_check = temp_data[4].level if temp_data && temp_data[4]
- end
- lvl_check = 0 unless lvl_check.is_a?(Numeric)
- end
- if f[4].is_a?(Range)
- return false unless f[4].include?(item.level)
- elsif lvl_check != 0
- return false unless item.level == lvl_check
- end
- return false unless item.normeff == f[5] || f[5] == 0
- return false unless item.frame == f[6] || f[6] == 0
- return false unless item.archetype == f[7] || f[7] == 0
- return false unless item.atk == f[8] || f[8] == 0
- return false unless item.def == f[9] || f[9] == 0
- return false unless item.special == f[10]|| f[10] == 0
- if f[11] == :exclude_active
- scene = SceneManager.scene
- if scene.is_a?(Scene_Battle)
- active_card = scene.instance_variable_get(:@active_effect_card)
- return false if active_card && active_card.id == item.id
- end
- end
- return true
- end
- def show
- super
- activate
- select(0) if @data && !@data.empty?
- end
- def activate
- self.active = true
- end
- def hide
- @help_window.hide
- super
- end
- alias archo_draw_item draw_item
- def draw_item(index)
- archo_draw_item(index)
- source = @zone_tags[index] if @zone_tags
- if source
- rect = item_rect(index)
- icon_id = nil
- icon_id = 1015 if source == :field
- icon_id = 800 if source == :hand
- icon_id = 801 if source == :grave # Icono Cementerio
- icon_id = 783 if source == :deck # Icono Mazo
- draw_icon(icon_id, rect.x + 190 - 28, rect.y + 4) if icon_id
- end
- end
- end
- #===============================================================================
- # Field Map
- #===============================================================================
- class Window_FieldMap < Window_Selectable
- attr_accessor :actor
- attr_accessor :preview_window
- def initialize(x, y, actor)
- @actor = actor
- super(0, 0, Graphics.width, 300)
- @zones = []
- make_zone_list
- select(0)
- activate
- refresh
- end
- alias fieldmap_select select
- def select(index)
- fieldmap_select(index)
- update_preview
- end
- def refresh
- contents.clear
- draw_all_items
- end
- def update
- super
- end
- def update_preview
- return unless @preview_window
- return unless @actor
- zone, i = current_zone
- card = @actor.card_in_zone(zone, i)
- @preview_window.set_card(card)
- end
- def make_zone_list
- @zones = []
- 5.times { |i| @zones << [:monster, i] }
- 5.times { |i| @zones << [:spell, i] }
- @zones << [:fieldspell, 0]
- end
- def item_max
- @zones ? @zones.size : 0
- end
- def item_rect(index)
- rect = Rect.new
- zone, i = @zones[index]
- base_x = 40
- case zone
- when :monster
- rect.x = base_x + i * 48
- rect.y = 120
- when :spell
- rect.x = base_x + i * 48
- rect.y = 180
- when :fieldspell
- rect.x = base_x + 2 * 48
- rect.y = 60
- end
- rect.width = 24; rect.height = 24
- rect
- end
- def draw_item(index)
- zone, i = @zones[index]
- rect = item_rect(index)
- actor = @actor || BattleManager.actor
- card = actor.card_in_zone(zone, i) rescue nil
- if card
- is_fd = false
- if zone == :monster
- states = actor.monster_zones_state rescue nil
- state = states ? states[i] : { face_down: false, position: :attack }
- is_fd = state[:face_down]
- if is_fd
- draw_icon(840, rect.x, rect.y)
- else
- draw_icon(card.icon_index, rect.x, rect.y)
- end
- pos_icon = (state[:position] == :defense) ? 526 : 525
- draw_icon(pos_icon, rect.x + 4, rect.y + 4)
- elsif zone == :spell
- states = actor.st_zones_state rescue nil
- state = states ? states[i] : nil
- is_fd = state && state[:face_down]
- if is_fd
- draw_icon(840, rect.x, rect.y)
- else
- draw_icon(card.icon_index, rect.x, rect.y)
- end
- elsif zone == :fieldspell
- f_state = actor.field_zone_state rescue nil
- is_fd = f_state && f_state[:face_down]
- if is_fd
- draw_icon(840, rect.x, rect.y)
- else
- draw_icon(card.icon_index, rect.x, rect.y)
- end
- else
- draw_icon(card.icon_index, rect.x, rect.y)
- end
- draw_card_counters(actor, card, rect.x, rect.y, false) unless is_fd
- else
- case zone
- when :monster then draw_icon(1019, rect.x, rect.y)
- when :spell then draw_icon(1020, rect.x, rect.y)
- when :fieldspell then draw_icon(1021, rect.x, rect.y)
- end
- end
- end
- def cursor_up(wrap = false)
- zone, i = @zones[index]
- case zone
- when :monster
- select(10)
- when :spell
- select(i)
- end
- end
- def cursor_down(wrap = false)
- zone, i = @zones[index]
- case zone
- when :monster
- select(5 + i)
- when :fieldspell
- select(0)
- end
- end
- def cursor_left(wrap = false)
- return if index == 10
- select([index - 1, row_start(index)].max)
- end
- def cursor_right(wrap = false)
- return if index == 10
- select([index + 1, row_end(index)].min)
- end
- def row_start(index)
- return 10 if index == 10
- index < 5 ? 0 : 5
- end
- def row_end(index)
- return 10 if index == 10
- index < 5 ? 4 : 9
- end
- def current_zone
- @zones[index]
- end
- end
- #===============================================================================
- # Field Preview
- #===============================================================================
- class Window_FieldPreview < Window_Base
- def standard_padding
- return 0
- end
- def initialize(x, y)
- super(Graphics.width - 200, 10, 190, 264)
- self.z = 150
- self.opacity = 0
- self.back_opacity = 0
- @current_card = nil
- refresh
- end
- def set_card(card)
- return if @current_card == card
- @current_card = card
- refresh
- end
- def refresh
- contents.clear
- picture_name =
- if @current_card
- "Card#{@current_card.id}"
- else
- "BackCard"
- end
- bitmap = Cache.picture(picture_name)
- x = (contents.width - bitmap.width) / 2
- y = (contents.height - bitmap.height) / 2
- contents.blt(x, y, bitmap, bitmap.rect)
- draw_dynamic_stats(@current_card, x, y)
- end
- def draw_dynamic_stats(card, base_x, base_y)
- return unless card
- return unless card.type == 3
- base_atk = card.atk rescue 0
- base_def = card.def rescue 0
- real_atk = BattleManager.actor.current_monster_atk(card, "at_field")
- real_def = BattleManager.actor.current_monster_def(card, "at_field")
- if real_atk != base_atk || real_def != base_def
- ajuste_x_atk = 40
- ajuste_x_def = 100
- ajuste_y = 150
- rect_w = 140
- rect_h = 20
- cover_color = Color.new(0, 0, 0, 220)
- contents.fill_rect(base_x + ajuste_x_atk, base_y + ajuste_y, rect_w, rect_h, cover_color)
- old_size = contents.font.size
- contents.font.bold = true
- atk_text = "ATK:#{real_atk}"
- if atk_text.length >= 12
- contents.font.size = 18
- elsif atk_text.length >= 10
- contents.font.size = 19
- else
- contents.font.size = 20
- end
- if real_atk > base_atk
- change_color(text_color(3))
- elsif real_atk < base_atk
- change_color(text_color(2))
- else
- change_color(normal_color)
- end
- draw_text(base_x + ajuste_x_atk, base_y + ajuste_y, 60, rect_h, atk_text, 0)
- def_text = "DEF:#{real_def}"
- if def_text.length >= 12
- contents.font.size = 18
- elsif def_text.length >= 10
- contents.font.size = 19
- else
- contents.font.size = 20
- end
- if real_def > base_def
- change_color(text_color(3))
- elsif real_def < base_def
- change_color(text_color(2))
- else
- change_color(normal_color)
- end
- draw_text(base_x + ajuste_x_def, base_y + ajuste_y, 60, rect_h, def_text, 0)
- contents.font.size = old_size
- contents.font.bold = false
- change_color(normal_color)
- end
- end
- end
- #===============================================================================
- # Scene_Battle
- #===============================================================================
- class Scene_Battle < Scene_Base
- include FlowTrace
- ZONE_LABELS = {
- hand: ["Hand", 800],
- field: ["Field", 1015],
- grave: ["Graveyard", 801],
- graveyard: ["Graveyard", 801],
- banish: ["Banish", 806],
- extra: ["Extra", 815],
- deck: ["Deck", 783],
- hand_or_field: ["Hand & Field", 800],
- hand_or_grave: ["Hand & Graveyard", 800],
- hand_or_deck: ["Hand & Deck", 800]
- }
- alias pc27_turn_start_fix turn_start unless method_defined?(:pc27_turn_start_fix)
- def turn_start
- pc27_turn_start_fix
- if BattleManager.actor
- BattleManager.actor.used_turn_effects.clear
- BattleManager.actor.monster_zones_state.each do |state|
- state[:changed_this_turn] = false if state
- end
- end
- @pending_triggers ||= []
- end
- def prior_command
- start_actor_command_selection
- end
- alias rescate_seguro_on_skill_cancel on_skill_cancel
- def on_skill_cancel
- rescate_seguro_on_skill_cancel
- if @actor_command_window
- @actor_command_window.show
- @actor_command_window.activate
- end
- end
- def update_field_preview
- return unless @field_map_window && @field_map_window.active
- zone, index = @field_map_window.current_zone
- card = BattleManager.actor.card_in_zone(zone, index)
- @field_preview_window.set_card(card)
- end
- def command_skill
- @skill_window.make_item_list
- @skill_window.refresh
- @skill_window.show
- @skill_window.activate
- end
- def on_field_map_ok
- zone, index = @field_map_window.current_zone
- actor = BattleManager.actor
- card = @pending_card
- if actor.card_to_field?(card.id, zone, index)
- Sound.play_ok
- @field_map_window.refresh
- @field_preview_window.set_card(nil)
- @pending_card = nil
- skill_select(1)
- else
- Sound.play_buzzer
- end
- end
- def on_field_ok
- zone_type, zone_index = @field_map_window.current_zone
- card = BattleManager.actor.card_in_zone(zone_type, zone_index)
- @selected_card = card
- if @targeting_mode
- if card
- filter = @targeting_filter
- sim_lvl = $chain_memory_card ? $chain_memory_card.level : nil
- ok = BattleManager.actor.match_complex_filter?(card, filter, @active_effect_card, sim_lvl, zone_index)
- if ok && filter.is_a?(Array)
- f_str = filter.flatten.map(&:to_s)
- if f_str.include?("exclude_itself")
- if @active_effect_card && @active_effect_zone_index
- if zone_type == @active_effect_zone_type && zone_index == @active_effect_zone_index
- ok = false
- end
- end
- end
- end
- if ok
- @targeting_mode = false
- @temp_effect_data[3] = [card]
- BattleManager.actor.field.delete(card)
- if zone_type == :monster
- BattleManager.actor.monster_zones[zone_index] = nil
- end
- @field_map_window.hide
- @field_map_window.deactivate
- @field_preview_window.hide if @field_preview_window
- $game_message.clear
- restore_taken_cards(:proceed)
- else
- Sound.play_buzzer
- @field_map_window.activate
- end
- else
- Sound.play_buzzer
- @field_map_window.activate
- end
- return
- end
- if card
- options = []
- disabled_indices = []
- can_eff = BattleManager.actor.can_activate_field_effect?(card)
- options << "Activate Effect" if can_eff
- if zone_type == :monster
- state = BattleManager.actor.monster_zones_state[zone_index]
- can_change = !state[:changed_this_turn]
- if can_change
- if state[:face_down]
- options << "Flip Summon"
- else
- options << (state[:position] == :attack ? "Change to Defense" : "Change to Attack")
- end
- end
- end
- if zone_type == :spell
- st_states = BattleManager.actor.st_zones_state rescue nil
- st_state = st_states ? st_states[zone_index] : nil
- if st_state && st_state[:face_down]
- options << "Activate"
- can_act = true
- impact_name = nil
- if card.note =~ /<card impact:\s*(.+?)>/i || card.note =~ /<spell_impact:\s*(.+?)>/i || card.note =~ /<hand_impact:\s*(.+?)>/i
- impact_name = $1.to_s.strip
- end
- can_act = false if impact_name && !BattleManager.actor.can_activate_impact?(impact_name)
- can_act = false unless BattleManager.actor.custom_req_met?(card)
- can_act = false unless BattleManager.actor.can_pay_card_cost?(card)
- can_act = false if card.note =~ /<reactive_only>/i
- can_act = false if card.respond_to?(:mp_cost) && BattleManager.actor.mp < card.mp_cost
- is_trap = (card.type == 2)
- is_quick_play = (card.subtype == 25)
- if st_state[:set_this_turn] && (is_trap || is_quick_play)
- can_act = false
- end
- can_act = false if BattleManager.actor.hopt_blocked?(card, impact_name)
- disabled_indices << (options.size - 1) unless can_act
- end
- elsif zone_type == :fieldspell
- f_state = BattleManager.actor.field_zone_state rescue nil
- if f_state && f_state[:face_down]
- options << "Activate"
- can_act = true
- impact_name = nil
- if card.note =~ /<card impact:\s*(.+?)>/i || card.note =~ /<spell_impact:\s*(.+?)>/i || card.note =~ /<hand_impact:\s*(.+?)>/i
- impact_name = $1.to_s.strip
- end
- can_act = false if impact_name && !BattleManager.actor.can_activate_impact?(impact_name)
- can_act = false unless BattleManager.actor.custom_req_met?(card)
- can_act = false if card.respond_to?(:mp_cost) && BattleManager.actor.mp < card.mp_cost
- can_act = false if BattleManager.actor.hopt_blocked?(card, impact_name)
- disabled_indices << (options.size - 1) unless can_act
- end
- end
- options << "Cancel"
- if options.size > 1
- show_advanced_options(options, disabled_indices) do |choice|
- selected = options[choice]
- $game_message.choice_proc = nil
- $game_message.clear
- if @message_window
- choice_window = @message_window.instance_variable_get(:@choice_window)
- choice_window.openness = 0 if choice_window
- @message_window.openness = 0
- @message_window.visible = false
- end
- case selected
- when "Activate Effect"
- @field_map_window.hide
- @field_map_window.deactivate
- @field_preview_window.hide if @field_preview_window
- @current_card_action = :field_effect
- @active_effect_card = card
- @active_effect_zone_type = zone_type
- @active_effect_zone_index = zone_index
- eff_name = nil
- if card.note =~ /<field_impact:\s*(.+?)>/i || card.note =~ /<field impact:\s*(.+?)>/i
- eff_name = $1.to_s.strip
- end
- BattleManager.actor.used_turn_effects << eff_name if eff_name
- if card.note =~ /<shared_opt:\s*(.+?)>/i
- BattleManager.actor.used_turn_effects << $1.to_s.strip
- end
- resolve_card_effect(card)
- when "Activate"
- if zone_type == :fieldspell
- active_state = BattleManager.actor.field_zone_state
- else
- active_state = BattleManager.actor.st_zones_state[zone_index]
- end
- active_state[:face_down] = false
- if @field_map_window
- @field_map_window.dispose
- @field_map_window = nil
- end
- if @field_preview_window
- @field_preview_window.dispose
- @field_preview_window = nil
- end
- @field_ui_created = false
- @field_zone_label.hide if @field_zone_label
- @skill = card
- @selected_card = card
- @current_card_action = :field_effect
- @active_effect_card = card
- @active_effect_zone_type = zone_type
- @active_effect_zone_index = zone_index
- impact_name = nil
- if card.note =~ /<card impact:\s*(.+?)>/i || card.note =~ /<spell_impact:\s*(.+?)>/i || card.note =~ /<hand_impact:\s*(.+?)>/i
- impact_name = $1.to_s.strip
- end
- BattleManager.actor.used_turn_effects << impact_name if impact_name
- if card.note =~ /<shared_opt:\s*(.+?)>/i
- BattleManager.actor.used_turn_effects << $1.to_s.strip
- end
- restore_skill_window_layout
- refresh_card_zone_label
- @card_zone_label.show if @card_zone_label
- if impact_name
- resolve_card_effect(card)
- else
- @active_effect_card = nil
- @current_processing_card = nil
- $temp_active_card = nil
- $chain_memory_card = nil
- create_field_ui unless @field_ui_created rescue nil
- end
- when "Change to Defense"
- state[:position] = :defense
- state[:changed_this_turn] = true
- @field_map_window.refresh
- @field_map_window.activate
- when "Change to Attack"
- state[:position] = :attack
- state[:changed_this_turn] = true
- @field_map_window.refresh
- @field_map_window.activate
- when "Flip Summon"
- state[:position] = :attack
- state[:face_down] = false
- state[:changed_this_turn] = true
- @field_map_window.refresh
- @field_map_window.activate
- when "Cancel"
- @field_map_window.activate
- end
- end
- else
- Sound.play_buzzer
- @field_map_window.activate
- end
- else
- Sound.play_buzzer
- @field_map_window.activate
- end
- end
- alias pc27_cg_process_action_end process_action_end
- def process_action_end
- pc27_cg_process_action_end
- if @pending_triggers && @pending_triggers.size > 0
- check_pending_triggers
- end
- end
- #--------------------------------------------------------------------------
- # Efecto con monedas!
- #--------------------------------------------------------------------------
- def process_coin_toss(num_coins, conditions_text)
- @is_interrupt_effect = true # Clavamos los frenos de la batalla
- results = []
- sprites = []
- offsets = case num_coins
- when 1 then [0]
- when 2 then [-50, 50]
- when 3 then [-70, 0, 70]
- else Array.new(num_coins, 0)
- end
- num_coins.times do |i|
- res = (rand(2) == 0 ? :heads : :tails)
- results << res
- anim_id = (res == :heads ? 136 : 137)
- dummy = Sprite_Base.new(nil)
- dummy.bitmap = Bitmap.new(1, 1)
- dummy.x = (Graphics.width / 2) + offsets[i]
- dummy.y = (Graphics.height / 2) - 50
- anim = $data_animations[anim_id]
- dummy.start_animation(anim, false) if anim
- sprites << dummy
- if i < num_coins - 1
- 20.times do
- sprites.each { |s| s.update }
- update_basic
- end
- end
- end
- while sprites.any? { |s| s.animation? }
- sprites.each { |s| s.update }
- update_basic
- end
- sprites.each { |s| s.dispose }
- txt_res = results.map { |r| r == :heads ? "Heads" : "Tails" }.join(", ")
- $game_message.clear
- if @message_window
- @message_window.openness = 255
- @message_window.visible = true
- end
- $game_message.background = 1
- $game_message.position = 1
- $game_message.add("Coin Toss Result:")
- $game_message.add(txt_res + "!")
- wait_for_message
- # ===================================================================
- # SISTEMA: SECOND COIN TOSS
- # ===================================================================
- player = @active_effect_owner || BattleManager.actor || $game_party.members[0]
- available_repeaters = []
- if player.respond_to?(:st_zones)
- player.st_zones.each_with_index do |c, i|
- next unless c && c.note =~ /<repeat coin>/i
- state = player.st_zones_state[i] rescue nil
- next if state && state[:face_down] # Tiene que estar boca arriba
- # Soft Once Per Turn: Usamos el ID interno del objeto en el motor
- player.used_turn_effects ||= []
- next if player.used_turn_effects.include?("repeat_coin_#{c.object_id}")
- available_repeaters << c
- end
- end
- # Si encontramos al menos una copia válida y es el jugador (no la IA)
- if available_repeaters.size > 0 && player.actor?
- $game_message.clear
- if @message_window
- @message_window.openness = 0
- @message_window.visible = true
- end
- $game_message.background = 1
- $game_message.position = 1
- $game_message.add("Activate Second Coin Toss to retry?")
- @status_window.hide if respond_to?(:@status_window) && @status_window
- @status_back_window.hide if respond_to?(:@status_back_window) && @status_back_window
- show_options(["Yes", "No"], 2) do |choice|
- @status_window.show if respond_to?(:@status_window) && @status_window
- @status_back_window.show if respond_to?(:@status_back_window) && @status_back_window
- $game_message.choice_proc = nil
- $game_message.clear
- if @message_window
- choice_window = @message_window.instance_variable_get(:@choice_window)
- choice_window.openness = 0 if choice_window
- end
- if choice == 0
- # ¡ELIGIO REPETIR!
- repeater = available_repeaters[0]
- # Marcamos esta copia física específica como usada
- player.used_turn_effects << "repeat_coin_#{repeater.object_id}"
- # Llamada recursiva: Borrón y cuenta nueva
- process_coin_toss(num_coins, conditions_text)
- else
- # ¡ELIGIO NO REPETIR! Continuamos a la Parte 2.
- finalize_coin_toss(results, num_coins, conditions_text)
- end
- end
- wait_for_message
- return # Cortamos acá porque el futuro se decide adentro del bloque de arriba
- end
- # Si no tenías Second Coin Toss, pasamos directo a la Parte 2
- finalize_coin_toss(results, num_coins, conditions_text)
- end
- #==============================================================================
- # MOTOR DE MONEDAS: PARTE 2 (Traducción y Resolución)
- #==============================================================================
- def finalize_coin_toss(results, num_coins, conditions_text)
- heads_count = results.count(:heads)
- tails_count = results.count(:tails)
- final_impact = nil
- conditions_text.split("\n").each do |line|
- next if line.strip.empty?
- if line =~ /(heads|tails)(?:,\s*(\d+)(?:\.\.(\d+))?)?\s*:\s*(.+)/i
- face = $1.downcase.to_sym
- min = $2 ? $2.to_i : 1
- max = $3 ? $3.to_i : ($2 ? $2.to_i : num_coins)
- effect = $4.strip
- count_to_check = face == :heads ? heads_count : tails_count
- if count_to_check >= min && count_to_check <= max
- final_impact = effect
- break
- end
- end
- end
- @is_interrupt_effect = false # Soltamos los frenos
- if final_impact
- invoke_card_impact(final_impact)
- else
- finish_proceed_selection
- end
- end
- #--------------------------------------------------------------------------
- # Animación Visual de Mezclar el Mazo (Scene_Battle) - VERSIÓN NATIVA
- #--------------------------------------------------------------------------
- def show_deck_shuffle_visuals
- if @card_zone_label
- @card_zone_label.hide
- @card_zone_label.visible = false
- end
- if @field_zone_label
- @field_zone_label.hide
- @field_zone_label.visible = false
- end
- if @log_window && @shuffle_message
- @log_window.clear
- @log_window.add_text(@shuffle_message)
- @shuffle_message = nil
- @added_card_name = nil
- end
- cx = Graphics.width / 2
- cy = (Graphics.height / 2) - 40
- sprites = []
- 3.times do |i|
- s = Sprite.new
- begin
- s.bitmap = Cache.picture("BackCard")
- rescue
- s.bitmap = Bitmap.new(190, 264)
- end
- s.ox = s.bitmap.width / 2
- s.oy = s.bitmap.height / 2
- s.x = cx
- s.y = cy
- s.z = 400 + i
- s.zoom_x = 0.80
- s.zoom_y = 0.80
- sprites << s
- end
- 4.times do
- RPG::SE.new(PC27::CG::DRAW_SOUND[0], 100, 150).play rescue nil
- 8.times do
- sprites[0].x -= 10
- sprites[2].x += 10
- sprites.each(&:update)
- @card_zone_label.visible = false if @card_zone_label
- update_basic
- end
- RPG::SE.new(PC27::CG::DRAW_SOUND[0], 100, 100).play rescue nil
- sprites[0].z, sprites[2].z = sprites[2].z, sprites[0].z
- 8.times do
- sprites[0].x += 10
- sprites[2].x -= 10
- sprites.each(&:update)
- @card_zone_label.visible = false if @card_zone_label
- update_basic
- end
- end
- sprites.each do |s|
- s.bitmap.dispose if s.bitmap
- s.dispose
- end
- @log_window.clear if @log_window
- end
- #--------------------------------------------------------------------------
- # Muestra los efectos visuales de Invocación (Escalado 80% y HUD intacto)
- #--------------------------------------------------------------------------
- def show_special_summon_visuals(card, is_special = false)
- BattleManager.actor.used_turn_effects ||= []
- BattleManager.actor.used_turn_effects << "special_summon_performed"
- return unless card
- player = @active_effect_owner || BattleManager.actor || $game_party.members[0]
- if @card_zone_label
- @card_zone_label.hide
- @card_zone_label.visible = false
- end
- if @field_zone_label
- @field_zone_label.hide
- @field_zone_label.visible = false
- end
- @skill_window.hide if @skill_window
- if @log_window
- @log_window.clear
- @log_window.add_text(player.name + " summons " + card.name + "!")
- end
- # 1. Obtenemos el índice del actor
- actor_index = $game_party.battle_members.index(player) || 0
- begin
- ring_x = MOG_BATTLE_COMMAND_EX::FIXED_COMMAND_POSITION[actor_index][0]
- rescue
- ring_x = 65 + (actor_index * 100)
- end
- offset_x = ring_x - 60
- # 2. BÚSQUEDA SEGURA
- zone_index = player.monster_zones.rindex { |c| c && c.id == card.id } || 2
- # 3. Calculamos la posición de aterrizaje
- final_x = offset_x + (zone_index * 24) + 12
- final_y = (Graphics.height - 120 - 76) + 24 + 12
- # === DEBUG SPECIAL SUMMON ===
- p "--- DEBUG SPECIAL SUMMON ---"
- p "Carta: #{card.name} (ID: #{card.id})"
- p "Offset X del jugador: #{offset_x}"
- p "Casillero encontrado (zone_index): #{zone_index}"
- p "Destino Final -> X: #{final_x} | Y: #{final_y}"
- p "----------------------------"
- # 4. Posición inicial
- start_x = player.screen_x
- start_y = player.screen_y - 150
- start_scale = 0.50
- final_scale = 0.10
- if card.note =~ /<summon_anim:\s*(\d+)>/i
- anim_id = $1.to_i
- else
- anim_id = 43
- end
- card_sprite = Sprite.new
- begin
- card_sprite.bitmap = Cache.picture("Card" + card.id.to_s)
- rescue
- card_sprite.bitmap = Bitmap.new(190, 264)
- end
- card_sprite.ox = card_sprite.bitmap.width / 2
- card_sprite.oy = card_sprite.bitmap.height / 2
- card_sprite.zoom_x = start_scale
- card_sprite.zoom_y = start_scale
- card_sprite.x = start_x
- card_sprite.y = start_y
- card_sprite.z = 300
- card_sprite.opacity = 0
- # FASE 1
- 15.times do
- card_sprite.opacity += 17
- @card_zone_label.visible = false if @card_zone_label
- update_basic
- end
- # FASE 2
- frames_viaje = 20
- frames_viaje.times do |i|
- progress = (i + 1).to_f / frames_viaje
- card_sprite.x = start_x + (final_x - start_x) * progress
- card_sprite.y = start_y + (final_y - start_y) * progress
- current_scale = start_scale - ((start_scale - final_scale) * progress)
- card_sprite.zoom_x = current_scale
- card_sprite.zoom_y = current_scale
- @card_zone_label.visible = false if @card_zone_label
- update_basic
- end
- # FASE 3
- player.animation_id = anim_id
- card_sprite.flash(Color.new(255, 255, 255, 255), 30)
- 30.times do
- card_sprite.update
- @card_zone_label.visible = false if @card_zone_label
- update_basic
- end
- # FASE 4
- 15.times do
- card_sprite.opacity -= 17
- card_sprite.update
- @card_zone_label.visible = false if @card_zone_label
- update_basic
- end
- card_sprite.bitmap.dispose if card_sprite.bitmap
- card_sprite.dispose
- @log_window.clear if @log_window
- end
- def show_set_card_visuals
- player = @active_effect_owner || BattleManager.actor || $game_party.members[0]
- if @card_zone_label
- @card_zone_label.hide
- @card_zone_label.visible = false
- end
- if @field_zone_label
- @field_zone_label.hide
- @field_zone_label.visible = false
- end
- @skill_window.hide if @skill_window
- if @log_window
- @log_window.clear
- @log_window.add_text(player.name + " sets a card!")
- end
- # 1. Matemática de Posición
- actor_index = $game_party.battle_members.index(player) || 0
- begin
- ring_x = MOG_BATTLE_COMMAND_EX::FIXED_COMMAND_POSITION[actor_index][0]
- rescue
- ring_x = 65 + (actor_index * 100)
- end
- offset_x = ring_x - 60
- # 2. FILTRO
- card = @selected_card
- if card.nil? || (card.type.nil? rescue true)
- card = @skill if @skill && (@skill.type != nil rescue false)
- end
- card = player.field.last if card.nil? || (card.type.nil? rescue true)
- # Corrección: Asignamos el Type 3 para Monstruos (Ajustar si tus monstruos usan otro Type)
- is_monster = card.type == 3 rescue false
- is_field_spell = card.subtype == 27 rescue false
- p "--- DEBUG SET CARD ---"
- p "Carta leída: #{card ? card.name : 'NINGUNA'} (ID: #{card ? card.id : 'N/A'})"
- p "Type interno: #{card ? card.type : 'N/A'} | Subtype: #{card ? card.subtype : 'N/A'}"
- p "Es monstruo?: #{is_monster} | Es Field Spell?: #{is_field_spell}"
- if is_field_spell
- final_x = offset_x + 48 + 12
- final_y = (Graphics.height - 120 - 76) + 12
- p "Calculando para Zona: Field Spell"
- elsif is_monster
- zone_index = player.monster_zones.rindex { |c| c && c.id == card.id } || 2
- final_x = offset_x + (zone_index * 24) + 12
- final_y = (Graphics.height - 120 - 76) + 24 + 12
- p "Calculando para Zona: Monstruo | Índice (zone_index): #{zone_index}"
- else
- zone_index = player.st_zones.rindex { |c| c && c.id == card.id } || 2
- final_x = offset_x + (zone_index * 24) + 12
- final_y = (Graphics.height - 120 - 76) + 48 + 12
- p "Calculando para Zona: Magia/Trampa | Índice (zone_index): #{zone_index}"
- end
- p "Destino Final -> X: #{final_x} | Y: #{final_y}"
- p "----------------------"
- start_x = player.screen_x
- start_y = player.screen_y - 150
- start_scale = 0.50
- final_scale = 0.10
- card_sprite = Sprite.new
- begin
- card_sprite.bitmap = Cache.picture("BackCard")
- rescue
- card_sprite.bitmap = Bitmap.new(190, 264)
- end
- card_sprite.ox = card_sprite.bitmap.width / 2
- card_sprite.oy = card_sprite.bitmap.height / 2
- card_sprite.zoom_x = start_scale
- card_sprite.zoom_y = start_scale
- card_sprite.x = start_x
- card_sprite.y = start_y
- card_sprite.z = 300
- card_sprite.opacity = 0
- 15.times do
- card_sprite.opacity += 17
- @card_zone_label.visible = false if @card_zone_label
- update_basic
- end
- RPG::SE.new("Equip1", 80, 100).play
- frames_viaje = 20
- frames_viaje.times do |i|
- progress = (i + 1).to_f / frames_viaje
- card_sprite.x = start_x + (final_x - start_x) * progress
- card_sprite.y = start_y + (final_y - start_y) * progress
- current_scale = start_scale - ((start_scale - final_scale) * progress)
- card_sprite.zoom_x = current_scale
- card_sprite.zoom_y = current_scale
- @card_zone_label.visible = false if @card_zone_label
- update_basic
- end
- # Animación de Set
- player.animation_id = 138
- card_sprite.flash(Color.new(255, 255, 255, 255), 30)
- 30.times { card_sprite.update; update_basic; @card_zone_label.visible = false if @card_zone_label }
- 15.times do
- card_sprite.opacity -= 17
- card_sprite.update
- update_basic
- @card_zone_label.visible = false if @card_zone_label
- end
- card_sprite.bitmap.dispose if card_sprite.bitmap
- card_sprite.dispose
- @log_window.clear if @log_window
- end
- def restore_hud_visibility
- @status_window.show if @status_window
- @status_back_window.show if @status_back_window
- refresh_card_zone_label
- @card_zone_label.show if @card_zone_label
- end
- #--------------------------------------------------------------------------
- # Add end turn command and remove prior command (overwrite)
- #--------------------------------------------------------------------------
- def create_actor_command_window
- @actor_command_window = Window_ActorCommand.new
- @actor_command_window.viewport = @info_viewport
- @actor_command_window.set_handler(:attack, method(:command_attack))
- @actor_command_window.set_handler(:skill, method(:command_look_hand))
- @actor_command_window.set_handler(:guard, method(:command_guard))
- @actor_command_window.set_handler(:item, method(:command_item))
- @actor_command_window.set_handler(:look_grave, method(:command_look_grave))
- @actor_command_window.set_handler(:look_banish, method(:command_look_banish))
- @actor_command_window.set_handler(:look_extra, method(:command_look_extra))
- @actor_command_window.set_handler(:look_field, method(:command_look_field))
- @actor_command_window.set_handler(:end_turn, method(:command_end_turn))
- @actor_command_window.x = Graphics.width
- end
- #--------------------------------------------------------------------------
- # Handles the Look Grave command
- #--------------------------------------------------------------------------
- def command_look_grave
- actor = BattleManager.actor
- return unless actor
- actor.current_zone = :graveyard
- @skill_window.instance_variable_set(:@actor, actor)
- @skill_window.make_item_list
- @skill_window.refresh
- @skill_window.select(0) if @skill_window.item_max > 0
- @skill_window.show
- @skill_window.activate
- refresh_card_zone_label
- @card_zone_label.show
- end
- #--------------------------------------------------------------------------
- # Handles the Look Banish command
- #--------------------------------------------------------------------------
- def command_look_banish
- actor = BattleManager.actor
- return unless actor
- actor.current_zone = :banish
- @skill_window.instance_variable_set(:@actor, actor)
- @skill_window.make_item_list
- @skill_window.refresh
- @skill_window.select(0) if @skill_window.item_max > 0
- @skill_window.show
- @skill_window.activate
- refresh_card_zone_label
- @card_zone_label.show
- end
- #--------------------------------------------------------------------------
- # Handles the Look Extra command
- #--------------------------------------------------------------------------
- def command_look_extra
- actor = BattleManager.actor
- return unless actor
- actor.current_zone = :extra
- @skill_window.instance_variable_set(:@actor, actor)
- @skill_window.make_item_list
- @skill_window.refresh
- @skill_window.select(0) if @skill_window.item_max > 0
- @skill_window.show
- @skill_window.activate
- refresh_card_zone_label
- @card_zone_label.show
- end
- #--------------------------------------------------------------------------
- # Handles the Look Deck command
- #--------------------------------------------------------------------------
- def command_look_deck
- actor = BattleManager.actor
- return unless actor
- actor.current_zone = :deck
- @skill_window.instance_variable_set(:@actor, actor)
- @skill_window.make_item_list
- @skill_window.refresh
- @skill_window.select(0) if @skill_window.item_max > 0
- @skill_window.show
- @skill_window.activate
- refresh_card_zone_label
- @card_zone_label.show
- end
- #--------------------------------------------------------------------------
- # Handles the Look Field command
- #--------------------------------------------------------------------------
- def command_look_field
- actor = BattleManager.actor
- return unless actor
- actor.current_zone = :field
- @skill_window_backup ||= {
- x: @skill_window.x,
- y: @skill_window.y,
- width: @skill_window.width,
- height: @skill_window.height
- }
- @skill_window.instance_variable_set(:@actor, actor)
- @skill_window.hide
- @skill_window.deactivate
- @skill_window.x = 0
- @skill_window.y = 0
- @skill_window.width = Graphics.width / 2
- @skill_window.height = Graphics.height
- @skill_window.refresh
- @skill_window.select(0) if @skill_window.item_max > 0
- create_field_ui unless @field_ui_created
- refresh_card_zone_label
- @card_zone_label.show
- create_field_label
- end
- def create_field_label
- @field_zone_label = Window_CardZoneLabel.new(0, 0)
- @field_zone_label.set_text("Field", 1015)
- end
- def create_field_ui
- @field_map_window = Window_FieldMap.new(0, 0, BattleManager.actor)
- @field_map_window.actor = BattleManager.actor
- @field_preview_window = Window_FieldPreview.new(Graphics.width / 2, 0)
- @field_map_window.preview_window = @field_preview_window
- @field_map_window.update_preview
- @field_map_window.set_handler(:cancel, method(:on_field_cancel))
- @field_map_window.set_handler(:ok, method(:on_field_ok))
- @field_ui_created = true
- end
- def on_field_cancel
- if @targeting_mode
- effect_name = @temp_effect_data[1]
- effect_data = PC27::CG::CARD_EFFECT[effect_name]
- type = effect_data ? effect_data[0] : nil
- if type == :takem
- Sound.play_buzzer
- @field_map_window.activate
- return
- else
- if @active_effect_card
- eff = @active_effect_card.field_impact
- BattleManager.actor.used_turn_effects.delete(eff) if eff
- if @active_effect_card.note =~ /<shared_opt:\s*(.+?)>/i
- BattleManager.actor.used_turn_effects.delete($1.to_s.strip)
- end
- end
- @targeting_mode = false
- $game_message.clear
- end
- end
- actor = BattleManager.actor
- actor.current_zone = nil
- if @field_map_window
- @field_map_window.dispose
- @field_map_window = nil
- end
- if @field_preview_window
- @field_preview_window.dispose
- @field_preview_window = nil
- end
- @field_ui_created = false
- restore_skill_window_layout
- refresh_card_zone_label
- @field_zone_label.hide if @field_zone_label
- @card_zone_label.hide if @card_zone_label
- @actor_command_window.show
- @actor_command_window.activate
- end
- def restore_skill_window_layout
- return unless @skill_window_backup
- @skill_window.x = @skill_window_backup[:x]
- @skill_window.y = @skill_window_backup[:y]
- @skill_window.width = @skill_window_backup[:width]
- @skill_window.height = @skill_window_backup[:height]
- @skill_window.hide
- @skill_window.deactivate
- end
- def update_field_preview
- return unless @skill_window.active
- card = @skill_window.item
- end
- #--------------------------------------------------------------------------
- # Handles the Look Hand command
- #--------------------------------------------------------------------------
- def command_look_hand
- actor = BattleManager.actor
- return unless actor
- if @party_command_window
- @party_command_window.hide
- @party_command_window.deactivate
- end
- actor.current_zone = :hand
- @skill_window.instance_variable_set(:@actor, actor)
- @skill_window.make_item_list
- @skill_window.refresh
- @skill_window.select(0) if @skill_window.item_max > 0
- @skill_window.show
- @skill_window.activate
- refresh_card_zone_label
- @card_zone_label.show
- end
- #--------------------------------------------------------------------------
- # Clears actions and ends the actors turn
- #--------------------------------------------------------------------------
- def command_end_turn
- if BattleManager.actor && BattleManager.actor.respond_to?(:used_turn_effects)
- BattleManager.actor.used_turn_effects.clear if BattleManager.actor.used_turn_effects
- end
- ($game_party.battle_members + $game_troop.members).each do |battler|
- next unless battler.alive?
- battler.states.each do |state|
- if state.note =~ /<end_phase>/i
- battler.remove_state(state.id)
- end
- end
- end
- @return_to_hand_flag = false
- BattleManager.actor.clear_actions
- next_command
- end
- #--------------------------------------------------------------------------
- # Prevents messages from closing windows (overwrite)
- #--------------------------------------------------------------------------
- def update_message_open
- end
- #--------------------------------------------------------------------------
- # Shows a different Help Window in Battle (alias)
- #--------------------------------------------------------------------------
- alias pc27_cardgame_scenebattle_create_help_window create_help_window
- def create_help_window
- pc27_cardgame_scenebattle_create_help_window
- @cardhelp_window = Window_CardHelp.new
- @cardhelp_window.visible = false
- @cardhelp_window.opacity = 0
- @cardhelp_window.contents_opacity = 0
- @help_window.hide if @help_window
- @help_window.opacity = 0 if @help_window
- @help_window.contents_opacity = 0 if @help_window
- end
- #--------------------------------------------------------------------------
- # Create Skill Window with card help window instead of normal help window (overwrite)
- #--------------------------------------------------------------------------
- def create_skill_window
- @skill_window = Window_BattleSkill.new(@cardhelp_window, @info_viewport)
- @skill_window.set_handler(:ok, method(:on_skill_ok))
- @skill_window.set_handler(:cancel, method(:on_skill_cancel))
- end
- #--------------------------------------------------------------------------
- # Create Extra Window with card help window instead of normal help window (overwrite)
- #--------------------------------------------------------------------------
- def create_extra_window
- @extra_window = Window_BattleSkill.new(@cardhelp_window, @info_viewport)
- @extra_window.set_handler(:ok, method(:on_skill_ok))
- @extra_window.set_handler(:cancel, method(:on_skill_cancel))
- end
- #--------------------------------------------------------------------------
- # Creates the window needed to select cards (new)
- #--------------------------------------------------------------------------
- def create_card_select_window
- @card_select_window = Window_CardSelect.new(@cardhelp_window, @info_viewport)
- end
- #--------------------------------------------------------------------------
- # Adds the select window to the scene (alias)
- #--------------------------------------------------------------------------
- alias pc27_cardgame_scenebattle_create_all_windows create_all_windows
- def create_all_windows
- pc27_cardgame_scenebattle_create_all_windows
- create_card_select_window
- create_card_zone_label
- end
- def create_card_zone_label
- @card_zone_label = Window_CardZoneLabel.new(
- @skill_window.x,
- @skill_window.y
- )
- @card_zone_label.hide
- end
- alias pc27_cardgame_on_skill_cancel on_skill_cancel
- def on_skill_cancel
- refresh_card_zone_label
- @card_zone_label.hide if @card_zone_label
- @field_zone_label.hide if @field_zone_label
- pc27_cardgame_on_skill_cancel
- end
- alias pc27_cg_start_cmd_select_fix start_actor_command_selection
- def start_actor_command_selection
- if @card_select_window && @card_select_window.visible
- return
- elsif @return_to_hand_flag
- @return_to_hand_flag = false
- command_look_hand
- if @card_zone_label
- refresh_card_zone_label
- @card_zone_label.visible = true
- @card_zone_label.show
- end
- else
- pc27_cg_start_cmd_select_fix
- end
- end
- alias pc27_cardgame_scene_battle_update update
- def update
- pc27_cardgame_scene_battle_update
- update_field_preview
- return unless SceneManager.scene_is?(Scene_Battle)
- return unless BattleManager.in_turn?
- return unless BattleManager.actor
- return unless BattleManager.actor.input
- update_card_zone_label_visibility
- end
- def update_card_zone_label_visibility
- return unless @card_zone_label
- return unless @skill_window
- if @skill_window.visible
- @card_zone_label.show
- else
- refresh_card_zone_label
- @card_zone_label.hide
- end
- end
- def refresh_card_zone_label
- return unless @card_zone_label
- actor = BattleManager.actor
- return unless actor
- text = case actor.current_zone
- when :hand then "Hand"
- when :grave then "Graveyard"
- when :field then "Field"
- when :banish then "Banished"
- when :extra then "Extra Deck"
- when :deck then "Deck"
- else ""
- end
- zone = BattleManager.actor.current_zone
- data = ZONE_LABELS[zone]
- return unless data
- text, icon = data
- @card_zone_label.set_text(text, icon)
- end
- def card_has_grave_effect?(skill)
- skill.note =~ /<grave[-_ ]?effect/i || skill.note =~ /<grave/i
- end
- def monster_has_hand_effect?(skill)
- skill.note =~ /<hand[-_ ]?effect>/i || skill.note =~ /<hand/i
- end
- #--------------------------------------------------------------------------
- # On Skill Ok checks for card costs
- #--------------------------------------------------------------------------
- alias pc27_cardgame_scene_battle_on_skill_ok on_skill_ok
- def on_skill_ok
- @subject = BattleManager.actor
- @skill = @skill_window.item
- @selected_card = @skill
- case @subject.current_zone
- when :hand
- handle_hand_skill(@selected_card)
- when :field
- handle_field_skill(@selected_card)
- when :grave
- handle_graveyard_skill(@selected_card)
- else
- end
- end
- def resolve_card_effect(skill)
- if skill.cost
- invoke_card_cost(skill.cost)
- else
- skill_select(1)
- end
- end
- def show_advanced_options(options, disabled_indices, &block)
- @advanced_options_window = Window_CardOptions.new(options, disabled_indices)
- result = nil
- @advanced_options_window.set_handler(:ok, Proc.new { result = @advanced_options_window.index })
- @advanced_options_window.set_handler(:cancel, Proc.new { result = options.index("Cancel") || (options.size - 1) })
- loop do
- update_basic if respond_to?(:update_basic)
- if result != nil
- @advanced_options_window.dispose
- @advanced_options_window = nil
- block.call(result)
- break
- end
- end
- end
- def handle_hand_skill(skill)
- @selected_card = skill
- case skill.type
- when 1
- options = []
- disabled_indices = []
- has_space = (skill.subtype == 27 || BattleManager.actor.st_zone_available?)
- can_act = true
- impact_name = nil
- if skill.note =~ /<card impact:\s*(.+?)>/i || skill.note =~ /<spell_impact:\s*(.+?)>/i || skill.note =~ /<hand_impact:\s*(.+?)>/i
- impact_name = $1.to_s.strip
- end
- if impact_name
- can_act = false unless BattleManager.actor.can_activate_impact?(impact_name)
- end
- can_act = false unless BattleManager.actor.custom_req_met?(skill) && BattleManager.actor.can_pay_card_cost?(skill)
- options << "Activate"
- disabled_indices << (options.size - 1) unless can_act
- options << "Set" if has_space
- options << "Cancel"
- show_advanced_options(options, disabled_indices) do |choice|
- selected = options[choice]
- case selected
- when "Activate"
- $game_message.choice_proc = nil
- $game_message.clear
- if @message_window
- choice_window = @message_window.instance_variable_get(:@choice_window)
- choice_window.openness = 0 if choice_window
- end
- placed_index = BattleManager.actor.spell_to_field?(skill)
- if placed_index
- # =========================================================
- # FIX DE CLONACIÓN: INDEPENDENCIA DE OBJETOS EN CAMPO
- # =========================================================
- cloned_skill = skill.dup
- if placed_index == :field
- BattleManager.actor.field_zone = cloned_skill
- else
- BattleManager.actor.st_zones[placed_index] = cloned_skill
- end
- idx_f = BattleManager.actor.field.index(skill)
- BattleManager.actor.field[idx_f] = cloned_skill if idx_f
- skill = cloned_skill # Reasignamos la variable para el resto del código
- # =========================================================
- @active_effect_zone_type = (skill.subtype == 27 ? :fieldspell : :spell)
- @active_effect_zone_index = (placed_index == :field ? nil : placed_index)
- @field_map_window.refresh if @field_map_window
- @field_preview_window.set_card(nil) if @field_preview_window
- @skill_window.hide
- @skill_window.deactivate
- @card_zone_label.hide if @card_zone_label
- if impact_name
- resolve_card_effect(skill)
- else
- @active_effect_card = nil
- @current_processing_card = nil
- $temp_active_card = nil
- $chain_memory_card = nil
- show_set_card_visuals rescue nil
- @skill_window.make_item_list
- @skill_window.refresh
- @skill_window.show
- @skill_window.activate
- if @card_zone_label
- refresh_card_zone_label
- @card_zone_label.visible = true
- @card_zone_label.show
- end
- end
- else
- Sound.play_buzzer
- @skill_window.activate
- end
- when "Set"
- $game_message.choice_proc = nil
- $game_message.clear
- if @message_window
- choice_window = @message_window.instance_variable_get(:@choice_window)
- choice_window.openness = 0 if choice_window
- end
- @active_effect_card = nil
- @current_processing_card = nil
- $temp_active_card = nil
- $chain_memory_card = nil
- idx_hand = BattleManager.actor.hand.index { |c| c.equal?(skill) }
- success = false
- cloned_skill = skill.dup # FIX CLONACIÓN
- if skill.subtype == 27
- if BattleManager.actor.field_zone != nil
- BattleManager.actor.grave.push(BattleManager.actor.field_zone)
- BattleManager.actor.field.delete(BattleManager.actor.field_zone)
- end
- BattleManager.actor.hand.delete_at(idx_hand) if idx_hand
- BattleManager.actor.field_zone = cloned_skill
- BattleManager.actor.field.push(cloned_skill)
- BattleManager.actor.field_zone_state = { face_down: true, set_this_turn: true }
- success = true
- else
- idx = BattleManager.actor.st_zones.index(nil)
- if idx && idx_hand
- BattleManager.actor.hand.delete_at(idx_hand)
- BattleManager.actor.st_zones[idx] = cloned_skill
- BattleManager.actor.field.push(cloned_skill)
- BattleManager.actor.st_zones_state ||= []
- BattleManager.actor.st_zones_state[idx] = { face_down: true, set_this_turn: true }
- success = true
- end
- end
- if success
- @field_map_window.refresh if @field_map_window
- @field_preview_window.set_card(nil) if @field_preview_window
- show_set_card_visuals
- @skill_window.make_item_list
- @skill_window.refresh
- @skill_window.show
- @skill_window.activate
- if @card_zone_label
- refresh_card_zone_label
- @card_zone_label.visible = true
- @card_zone_label.show
- end
- else
- Sound.play_buzzer
- @skill_window.activate
- end
- when "Cancel"
- $game_message.choice_proc = nil
- $game_message.clear
- @skill_window.activate
- end
- end
- when 2
- show_advanced_options(["Set", "Cancel"], []) do |choice|
- if choice == 0
- $game_message.choice_proc = nil
- $game_message.clear
- if @message_window
- choice_window = @message_window.instance_variable_get(:@choice_window)
- choice_window.openness = 0 if choice_window
- end
- @active_effect_card = nil
- @current_processing_card = nil
- $temp_active_card = nil
- $chain_memory_card = nil
- idx_hand = BattleManager.actor.hand.index { |c| c.equal?(skill) }
- idx = BattleManager.actor.st_zones.index(nil)
- if idx && idx_hand
- cloned_skill = skill.dup # FIX CLONACIÓN
- BattleManager.actor.hand.delete_at(idx_hand)
- BattleManager.actor.st_zones[idx] = cloned_skill
- BattleManager.actor.field.push(cloned_skill)
- BattleManager.actor.st_zones_state ||= []
- BattleManager.actor.st_zones_state[idx] = { face_down: true, set_this_turn: true }
- @field_map_window.refresh if @field_map_window
- @field_preview_window.set_card(nil) if @field_preview_window
- show_set_card_visuals
- @skill_window.make_item_list
- @skill_window.refresh
- @skill_window.show
- @skill_window.activate
- if @card_zone_label
- refresh_card_zone_label
- @card_zone_label.visible = true
- @card_zone_label.show
- end
- else
- Sound.play_buzzer
- @skill_window.activate
- end
- else
- $game_message.choice_proc = nil
- $game_message.clear
- @skill_window.activate
- end
- end
- when 3
- special_eff = nil
- is_special_only = false
- is_special = false
- if skill.note =~ /<special_only:\s*(.+?)>/i
- is_special_only = true
- special_eff = $1.to_s.strip
- elsif skill.note =~ /<special:\s*(.+?)>/i
- is_special = true
- special_eff = $1.to_s.strip
- end
- options = []
- disabled_indices = []
- if !is_special_only && @subject.tp >= skill.tp_cost
- if BattleManager.actor.free_monster_zone_available?
- options << "Normal Summon (ATK)"
- options << "Normal Summon (DEF)"
- options << "Set"
- end
- end
- if special_eff && BattleManager.actor.free_monster_zone_available?
- if BattleManager.actor.meets_activation_requirements?(skill, special_eff)
- options << "Special Summon"
- if @subject.state?(18)
- disabled_indices << (options.size - 1)
- end
- end
- end
- if skill.hand_impact && BattleManager.actor.can_activate_impact?(skill.hand_impact) && BattleManager.actor.custom_req_met?(skill) && BattleManager.actor.can_pay_card_cost?(skill)
- options << "Activate"
- end
- options << "Cancel"
- show_advanced_options(options, disabled_indices) do |choice|
- selected = options[choice]
- case selected
- when "Normal Summon (ATK)", "Normal Summon (DEF)", "Set"
- $game_message.choice_proc = nil
- $game_message.clear
- if @message_window
- choice_window = @message_window.instance_variable_get(:@choice_window)
- choice_window.openness = 0 if choice_window
- end
- @last_summon_is_set = (selected == "Set")
- zone_index = BattleManager.actor.card_to_field?(skill.id)
- if !zone_index.nil?
- # FIX CLONACIÓN MONSTRUOS
- cloned_skill = skill.dup
- BattleManager.actor.monster_zones[zone_index] = cloned_skill
- idx_f = BattleManager.actor.field.index { |c| c && c.id == skill.id }
- BattleManager.actor.field[idx_f] = cloned_skill if idx_f
- skill = cloned_skill
- state = BattleManager.actor.monster_zones_state[zone_index]
- if selected == "Normal Summon (ATK)"
- state[:position] = :attack
- state[:face_down] = false
- elsif selected == "Normal Summon (DEF)"
- state[:position] = :defense
- state[:face_down] = false
- elsif selected == "Set"
- state[:position] = :defense
- state[:face_down] = true
- end
- state[:changed_this_turn] = true
- @field_map_window.refresh if @field_map_window
- @field_preview_window.set_card(nil) if @field_preview_window
- @skill_window.hide
- @card_zone_label.hide if @card_zone_label
- if selected == "Set"
- @active_effect_card = nil
- @current_processing_card = nil
- $temp_active_card = nil
- $chain_memory_card = nil
- show_set_card_visuals
- else
- show_special_summon_visuals(skill)
- end
- @current_card_action = :summon
- skill_select(1)
- else
- Sound.play_buzzer
- @skill_window.activate
- end
- when "Special Summon"
- $game_message.choice_proc = nil
- $game_message.clear
- if @message_window
- choice_window = @message_window.instance_variable_get(:@choice_window)
- choice_window.openness = 0 if choice_window
- end
- @field_map_window.refresh if @field_map_window
- @skill_window.hide.deactivate
- @card_zone_label.hide if @card_zone_label
- @active_effect_card = skill
- @current_processing_card = skill
- $temp_active_card = skill
- $chain_memory_card = skill
- invoke_card_impact(special_eff)
- when "Activate"
- $game_message.choice_proc = nil
- $game_message.clear
- if @message_window
- choice_window = @message_window.instance_variable_get(:@choice_window)
- choice_window.openness = 0 if choice_window
- end
- BattleManager.actor.card_to_stack?(skill.id)
- @current_card_action = :hand_effect
- resolve_card_effect(skill)
- when "Cancel"
- $game_message.choice_proc = nil
- $game_message.clear
- @skill_window.activate
- end
- end
- end
- end
- def show_options(choices, cancel_type, &block)
- choices.each { |s| $game_message.choices.push(s) }
- $game_message.choice_cancel_type = cancel_type
- $game_message.choice_proc = Proc.new { |n| block.call(n) }
- end
- def skill_select(value)
- @skill_window.hide if @skill_window.visible
- @card_zone_label.hide if @card_zone_label.visible
- $game_message.clear
- $game_message.visible = false
- if @skill.cost
- invoke_card_cost(@skill.cost)
- @skill_window.hide
- @card_zone_label.hide
- else
- effect = @skill.handeff if value == 0
- effect = @skill.id
- @current_card_action = :hand_effect if value == 0
- @current_card_action = :summon if value == 1
- BattleManager.actor.input.set_skill(effect)
- BattleManager.actor.last_skill.object = @skill
- if !@skill.need_selection?
- @skill_window.hide
- @card_zone_label.hide
- next_command
- elsif @skill.for_opponent?
- select_enemy_selection
- else
- select_actor_selection
- end
- end
- end
- def skill_field_select(value)
- $game_message.clear
- $game_message.visible = false
- if @skill.cost
- invoke_card_cost(@skill.cost)
- @skill_window.hide
- @card_zone_label.hide
- else
- @skill.id = @skill.fieldeff if value == 1
- BattleManager.actor.input.set_skill(@skill.id)
- BattleManager.actor.last_skill.object = @skill
- if !@skill.need_selection?
- @skill_window.hide
- @card_zone_label.hide
- next_command
- elsif @skill.for_opponent?
- select_enemy_selection
- else
- select_actor_selection
- end
- end
- end
- def on_enemy_cancel
- restore_taken_cards(:cancel)
- BattleManager.actor.hand += BattleManager.actor.stack
- BattleManager.actor.stack = []
- ygo_rescue_canceled_card
- @enemy_window.hide
- @skill_window.hide
- @card_zone_label.hide if @card_zone_label
- @item_window.hide
- @status_window.show
- @actor_command_window.activate
- refresh_card_zone_label if respond_to?(:refresh_card_zone_label)
- @card_zone_label.hide if @card_zone_label
- end
- def on_actor_cancel
- restore_taken_cards(:cancel)
- BattleManager.actor.hand += BattleManager.actor.stack
- BattleManager.actor.stack = []
- ygo_rescue_canceled_card
- @actor_window.hide
- @skill_window.hide
- @item_window.hide
- @status_window.show
- @actor_command_window.activate
- refresh_card_zone_label if respond_to?(:refresh_card_zone_label)
- @card_zone_label.hide if @card_zone_label
- end
- def ygo_rescue_canceled_card
- actor = BattleManager.actor
- return unless actor
- card = $game_temp.battle_aid || actor.input.item || @skill || @active_effect_card rescue nil
- return unless card
- if actor.respond_to?(:st_zones) && actor.st_zones
- idx = actor.st_zones.index { |c| c && c.equal?(card) }
- if idx
- actor.st_zones[idx] = nil
- actor.hand << card unless actor.hand.include?(card)
- idx_field = actor.field.index { |c| c && c.equal?(card) }
- actor.field.delete_at(idx_field) if idx_field
- end
- end
- if actor.respond_to?(:monster_zones) && actor.monster_zones
- idx = actor.monster_zones.index { |c| c && c.equal?(card) }
- if idx
- actor.monster_zones[idx] = nil
- actor.hand << card unless actor.hand.include?(card)
- idx_field = actor.field.index { |c| c && c.equal?(card) }
- actor.field.delete_at(idx_field) if idx_field
- end
- end
- @minifield_window.refresh if defined?(@minifield_window) && @minifield_window
- @field_map_window.refresh if defined?(@field_map_window) && @field_map_window
- end
- #-----------------------------------------------------------------------------
- # Changes Next Command so it performs Actions (alias)
- #-----------------------------------------------------------------------------
- alias pc27_cardgame_scenebattle_next_command next_command
- def next_command
- return if @card_select_window.active
- if action?
- evaluate_item(BattleManager.actor, BattleManager.actor.input.item)
- perform_action
- else
- pc27_cardgame_scenebattle_next_command
- end
- end
- #-----------------------------------------------------------------------------
- # Disables stuff based on used skill (new)
- #-----------------------------------------------------------------------------
- def evaluate_item(actor, item)
- case item.id
- when actor.attack_skill_id
- actor.turn_actions[:can_attack] = false
- actor.turn_actions[:can_guard] = false
- actor.turn_actions[:actions] -= 1 unless actor.turn_actions[:actions] == -1
- when actor.guard_skill_id
- actor.turn_actions[:can_attack] = false
- actor.turn_actions[:can_guard] = false
- actor.turn_actions[:actions] -= 1 unless actor.turn_actions[:actions] == -1
- end
- end
- #--------------------------------------------------------------------------
- # Checks if there is an Action to use (new)
- #--------------------------------------------------------------------------
- def action?
- return false if BattleManager.actor.nil?
- return false if BattleManager.actor.input.nil?
- action = BattleManager.actor.input.item
- return false if action.nil?
- return true
- end
- #--------------------------------------------------------------------------
- # Performs Action (new)
- #--------------------------------------------------------------------------
- def perform_action
- @subject = BattleManager.actor
- hide_instant_action_windows
- if @subject.current_action.valid?
- execute_action
- end
- process_event
- loop do
- @subject.remove_current_action
- break if $game_troop.all_dead?
- break unless @subject.current_action
- @subject.current_action.prepare
- execute_action if @subject.current_action.valid?
- end
- process_action_end
- @subject.make_actions
- @subject = nil
- show_instant_action_windows
- refresh_card_zone_label
- @card_zone_label.hide
- end
- def set_card
- @subject = BattleManager.actor
- @subject.field += @subject.stack
- @subject.stack = []
- restore_taken_cards(:proceed)
- @skill_window.hide
- refresh_card_zone_label
- @field_zone_label.hide
- @card_zone_label.hide
- @actor_command_window.activate
- end
- #--------------------------------------------------------------------------
- # From Yanflys Instantcast (new)
- #--------------------------------------------------------------------------
- def hide_instant_action_windows
- if $imported["YEA-BattleEngine"]
- @info_viewport.visible = true
- @status_aid_window.hide
- @status_window.show
- @actor_command_window.show
- end
- end
- #--------------------------------------------------------------------------
- # Activates actor (new)
- #--------------------------------------------------------------------------
- def show_instant_action_windows
- if $imported["YEA-BattleEngine"]
- @info_viewport.visible = true
- end
- start_actor_command_selection unless @card_select_window.active
- @card_zone_label.hide if @card_zone_label.visible
- status_redraw_target(BattleManager.actor)
- next_command unless BattleManager.actor.inputable?
- end
- #--------------------------------------------------------------------------
- # Redrawas target after action (new)
- #--------------------------------------------------------------------------
- def status_redraw_target(target)
- return unless target.actor?
- @status_window.draw_item($game_party.battle_members.index(target))
- end
- #--------------------------------------------------------------------------
- # Handles card costs
- #--------------------------------------------------------------------------
- def invoke_card_cost(effect_name)
- effect_array = PC27::CG::CARD_EFFECT[effect_name]
- if effect_array[0] == :draw
- card_effect_draw_cards(effect_array[1], effect_array[2], effect_array[3])
- BattleManager.actor.input.set_skill(@skill.id)
- BattleManager.actor.last_skill.object = @skill
- if !@skill.need_selection?
- @skill_window.hide
- @card_zone_label.hide
- next_command
- elsif @skill.for_opponent?
- select_enemy_selection
- else
- select_actor_selection
- end
- else
- $game_message.background = 1
- $game_message.position = 1
- $game_message.add(PC27::CG::CARD_EFF_TEXT)
- prepare_select_window(:cost, effect_array[0])
- @temp_effect_data = [] unless @temp_effect_data
- @temp_effect_data[0] = :cost
- process_select_cards(effect_name)
- end
- end
- #-----------------------------------------------------------------------------
- # Monster's inherent summon
- #-----------------------------------------------------------------------------
- def invoke_inherent_summon(card, effect_name)
- array = PC27::CG::CARD_EFFECT[effect_name]
- prepare_select_window(:cost, array[0])
- @temp_effect_data = [] unless @temp_effect_data
- @temp_effect_data[0] = :cost
- @temp_effect_data[1] = effect_name
- @inherent_summon_pending = card
- process_select_cards(effect_name)
- end
- #-----------------------------------------------------------------------------
- # Evaluates card effects and puts the stack to the grave (alias)
- #-----------------------------------------------------------------------------
- alias pc27_cardgame_scenebattle_use_item use_item
- def use_item
- pc27_cardgame_scenebattle_use_item
- return unless @subject.is_a?(Game_Actor)
- card = @subject.current_action.item
- if card && card.id == 1
- @subject.used_turn_effects ||= []
- @subject.used_turn_effects << "attack_declared"
- end
- effect_name = nil
- if card.type == 3
- if @current_card_action == :hand_effect
- effect_name = card.hand_impact
- elsif @current_card_action != :summon
- effect_name = card.impact
- end
- else
- effect_name = card.impact
- end
- invoke_card_impact(effect_name) if effect_name
- if card.type == 3 && @current_card_action == :summon
- is_face_down = card.instance_variable_get(:@face_down)
- if !@last_summon_is_set && card.summon_impact && BattleManager.actor.can_activate_summon_effect?(card)
- $game_message.clear
- if @message_window
- @message_window.openness = 0
- @message_window.visible = true
- end
- $game_message.background = 1
- $game_message.position = 1
- $game_message.add("Do you want to activate the effect of")
- $game_message.add('"' + card.name + '"?')
- @status_window.hide if @status_window
- @status_back_window.hide if @status_back_window
- show_options(["Yes", "No"], 2) do |choice|
- @status_window.show if @status_window
- @status_back_window.show if @status_back_window
- $game_message.choice_proc = nil
- $game_message.clear
- if @message_window
- choice_window = @message_window.instance_variable_get(:@choice_window)
- choice_window.openness = 0 if choice_window
- end
- if choice == 0
- BattleManager.actor.used_turn_effects ||= []
- BattleManager.actor.used_turn_effects << card.summon_impact
- if card.note =~ /<shared_opt:\s*(.+?)>/i
- BattleManager.actor.used_turn_effects << $1.to_s.strip
- end
- @active_effect_owner = BattleManager.actor
- @active_effect_card = card
- $temp_active_card = card
- $chain_memory_card = card
- @current_processing_card = card
- invoke_card_impact(card.summon_impact)
- else
- @return_to_hand_flag = true
- if @actor_command_window
- @actor_command_window.hide.deactivate
- end
- command_look_hand
- end
- end
- wait_for_message
- return
- else
- @return_to_hand_flag = true
- end
- end
- if @subject.stack.size > 0
- @subject.grave += @subject.stack
- @subject.stack = []
- end
- if !effect_name && @subject.current_zone == :hand
- @return_to_hand_flag = true
- end
- end
- #-----------------------------------------------------------------------------
- # Intercepta el menú de comandos para volver a la mano si es necesario
- #-----------------------------------------------------------------------------
- alias pc27_cg_start_actor_command_selection start_actor_command_selection
- def start_actor_command_selection
- if @return_to_hand_flag
- @return_to_hand_flag = false
- command_look_hand
- if @card_zone_label
- refresh_card_zone_label
- @card_zone_label.visible = true
- @card_zone_label.show
- end
- else
- pc27_cg_start_actor_command_selection
- end
- end
- #-----------------------------------------------------------------------------
- # Forzamos la vigilancia de la etiqueta en el bucle principal de la escena
- #-----------------------------------------------------------------------------
- alias pc27_cg_scenebattle_update update
- def update
- pc27_cg_scenebattle_update
- if @field_ui_created && @skill_window && (@skill_window.visible || @skill_window.active)
- @skill_window.hide
- @skill_window.deactivate
- end
- if @card_select_window && @card_select_window.active && @skill_window && (@skill_window.visible || @skill_window.active)
- @skill_window.hide
- @skill_window.deactivate
- end
- if @skill_window && @skill_window.visible && @card_zone_label
- update_card_zone_label_visibility
- end
- end
- #-----------------------------------------------------------------------------
- # Card effects
- #-----------------------------------------------------------------------------
- def invoke_card_impact(effect_name)
- return unless effect_name
- @active_effect_card = @current_processing_card if @current_processing_card
- if @active_effect_card && @active_effect_card.is_a?(RPG::UsableItem) && @last_state_card_id != @active_effect_card.object_id
- @last_state_card_id = @active_effect_card.object_id
- player = @active_effect_owner || BattleManager.actor || $game_party.members[0]
- if player && player.alive?
- @active_effect_card.effects.each do |eff|
- player.add_state(eff.data_id) if eff.code == 21
- end
- end
- end
- array = PC27::CG::CARD_EFFECT[effect_name]
- if array[0] == :draw
- card_effect_draw_cards(array[1], array[2], array[3])
- next_eff = array.find { |e| e.is_a?(String) && PC27::CG::CARD_EFFECT.key?(e) }
- if next_eff
- invoke_card_impact(next_eff)
- else
- finish_proceed_selection
- end
- elsif array[0] == :none
- finish_proceed_selection
- elsif array[0] == :quick_reactive
- process_quick_reactive(array)
- elsif array[0] == :add_state
- target_type = array[2]
- state_id = array[3]
- player = @active_effect_owner || BattleManager.actor || $game_party.members[0]
- if target_type == :user
- player.add_state(state_id)
- RPG::SE.new("Skill2", 80, 100).play
- end
- finish_proceed_selection
- else
- prepare_select_window(:impact, array[0])
- @temp_effect_data = [] unless @temp_effect_data
- @temp_effect_data[0] = :impact
- process_select_cards(effect_name)
- end
- end
- def process_quick_reactive(array)
- player = @current_quick_owner || $game_party.battle_members[0]
- icon = @active_effect_card ? @active_effect_card.icon_index : 0
- total_heal = 0
- total_damage = 0
- array.each do |instruction|
- case instruction.to_s
- when "negate_attack"
- @attack_negated = true
- when "heal_atk"
- if @current_quick_subject
- total_heal += @current_quick_subject.atk
- end
- when /^heal_(\d+)$/i
- total_heal += $1.to_i
- when /^heal_(\d+)_x_(\d+)_grave$/i
- multiplier = $1.to_i
- target_card_id = $2.to_i
- if player && player.respond_to?(:grave)
- cards_in_grave = player.grave.count { |c| c && c.id == target_card_id }
- if @active_effect_card && @active_effect_card.id == target_card_id
- cards_in_grave -= 1
- end
- if cards_in_grave > 0
- total_heal += (multiplier * cards_in_grave)
- end
- end
- when /^damage_(\d+)$/i
- total_damage += $1.to_i
- when /^damage_(\d+)_x_(\d+)_grave$/i
- multiplier = $1.to_i
- target_card_id = $2.to_i
- enemy = $game_troop.members[0]
- if player && player.respond_to?(:grave) && enemy && enemy.alive?
- cards_in_grave = player.grave.count { |c| c && c.id == target_card_id }
- if @active_effect_card && @active_effect_card.id == target_card_id
- cards_in_grave -= 1
- end
- if cards_in_grave > 0
- total_damage += (multiplier * cards_in_grave)
- end
- end
- end
- end
- if total_heal > 0 && player
- player.hp = player.hp + total_heal
- player.damage.push([-total_heal, "HP", false, icon])
- end
- enemy = $game_troop.members[0]
- if total_damage > 0 && enemy && enemy.alive?
- enemy.hp = [enemy.hp - total_damage, 0].max
- enemy.damage.push([total_damage, "HP", false, icon])
- end
- finish_proceed_selection if respond_to?(:finish_proceed_selection)
- end
- #-----------------------------------------------------------------------------
- def card_effect_draw_cards(nr, prob, trg)
- need_wait = false
- drawer = @active_effect_owner || (@subject && @subject.actor? ? @subject : nil) || BattleManager.actor || $game_party.battle_members[0]
- if trg == :self
- if rand(100) < prob
- drawer.draw_cards(nr)
- need_wait = true
- end
- elsif trg == :target
- if @subject && @subject.current_action
- targets = @subject.current_action.make_targets.compact
- for target in targets
- if rand(100) < prob
- target.draw_cards(nr)
- need_wait = true
- end
- end
- end
- end
- wait_for_message if need_wait
- end
- #-----------------------------------------------------------------------------
- def process_select_cards(effect_name)
- $game_message.clear
- $game_message.visible = false
- @card_select_window.zone_tags = []
- @message_window.deactivate if @message_window
- @message_window.hide if @message_window
- @skill_window.hide
- @skill_window.deactivate
- @actor_command_window.deactivate if @actor_command_window
- player = @active_effect_owner || BattleManager.actor || $game_party.members[0]
- @card_select_window.actor = player
- actor = player
- active_c = @active_effect_card || $temp_active_card || $chain_memory_card
- @active_effect_card = active_c
- array = PC27::CG::CARD_EFFECT[effect_name]
- ui_filter = array[4]
- ui_active = active_c
- ui_sim_lvl = $chain_memory_card ? $chain_memory_card.level : nil
- ui_actor = actor
- @card_select_window.define_singleton_method(:enable?) do |item, source_tag = nil, z_idx = nil|
- return false if item.nil?
- src = source_tag
- if src.nil? && self.zone_tags && self.cards
- idx = self.cards.index(item)
- src = self.zone_tags[idx] if idx
- end
- return ui_actor.match_complex_filter?(item, ui_filter, ui_active, ui_sim_lvl, z_idx, src)
- end
- @temp_effect_data[1] = effect_name
- @temp_effect_data[2] = 0
- set_select_filter(array)
- @card_select_window.dry_run_eff2 = nil
- if active_c && active_c.note =~ /<req_dry_run:\s*#{effect_name}\s*,\s*([^,>]+)(?:\s*,\s*([^>]+))?>/i
- target_eff = $2 ? $2.to_s.strip : $1.to_s.strip
- @card_select_window.dry_run_eff2 = target_eff
- end
- case array[2]
- when :self_banished
- @temp_effect_data[3] = [$chain_memory_card] if $chain_memory_card
- restore_taken_cards(:proceed)
- return
- when :hand_or_field
- actor.current_zone = :hand_or_field
- @field_zone_label.hide if @field_zone_label
- @card_select_window.zone_tags = []
- @card_select_window.cards = []
- active_c = @active_effect_card || $temp_active_card || $chain_memory_card
- filter = array[4]
- exclude = false
- if filter.is_a?(Array)
- if filter[0].is_a?(Array)
- exclude = filter.any? { |f| f[11] == :exclude_active }
- else
- exclude = (filter[11] == :exclude_active)
- end
- end
- dry_run_filter = nil
- dry_run_zone = nil
- if @card_select_window.dry_run_eff2
- eff2_data = PC27::CG::CARD_EFFECT[@card_select_window.dry_run_eff2]
- if eff2_data
- dry_run_filter = eff2_data[4]
- dry_run_zone = eff2_data[2]
- end
- end
- check_validity = lambda do |card|
- next false if card.nil?
- next false if exclude && active_c && card.id == active_c.id
- if dry_run_filter && dry_run_zone == :deck
- has_future_target = actor.deck.any? do |d_card|
- next false if d_card.nil?
- actor.match_complex_filter?(d_card, dry_run_filter, active_c, card.level)
- end
- next false unless has_future_target
- end
- true
- end
- actor.hand.each do |card|
- if check_validity.call(card) && @card_select_window.enable?(card, :hand)
- @card_select_window.cards << card
- @card_select_window.zone_tags << :hand
- end
- end
- actor.monster_zones.each_with_index do |card, idx|
- next unless card
- if check_validity.call(card) && @card_select_window.enable?(card, :field, idx)
- @card_select_window.cards << card
- @card_select_window.zone_tags << :field
- end
- end
- when :hand_or_deck
- actor.current_zone = :hand_or_deck
- @card_select_window.zone_tags = []
- @card_select_window.cards = []
- filter = array[4]
- active_c = @active_effect_card || $temp_active_card || $chain_memory_card
- sim_lvl = $chain_memory_card ? $chain_memory_card.level : nil
- actor.hand.each do |card|
- next if card.nil?
- if actor.match_complex_filter?(card, filter, active_c, sim_lvl)
- @card_select_window.cards << card
- @card_select_window.zone_tags << :hand
- end
- end
- actor.deck.each do |card|
- next if card.nil?
- if actor.match_complex_filter?(card, filter, active_c, sim_lvl)
- @card_select_window.cards << card
- @card_select_window.zone_tags << :deck
- end
- end
- when :hand_or_grave
- actor.current_zone = :hand_or_grave
- @field_zone_label.hide if @field_zone_label
- @card_select_window.zone_tags = []
- @card_select_window.cards = []
- active_c = @active_effect_card || $temp_active_card || $chain_memory_card
- filter = array[4]
- exclude = false
- if filter.is_a?(Array)
- if filter[0].is_a?(Array)
- exclude = filter.any? { |f| f[11] == :exclude_active }
- else
- exclude = (filter[11] == :exclude_active)
- end
- end
- dry_run_filter = nil
- dry_run_zone = nil
- if @card_select_window.dry_run_eff2
- eff2_data = PC27::CG::CARD_EFFECT[@card_select_window.dry_run_eff2]
- if eff2_data
- dry_run_filter = eff2_data[4]
- dry_run_zone = eff2_data[2]
- end
- end
- check_validity = lambda do |card|
- next false if card.nil?
- next false if exclude && active_c && card.id == active_c.id
- if dry_run_filter && (dry_run_zone == :deck || dry_run_zone == :hand_or_deck)
- has_future_target = actor.deck.any? do |d_card|
- next false if d_card.nil?
- actor.match_complex_filter?(d_card, dry_run_filter, active_c, card.level)
- end
- if dry_run_zone == :hand_or_deck && !has_future_target
- has_future_target = actor.hand.any? do |h_card|
- next false if h_card.nil?
- next false if h_card == card
- actor.match_complex_filter?(h_card, dry_run_filter, active_c, card.level)
- end
- end
- next false unless has_future_target
- end
- true
- end
- actor.hand.each do |card|
- if check_validity.call(card) && @card_select_window.enable?(card)
- @card_select_window.cards << card
- @card_select_window.zone_tags << :hand
- end
- end
- actor.grave.each do |card|
- if check_validity.call(card) && @card_select_window.enable?(card)
- @card_select_window.cards << card
- @card_select_window.zone_tags << :grave
- end
- end
- when :special_summon_self
- @temp_effect_data[3] = [$chain_memory_card] if $chain_memory_card
- restore_taken_cards(:proceed)
- return
- when :deck
- actor.current_zone = :deck
- @card_select_window.zone_tags = []
- @card_select_window.cards = []
- filter = array[4]
- deck = @card_select_window.actor.deck
- selectable = []
- active_c = @active_effect_card || $temp_active_card || $chain_memory_card
- sim_lvl = $chain_memory_card ? $chain_memory_card.level : nil
- deck.each do |card|
- next if card.nil?
- if actor.match_complex_filter?(card, filter, active_c, sim_lvl)
- selectable << card
- end
- end
- amn = (array[1] == 0 ? selectable.size : array[1])
- selectable.first(amn).each do |card|
- idx = deck.index(card)
- deck.delete_at(idx) if idx
- @card_select_window.cards.push(card)
- @card_select_window.zone_tags.push(:deck)
- end
- when :hand
- actor.current_zone = :hand
- @card_select_window.zone_tags = []
- @card_select_window.cards = []
- filter = array[4]
- active_c = @active_effect_card || $temp_active_card || $chain_memory_card
- sim_lvl = $chain_memory_card ? $chain_memory_card.level : nil
- selectable = []
- actor.hand.each do |card|
- next if card.nil?
- if actor.match_complex_filter?(card, filter, active_c, sim_lvl)
- selectable << card
- end
- end
- amn = (array[1] == 0 ? selectable.size : array[1])
- selectable.first(amn).each do |card|
- idx = actor.hand.index(card)
- actor.hand.delete_at(idx) if idx
- @card_select_window.cards << card
- @card_select_window.zone_tags << :hand
- end
- when :grave
- actor.current_zone = :grave
- @field_zone_label.hide if @field_zone_label
- grave_array = @card_select_window.actor.grave
- selectable = []
- grave_array.each do |card|
- next if card.nil?
- selectable << card if @card_select_window.enable?(card)
- end
- amn = (array[1] == 0 ? selectable.size : array[1])
- selectable.first(amn).each do |card|
- grave_array.delete(card)
- @card_select_window.cards.push(card)
- end
- when :banish
- actor.current_zone = :banish
- (array[1] == 0 ? amn = @card_select_window.actor.banish.size : amn = array[1])
- amn.times do
- next if @card_select_window.actor.banish.size == 0
- @card_select_window.cards.push(@card_select_window.actor.banish.shift)
- end
- when :extra
- actor.current_zone = :extra
- (array[1] == 0 ? amn = @card_select_window.actor.extra.size : amn = array[1])
- amn.times do
- next if @card_select_window.actor.extra.size == 0
- @card_select_window.cards.push(@card_select_window.actor.extra.shift)
- end
- when :field
- @targeting_mode = true
- @targeting_filter = array[4]
- @temp_effect_data[1] = effect_name
- @temp_effect_data[2] = 0
- @card_select_window.hide.deactivate
- @skill_window.hide.deactivate
- @card_zone_label.hide if @card_zone_label
- @field_map_window.show.activate
- @field_preview_window.show if @field_preview_window
- $game_message.clear
- $game_message.background = 1
- $game_message.position = 1
- $game_message.add("Select a target on your field.")
- if @message_window
- @message_window.openness = 255
- @message_window.visible = true
- end
- return
- end
- @card_select_window.make_item_list
- dest = array[5]
- if [:special_summon, :special_summon_def, :special_summon_atk].include?(dest)
- @card_select_window.cards.reject! do |card|
- (card.note =~ /<special_only:/i) && !card.properly_summoned
- end
- end
- if [:special_summon, :special_summon_def, :special_summon_atk].include?(array[5]) && !actor.free_monster_zone_available?
- Sound.play_buzzer
- $game_message.clear
- $game_message.background = 1
- $game_message.position = 1
- $game_message.add("No monster zones available.")
- if @message_window
- @message_window.openness = 255
- @message_window.show
- end
- wait_for_message
- restore_selected_cards
- @temp_effect_data = []
- finish_proceed_selection
- return
- end
- valid_targets = @card_select_window.cards.size > 0
- if !valid_targets
- Sound.play_buzzer
- $game_message.clear
- $game_message.background = 1
- $game_message.position = 1
- $game_message.add("No targets available.")
- if @message_window
- @message_window.openness = 255
- @message_window.show
- end
- wait_for_message
- restore_selected_cards
- @temp_effect_data = []
- finish_proceed_selection
- return
- end
- @card_select_window.refresh
- @card_select_window.show
- @card_select_window.activate
- refresh_card_zone_label
- @card_zone_label.show if @card_zone_label
- end
- #-----------------------------------------------------------------------------
- def set_select_filter(array)
- if array[4]
- @card_select_window.filter = array[4]
- elsif array[0] == :view
- @card_select_window.filter = [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]
- else
- @card_select_window.filter = [0,0,0,0,0,0,0,0,0,0,0]
- end
- end
- #-----------------------------------------------------------------------------
- def select_cards_ok_sort
- if @card_select_window.cards.size == 0
- select_cancel
- return
- end
- if @card_select_window.sort_index != -1
- swap_cards(@card_select_window.sort_index, @card_select_window.index)
- @card_select_window.sort_index = -1
- @card_select_window.make_item_list
- @card_select_window.refresh
- else
- @card_select_window.sort_index = @card_select_window.index
- end
- @card_select_window.activate
- end
- #-----------------------------------------------------------------------------
- def select_cards_ok_take
- if @card_select_window.cards.size == 0
- select_cancel
- return
- end
- card = @card_select_window.item
- player = @card_select_window.actor
- if card
- $chain_memory_card = card
- @temp_effect_data[3] = [] unless @temp_effect_data[3]
- @temp_effect_data[3].push(card) unless card.frame == 5
- idx_window = @card_select_window.cards.index(card)
- @card_select_window.cards.delete_at(idx_window) if idx_window
- source = @card_select_window.zone_tags[@card_select_window.index]
- card.instance_variable_set(:@temp_source_zone, source)
- if source == :hand
- idx_hand = player.hand.index(card)
- player.hand.delete_at(idx_hand) if idx_hand
- elsif source == :field
- idx_field = player.monster_zones.index(card)
- player.monster_zones[idx_field] = nil if idx_field
- idx_f = player.field.index(card)
- player.field.delete_at(idx_f) if idx_f
- elsif source == :grave
- idx_grave = player.grave.index(card)
- player.grave.delete_at(idx_grave) if idx_grave
- elsif source == :deck
- idx_deck = player.deck.index(card)
- player.deck.delete_at(idx_deck) if idx_deck
- elsif source == :banish
- idx_banish = player.banish.index(card)
- player.banish.delete_at(idx_banish) if idx_banish
- elsif source == :extra
- idx_extra = player.extra.index(card)
- player.extra.delete_at(idx_extra) if idx_extra
- end
- end
- @temp_effect_data[2] += 1
- if PC27::CG::CARD_EFFECT[@temp_effect_data[1]][6] != @temp_effect_data[2]
- @card_select_window.make_item_list
- @card_select_window.refresh
- @card_select_window.activate
- else
- proceed_selection
- end
- end
- #-----------------------------------------------------------------------------
- def proceed_selection
- @added_card_name = nil
- if @temp_effect_data && @temp_effect_data[3] && !@temp_effect_data[3].empty?
- @added_card_name = @temp_effect_data[3][0].name
- end
- @card_select_window.hide.deactivate
- @card_select_window.sort_index = -1
- restore_selected_cards
- player = @active_effect_owner || BattleManager.actor || $game_party.members[0]
- unless @current_card_action == :field_effect
- player.current_zone = :hand
- end
- if @temp_effect_data[0] == :cost
- effect_data = PC27::CG::CARD_EFFECT[@temp_effect_data[1]]
- is_chain = effect_data && effect_data[5].to_s.include?("chain")
- restore_taken_cards(:proceed)
- if @is_interrupt_effect
- puts "[DEBUG] Costo de Quick Effect pagado. Saltando next_command e invocando impacto."
- skill_to_use = @skill || @active_effect_card
- if skill_to_use && player.respond_to?(:pay_skill_cost)
- player.pay_skill_cost(skill_to_use)
- RPG::SE.new("Magic1", 80, 100).play rescue nil
- player.popup_destroyed_card(skill_to_use.icon_index, "Activated!") if player.respond_to?(:popup_destroyed_card)
- end
- impact_to_use = nil
- if skill_to_use.note =~ /<card impact:\s*(.+?)>/i ||
- skill_to_use.note =~ /<spell_impact:\s*(.+?)>/i ||
- skill_to_use.note =~ /<field_impact:\s*(.+?)>/i
- impact_to_use = $1.to_s.strip.downcase
- end
- @temp_effect_data = []
- invoke_card_impact(impact_to_use) if impact_to_use
- else
- unless is_chain
- if player && player.respond_to?(:input) && player.input
- player.input.set_skill(@skill.id)
- player.last_skill.object = @skill
- end
- @temp_effect_data = []
- next_command
- end
- end
- elsif @temp_effect_data[0] == :impact
- unless restore_taken_cards(:proceed)
- finish_proceed_selection
- end
- end
- end
- def finish_proceed_selection
- player = @active_effect_owner || BattleManager.actor || $game_party.members[0]
- if @temp_effect_data && @temp_effect_data[2] == :deck
- player.shuffle_deck(true)
- end
- if @selected_card && [24, 25, 29, 31].include?(@selected_card.subtype)
- idx_to_clear = nil
- if @active_effect_zone_type == :spell && @active_effect_zone_index
- if player.st_zones[@active_effect_zone_index] && player.st_zones[@active_effect_zone_index].id == @selected_card.id
- idx_to_clear = @active_effect_zone_index
- end
- end
- if idx_to_clear.nil?
- idx_to_clear = player.st_zones.index { |c| c && c.equal?(@selected_card) }
- end
- if idx_to_clear && player.st_zones[idx_to_clear]
- actual_card = player.st_zones[idx_to_clear]
- player.st_zones[idx_to_clear] = nil
- idx_field = player.field.index { |c| c && c.equal?(@selected_card) }
- player.field.delete_at(idx_field) if idx_field
- player.grave.push(actual_card)
- @field_map_window.refresh if defined?(@field_map_window) && @field_map_window
- @minifield_window.refresh if defined?(@minifield_window) && @minifield_window
- end
- end
- if player.stack.size > 0
- player.grave += player.stack
- player.stack = []
- end
- if @temp_effect_data && @temp_effect_data[1]
- effect_data = PC27::CG::CARD_EFFECT[@temp_effect_data[1]]
- if effect_data && effect_data[2] == :deck
- @deck_was_searched = true
- dest_id = @last_chosen_destination || effect_data[5] || :hand
- if [:special_summon, :inherent_landing, :field].include?(dest_id)
- @shuffle_message = "Shuffling Deck..."
- elsif @added_card_name
- if dest_id == :grave
- @shuffle_message = "#{@added_card_name} sent to the Graveyard! / Shuffling Deck"
- else
- @shuffle_message = "#{@added_card_name} added to the Hand! / Shuffling Deck"
- end
- else
- @shuffle_message = "Shuffling Deck..."
- end
- @last_chosen_destination = nil
- end
- end
- @temp_effect_data = []
- if @field_map_window
- @field_map_window.dispose
- @field_map_window = nil
- end
- if @field_preview_window
- @field_preview_window.dispose
- @field_preview_window = nil
- end
- @field_ui_created = false
- @field_zone_label.hide if @field_zone_label
- restore_skill_window_layout
- if @pending_triggers && @pending_triggers.size > 0
- check_pending_triggers
- return
- end
- card_to_trigger = @specially_summoned_card
- @specially_summoned_card = nil
- if card_to_trigger && card_to_trigger.summon_impact && player.can_activate_summon_effect?(card_to_trigger)
- @is_interrupt_effect = true if @active_effect_owner
- $game_message.clear
- if @message_window
- @message_window.openness = 0
- @message_window.visible = true
- end
- $game_message.background = 1
- $game_message.position = 1
- $game_message.add("Do you want to activate the effect of")
- $game_message.add('"' + card_to_trigger.name + '"?')
- @status_window.hide if @status_window
- @status_back_window.hide if @status_back_window
- show_options(["Yes", "No"], 2) do |choice|
- @status_window.show if @status_window
- @status_back_window.show if @status_back_window
- $game_message.choice_proc = nil
- $game_message.clear
- if @message_window
- choice_window = @message_window.instance_variable_get(:@choice_window)
- choice_window.openness = 0 if choice_window
- end
- if choice == 0
- player.used_turn_effects ||= []
- player.used_turn_effects << card_to_trigger.summon_impact
- if card_to_trigger.note =~ /<shared_opt:\s*(.+?)>/i
- player.used_turn_effects << $1.to_s.strip
- end
- @active_effect_owner = player
- @active_effect_card = card_to_trigger
- $temp_active_card = card_to_trigger
- $chain_memory_card = card_to_trigger
- @current_processing_card = card_to_trigger
- invoke_card_impact(card_to_trigger.summon_impact)
- else
- execute_finish_proceed_cleanup
- end
- end
- wait_for_message
- return
- end
- execute_finish_proceed_cleanup
- if (@pending_triggers.nil? || @pending_triggers.empty?) && !$game_message.busy?
- cmd_active = @actor_command_window && @actor_command_window.active
- crd_active = @card_select_window && @card_select_window.active
- fld_active = @field_map_window && @field_map_window.active
- skl_active = @skill_window && @skill_window.active
- if !cmd_active && !crd_active && !fld_active && !skl_active
- @actor_command_window.show.activate if @actor_command_window
- end
- end
- end
- def execute_finish_proceed_cleanup
- puts "[DEBUG] Ejecutando execute_finish_proceed_cleanup. Interrupt flag: #{@is_interrupt_effect}"
- @card_select_window.hide.deactivate if @card_select_window
- @skill_window.hide.deactivate if @skill_window
- player = @active_effect_owner || $game_party.members[0]
- if @deck_was_searched
- player.is_official_shuffle = true
- player.shuffle_deck(true)
- player.is_official_shuffle = false
- @deck_was_searched = false
- else
- player.shuffle_deck(false)
- end
- @last_summon_is_set = false
- @current_card_action = nil
- @active_effect_card = nil
- @current_processing_card = nil
- $game_message.clear
- @message_window.close if @message_window
- @log_window.clear if @log_window
- @status_window.show if @status_window
- @status_back_window.show if @status_back_window
- @info_viewport.visible = true if @info_viewport
- if @is_interrupt_effect
- puts "[DEBUG] Limpiando UI post-Quick Effect. Devolviendo control al motor."
- @is_interrupt_effect = false
- @active_effect_owner = nil
- @return_to_hand_flag = false
- else
- if BattleManager.actor
- @return_to_hand_flag = true
- @actor_command_window.hide.deactivate if @actor_command_window
- command_look_hand
- elsif !BattleManager.in_turn?
- @party_command_window.show if @party_command_window && @party_command_window.active
- @actor_command_window.show if @actor_command_window && @actor_command_window.active
- end
- end
- end
- def process_banish_triggers(taken_cards)
- @pending_triggers ||= []
- taken_cards.each do |c|
- next unless c
- next if c.instance_variable_get(:@banished_face_down)
- c.instance_variable_set(:@temp_source_zone, nil)
- eff = nil
- mandatory = true
- if c.note =~ /<trigger_banish_effect:\s*(.+?)>/i
- eff = $1.to_s.strip
- elsif c.note =~ /<trigger_banish_effect_optional:\s*(.+?)>/i
- eff = $1.to_s.strip
- mandatory = false
- end
- if eff
- actor = BattleManager.actor
- next if actor.state?(18) && actor.leads_to_special_summon?(eff)
- next if actor.hopt_blocked?(c, eff)
- @pending_triggers << { card: c, effect: eff, expected_zone: :banish, mandatory: mandatory }
- end
- end
- end
- def check_pending_triggers
- @pending_triggers ||= []
- if @pending_triggers.size > 0
- trigger = @pending_triggers.shift
- card = trigger[:card]
- effect_name = trigger[:effect]
- expected_zone = trigger[:expected_zone] || :grave
- player = trigger[:owner] || $game_party.members[0]
- if player.state?(18) && player.leads_to_special_summon?(effect_name)
- finish_proceed_selection
- return
- end
- if player.hopt_blocked?(card, effect_name)
- finish_proceed_selection
- return
- end
- zone_array = case expected_zone
- when :grave then player.grave
- when :hand then player.hand
- when :deck then player.deck
- when :banish then player.banish
- when :extra then player.extra
- else []
- end
- unless zone_array.include?(card)
- finish_proceed_selection
- return
- end
- if trigger[:mandatory] == false
- $game_message.clear
- if @message_window
- @message_window.openness = 0
- @message_window.visible = true
- end
- $game_message.background = 1
- $game_message.position = 1
- $game_message.add("Do you want to activate the effect of")
- $game_message.add('"' + card.name + '"?')
- @status_window.hide if @status_window
- @status_back_window.hide if @status_back_window
- show_options(["Yes", "No"], 2) do |choice|
- @status_window.show if @status_window
- @status_back_window.show if @status_back_window
- $game_message.choice_proc = nil
- $game_message.clear
- if @message_window
- choice_window = @message_window.instance_variable_get(:@choice_window)
- choice_window.openness = 0 if choice_window
- end
- if choice == 0
- execute_pending_trigger(player, card, effect_name)
- else
- finish_proceed_selection
- end
- end
- wait_for_message
- return
- else
- execute_pending_trigger(player, card, effect_name)
- end
- end
- end
- def execute_pending_trigger(player, card, effect_name)
- player.used_turn_effects ||= []
- player.used_turn_effects << effect_name
- @is_interrupt_effect = true
- @active_effect_owner = player
- @active_effect_card = card
- $temp_active_card = card
- $chain_memory_card = card
- @current_processing_card = card
- RPG::SE.new("Skill2", 80, 100).play
- $game_message.clear
- if @message_window
- @message_window.openness = 255
- @message_window.visible = true
- end
- $game_message.background = 1
- $game_message.position = 1
- $game_message.add("The effect of " + card.name + " activates!")
- wait_for_message
- @current_card_action = :field_effect
- if effect_name.upcase.include?("LUNATIC_")
- player.invoke_lunatic_card(effect_name, card)
- finish_proceed_selection if respond_to?(:finish_proceed_selection)
- else
- invoke_card_impact(effect_name)
- end
- end
- def select_cancel
- @card_zone_label.hide
- @card_select_window.hide.deactivate
- @card_select_window.sort_index = -1
- restore_taken_cards(:cancel)
- restore_selected_cards
- if @field_map_window
- @field_map_window.dispose
- @field_map_window = nil
- end
- if @field_preview_window
- @field_preview_window.dispose
- @field_preview_window = nil
- end
- @field_ui_created = false
- @field_zone_label.hide if @field_zone_label
- restore_skill_window_layout
- if BattleManager.actor
- BattleManager.actor.current_zone = :hand
- end
- refresh_card_zone_label
- if @temp_effect_data[0] == :cost
- BattleManager.actor.hand += BattleManager.actor.stack
- BattleManager.actor.stack = []
- on_skill_cancel
- elsif @temp_effect_data[0] == :impact
- @return_to_hand_flag = true
- command_look_hand
- end
- end
- def restore_taken_cards(target)
- return false unless @temp_effect_data && @temp_effect_data[3] && @temp_effect_data[3] != []
- effect_name = @temp_effect_data[1]
- effect_data = PC27::CG::CARD_EFFECT[effect_name]
- destination = effect_data ? effect_data[5] : nil
- if @card_zone_label
- @card_zone_label.hide
- @card_zone_label.visible = false
- end
- if target == :proceed
- if effect_data && effect_data[6].is_a?(Numeric)
- required_amount = effect_data[6]
- if @temp_effect_data[3].size < required_amount
- target = :cancel
- end
- end
- end
- if target == :proceed
- if destination == :inherent_landing
- taken_cards = @temp_effect_data[3].dup
- @temp_effect_data[3] = []
- process_banish_triggers(taken_cards)
- @card_select_window.actor.banish += taken_cards
- if @active_effect_card
- hand_card = BattleManager.actor.hand.find { |c| c && c.id == @active_effect_card.id }
- if hand_card && BattleManager.actor.free_monster_zone_available?
- idx = BattleManager.actor.hand.index(hand_card)
- BattleManager.actor.hand.delete_at(idx) if idx
- hand_card.properly_summoned = true
- BattleManager.actor.field << hand_card
- empty_index = BattleManager.actor.monster_zones.index(nil)
- BattleManager.actor.monster_zones[empty_index] = hand_card
- BattleManager.actor.monster_zones_state[empty_index][:changed_this_turn] = true
- @field_map_window.refresh if @field_map_window
- show_special_summon_visuals(hand_card, true)
- @specially_summoned_card = hand_card
- end
- end
- @active_effect_card = nil
- check_pending_triggers if @pending_triggers && @pending_triggers.size > 0
- finish_proceed_selection
- return true
- end
- if destination == :choice_hand_grave
- taken_cards = @temp_effect_data[3].dup
- @temp_effect_data[3] = []
- $game_message.clear
- if @message_window
- @message_window.openness = 0
- @message_window.visible = true
- end
- $game_message.background = 1
- $game_message.position = 1
- card_name = taken_cards[0] ? taken_cards[0].name : "this card"
- $game_message.add("Where do you want to send")
- $game_message.add('"' + card_name + '"?')
- @status_window.hide if @status_window
- @status_back_window.hide if @status_back_window
- show_options(["Add to Hand", "Send to Graveyard"], 2) do |choice|
- @status_window.show if @status_window
- @status_back_window.show if @status_back_window
- $game_message.choice_proc = nil
- $game_message.clear
- if @message_window
- choice_window = @message_window.instance_variable_get(:@choice_window)
- choice_window.openness = 0 if choice_window
- end
- if choice == 0
- @card_select_window.actor.hand += taken_cards
- @last_chosen_destination = :hand
- else
- @card_select_window.actor.grave += taken_cards
- @last_chosen_destination = :grave
- end
- finish_proceed_selection
- end
- return true
- end
- if destination == :destroy_and_chain || destination == :send_to_grave_and_chain
- taken_cards = @temp_effect_data[3].dup
- @temp_effect_data[3] = []
- @temp_effect_data[4] = taken_cards[0]
- $chain_memory_card = taken_cards[0]
- @pending_triggers ||= []
- actor = @active_effect_owner || BattleManager.actor || $game_party.members[0]
- taken_cards.each do |c|
- source = c.instance_variable_get(:@temp_source_zone)
- c.instance_variable_set(:@temp_source_zone, nil)
- if destination == :destroy_and_chain && c.note =~ /<trigger_destroy_effect:\s*(.+?)>/i
- eff = $1.to_s.strip
- next if actor.state?(18) && actor.leads_to_special_summon?(eff)
- @pending_triggers << { card: c, effect: eff, expected_zone: :grave, owner: actor }
- end
- if c.note =~ /<trigger_sent_field_grave:\s*(.+?)>/i
- if source == :monster || source == :spell || source == :fieldspell
- eff = $1.to_s.strip
- @pending_triggers << { card: c, effect: eff, expected_zone: :grave, owner: actor }
- end
- end
- end
- actor.grave += taken_cards
- effect_data = PC27::CG::CARD_EFFECT[@temp_effect_data[1]] rescue nil
- next_effect = effect_data ? (effect_data[7] || effect_data[6]) : nil
- $game_message.clear
- @current_card_action = :field_effect
- actor.current_zone = :grave
- refresh_card_zone_label if respond_to?(:refresh_card_zone_label)
- if next_effect.is_a?(String)
- invoke_card_impact(next_effect)
- else
- check_pending_triggers if respond_to?(:check_pending_triggers)
- end
- return true
- end
- if destination == :special_summon_self
- card_to_summon = @temp_effect_data[3][0]
- @temp_effect_data[3] = []
- player = @card_select_window.actor
- source_zone = player.banish.include?(card_to_summon) ? player.banish : (player.grave.include?(card_to_summon) ? player.grave : nil)
- if card_to_summon && player.free_monster_zone_available? && source_zone
- atk_buff = 0
- def_buff = 0
- level_buff = 0
- regex = /<self_summon_buff:\s*(atk|def|level)\s*,\s*(banish|grave|field|hand)\s*,\s*(type|subtype|element)\s*,\s*(\d+)\s*,\s*(\d+)>/i
- card_to_summon.note.scan(regex) do |stat, zone, f_type, f_val, multiplier|
- target_array = case zone.downcase
- when "banish" then player.banish
- when "grave" then player.grave
- when "field" then player.field
- when "hand" then player.hand
- else []
- end
- match_count = target_array.count do |c|
- next false unless c
- next false if c == card_to_summon
- case f_type.downcase
- when "subtype" then c.respond_to?(:subtype) && c.subtype.to_s == f_val
- when "type" then c.respond_to?(:type) && c.type.to_s == f_val
- when "element" then c.respond_to?(:damage) && c.attribute.to_s == f_val
- else false
- end
- end
- total_buff = match_count * multiplier.to_i
- case stat.downcase
- when "atk" then atk_buff += total_buff
- when "def" then def_buff += total_buff
- when "level" then level_buff += total_buff
- end
- end
- empty_index = player.monster_zones.index(nil)
- player.monster_zones_state[empty_index] = {
- face_down: false,
- changed_this_turn: true,
- personal_atk_buff: atk_buff,
- personal_def_buff: def_buff,
- personal_level_buff: level_buff
- }
- state = player.monster_zones_state[empty_index]
- source_zone.delete_at(source_zone.index(card_to_summon))
- state[:face_down] = false
- state[:changed_this_turn] = true
- state[:personal_atk_buff] = atk_buff
- state[:personal_def_buff] = def_buff
- state[:personal_level_buff] = level_buff
- idx = source_zone.index(card_to_summon)
- source_zone.delete_at(idx) if idx
- options = ["Summon in Attack", "Summon in Defense"]
- show_options(options, 2) do |choice|
- $game_message.choice_proc = nil
- $game_message.clear
- if @message_window
- choice_window = @message_window.instance_variable_get(:@choice_window)
- choice_window.openness = 0 if choice_window
- end
- state[:position] = (choice == 0) ? :attack : :defense
- player.monster_zones[empty_index] = card_to_summon
- player.field << card_to_summon
- @field_map_window.refresh if @field_map_window
- show_special_summon_visuals(card_to_summon)
- @specially_summoned_card = card_to_summon
- finish_proceed_selection
- end
- return true
- else
- Sound.play_buzzer
- finish_proceed_selection
- return true
- end
- end
- if destination == :banish_and_chain
- taken_cards = @temp_effect_data[3].dup
- @temp_effect_data[3] = []
- @temp_effect_data[4] = taken_cards[0]
- $chain_memory_card = taken_cards[0]
- @pending_triggers ||= []
- taken_cards.each do |c|
- c.instance_variable_set(:@temp_source_zone, nil)
- if c.note =~ /<trigger_banish_effect:\s*(.+?)>/i
- @pending_triggers << { card: c, effect: $1.to_s.strip, expected_zone: :banish }
- end
- end
- @card_select_window.actor.banish += taken_cards
- process_banish_triggers(taken_cards)
- effect_data = PC27::CG::CARD_EFFECT[@temp_effect_data[1]]
- next_effect = effect_data[7] || effect_data[6]
- $game_message.clear
- if @temp_effect_data[0] == :cost
- invoke_card_cost(next_effect) if next_effect.is_a?(String)
- else
- @current_card_action = :field_effect
- @card_select_window.actor.current_zone = :banish
- refresh_card_zone_label if respond_to?(:refresh_card_zone_label)
- invoke_card_impact(next_effect) if next_effect.is_a?(String)
- end
- return true
- end
- if destination == :special_summon || destination == :special_summon_ignore || destination == :special_summon_def || destination == :special_summon_atk
- taken_cards = @temp_effect_data[3].dup
- @temp_effect_data[3] = []
- player = @card_select_window.actor
- if player.free_monster_zone_available?
- card_to_summon = taken_cards[0]
- empty_index = player.monster_zones.index(nil)
- state = player.monster_zones_state[empty_index]
- state[:face_down] = false
- @last_summon_is_set = false
- if destination == :special_summon_def
- state[:position] = :defense
- state[:changed_this_turn] = true
- player.monster_zones[empty_index] = card_to_summon
- player.field << card_to_summon
- @field_map_window.refresh if @field_map_window
- show_special_summon_visuals(card_to_summon)
- $game_message.clear
- @specially_summoned_card = card_to_summon
- finish_proceed_selection
- elsif destination == :special_summon_atk
- state[:position] = :attack
- state[:changed_this_turn] = true
- player.monster_zones[empty_index] = card_to_summon
- player.field << card_to_summon
- @field_map_window.refresh if @field_map_window
- show_special_summon_visuals(card_to_summon)
- $game_message.clear
- @specially_summoned_card = card_to_summon
- finish_proceed_selection
- else
- options = ["Summon in Attack", "Summon in Defense"]
- show_options(options, 2) do |choice|
- $game_message.choice_proc = nil
- $game_message.clear
- if @message_window
- choice_window = @message_window.instance_variable_get(:@choice_window)
- choice_window.openness = 0 if choice_window
- end
- state[:position] = (choice == 0) ? :attack : :defense
- state[:changed_this_turn] = true
- player.monster_zones[empty_index] = card_to_summon
- player.field << card_to_summon
- @field_map_window.refresh if @field_map_window
- show_special_summon_visuals(card_to_summon)
- @specially_summoned_card = card_to_summon
- finish_proceed_selection
- end
- return true
- end
- else
- player.grave += taken_cards
- Sound.play_buzzer
- finish_proceed_selection
- end
- return true
- end
- taken_cards = @temp_effect_data[3].dup
- taken_cards.each { |c| c.instance_variable_set(:@temp_source_zone, nil) if c.instance_variable_defined?(:@temp_source_zone) }
- case destination
- when :hand then @card_select_window.actor.hand += taken_cards
- when :deck
- @card_select_window.actor.deck += taken_cards
- @card_select_window.actor.shuffle_deck(false)
- when :grave then @card_select_window.actor.grave += taken_cards
- when :banish
- process_banish_triggers(taken_cards)
- @card_select_window.actor.banish += taken_cards
- when :extra then @card_select_window.actor.extra += taken_cards
- when :field then @card_select_window.actor.field += taken_cards
- end
- end
- if target == :cancel
- @active_effect_card = nil
- @temp_effect_data[3].each do |card|
- src = card.instance_variable_get(:@temp_source_zone)
- case src
- when :field
- empty_index = @card_select_window.actor.monster_zones.index(nil)
- @card_select_window.actor.monster_zones[empty_index] = card if empty_index
- @card_select_window.actor.field.push(card)
- when :hand then @card_select_window.actor.hand.push(card)
- when :deck then @card_select_window.actor.deck.push(card)
- when :grave then @card_select_window.actor.grave.push(card)
- when :banish then @card_select_window.actor.banish.push(card)
- when :extra then @card_select_window.actor.extra.push(card)
- end
- card.instance_variable_set(:@temp_source_zone, nil)
- end
- end
- if @temp_effect_data[0] == :cost
- @temp_effect_data[3] = []
- return true
- end
- @temp_effect_data[3] = []
- finish_proceed_selection
- check_pending_triggers if @pending_triggers && @pending_triggers.size > 0
- return true
- end
- #-----------------------------------------------------------------------------
- def restore_selected_cards
- array = PC27::CG::CARD_EFFECT[@temp_effect_data[1]]
- case array[3]
- when :hand_or_field
- @card_select_window.cards = []
- return
- when :deck
- @card_select_window.cards.reverse.each { |card|
- @card_select_window.actor.deck.unshift(card)
- }
- @card_select_window.actor.shuffle_deck if array[0] == :take && @card_select_window.actor.deck.size != 0
- @status_window.refresh
- when :hand
- @card_select_window.cards.reverse.each { |card|
- @card_select_window.actor.hand.unshift(card)
- }
- when :grave
- @card_select_window.cards.reverse.each { |card|
- @card_select_window.actor.grave.unshift(card)
- }
- when :banish
- @card_select_window.cards.reverse.each { |card|
- @card_select_window.actor.banish.unshift(card)
- }
- when :extra
- @card_select_window.cards.reverse.each { |card|
- @card_select_window.actor.extra.unshift(card)
- }
- when :field
- @card_select_window.cards.reverse.each { |card|
- @card_select_window.actor.field.unshift(card)
- }
- end
- @card_select_window.cards = []
- end
- #-----------------------------------------------------------------------------
- def prepare_select_window(moment, type)
- if moment == :impact
- if type == :view
- @card_select_window.set_handler(:ok, method(:no_method))
- @card_select_window.set_handler(:cancel, method(:select_cancel))
- elsif type == :sort
- @card_select_window.set_handler(:ok, method(:select_cards_ok_sort))
- @card_select_window.set_handler(:cancel, method(:select_cancel))
- elsif type == :take
- @card_select_window.set_handler(:ok, method(:select_cards_ok_take))
- @card_select_window.set_handler(:cancel, method(:proceed_selection))
- elsif type == :takem
- @card_select_window.set_handler(:ok, method(:select_cards_ok_take))
- @card_select_window.set_handler(:cancel, method(:no_method))
- end
- elsif moment == :cost
- if type == :view
- @card_select_window.set_handler(:ok, method(:no_method))
- @card_select_window.set_handler(:cancel, method(:proceed_selection))
- elsif type == :sort
- @card_select_window.set_handler(:ok, method(:select_cards_ok_sort))
- @card_select_window.set_handler(:cancel, method(:proceed_selection))
- elsif type == :take
- @card_select_window.set_handler(:ok, method(:select_cards_ok_take))
- @card_select_window.set_handler(:cancel, method(:select_cancel))
- elsif type == :takem
- @card_select_window.set_handler(:ok, method(:select_cards_ok_take))
- @card_select_window.set_handler(:cancel, method(:no_method))
- elsif type == :takeup
- @card_select_window.set_handler(:ok, method(:select_cards_ok_take))
- @card_select_window.set_handler(:cancel, method(:proceed_selection))
- end
- end
- end
- def no_method
- @card_select_window.activate
- end
- alias pc27_ygo_execute_action_cleanup execute_action
- def execute_action
- pc27_ygo_execute_action_cleanup
- actor = @subject
- item = actor.current_action.item rescue nil
- return unless actor && actor.is_a?(Game_Actor) && item
- if item.subtype == 24 || item.subtype == 25
- idx = @active_effect_zone_index || actor.st_zones.index { |c| c && c.equal?(item) }
- if idx && actor.st_zones[idx]
- card_on_field = actor.st_zones[idx]
- actor.st_zones[idx] = nil
- idx_field = actor.field.index { |c| c && c.equal?(card_on_field) }; actor.field.delete_at(idx_field) if idx_field
- actor.grave.push(card_on_field)
- @field_map_window.refresh if @field_map_window
- @minifield_window.refresh if defined?(@minifield_window) && @minifield_window
- end
- end
- end
- #-----------------------------------------------------------------------------
- def swap_cards(index1, index2)
- @card_select_window.cards[index1], @card_select_window.cards[index2] =
- @card_select_window.cards[index2], @card_select_window.cards[index1]
- end
- alias _trace_on_skill_ok on_skill_ok
- def on_skill_ok
- trace_call("on_skill_ok")
- _trace_on_skill_ok
- end
- alias _trace_handle_hand_skill handle_hand_skill
- def handle_hand_skill(skill)
- trace_call("handle_hand_skill")
- _trace_handle_hand_skill(skill)
- end
- alias _trace_invoke_card_cost invoke_card_cost
- def invoke_card_cost(effect)
- trace_call("invoke_card_cost (#{effect})")
- _trace_invoke_card_cost(effect)
- end
- alias _trace_resolve_card_effect resolve_card_effect
- def resolve_card_effect(skill)
- @last_state_card_id = nil
- if skill.is_a?(RPG::UsableItem) && @last_state_card_id != skill.object_id
- @last_state_card_id = skill.object_id
- player = @active_effect_owner || BattleManager.actor || $game_party.members[0]
- if player && player.alive?
- skill.effects.each { |eff| player.add_state(eff.data_id) if eff.code == 21 }
- end
- end
- impact = nil
- if skill.note =~ /<card impact:\s*(.+?)>/i || skill.note =~ /<spell_impact:\s*(.+?)>/i || skill.note =~ /<field_impact:\s*(.+?)>/i || skill.note =~ /<hand_impact:\s*(.+?)>/i
- impact = $1.to_s.strip
- end
- if skill.cost
- invoke_card_cost(skill.cost)
- elsif impact
- if @current_card_action == :field_effect
- player = @active_effect_owner || BattleManager.actor || $game_party.members[0]
- if player && player.respond_to?(:pay_skill_cost)
- player.pay_skill_cost(skill)
- RPG::SE.new("Magic1", 80, 100).play rescue nil
- player.popup_destroyed_card(skill.icon_index, "Activated!") if player.respond_to?(:popup_destroyed_card)
- end
- end
- invoke_card_impact(impact)
- else
- skill_select(1)
- end
- end
- alias _trace_process_select_cards process_select_cards
- def process_select_cards(effect)
- trace_call("process_select_cards (#{effect})")
- _trace_process_select_cards(effect)
- end
- alias pc27_coin_invoke_impact invoke_card_impact unless method_defined?(:pc27_coin_invoke_impact)
- def invoke_card_impact(effect_name)
- # Buscamos cuál es la carta que está intentando resolver un efecto ahora mismo
- card = @active_effect_card || @skill || $chain_memory_card || @selected_card
- if card
- # 1. ESCÁNER DE MONEDAS (<coin data>)
- regex_coin = /<coin data:\s*#{Regexp.escape(effect_name.to_s)}\s*,\s*(\d+)>(.*?)<\/coin data>/im
- if card.note =~ regex_coin
- num_coins = $1.to_i
- conditions_text = $2.strip
- process_coin_toss(num_coins, conditions_text)
- return # Cortamos acá
- end
- # 2. ESCÁNER DE CONDICIONES (<condition data>)
- regex_cond = /<condition data:\s*#{Regexp.escape(effect_name.to_s)}\s*>(.*?)<\/condition data>/im
- if card.note =~ regex_cond
- conditions_text = $1.strip
- process_conditional_impact(conditions_text)
- return # Cortamos acá
- end
- end
- # 3. IMPACTO NORMAL (Si no es moneda ni condición)
- pc27_coin_invoke_impact(effect_name)
- end
- #==============================================================================
- # CANDADO DE LIMPIEZA (Evita que la carta se borre antes de tiempo)
- #==============================================================================
- alias pc27_macro_finish_proceed finish_proceed_selection unless method_defined?(:pc27_macro_finish_proceed)
- def finish_proceed_selection
- return if @suppress_finish_proceed # Si el candado está puesto, cancela la limpieza
- pc27_macro_finish_proceed
- end
- #==============================================================================
- # PROCESADOR DE IMPACTOS CONDICIONALES (VERSIÓN BLINDADA)
- #==============================================================================
- def process_conditional_impact(conditions_text)
- player = @active_effect_owner || BattleManager.actor || $game_party.members[0]
- # 1. Creamos una lista para anotar todos los impactos que aprueben el chequeo
- impacts_to_run = []
- conditions_text.split("\n").each do |line|
- next if line.strip.empty?
- if line =~ /(.+?)\s*:\s*(.+)/i
- condition_str = $1.strip
- impact_to_execute = $2.strip.downcase
- is_valid = false
- if condition_str.downcase == "always"
- is_valid = true
- else
- # Evaluamos la matemática en vivo
- begin
- is_valid = player.instance_eval(condition_str)
- rescue => e
- puts "[DEBUG] Error leyendo condition data: #{e.message}"
- end
- end
- # Si da luz verde, lo anotamos en la lista de espera
- impacts_to_run << impact_to_execute if is_valid
- end
- end
- # 2. PONEMOS EL CANDADO: ¡Nadie toca la carta de la mesa!
- @suppress_finish_proceed = true
- # 3. Ejecutamos todos los impactos aprobados uno por uno
- impacts_to_run.each_with_index do |imp, idx|
- invoke_card_impact(imp)
- # Hacemos la pausa dramática solo si queda otro impacto por ejecutarse
- 20.times { update_basic } if SceneManager.scene_is?(Scene_Battle) && idx < impacts_to_run.size - 1
- end
- # 4. SACAMOS EL CANDADO
- @suppress_finish_proceed = false
- # 5. Ahora sí, soltamos los frenos y limpiamos la trampa al cementerio
- @is_interrupt_effect = false
- finish_proceed_selection if respond_to?(:finish_proceed_selection)
- end
- end
- #===============================================================================
- # Scene_Deck
- #===============================================================================
- class Scene_Deck < Scene_MenuBase
- include PC27::CG
- #-----------------------------------------------------------------------------
- # Start
- #-----------------------------------------------------------------------------
- def start
- super()
- create_filter_window
- create_deck_window
- create_extra_window
- create_coll_window
- create_text_window
- create_card_window
- create_info_window
- @extra_window.deactivate
- @coll_window.deactivate
- @deck_window.activate
- @deck_window.select(0)
- update_text_window
- end
- def return_scene
- if $game_party.menu_actor.deck.size <= 39
- RPG::SE.new("Buzzer1", 80, 100).play
- $game_message.add('Your deck has less than 40 cards.')
- SceneManager.return if $game_party.menu_actor.deck.size == 0
- else
- SceneManager.return
- end
- end
- #-----------------------------------------------------------------------------
- # Creates a window to display deck cards
- #-----------------------------------------------------------------------------
- def create_deck_window
- @deck_window = Window_Deck.new(0,64)
- @deck_window.set_handler(:cancel, method(:return_scene))
- @deck_window.set_handler(:ok, method(:deck_to_coll))
- end
- #-----------------------------------------------------------------------------
- # Creates a window to display extra deck cards
- #-----------------------------------------------------------------------------
- def create_extra_window
- @extra_window = Window_Extra.new(0,280)
- @extra_window.set_handler(:cancel, method(:return_scene))
- @extra_window.set_handler(:ok, method(:extra_to_coll))
- end
- #-----------------------------------------------------------------------------
- # Creates a window to display collection cards
- #-----------------------------------------------------------------------------
- def create_coll_window
- @coll_window = Window_Coll.new((Graphics.width - 210)*0.5, 64)
- @coll_window.set_handler(:cancel, method(:return_scene))
- @coll_window.set_handler(:ok, method(:coll_to_deck))
- @coll_window.deactivate
- end
- #-----------------------------------------------------------------------------
- # Creates the window that shows where you are
- #-----------------------------------------------------------------------------
- def create_text_window
- @text_window = Window_Base.new(0, 0, Graphics.width - 210, 64)
- update_text_window
- end
- #-----------------------------------------------------------------------------
- # Creates the window that shows the currently selected card
- #-----------------------------------------------------------------------------
- def create_card_window
- @card_window = Window_CardHelp.new()
- @card_window.windowskin = Cache.system(CUSTOM_CARD_BG) if CUSTOM_CARD_BG
- @card_window.tone.set(*PC27::CG::ELEMENT_COLOR[0])
- @card_window.back_opacity = PC27::CG::CARD_BACK_OP
- end
- #-----------------------------------------------------------------------------
- # Creates a info window
- #-----------------------------------------------------------------------------
- def create_info_window
- height = Graphics.height - 284
- @info_window = Window_Base.new(Graphics.width - 210, Graphics.height - height, 210, height)
- @info_window.contents.font.size = 22
- @info_window.change_color(@info_window.normal_color)
- @info_window.draw_text(0, 0, 180, 20, "(Z/Enter): Move Card")
- @info_window.draw_text(0, 20, 180, 20, "(X/Esc): Exit")
- @info_window.draw_text(0, 40, 180, 20, "(A): Filter")
- @info_window.draw_text(0, 60, 180, 20, "(Q/W): Change Actor")
- @info_window.draw_text(0, 80, 180, 20, "(Shift): Main <-> Extra")
- end
- #-----------------------------------------------------------------------------
- # Creates a window to filter cards
- #-----------------------------------------------------------------------------
- def create_filter_window
- @filter_window = Window_Filter.new(0,Graphics.height * 0.5 - 48)
- @filter_window.set_handler(:cancel, method(:close_filter))
- @filter_window.set_handler(:ok, method(:change_filter))
- @filter_window.z = 150
- @filter_window.hide
- @filter_window.deactivate
- end
- #-----------------------------------------------------------------------------
- # Changes between collection and deck window
- #-----------------------------------------------------------------------------
- def change_to_coll
- @coll_window.activate
- @deck_window.deactivate
- @extra_window.deactivate
- Sound.play_cursor
- Input.update
- update_text_window
- end
- def change_to_deck
- @deck_window.activate
- @coll_window.deactivate
- @extra_window.deactivate
- Sound.play_cursor
- Input.update
- update_text_window
- end
- def change_to_extra
- @deck_window.deactivate
- @coll_window.deactivate
- @extra_window.activate
- Sound.play_cursor
- Input.update
- update_text_window
- end
- #-----------------------------------------------------------------------------
- # Adds commands to exchange cards
- #-----------------------------------------------------------------------------
- def coll_to_deck
- for skill in $game_party.coll
- /coll(?<skill_id>\d+)/ =~ @coll_window.current_symbol.to_s
- skill_id = skill_id.to_i
- max_cards = (MAX_SAME_EXCEP.has_key?(skill_id) ? MAX_SAME_EXCEP[skill_id] : MAX_SAME_CARDS)
- if skill.id == skill_id && skill.type == 4
- if $game_party.menu_actor.extra.size >= MAX_EXTRA_SIZE
- RPG::SE.new("Buzzer1", 80, 100).play
- return
- end
- if $game_party.menu_actor.extra.count{ |skill| skill.id == skill_id } >= max_cards
- RPG::SE.new("Buzzer1", 80, 100).play
- return
- end
- $game_party.menu_actor.extra.push(
- $game_party.coll.slice!($game_party.coll.index(skill)))
- break
- elsif skill.id == skill_id
- if $game_party.menu_actor.deck.size >= MAX_DECK_SIZE
- RPG::SE.new("Buzzer1", 80, 100).play
- return
- end
- if $game_party.menu_actor.deck.count{ |skill| skill.id == skill_id } >= max_cards
- RPG::SE.new("Buzzer1", 80, 100).play
- return
- end
- $game_party.menu_actor.deck.push(
- $game_party.coll.slice!($game_party.coll.index(skill)))
- break
- end
- end
- RPG::SE.new("Cursor1", 80, 100).play
- @deck_window.refresh
- @extra_window.refresh
- @coll_window.refresh
- update_text_window
- end
- def deck_to_coll
- /deck(?<skill_id>\d+)/ =~ @deck_window.current_symbol.to_s
- skill_id = skill_id.to_i
- for skill in $game_party.menu_actor.deck
- if skill.id == skill_id
- $game_party.coll.push(
- $game_party.menu_actor.deck.slice!($game_party.menu_actor.deck.index(skill)))
- break
- end
- end
- RPG::SE.new("Cursor1", 80, 100).play
- @deck_window.refresh
- @coll_window.refresh
- update_text_window
- end
- def extra_to_coll
- /extra(?<skill_id>\d+)/ =~ @extra_window.current_symbol.to_s
- skill_id = skill_id.to_i
- for skill in $game_party.menu_actor.extra
- if skill.id == skill_id
- $game_party.coll.push(
- $game_party.menu_actor.extra.slice!($game_party.menu_actor.extra.index(skill)))
- break
- end
- end
- RPG::SE.new("Cursor1", 80, 100).play
- @extra_window.refresh
- @coll_window.refresh
- update_text_window
- end
- #-----------------------------------------------------------------------------
- # Activates filter
- #-----------------------------------------------------------------------------
- def activate_filter
- @filter_window.show
- @filter_window.activate
- @deck_window.deactivate
- @extra_window.deactivate
- @coll_window.deactivate
- end
- #-----------------------------------------------------------------------------
- # Changes filter settings
- #-----------------------------------------------------------------------------
- def change_filter
- case @filter_window.current_symbol
- when :filter_element
- @coll_window.filter[0] += 1
- @filter_window.filter[0] += 1
- @coll_window.filter[0] = 0 if $data_system.elements.size == @coll_window.filter[0]
- @filter_window.filter[0] = 0 if $data_system.elements.size == @filter_window.filter[0]
- when :filter_type
- @coll_window.filter[1] += 1
- @filter_window.filter[1] += 1
- @coll_window.filter[1] = 0 unless TYPE.has_key?(@coll_window.filter[1])
- @filter_window.filter[1] = 0 unless TYPE.has_key?(@filter_window.filter[1])
- when :filter_rarity
- @coll_window.filter[2] += 1
- @filter_window.filter[2] += 1
- @coll_window.filter[2] = 0 unless RARITY.has_key?(@coll_window.filter[2])
- @filter_window.filter[2] = 0 unless RARITY.has_key?(@filter_window.filter[2])
- when :filter_subtype
- @coll_window.filter[3] += 1
- @filter_window.filter[3] += 1
- @coll_window.filter[3] = 0 unless SUBTYPE.has_key?(@coll_window.filter[3])
- @filter_window.filter[3] = 0 unless SUBTYPE.has_key?(@filter_window.filter[3])
- when :filter_level
- @coll_window.filter[4] += 1
- @filter_window.filter[4] += 1
- @coll_window.filter[4] = 0 unless LEVEL.has_key?(@coll_window.filter[4])
- @filter_window.filter[4] = 0 unless LEVEL.has_key?(@filter_window.filter[4])
- when :filter_normeff
- @coll_window.filter[5] += 1
- @filter_window.filter[5] += 1
- @coll_window.filter[5] = 0 unless NORMEFF.has_key?(@coll_window.filter[5])
- @filter_window.filter[5] = 0 unless NORMEFF.has_key?(@filter_window.filter[5])
- when :filter_frame
- @coll_window.filter[6] += 1
- @filter_window.filter[6] += 1
- @coll_window.filter[6] = 0 unless FRAME.has_key?(@coll_window.filter[6])
- @filter_window.filter[6] = 0 unless FRAME.has_key?(@filter_window.filter[6])
- when :filter_archetype
- @coll_window.filter[7] += 1
- @filter_window.filter[7] += 1
- @coll_window.filter[7] = 0 unless ARCHETYPE.has_key?(@coll_window.filter[7])
- @filter_window.filter[7] = 0 unless ARCHETYPE.has_key?(@filter_window.filter[7])
- when :filter_atk
- @coll_window.filter[8] += 1
- @filter_window.filter[8] += 1
- @coll_window.filter[8] = 0 unless ATK.has_key?(@coll_window.filter[8])
- @filter_window.filter[8] = 0 unless ATK.has_key?(@filter_window.filter[8])
- when :filter_DEF
- @coll_window.filter[9] += 1
- @filter_window.filter[9] += 1
- @coll_window.filter[9] = 0 unless DEF.has_key?(@coll_window.filter[9])
- @filter_window.filter[9] = 0 unless DEF.has_key?(@filter_window.filter[9])
- when :filter_special
- @coll_window.filter[10] += 1
- @filter_window.filter[10] += 1
- @coll_window.filter[10] = 0 unless SPECIAL.has_key?(@coll_window.filter[10])
- @filter_window.filter[10] = 0 unless SPECIAL.has_key?(@filter_window.filter[10])
- when :confirm
- $game_party.coll += $game_party.menu_actor.deck + $game_party.menu_actor.extra
- $game_party.menu_actor.deck = []
- $game_party.menu_actor.extra = []
- @filter_window.confirm = false
- @filter_window.refresh
- when :call_confirm
- @filter_window.confirm = true
- @filter_window.refresh
- end
- @filter_window.refresh
- @coll_window.refresh
- @deck_window.refresh
- @extra_window.refresh
- update_text_window
- end
- #-----------------------------------------------------------------------------
- # Deativates filter
- #-----------------------------------------------------------------------------
- def close_filter
- @filter_window.hide
- @filter_window.deactivate
- @coll_window.activate
- @coll_window.select(0)
- end
- def next_actor
- if $game_party.menu_actor.deck.size <= 39
- RPG::SE.new("Buzzer1", 80, 100).play
- $game_message.add('Your deck has less than 40 cards.')
- else
- @actor = $game_party.menu_actor_next
- on_actor_change
- end
- end
- def prev_actor
- if $game_party.menu_actor.deck.size <= 39
- RPG::SE.new("Buzzer1", 80, 100).play
- $game_message.add('Your deck has less than 40 cards.')
- else
- @actor = $game_party.menu_actor_prev
- on_actor_change
- end
- end
- #-----------------------------------------------------------------------------
- # * Frame Update
- #-----------------------------------------------------------------------------
- def update
- super()
- if @filter_window.visible == false
- if Input.trigger?(:A)
- if @deck_window.active
- change_to_extra
- elsif @extra_window.active
- change_to_deck
- else
- change_to_extra
- end
- end
- change_to_coll if Input.trigger?(:RIGHT) && !@coll_window.active
- change_to_deck if Input.trigger?(:LEFT) && @coll_window.active
- activate_filter if Input.trigger?(:X)
- next_actor if Input.trigger?(:R)
- prev_actor if Input.trigger?(:L)
- end
- if @coll_window.active
- symbol = @coll_window.current_symbol
- elsif @deck_window.active
- symbol = @deck_window.current_symbol
- elsif @extra_window.active
- symbol = @extra_window.current_symbol
- end
- if symbol != @symbol
- @symbol = symbol
- id_string = @symbol.to_s[/\d+/]
- skill = (id_string ? $data_skills[id_string.to_i] : nil)
- @card_window.set_item(skill)
- end
- end
- def on_actor_change
- RPG::SE.new("Cursor2", 80, 100).play
- @deck_window.refresh
- @extra_window.refresh
- @deck_window.select(0)
- @extra_window.select(0)
- @coll_window.select(0)
- update_text_window
- end
- def update_text_window
- return unless @text_window
- @text_window.contents.clear
- @text_window.contents.font.size = 20
- active_win = :none
- active_win = :deck if @deck_window && @deck_window.active
- active_win = :extra if @extra_window && @extra_window.active
- active_win = :coll if @coll_window && @coll_window.active
- hl_color = @text_window.text_color(14)
- nm_color = @text_window.normal_color
- current_actor = @actor || $game_party.menu_actor
- @text_window.change_color(active_win == :deck ? hl_color : nm_color)
- @text_window.draw_text(0, -4, 90, 24, "Main Deck:")
- @text_window.change_color(nm_color)
- @text_window.draw_text(90, -4, 60, 24, "#{current_actor.deck.size}/#{MAX_DECK_SIZE}")
- @text_window.change_color(active_win == :extra ? hl_color : nm_color)
- @text_window.draw_text(0, 18, 90, 24, "Extra Deck:")
- @text_window.change_color(nm_color)
- @text_window.draw_text(90, 18, 60, 24, "#{current_actor.extra.size}/#{MAX_EXTRA_SIZE}")
- coll_x = 160
- @text_window.change_color(active_win == :coll ? hl_color : nm_color)
- @text_window.draw_text(coll_x, -4, 90, 24, "Collection:")
- @text_window.change_color(nm_color)
- @text_window.draw_text(coll_x + 90, -4, 50, 24, "#{$game_party.coll.size}")
- @text_window.change_color(hl_color)
- @text_window.draw_text(coll_x, 18, 140, 24, current_actor.name, 0)
- end
- end
- class Window_Deck < Window_Command
- #--------------------------------------------------------------------------
- # Makes Command List
- #--------------------------------------------------------------------------
- def make_command_list
- add_deck_commands
- end
- #--------------------------------------------------------------------------
- # Add Card Commands to List
- #--------------------------------------------------------------------------
- def add_deck_commands
- $game_party.menu_actor.sort_cards(:deck)
- deck = $game_party.menu_actor.deck
- if deck.empty?
- add_command("---", :nothing)
- return
- end
- hash = {}
- for skill in deck
- if hash.has_key?(skill.id)
- hash[skill.id] += 1
- else
- hash[skill.id] = 1
- end
- end
- hash.each_key do |id|
- add_command(hash[id].to_s + "x " + $data_skills[id].name, ("deck" + id.to_s).to_sym, true, id)
- end
- end
- def draw_item(index)
- change_color(normal_color, command_enabled?(index))
- rect = item_rect_for_text(index)
- card_id = @list[index][:ext]
- if card_id && card_id.is_a?(Integer)
- icon_index = $data_skills[card_id].icon_index
- draw_icon(icon_index, rect.x, rect.y)
- rect.x += 28
- rect.width -= 28
- end
- draw_text(rect, command_name(index), alignment)
- end
- #--------------------------------------------------------------------------
- # Get Window Height
- #--------------------------------------------------------------------------
- def window_height
- Graphics.height - 200
- end
- #--------------------------------------------------------------------------
- # Get Window width
- #--------------------------------------------------------------------------
- def window_width
- (Graphics.width - 210) * 0.5
- end
- #--------------------------------------------------------------------------
- # Overwrite process_ok so the window won't be disabled
- #--------------------------------------------------------------------------
- def process_ok
- if current_item_enabled?
- Input.update
- call_ok_handler
- select(index - 1) unless current_symbol
- else
- Sound.play_buzzer
- end
- end
- end
- class Window_Extra < Window_Command
- #--------------------------------------------------------------------------
- # Makes Command List
- #--------------------------------------------------------------------------
- def make_command_list
- add_extra_commands
- end
- #--------------------------------------------------------------------------
- # Add Card Commands to List
- #--------------------------------------------------------------------------
- def add_extra_commands
- $game_party.menu_actor.sort_cards(:extra)
- extra = $game_party.menu_actor.extra
- if extra.empty?
- add_command("---", :nothing)
- return
- end
- hash = {}
- for skill in extra
- if hash.has_key?(skill.id)
- hash[skill.id] += 1
- else
- hash[skill.id] = 1
- end
- end
- hash.each_key do |id|
- add_command(hash[id].to_s + "x " + $data_skills[id].name, ("extra" + id.to_s).to_sym, true, id)
- end
- end
- def draw_item(index)
- change_color(normal_color, command_enabled?(index))
- rect = item_rect_for_text(index)
- card_id = @list[index][:ext]
- if card_id && card_id.is_a?(Integer)
- icon_index = $data_skills[card_id].icon_index
- draw_icon(icon_index, rect.x, rect.y)
- rect.x += 28
- rect.width -= 28
- end
- draw_text(rect, command_name(index), alignment)
- end
- #--------------------------------------------------------------------------
- # Get Window Height
- #--------------------------------------------------------------------------
- def window_height
- 136
- end
- #--------------------------------------------------------------------------
- # Get Window width
- #--------------------------------------------------------------------------
- def window_width
- (Graphics.width - 210) * 0.5
- end
- #--------------------------------------------------------------------------
- # Overwrite process_ok so the window won't be disabled
- #--------------------------------------------------------------------------
- def process_ok
- if current_item_enabled?
- Input.update
- call_ok_handler
- select(index - 1) unless current_symbol
- else
- Sound.play_buzzer
- end
- end
- end
- class Window_Coll < Window_Command
- attr_accessor :filter
- def initialize(width, heigth)
- @filter = [0,0,0,0,0,0,0,0,0,0,0]
- super(width, heigth)
- end
- #--------------------------------------------------------------------------
- # Makes Command List
- #--------------------------------------------------------------------------
- def make_command_list
- add_coll_commands
- end
- #--------------------------------------------------------------------------
- # Add Collection Commands to List
- #--------------------------------------------------------------------------
- def add_coll_commands
- $game_party.coll.sort!{|a,b| a.id <=> b.id}
- coll = $game_party.coll
- if coll.empty?
- add_command("---", :nothing)
- return
- end
- hash = {}
- for skill in coll
- next unless match_filter?(skill)
- if hash.has_key?(skill.id)
- hash[skill.id] += 1
- else
- hash[skill.id] = 1
- end
- end
- hash.each_key do |id|
- add_command(hash[id].to_s + "x " + $data_skills[id].name, ("coll" + id.to_s).to_sym, true, id)
- end
- end
- def draw_item(index)
- change_color(normal_color, command_enabled?(index))
- rect = item_rect_for_text(index)
- card_id = @list[index][:ext]
- if card_id && card_id.is_a?(Integer)
- icon_index = $data_skills[card_id].icon_index
- draw_icon(icon_index, rect.x, rect.y)
- rect.x += 28
- rect.width -= 28
- end
- draw_text(rect, command_name(index), alignment)
- end
- #--------------------------------------------------------------------------
- # Checks if a card meets the specified filter criteria
- #--------------------------------------------------------------------------
- def match_filter?(skill)
- return false unless skill.attribute == @filter[0] || @filter[0] == 0
- return false unless skill.type == @filter[1] || @filter[1] == 0
- return false unless skill.rarity == @filter[2] || @filter[2] == 0
- return false unless skill.subtype == @filter[3] || @filter[3] == 0
- return false unless skill.level == @filter[4] || @filter[4] == 0
- return false unless skill.normeff == @filter[5] || @filter[5] == 0
- return false unless skill.frame == @filter[6] || @filter[6] == 0
- return false unless skill.archetype == @filter[7] || @filter[7] == 0
- return false unless skill.atk == @filter[8] || @filter[8] == 0
- return false unless skill.def == @filter[9] || @filter[9] == 0
- return false unless skill.special == @filter[10] || @filter[10] == 0
- return true
- end
- #--------------------------------------------------------------------------
- # Get Window Height
- #--------------------------------------------------------------------------
- def window_height
- Graphics.height - 64
- end
- #--------------------------------------------------------------------------
- # Get Window width
- #--------------------------------------------------------------------------
- def window_width
- (Graphics.width - 210) * 0.5
- end
- def process_ok
- if current_item_enabled?
- Input.update
- call_ok_handler
- select(index - 1) unless current_symbol
- else
- Sound.play_buzzer
- end
- end
- end
- class Window_Filter < Window_Command
- include PC27::CG
- attr_accessor :filter
- attr_accessor :confirm
- def initialize(width, heigth)
- @filter = [0,0,0,0,0,0,0,0,0,0,0]
- @confirm = false
- super(width, heigth)
- hide
- end
- #--------------------------------------------------------------------------
- # Makes Command List
- #--------------------------------------------------------------------------
- def make_command_list
- add_filter_commands
- end
- #--------------------------------------------------------------------------
- # Add Collection Commands to List
- #--------------------------------------------------------------------------
- def add_filter_commands
- add_command(FILTER_TEXT + F_ELEMENT + (@filter[0]==0 ? "---" : $data_system.elements[@filter[0]] ), :filter_element)
- add_command(FILTER_TEXT + F_TYPE + (@filter[1]==0 ? "---" : TYPE[@filter[1]]), :filter_type)
- add_command(FILTER_TEXT + F_RARITY + (@filter[2]==0 ? "---" : RARITY[@filter[2]][1]), :filter_rarity)
- add_command(FILTER_TEXT + F_SUBTYPE + (@filter[3]==0 ? "---" : SUBTYPE[@filter[3]][1]), :filter_subtype)
- add_command(FILTER_TEXT + F_LEVEL + (@filter[4]==0 ? "---" : LEVEL[@filter[4]][1]), :filter_level)
- add_empty_deck_command
- end
- #--------------------------------------------------------------------------
- # Get Window Height
- #--------------------------------------------------------------------------
- def window_height
- 96
- end
- #--------------------------------------------------------------------------
- # Get Window width
- #--------------------------------------------------------------------------
- def window_width
- Graphics.width
- end
- def process_ok
- if current_item_enabled?
- RPG::SE.new("Cursor1", 80, 100)
- Input.update
- call_ok_handler
- else
- Sound.play_buzzer
- end
- end
- def add_empty_deck_command
- if @confirm
- add_command(CONFIRM, :confirm)
- else
- add_command(EMPTY_DECK, :call_confirm)
- end
- end
- def hide
- @confirm = false
- super
- end
- end
- class Window_MenuCommand < Window_Command
- #--------------------------------------------------------------------------
- # Replaces skills with Deck (overwrite)
- #--------------------------------------------------------------------------
- def add_main_commands
- add_command(Vocab::item, :item, main_commands_enabled)
- add_command(PC27::CG::DECK, :deck, main_commands_enabled)
- add_command(Vocab::equip, :equip, main_commands_enabled)
- add_command(Vocab::status, :status, main_commands_enabled)
- end
- end
- class Scene_Menu < Scene_MenuBase
- #--------------------------------------------------------------------------
- # Adds a handler to access the deck scene (alias)
- #--------------------------------------------------------------------------
- alias pc27_cardgame_scenemenu_create_cmd_wdw create_command_window
- def create_command_window
- pc27_cardgame_scenemenu_create_cmd_wdw
- @command_window.set_handler(:deck, method(:command_personal))
- end
- #--------------------------------------------------------------------------
- # Adds :deck to the personal command process (alias)
- #--------------------------------------------------------------------------
- alias pc27_cardgame_scenemenu_on_personal_ok on_personal_ok
- def on_personal_ok
- pc27_cardgame_scenemenu_on_personal_ok
- case @command_window.current_symbol
- when :deck
- SceneManager.call(Scene_Deck)
- end
- end
- end
- class Window_CardOptions < Window_Command
- def initialize(options, disabled_indices)
- @options = options
- @disabled_indices = disabled_indices
- super(0, 0)
- self.x = Graphics.width - 240
- ideal_y = 274
- max_y = Graphics.height - 114 - self.window_height
- self.y = [ideal_y, max_y].min
- self.z = 500
- end
- def window_width; return 240; end
- def make_command_list
- @options.each_with_index do |opt, i|
- add_command(opt, :ok, !@disabled_indices.include?(i))
- end
- end
- end
- ################################################################################
- # End of script #
- ################################################################################
Add Comment
Please, Sign In to add comment