Explanation of why Krugal Trapper (ll073)'s ability seek does not reveal the trap card
… still in v4.981
Code Summary and Detailed Code
FILE REFERENCES IN THE GAME |
TERMS TO LOCATE SEEK REFERENCE
|
- SpecificCard.cs: Contains the logic related to specific cards and abilities such as:
`OnUseAbility()`, `CanUseAbility()`, `StartTargetingForSeek()`, `GetAbilityTargets()`, and `DoSeek()`.
- GameModel.cs: Manages the core game functions, such as:
`RemoveDeck()`, `ShowCardForPlayer()`, `AddHand()`, and `ShuffleDeck()`.
|
- OnSeek
- DoSeek
- Seek
- StartTargetingForSeek
- GetAbilityTargets
- RemoveDeck
- ShowCardForPlayer
- AddHand
|
SUMMARY OF THE SEEK PROCESS:
|
- `OnUseAbility()`: Handles the activation of the seek ability.
- `CanUseAbility()`: Checks if the seek ability can be used.
- `StartTargetingForSeek()`: Initiates the targeting process for the seek.
- `GetAbilityTargets()`: Retrieves valid targets for the seek.
- `IsValidAbilityTarget()`: Check valid target.
- `DoSeek()`: Executes the seek action:
- `GameModel.RemoveDeck(ShadowEraCard card)`: Removes the card from the deck.
- `GameModel.ShowCardForPlayer(ShadowEraCard card)`: Displays the card to the opponent.
- `GameModel.AddHand(ShadowEraCard card)`: Adds the card to the player's hand.
- `OnSeek()`: May handle additional effects after the card is added to the hand.
- `ShuffleOurDeck()`: Shuffles the deck after the seek is completed.
|
DETAILED CODE
|
This code is a collection of all the functions involved in the Seek mechanic, though it doesn't exist as a single block in any one file.
|
public override void OnUseAbility()
{
if (!isPartTwo)
{
if (!parent.IsDead())
{
MoveToCastPosition();
GameModel.QueuePart2(parent);
isPartTwo = true;
}
}
else
{
isPartTwo = false;
DoSeek(usedShadowEnergy: true);
}
// Handles the activation of the seek ability
}
public override bool CanUseAbility()
{
if (GameModel.isSimulating)
{
return false;
}
if (GameModel.DeckCount() == 0)
{
return false;
}
if (GameModel.HandCount() == GameModel.MaxHandSize())
{
return false;
}
return true;
// Checks if the seek ability can be used
}
public void StartTargetingForSeek()
{
ClearTargets();
MoveToCastPosition();
GameModel.UnhighlightCards();
GameModel.SetGameState(GameState.GameStateType.target);
List<ShadowEraCard> abilityTargets = GetAbilityTargets();
for (int i = 0; i < GameModel.DeckCount(); i++)
{
ShadowEraCard deck = GameModel.GetDeck(i);
if (abilityTargets.Contains(deck))
{
GameModel.RemoveDeck(deck);
i--;
}
}
for (int j = 0; j < abilityTargets.Count; j++)
{
GameModel.AddDeck(abilityTargets[j]);
}
GameModel.HighlightCards(GetAbilityTargets());
DeckListDisplay.abilityCard = parent;
DeckListDisplay.ShowDeck(GameModel.CurSide());
// Initiates the targeting process for the seek
}
public override List<ShadowEraCard> GetAbilityTargets()
{
List<ShadowEraCard> list = new List<ShadowEraCard>();
for (int i = 0; i < GameModel.DeckCount(); i++)
{
ShadowEraCard deck = GameModel.GetDeck(i);
if (IsValidAbilityTarget(deck))
{
list.Add(deck);
}
}
return list;
// Retrieves valid targets for the seek.
}
private static bool IsValidAbilityTarget(ShadowEraCard check)
{
return check.cardType == CardTypeEnum.Ally && check.cardSubType == CardSubTypeEnum.Aldmor;
// Check valid targets for ll041's ability example.
}
public void DoSeek(bool usedShadowEnergy)
{
DeckListDisplay.CloseDeck();
if (targets.Count > 0 && GameModel.HandCount() < GameModel.MaxHandSize())
{
GameModel.RemoveDeck(targets[0]);
GameModel.ShowCardForPlayer(targets[0]);
GameModel.AddHand(targets[0]);
GameModel.OnSeek(targets[0]);
}
else
{
GameModel.OnSeek(null);
}
ShuffleOurDeck();
targets.Clear();
// Executes the seek action
}
public static void RemoveDeck(ShadowEraCard card)
{
// Code that handles removing a card from the deck
}
public static void ShowCardForPlayer(ShadowEraCard card)
{
if (!isSimulating && Gameplay.Instance != null)
{
Gameplay.Instance.UpdateHand(forceUpdate: true);
Gameplay.Instance.ShowCard(card);
Gameplay.Instance.BlockInput(2f);
if (card.gameObject != null)
{
CoroutineManager.Start(_ShowCardForPlayer(card));
}
}
}
public static void AddHand(ShadowEraCard card)
{
// Code that handles adding a card to the player's hand
}
public static void OnSeek(ShadowEraCard card)
{
// Handles additional effects or actions after the card is added to the hand
}
public void ShuffleOurDeck()
{
GameModel.ShuffleDeck();
// Shuffles the deck after the seek is completed
}
|
English Explanation
Alan said: "Card effects take precedence over the game rules."`
- This concept Alan said in english is the C# function
`AttachCard(ShadowEraCard card, bool doCallbacks = true):`
- `AttachCard()`: When a card is played or attached, the game makes it "linked" to a player, hero, or ally.
- During this pocress, if `doCallbacks = true`, additional logic, such as the card’s effects, is executed.
- `Callbacks` = Card effects: The `callbacks` trigger specific card effects, such as Rapid Fire allowing a hero to attack twice, or Net Trap disabling an enemy ally for several turns. These effects override general game rules.
- Effects > General rules: Once the `callbacks` are executed, the card effects modify or bypass the standard game rules. For example, the rule "one attack per turn" can be changed by the effect of Rapid Fire.
- Thus, `AttachCard()` and its `callbacks` manage these exceptions to the game’s general rules, allowing card-specific effects to take precedence when triggered.
- Relation to Traps and Why They Are Not Revealed
- The global mechanism for Traps, that they must remain face-down, is integrated into the steps of the Seek process. This mechanism takes priority over other rules, such as revealing a card that has been Seeked.
- When a Trap is Seeked, the face-down rule `(PlayFaceDown())` inherent to Traps is triggered before any reveal function `(ShowCardForPlayer())` can be called. This ensures that the Trap stays hidden, overriding the normal rule that states Seeked cards must be revealed.
- This behavior highlights how card effects take precedence over standard game rules. The face-down condition bypasses the normal `ShowCardForPlayer()` function, ensuring that Traps remain hidden in compliance with their unique mechanics.
- Therefore, while the Seek process normally requires cards to be revealed, the Trap mechanic ensures that this reveal is skipped. The handling of Traps shows how `AttachCard()` triggers card-specific logic (via `callbacks`) that overrides the default rules, allowing Traps to stay face-down as intended.
- Intentional or not?
Yes we may say that the behavior of Traps not revealed after Seek function is intentionally coded by the developers, and here is why:
- Traps have specific mechanics that are fundamental to their function: they are played facedown and only revealed when triggered. There is no exception; if a Trap is revealed faceup in the graveyard it is because cards are placed faceup in the graveyard process; if a trap is returned to hand, nothing says in the returned to hand process that it should be revealed.
- The fact that Traps aren’t revealed during a Seek mechanism follows the logic of the game. The code appears to be structured to ensure this rule is confirmed by preventing the `ShowCardForPlayer()` function from being triggered for Traps.
- Functions like `PlayFaceDown()` and specific conditions in the code show that the developers have built these special rules for Traps, and they take effect before the standard rules apply.
- Now, the following example code would essentially stop `PlayFaceDown()` from bypassing the reveal process for Seeked cards.
- So, if the deloppers of the game wanted to modify the `PlayFaceDown()` behavior as explicitly stated in the rulebook, they would likely handle the situation easily. It would only require a global phase test.
|void PlayFaceDown(ShadowEraCard card, bool isSeeked)
{
if (isSeeked)
{
// Allow ShowCardForPlayer() to be invoked for Seeked cards
ShowCardForPlayer(card);
}
else
{
// Keep the card face-down as usual (normal Trap behavior)
KeepCardFaceDown(card);
}
}
|