It is currently 18 Apr 2024, 06:28
   
Text Size

Manalink TODO list

Discuss Upcoming Releases, Coding New Cards, Etc.
PLEASE DO NOT REPORT BUGS HERE!

Moderators: BAgate, drool66, Aswan jaguar, gmzombie, stassy, CCGHQ Admins

Manalink TODO list

Postby Gargaroz » 17 Jul 2013, 13:34

Just in case anyone wants to help Korath and me ;)

Things still left to do (mostly regarding hardcoded stuff we know a little) :
1) What exactly happens when a card is "stolen" from his owner ? The decoding of Control Magic and linked functions is crucial.
2) It's possible to change the targets of a card when it's already cast / activated ?
3) How exactly works the function that "attach" an enchantment / effect to another card ? Cards like Aura Graft are doable ?
4) How exactly works the "mana_producer" function ? How the AI is able to choose which color to draw from multi-coloured sources ? A decode of Black Lotus would be nice.
5) When the "TRIGGER_CARD_DRAWN" and "TRIGGER_REPLACE_CARD_DRAW" are invoke, why they function per-card base only some times ? The number of cards to draw when the "draw_cards" functions is called is still available through some means during that event ?
6) Which are the still undiscovered uses of the "LAND_CAN_BE_PLAYED" global variable ?

For reference, grab the fundamental "magic.c", which is the decode of the EXE through HexRays Decompiler, from this thread : viewtopic.php?f=56&t=6528
For more references, download the latest pacth and check the "src" folder, in particular "manalink.h" and the stuff in the "functions" folder.
----
- Current / medium term task: adjusting the code for making Misdirection and such usable
- Long term task: inserting all the good stuff I left out from the "Golden Years" mod
Gargaroz
Programmer
 
Posts: 7097
Joined: 06 Nov 2009, 11:11
Has thanked: 82 times
Been thanked: 595 times

Re: Manalink TODO list

Postby Korath » 31 Jul 2013, 14:14

Rough outline for Control Magic's EVENT_RESOLVE_SPELL:
  1. real_validate_target().
  2. Copy aura->targets[0].player and .card into aura->damage_target_player and damage_target_card.
  3. Within _U4585F0(), special-case handling for Control Magics, Steal Artifacts, and legacy_effect_control that have the same damage_target_player and damage_target_card as this one (including this one). STATUS_CONTROLLED gets set or unset (on the aura/legacy cards, looks like), and the auras'/legacies' damage_source_player and damage_source_card are changed in a way that's not immediately obvious. Also in here, a special case for legacy_guardian_beast; if that prevents the aura from attaching, set aura->number_of_targets = 0 and return 0 (from control magic's function).
  4. Set STATUS_CONTROLLED in the aura's token_status. (Not the enchanted creature's, or at least not yet.)
  5. If the aura's targeted something its caster already controls, set aura->number_of_targets = 0 and return 0.
  6. Call _U435F50(41). (I think that that plays a sound effect, judging solely from the other places I've seen it; but its code is far beyond my ability to even sort of follow.)
  7. aura->damage_target_card = _U4B6860(aura->damage_target_player, aura->damage_target_card), then aura->damage_target_player = caster, aura->number_of_targets = 0, and return 0.
_U4B6860 does most of the interesting stuff; I believe it's a self-contained control swap of its player/card arguments:
  1. original_target = get_card_instance(arg1, arg2)
  2. opposite_player = 1-arg1
  3. add_card_to_hand(opposite_player, original_target->internal_card_id); new_target = get_card_instance() of that.
  4. memcpy's *original_target into *new_target!
  5. sets STATE_SUMMON_SICK and removes STATE_ATTACKING and STATE_BLOCKING from new_target->state
  6. dword_507EC0[original_target->timestamp] = opposite_player; dword_5076F0[original_target->timestamp] = new_target's card number (that is, the latter half of its player/card pair - is there a better way to refer to this?)
  7. For both players, loop 0 to active_cards_count[]; if damage_target_player/damage_target_card, damage_source_player/damage_source_card, or any target in its target array (up to number_of_targets-1) is original_target's player/card, set them to new_target's
  8. If the original target is a creature (from cards_data[original_target->internal_card_id].type), increment dword_4EF1CC[opposite_player].
  9. If it's an artifact, increment dword_4EF1D4[opposite_player]
  10. If it's an enchantment, increment dword_4EF1DC[opposite_player]
  11. dword_4EF17C[opposite_player] |= cards_data[original_target->internal_card_id].type
  12. mark some graphics to be redrawn
  13. original_target->token_status |= (STATUS_CANNOT_LEAVE_PLAY | STATUS_OBLITERATED), and call kill_card(..., KILL_REMOVE) on it
  14. If (dword_4EF188 & 0x10000000) dispatch_event(new_target's player, new_target's card number, EVENT_CARDCONTROLLER)
  15. And return new_target's card number.
The low word of dword_4EF188 looks to be a series of global bits, like land_has_been_played. The bit in question and most of the rest of the high word (everything in the mask 0x1FFC0000) accumulates the corresponding bits in cards_data[instance->internal_card_id].extra_abilities whenever get_abilities(..., EVENT_CHANGE_TYPE) is called on a card with STATE_IN_PLAY set. (When they're unset is less clear.) The bit _U4B6860 checks for is EA_CONTROLLED. The overall effect is that EVENT_CARDCONTROLLER is only dispatched if there's a card in play that's set to respond to it, which is currently only Ifh-Biff Efreet (for its weird legacy card, most likely) and Instill Energy. Quirion Ranger should probably be set up to do so, too, I suppose.

Control Magic's handler for TRIGGER_LEAVE_PLAY is significantly more complicated than its EVENT_RESOLVE_SPELL, but it again calls _U4B6860 to do the actual change of control.
User avatar
Korath
DEVELOPER
 
Posts: 3707
Joined: 02 Jun 2013, 05:57
Has thanked: 496 times
Been thanked: 1106 times

Re: Manalink TODO list

Postby Gargaroz » 02 Aug 2013, 20:14

Fairly complicated, as I suspected. Could you double check with Aladdin and try to write down a more exaustive version of our function "gain_control" ?
----
- Current / medium term task: adjusting the code for making Misdirection and such usable
- Long term task: inserting all the good stuff I left out from the "Golden Years" mod
Gargaroz
Programmer
 
Posts: 7097
Joined: 06 Nov 2009, 11:11
Has thanked: 82 times
Been thanked: 595 times

Re: Manalink TODO list

Postby Korath » 04 Aug 2013, 10:50

switch_control looks essentially complete. Aladdin's EVENT_RESOLVE_ACTIVATION handle (after it's validated its target) reads like
Code: Select all
int legacy_card = create_legacy_effect(activating_player, activating_card, LEGACY_EFFECT_ALADDIN, instance->targets[0].player, instance->targets[0].card);
if (legacy_card != -1)
  {
    card_instance_t* legacy_inst = get_card_instance(player, legacy_card);
    legacy_inst->damage_source_player = -1;
    legacy_inst->damage_source_card = -1;
    legacy_inst->token_status |= STATUS_PERMANENT;
    legacy_inst->targets[0].player = activating_player;
    legacy_inst->targets[0].card = activating_card;
    legacy_inst->number_of_targets = 1;
    // Omitted: Aladdin keeps track of its legacy effects by storing them in its targets[] and a count as 18-info_slot
    if (u4585f0(player, legacy_card))   // backend_of_control_magic()
      {
        legacy_inst->token_status |= STATUS_CONTROLLED;
        if (legacy_inst->targets[0].player != player)
          {
            u435f50(0x29);  // WILDGUESS_play_sound_effect()
            int result = u4b6860(legacy_inst->damage_target_player, legacy_inst->damage_target_card);       // TENTATIVE_gain_control()
            legacy_inst->damage_target_player = player;
            legacy_inst->damage_target_card = result;
          }
      }
  }
Note that the check for player == tar_player (as gain_control() does before calling switch_control()) is much later, and that the return value of u4585f0() is checked. No idea if the difference is significant enough to be behind the Unwilling Recruit bug.
User avatar
Korath
DEVELOPER
 
Posts: 3707
Joined: 02 Jun 2013, 05:57
Has thanked: 496 times
Been thanked: 1106 times

Re: Manalink TODO list

Postby Gargaroz » 05 Aug 2013, 13:33

The real thing we need is the code of the Aladdin legacy card, so I could incorporate in it other effects like additional abilities, color change and such. Right now, we need a double legacy card wich is ugly as hell (check the code for "effect_act_of_treason").
----
- Current / medium term task: adjusting the code for making Misdirection and such usable
- Long term task: inserting all the good stuff I left out from the "Golden Years" mod
Gargaroz
Programmer
 
Posts: 7097
Joined: 06 Nov 2009, 11:11
Has thanked: 82 times
Been thanked: 595 times

Re: Manalink TODO list

Postby Gargaroz » 05 Aug 2013, 13:36

Also, a more customizable Aswan Jaguar legacy would be really cool (we're using it for "create_card_name_legacy").
----
- Current / medium term task: adjusting the code for making Misdirection and such usable
- Long term task: inserting all the good stuff I left out from the "Golden Years" mod
Gargaroz
Programmer
 
Posts: 7097
Joined: 06 Nov 2009, 11:11
Has thanked: 82 times
Been thanked: 595 times

Re: Manalink TODO list

Postby Aswan jaguar » 05 Aug 2013, 14:38

Now that we talk about the "Legacy" cards it would be nice to understand how the original cards add and show the correct pump bonus each time they are generated to the same "Legacy" card instead of one "Legacy" card for each pump we have.And only add a separate Legacy card if it concerns another ability.

Although the numerous pump-Legacy cards on top of cards seem more prestigious. :lol: You know like a veteran soldier with very much experience and medallions -so many pumps on battle-I am a BAD ASS in battle thing. :twisted:
---
Trying to squash some bugs and playtesting.
User avatar
Aswan jaguar
Super Tester Elite
 
Posts: 8078
Joined: 13 May 2010, 12:17
Has thanked: 730 times
Been thanked: 458 times

Re: Manalink TODO list

Postby Gargaroz » 05 Aug 2013, 15:20

Nah, AJ, the actual system is more in line with the stack structure : each activation has a separate slot, unless an X is the activation cost. The old system for, let's say, Shivan Dragon, is greatly uncorrect.
----
- Current / medium term task: adjusting the code for making Misdirection and such usable
- Long term task: inserting all the good stuff I left out from the "Golden Years" mod
Gargaroz
Programmer
 
Posts: 7097
Joined: 06 Nov 2009, 11:11
Has thanked: 82 times
Been thanked: 595 times

Re: Manalink TODO list

Postby Korath » 05 Aug 2013, 16:35

What do you need out of an Aswan Jaguar legacy? Just the ability to have a legacy card named whatever you want?

You can probably hide the extra effect cards by setting STATUS_INVISIBLE_FX in their token_status fields. They'll be visible if people turn on the "show invisible effects" from the right click option, but that's ugly enough already that double legacies will fit right in.

And I think what Aswan Jaguar was asking for was for the legacy effects attached to, say, Gateway Shade to be combined, not the separate effects that go onto the stack each time you activate it. If STATUS_INVISIBLE_FX is all that's needed to hide legacies, then setting the bit if there's already an identical legacy attached to the card should do it.
User avatar
Korath
DEVELOPER
 
Posts: 3707
Joined: 02 Jun 2013, 05:57
Has thanked: 496 times
Been thanked: 1106 times

Re: Manalink TODO list

Postby Sonic » 05 Aug 2013, 22:43

The manalink text format allows for the effect/legacy text entries to list the text for each effect/legacy card a cards effect/abilities could generate by using |#1, |#2, |#3. Although it still works on the older ASM cards, it's never been used in C. So we've just ended up listing everything in the same single effect/legacy card.

Runesword - |#1Target creature gets +2/+0 until end of turn.|#2Target creature can't be regenerated this turn. If the creature would be put into a graveyard this turn, remove it from the game instead.

Other stuff

|n - variable number (power, toughness, mana, etc.)
Blessing - Target creature gets +|n/+|n until end of turn.

|C - variable color
Chaoslace - The color of target permanent is changed to |C.
Working On: Life, the Universe, and Everything.
User avatar
Sonic
Apprentice
 
Posts: 827
Joined: 27 Feb 2010, 00:37
Has thanked: 3 times
Been thanked: 161 times

Re: Manalink TODO list

Postby Korath » 06 Aug 2013, 00:20

The |#1 trick is controlled by legacy_instance->eot_toughness; set it to the number of the alternative you want displayed. It works only on effect cards with csv id 903 (which includes the custom effect used throughout C-coded cards). It can't be immediately followed by another digit in its text, or it won't work quite right (the exe function uses atoi() to extract the number to compare to instead of the ch-'0' idiom, but only advances the string by 1 - a string of "...#12text" would match eot_toughness=12 and display "2text"). Runesword's been recoded, but Order of Leitbur still uses this if you want to experiment with it.

Unfortunately, the function that does that replacement (0x4D4ED0; I'm labelling it copy_string_alternative_by_pipe_hash_digit()) doesn't get enough information to know exactly which legacy card it's working with; it only gets a source string, a destination string, and eot_toughness. Otherwise, it'd be an ideal location to inject into to get arbitrary text for effect cards. It's called in four places, all for effect cards with csv id 903. Other than the call from get_displayable_cardname_from_player_card() (0x439690), it's not immediately obvious which string is which. So effect cards' card names could be made to call the custom legacy's func_ptr with a specific event code to set the title, but I'm not confident doing so for other text.

The | codes, typically enough, aren't handled anywhere near each other, so there's no easy way to make a complete list of which are at our disposal.
---
I'm pretty confident in saying that changing a card's target to another legal target can't be done without recoding every card to handle it; there's no way to extract what its legal targets are, and cards do too many other different things in EVENT_CAST_SPELL or EVENT_ACTIVATE.

The best approximation I can think of would be to copy the spell and counter the original. It might be possible to limit it to spells that only have one target, but I'm not sure whether card_instance_t::number_of_targets decreases immediately when a target becomes illegal, or if they're checked on resolution, or if it's inconsistent between cards. Ruling on Deflection is that if a spell targets multiple things, you can't target it with Deflection, even if all but one of those targets has become illegal.
Last edited by Korath on 07 Aug 2013, 01:56, edited 1 time in total.
User avatar
Korath
DEVELOPER
 
Posts: 3707
Joined: 02 Jun 2013, 05:57
Has thanked: 496 times
Been thanked: 1106 times

Re: Manalink TODO list

Postby Gargaroz » 07 Aug 2013, 01:55

Korath wrote:What do you need out of an Aswan Jaguar legacy? Just the ability to have a legacy card named whatever you want?
Oh yeah !
----
- Current / medium term task: adjusting the code for making Misdirection and such usable
- Long term task: inserting all the good stuff I left out from the "Golden Years" mod
Gargaroz
Programmer
 
Posts: 7097
Joined: 06 Nov 2009, 11:11
Has thanked: 82 times
Been thanked: 595 times

Re: Manalink TODO list

Postby Korath » 11 Aug 2013, 02:49

I've sent Gargaroz code to rename effect cards, if anyone's idly curious.
---
Replacing Aladdin's effect card will be difficult, since a number of places look specifically for its internal_card_id (or Control Magic's or Steal Artifact's). If having multiple effect cards is ugly, I suggest making one of them invisible instead.
---
mana_producer_fixed() (the backend for e.g. the basic lands) is very simple:
int mana_producer_fixed(int player, int card, event_t event, color_t color) | Open
Code: Select all
int mana_producer_fixed(int player, int card, event_t event, color_t color)
{
  card_instance_t* instance = get_card_instance(player, card);
  switch (event)
    {
      case EVENT_COUNT_MANA:
        if (affect_me(player, card) && !is_tapped_or_a_summon_sick_creature(instance))
          declare_mana_available(player, color, 1);
        break;

      case EVENT_CAN_ACTIVATE:
        if (!is_tapped_or_a_summon_sick_creature(instance))
          return 1;
        break;

      case EVENT_ACTIVATE:
        undeclare_mana_available_and_produce_it(player, color, 1);
        instance->state |= STATE_TAPPED;
        tapped_for_mana_color = color;  // 0x7904bc
        break;

      case EVENT_RESOLVE_SPELL:
        play_sound_effect(color + 8);
        break;
    }
  return 0;
}
I've got a complete decompilation of Black Lotus that I'll install with Mana Reflection and the Mana Flare rewrite, but there's a more general version of the color choice in the common backend of mana_producer_tapped() and the beta dual lands. Its EVENT_ACTIVATE handler looks like:
part of int tap_for_multicolor_mana(int player, int card, event_t event, color_test_t colors) | Open
Code: Select all
// needed_mana_colors is a global at 0x7a2b68

int chosen_color, col;

if (needed_mana_colors != COLOR_TEST_COLORLESS
    && needed_mana_colors != COLOR_TEST_ARTIFACT    // 0x40
    && needed_mana_colors != (COLOR_TEST_ARTIFACT|COLOR_TEST_COLORLESS))
  {
    int colors_needed;
    if (needed_mana_colors)
      colors_needed = needed_mana_colors & colors;
    else
      colors_needed = colors;

    int default_color = -1;
    int num_colors_needed = 0;
    for (col = COLOR_COLORLESS; col <= COLOR_ARTIFACT; ++col)
      if ((1 << col) & colors_needed)
        {
          ++num_colors_needed;
          if (default_color == -1)
            default_color = col;
        }
    if (player == 1 && !(trace_mode & 2))     // seems like there should be an ai_is_speculating check here, too, but there isn't
      chosen_color = default_color;
    else
      chosen_color = choose_a_color_exe(player, text_lines[0],    // load_text() is called in the various front ends
                                        1,    // nonzero here makes the labels "Red", etc. instead of "Mountain", etc.
                                        -1, num_colors_needed == 1 ? colors_needed : colors);
  }
else
  {
    chosen_color = -1;
    for (col = COLOR_COLORLESS; col <= COLOR_ARTIFACT; ++col)
      if ((1 << col) & colors)
        {
          chosen_color = col;
          break;
        }
  }

if (chosen_color == -1)
  cancel = 1;
else
  {
    produce_mana(player, chosen_color, 1);
    undeclare_mana_available_hex(player, chosen_color, 1);  // unclear if this is truly needed
    card_instance_t* instance = get_card_instance(player, card);
    instance->state |= STATE_TAPPED;  // not tap_card(), since we're in this instance's own EVENT_ACTIVATE handler
    tapped_for_mana_color = chosen_color;
    if (player == 1 && !(trace_mode & 2)
        && ai_is_speculating != 1 && chosen_color >= COLOR_BLACK && chosen_color <= COLOR_WHITE)
      {
        load_text(0, (int)"MULTI_LANDS");
        do_dialog(player, player, card, -1, -1, text_lines[chosen_color - 1], 0);
      }
  }
---
Don't know on the draw triggers yet, but no, there's no way to know how many cards are to be drawn:
int draw_cards(int player, int numcards) | Open
Code: Select all
int draw_cards(int player, int numcards)
{
  int i;
  for (i = 0; i < numcards; ++i)
    {
      draw_a_card(player);
      if (player != 0)
        dword_60A4B0 = 0;   // this doesn't seem to be set to anything except 0 anywhere
    }
  return numcards;
}
User avatar
Korath
DEVELOPER
 
Posts: 3707
Joined: 02 Jun 2013, 05:57
Has thanked: 496 times
Been thanked: 1106 times

Re: Manalink TODO list

Postby Xenias » 11 Aug 2013, 19:29

Two variable found.

First one.
DWORD ENCAHNTMENT_ACTIVATION_COST_MODIFIER[8] 0x60A50C
0x60A50C = for COLOR_COLORLESS
0x60A510 = for COLOR_BLACK
...
0x60A528 = for COLOR_ANY

using at EVENT_COUNT_MANA
Example | Open
Code: Select all
if( event == EVENT_COUNT_MANA && affect_me(player, card) ) {
    ENCAHNTMENT_ACTIVATION_COST_MODIFIER[COLOR_WHITE] += 3;
    //COLOR_WHITE is checked whether is sleighted in actuality.
}
This was used by original Gloom code.( Now, It has been changed obviously)
So, it affects each player, casting and activation of enchantment.
COLOR_ARTIFACT and COLOR_ANY are meaningless, no effect.
COLOR_COLORLESS contains Land and Artifact, it refers to the color.

It seems to be strange behavior.
Even if mana is not enough for cast, you can cast.(maybe code changed?)

And then, so important thing, old original Microprose enchantment cards are affected(ex:Blessing), but new cards are not.
(Because it was coded without considering this. I feel it was natural.)
If has_mana_multi is changed, it works, maybe.

Q. Can I make Null Rod by using this variable?
A. No, absolutely.
:( :( :(
Xenias
 
Posts: 8
Joined: 13 Jul 2013, 16:41
Has thanked: 0 time
Been thanked: 3 times

Re: Manalink TODO list

Postby Xenias » 11 Aug 2013, 19:33

Second one.
DWORD AVAILABLE_MANA[2][8] 0x4EF3C0
AVAILABLE_MANA[player][color_t]

Code: Select all
    if (event == EVENT_CAN_COUNTER){
        if (dword_4EF3C8[8 * player] >= 2){       // No idea what this is.
            ai_modifier += 24;
        }
    }
is

Code: Select all
    if(event == EVENT_CAN_COUNTER){
        if(AVAILABLE_MANA[player][COLOR_BLUE]>=2){
            ai_modifier += 24;
        }
    }
It says,
"Wow, 2 blue mana remains. Pay attention!! Counterspell Sucks!"
or
"I keep 2 blue mana, time for counter! Just do it!!"
....maybe later one. :)
Xenias
 
Posts: 8
Joined: 13 Jul 2013, 16:41
Has thanked: 0 time
Been thanked: 3 times

Next

Return to Development

Who is online

Users browsing this forum: No registered users and 26 guests


Who is online

In total there are 26 users online :: 0 registered, 0 hidden and 26 guests (based on users active over the past 10 minutes)
Most users ever online was 4143 on 23 Jan 2024, 08:21

Users browsing this forum: No registered users and 26 guests

Login Form