Re: Card Development - talk about cards code here
Posted: 24 Jun 2021, 07:32
Hipparion seems to have issue only with Blaze of Glory which is quite fine by me, I will submit the code. Thanks for the help drool66.
High Quality Resources for Collectible Card Games and Home of the CCGHQ Team
https://www.slightlymagic.net/forum/
https://www.slightlymagic.net/forum/viewtopic.php?f=56&t=29928
I tried this but I can't do it, if you find some time please do it.drool66 wrote:From untap_phasing(), it looks like EVENT_PHASING won't be sent to Teferi's Curse because "player" is the player controlling it, and EVENT_PHASING is only sent to the cards of the player whose turn it is - so if played on another player's creature, it won't see Teferi's Curse at all. I'm pretty sure you'd have to special-case these cards into mirage.c::untap_phasing() and maybe even engine.c::untap_phase(). See how Shimmer is handled for reference - these would probably be less complicated than that card.
int card_kaerveks_torch(int player, int card, event_t event){
/* CARD_ID_KAERVEKS_TORCH 2522 //remain impossible???
Kaervek's Torch |X|R
Sorcery
As long as ~ is on the stack, spells that target it cost |2 more to cast.
~ deals X damage to any target. */
if( ! IS_GS_EVENT(player, card, event) ){
return 0;
}
target_definition_t td;
default_target_definition(player, card, &td, TYPE_CREATURE|TARGET_TYPE_PLANESWALKER);
td.zone = TARGET_ZONE_CREATURE_OR_PLAYER;
card_instance_t* instance = get_card_instance(player, card);
if( event == EVENT_CAST_SPELL && affect_me(player, card) ){
int card_added = generate_reserved_token_by_id(player, CARD_ID_SPECIAL_EFFECT);
card_instance_t *inst = get_card_instance(player, card_added);
inst->targets[0].card = SE_MOD_SPELLS_TARGETING_ME;
inst->targets[1].player = player;
inst->targets[1].card = card;
inst->targets[2].card = 2;
put_into_play(player, card_added);
}
if( event == EVENT_RESOLVE_SPELL ){
if( valid_target(&td) ){
damage_target0(player, card, instance->info_slot);
}
kill_card(player, card, KILL_DESTROY);
}
return generic_spell(player, card, event, GS_CAN_TARGET | GS_X_SPELL, &td, "TARGET_ANY", 1, NULL);
}
if( event == EVENT_MODIFY_COST_GLOBAL ){
...
if( flags & SE_MOD_SPELLS_TARGETING_ME ){
if(card_on_stack_controller == instance->targets[1].player && card_on_stack == instance->targets[1].card && is_what(affected_card_controller, affected_card, TYPE_INTERRUPT))
COST_COLORLESS += instance->targets[2].card;
}
}
static int brood_of_cockroaches_legacy(int player, int card, event_t event){
if( eot_trigger(player, card, event) ){
//card_instance_t *instance = get_card_instance(player, card);
int owner, position;
if( find_in_owners_graveyard(player, card, &owner, &position) ){
lose_life(player, 1);
int iid = get_grave(owner)[position];
remove_card_from_grave(owner, position);
add_card_to_hand(owner, iid);
}
kill_card(player, card, KILL_EXILE);
}
return 0;
}
int card_brood_of_cockroaches(int player, int card, event_t event){
/* CARD_ID_BROOD_OF_COCKROACHES 2678
Brood of Cockroaches |1|B
Creature - Insect 1/1
When ~ is put into your graveyard from the battlefield, at the beginning of the next end step, you lose 1 life and return ~ to your hand. */
if( this_dies_trigger_for_owner(player, card, event, RESOLVE_TRIGGER_MANDATORY) ){
create_legacy_effect(player, card, &brood_of_cockroaches_legacy);
}
return 0;
}
if( event == EVENT_LEAVES_PLAY_ABILITY &&
(instance->targets[0].card != -1 ||
(instance->damage_target_player != instance->targets[2].player && instance->damage_target_card != instance->targets[2].card))
){
instance->targets[2].player = instance->damage_target_player;
instance->targets[2].card = instance->damage_target_card;
}
if( event == EVENT_CHECK_ABILITIES && affect_me(player, card) && generic_activated_ability(player, card, EVENT_CAN_ACTIVATE, 0, MANACOST_G(1), 0, NULL, NULL) ){
check_abilities_keywords |= SP_KEYWORD_DEATHTOUCH;
}
manalink.h::
#define QUERYING(val) (event == EVENT_QUERY && attacking_card == (val))
produce_mana.c::
int plain_mana_producer(int player, int card, event_t event){
if( QUERYING(QUERY_IS_PLAIN_MANA_PRODUCER) )
return 1;
return mana_producer(player, card, event);
}
int can_autotap(int player, int card, autotap_t autotap_flags){
// 0x42fda0
card_instance_t* inst = in_play(player, card);
if( !inst )
return 0;
iid_t iid = inst->internal_card_id;
color_test_t colors = (inst->card_color & (COLOR_TEST_ANY | COLOR_TEST_ARTIFACT));
if( is_what(player, card, TYPE_LAND) )
colors |= mana_colors_added[player];
if ( !(colors & COLOR_TEST_ANY)
|| !((cards_data[iid].extra_ability & EA_MANA_SOURCE) || (is_what(player, card, TYPE_LAND) && (mana_colors_added[player] & COLOR_TEST_ANY)))
|| cards_data[iid].extra_ability & EA_PAID_MANASOURCE
|| !can_produce_mana(player, card) )
return 0;
if ( (autotap_flags & AUTOTAP_NO_BASIC_LANDS) && (is_basic_land(player, card) || query(player, card, -1, QUERY_IS_PLAIN_MANA_PRODUCER)) )
return 0;
if ( (autotap_flags & AUTOTAP_NO_NONBASIC_LANDS) && is_what(player, card, TYPE_LAND) && !is_basic_land(player, card) && !query(player, card, -1, QUERY_IS_PLAIN_MANA_PRODUCER) )
return 0;
if ( (autotap_flags & AUTOTAP_NO_DONT_AUTO_TAP) && (inst->state & STATE_NO_AUTO_TAPPING) )
return 0;
if ( (autotap_flags & AUTOTAP_NO_ARTIFACTS) && (is_what(player, card, TYPE_ARTIFACT) && !query(player, card, -1, QUERY_IS_PLAIN_MANA_PRODUCER)) )
return 0;
if ( (autotap_flags & AUTOTAP_NO_CREATURES) && (is_what(player, card, TYPE_CREATURE) && !query(player, card, -1, QUERY_IS_PLAIN_MANA_PRODUCER)) )
return 0;
return 1;
}
###############
# can_autotap #
###############
#42fda0: 55 push ebp
#42fda1: 8b ec mov ebp,esp
#42fda3: 83 ec 0c sub esp,0c
jmp_to(0x42fda0 => 0x2007884);
objdump -M intel -d Magic.exe --start-address=0x42fda0 --stop-address=0x42fdff
This will definitely be a problem if you're using make data, or the Makefile in magic_updater/ at all, to build data files - the first thing it does is "cp ../Magic.exe .".drool66 wrote:and then moved magic.exe (which had a new filestamp) from /src/patches to /magic_updater and built as normal
int card_scrying_glass(int player, int card, event_t event){ // remain
/* CARD_ID_SCRYING_GLASS 4189
Scrying Glass |2
Artifact
|3, |T: Choose a number greater than 0 and a color. Target opponent reveals their hand.
If that opponent reveals exactly the chosen number of cards of the chosen color, you draw a card. */
if( ! IS_GAA_EVENT(event) ){
return 0;
}
target_definition_t td;
default_target_definition(player, card, &td, 0);
td.zone = TARGET_ZONE_PLAYERS;
card_instance_t *instance = get_card_instance( player, card );
if( event == EVENT_RESOLVE_ACTIVATION ){
if( valid_target(&td) ){
int result = 0;
if( player == HUMAN ){
while( result == 0 ){
result = choose_a_number(player, "Choose a number greater than 0.", hand_count[1-player]);
if( result < 1 ){
result = 0;
}
}
}
int color_res = 1<<choose_a_color(player, get_deck_color(player, 1-player));
if( player == IS_AI(player) ){
result = recorded_rand(player, hand_count[1-player]) + 1;
}
reveal_target_player_hand(instance->targets[0].player);
test_definition_t this_test;
default_test_definition(&this_test, TYPE_ANY);
this_test.color = color_res;
this_test.qty = result;
this_test.zone = TARGET_ZONE_HAND;
if( check_battlefield_for_special_card(player, card, player, 0, &this_test) ){
draw_cards(player, 1);
}
}
}
return generic_activated_ability(player, card, event, GAA_UNTAPPED | GAA_CAN_ONLY_TARGET_OPPONENT, MANACOST_X(3), 0, &td, NULL);
}