Card Development - talk about cards code here
Discuss Upcoming Releases, Coding New Cards, Etc.
PLEASE DO NOT REPORT BUGS HERE!
PLEASE DO NOT REPORT BUGS HERE!
Moderators: BAgate, drool66, Aswan jaguar, gmzombie, stassy, CCGHQ Admins
Re: Card Development - talk about cards code here
by Aswan jaguar » 03 Jan 2023, 10:17
It needed store_attackers() to trigger, now fixed.
---
Trying to squash some bugs and playtesting.
Trying to squash some bugs and playtesting.
-
Aswan jaguar - Super Tester Elite
- Posts: 8078
- Joined: 13 May 2010, 12:17
- Has thanked: 730 times
- Been thanked: 458 times
Need Help to exile Planeswalkers when died
by etphonehome » 14 Jan 2023, 23:30
Hi
This card works fine but it doesn't exile a planeswalker when it dies. There's no other card with similar effect already coded to guide me.
This card works fine but it doesn't exile a planeswalker when it dies. There's no other card with similar effect already coded to guide me.
- Code: Select all
int card_scorching_dragonfire(int player, int card, event_t event) {
/*CARD_ID_SCORCHING_DRAGONFIRE 20722
Scorching Dragonfire |1|R
Instant
~ deals 3 damage to target creature or planeswalker. If that creature or planeswalker would die this turn, exile it instead.
*/
if (!IS_GS_EVENT(player, card, event)) {
return 0;
}
target_definition_t td;
default_target_definition(player, card, &td, TYPE_CREATURE | TYPE_PLANESWALKER);
if (event == EVENT_RESOLVE_SPELL) {
if (valid_target(&td)) {
card_instance_t* instance = get_card_instance(player, card);
exile_if_would_be_put_into_graveyard(player, card, instance->targets[0].player, instance->targets[0].card, 1);
damage_target0(player, card, 3);
}
kill_card(player, card, KILL_DESTROY);
}
return generic_spell(player, card, event, GS_CAN_TARGET, &td, "TARGET_CREATURE_OR_PLANESWALKER", 1, NULL);
}
- etphonehome
- Posts: 299
- Joined: 21 May 2020, 12:50
- Has thanked: 270 times
- Been thanked: 39 times
Re: Card Development - talk about cards code here
by drool66 » 15 Jan 2023, 01:57
It's not your card's fault - planeswalkers just don't have a way to handle this. Probably belongs in kill_card(), but I'm not sure if there are corner cases that break something
EDIT: Ok, it's working; your code is good to go
EDIT: Ok, it's working; your code is good to go
The latest images for Manalink will be here.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
-
drool66 - Programmer
- Posts: 1163
- Joined: 25 Nov 2010, 22:38
- Has thanked: 186 times
- Been thanked: 267 times
Re: Card Development - talk about cards code here
by etphonehome » 15 Jan 2023, 15:57
Hi
Need some help here! Can't make this card to reduce cost. Used "Angel's Mercy" to reduce cost but it doesn't happen.
Need some help here! Can't make this card to reduce cost. Used "Angel's Mercy" to reduce cost but it doesn't happen.
- Code: Select all
int card_sanguine_indulgence(int player, int card, event_t event) {
/* CARD_ID_SANGUINE_INDULGENCE 21659
Sanguine Indulgence |3|B
Sorcery
This spell costs |3 less to cast if you've gained 3 or more life this turn.
Return up to two target creature cards from your graveyard to your hand. */
if (event == EVENT_MODIFY_COST) {
if (get_trap_condition(player, TRAP_LIFE_GAINED) >= 3) {
COST_COLORLESS -= 3;
}
}
test_definition_t test;
new_default_test_definition(&test, TYPE_CREATURE, "Select up to two target creature cards.");
return spell_return_up_to_n_target_cards_from_your_graveyard_to_your_hand(player, card, event, 2, &test, 0);
}
- etphonehome
- Posts: 299
- Joined: 21 May 2020, 12:50
- Has thanked: 270 times
- Been thanked: 39 times
Re: Card Development - talk about cards code here
by drool66 » 15 Jan 2023, 16:57
Its another csv flag, this time "Modifies Casting Cost"
btw, if you want to modify the casting cost of something else, like with Sapphire Medallion eg., you use "Flags:Play Cost" in csv and EVENT_MODIFY_COST_GLOBAL on the card.
btw, if you want to modify the casting cost of something else, like with Sapphire Medallion eg., you use "Flags:Play Cost" in csv and EVENT_MODIFY_COST_GLOBAL on the card.
The latest images for Manalink will be here.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
-
drool66 - Programmer
- Posts: 1163
- Joined: 25 Nov 2010, 22:38
- Has thanked: 186 times
- Been thanked: 267 times
Re: Card Development - talk about cards code here
by etphonehome » 16 Jan 2023, 16:39
HI
I set the flag "Modifies Casting Cost" in ct_all.csv to 1, but it still doesn't work.
I set the flag "Modifies Casting Cost" in ct_all.csv to 1, but it still doesn't work.
- etphonehome
- Posts: 299
- Joined: 21 May 2020, 12:50
- Has thanked: 270 times
- Been thanked: 39 times
Re: Card Development - talk about cards code here
by Aswan jaguar » 16 Jan 2023, 17:44
Add 13 which is for traps to cc2 flag in ct_all.csv.
---
Trying to squash some bugs and playtesting.
Trying to squash some bugs and playtesting.
-
Aswan jaguar - Super Tester Elite
- Posts: 8078
- Joined: 13 May 2010, 12:17
- Has thanked: 730 times
- Been thanked: 458 times
Re: Card Development - talk about cards code here
by drool66 » 16 Jan 2023, 18:10
Right, here is a somewhat outdated, but still useful reference to cc[2] values
The latest images for Manalink will be here.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
-
drool66 - Programmer
- Posts: 1163
- Joined: 25 Nov 2010, 22:38
- Has thanked: 186 times
- Been thanked: 267 times
Riddleform not ending effect at EOT
by etphonehome » 16 Jan 2023, 18:49
It works fine if it me who activate effect, if it's AI, on it's turn, the effect only ends at the end of my turn and not at the end of AI turn.
- Code: Select all
int card_riddleform(int player, int card, event_t event) {
/* Riddleform |1|U
* Enchantment
* Whenever you cast a noncreature spell, you may have ~ become a 3/3 Sphinx creature with flying in addition to its other types until end of turn.
* |2|U: Scry 1. */
if (trigger_condition == TRIGGER_SPELL_CAST && affect_me(player, card)) {
test_definition_t test;
default_test_definition(&test, TYPE_CREATURE);
test.type_flag = DOESNT_MATCH;
sp_ability_trigger(player, event, RESOLVE_TRIGGER_MANDATORY, 0, &test, player, card);
}
if (event == EVENT_SP_ABILITY) {
int choice = 0;
choice = do_dialog(player, player, card, -1, -1, " Animate Riddleform\n Pass", 0);
if (choice == 0) {
int legacy = turn_into_creature(player, card, player, card, 1, 3, 3);
card_instance_t* instance = get_card_instance(player, legacy);
instance->targets[8].player = KEYWORD_FLYING;
instance->targets[9].player = instance->targets[9].player & 1;
instance->targets[9].card = SUBTYPE_SPHINX;
}
}
if (event == EVENT_RESOLVE_ACTIVATION) {
scry(player, 1);
}
return generic_activated_ability(player, card, event, 0, MANACOST_XU(2, 1), 0, NULL, NULL);
}
- etphonehome
- Posts: 299
- Joined: 21 May 2020, 12:50
- Has thanked: 270 times
- Been thanked: 39 times
Re: Card Development - talk about cards code here
by Aswan jaguar » 16 Jan 2023, 19:05
When did AI cast the non-creature spell to trigger Riddleform? If AI did it in eot then correctly the effect lasts till your eot.
---
Trying to squash some bugs and playtesting.
Trying to squash some bugs and playtesting.
-
Aswan jaguar - Super Tester Elite
- Posts: 8078
- Joined: 13 May 2010, 12:17
- Has thanked: 730 times
- Been thanked: 458 times
Re: Card Development - talk about cards code here
by etphonehome » 16 Jan 2023, 19:54
OK!
I think it did. Although it was a bad play. It should have played Lightning Strike during first main and then attack with Riddleform.|
That's why AI will never rule the world!
I think it did. Although it was a bad play. It should have played Lightning Strike during first main and then attack with Riddleform.|
That's why AI will never rule the world!
- etphonehome
- Posts: 299
- Joined: 21 May 2020, 12:50
- Has thanked: 270 times
- Been thanked: 39 times
fixed - Zombie Boa
by Aswan jaguar » 19 Jan 2023, 19:50
I have tried many 3 different ways to code Zombie Boa with no success. I can't find how to store correctly the chosen color to use it in function
for_each_creature_blocking_me() or mark_each_creature_blocking_me()
for_each_creature_blocking_me() or mark_each_creature_blocking_me()
- Code: Select all
static void destroy_creature_of_chosen_color_when_blocked(int player, int color, int blocking_controller, int blocking_card)
{
int color = get_card_instance(player, card)->targets[3].card;
if( get_color(blocking_controller, blocking_card) & color )
kill_card(blocking_controller, blocking_card, KILL_DESTROY);
}
int card_zombie_boa(int player, int card, event_t event){// see death charmer and treefolk mystic, Hedron Blade,
/* CARD_ID_ZOMBIE_BOA 5459 // in progress
Zombie Boa |4|B
Creature - Zombie Snake 3/3
|1|B: Choose a color. Whenever ~ becomes blocked by a creature of that color this turn, destroy that creature. Activate only as a sorcery. */
if( IS_GAA_EVENT(event) ){
if( event == EVENT_RESOLVE_ACTIVATION ){
card_instance_t *instance = get_card_instance(player, card);
instance->targets[3].card = 1<<choose_a_color_and_show_legacy(instance->parent_controller, instance->parent_card, 1-player, -1);
}
}
if( event == EVENT_DECLARE_BLOCKERS && !is_humiliated(player, card, AL_TRIG) ){
card_instance_t *instance = get_card_instance(player, card);
//int col = instance->targets[3].card;
if( current_turn == player && is_attacking(player, card) ){
for_each_creature_blocking_me(player, instance->targets[3].card, destroy_creature_of_chosen_color_when_blocked, player, card);
}
}
//kills all blocking
/*if( event == EVENT_DECLARE_BLOCKERS && is_attacking(player, card) && current_turn == player && !is_humiliated(player, card, AL_TRIG) ){
card_instance_t *instance = get_card_instance(player, card);
int clr = instance->targets[3].card;
char marked[2][151] = {{0}};
mark_each_creature_blocking_me(player, card, marked);
int c;
for( c = 0; c < active_cards_count[1-current_turn]; ++c )
if( marked[1-current_turn][c] && in_play(1-current_turn, c) && get_color(1-current_turn, c) & clr ){
kill_card(1-current_turn, c, KILL_DESTROY);
}
}*/
if( event == EVENT_CLEANUP )
get_card_instance(player, card)->targets[3].card = 0;
return generic_activated_ability(player, card, event, GAA_CAN_SORCERY_BE_PLAYED, MANACOST_XB(1,1), 0, NULL, NULL);
}
Last edited by Aswan jaguar on 20 Jan 2023, 15:39, edited 1 time in total.
Reason: fixed
Reason: fixed
---
Trying to squash some bugs and playtesting.
Trying to squash some bugs and playtesting.
-
Aswan jaguar - Super Tester Elite
- Posts: 8078
- Joined: 13 May 2010, 12:17
- Has thanked: 730 times
- Been thanked: 458 times
Re: Card Development - talk about cards code here
by drool66 » 19 Jan 2023, 23:05
Try this?
- Code: Select all
static void destroy_creature_of_chosen_color_when_blocked(int color, int unused, int blocking_controller, int blocking_card)
{
if( get_color(blocking_controller, blocking_card) & color )
kill_card(blocking_controller, blocking_card, KILL_DESTROY);
}
int card_zombie_boa(int player, int card, event_t event){// see death charmer and treefolk mystic, Hedron Blade,
/* CARD_ID_ZOMBIE_BOA 5459 // in progress
Zombie Boa |4|B
Creature - Zombie Snake 3/3
|1|B: Choose a color. Whenever ~ becomes blocked by a creature of that color this turn, destroy that creature. Activate only as a sorcery. */
if( IS_GAA_EVENT(event) ){
if( event == EVENT_RESOLVE_ACTIVATION ){
DECL_INST();
DECL_PARENT();
int colors = inst_info(parent, CARD_ID_ZOMBIE_BOA).data | 1<<choose_a_color_and_show_legacy(inst->parent_controller, inst->parent_card, 1-player, -1);
set_inst_info(parent, CARD_ID_ZOMBIE_BOA, colors, 0);
}
}
if( event == EVENT_DECLARE_BLOCKERS && !is_humiliated(player, card, AL_TRIG) ){
DECL_INST();
//int col = instance->targets[3].card;
if( current_turn == player && is_attacking(player, card) ){
for_each_creature_blocking_me(player, card, destroy_creature_of_chosen_color_when_blocked, inst_info(inst, CARD_ID_ZOMBIE_BOA).data, 0);
}
}
//kills all blocking
/*if( event == EVENT_DECLARE_BLOCKERS && is_attacking(player, card) && current_turn == player && !is_humiliated(player, card, AL_TRIG) ){
card_instance_t *instance = get_card_instance(player, card);
int clr = instance->targets[3].card;
char marked[2][151] = {{0}};
mark_each_creature_blocking_me(player, card, marked);
int c;
for( c = 0; c < active_cards_count[1-current_turn]; ++c )
if( marked[1-current_turn][c] && in_play(1-current_turn, c) && get_color(1-current_turn, c) & clr ){
kill_card(1-current_turn, c, KILL_DESTROY);
}
}*/
if( event == EVENT_CLEANUP )
clear_info(get_card_instance(player, card), CARD_ID_ZOMBIE_BOA);
return generic_activated_ability(player, card, event, GAA_CAN_SORCERY_BE_PLAYED, MANACOST_XB(1,1), 0, NULL, NULL);
}
The latest images for Manalink will be here.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
-
drool66 - Programmer
- Posts: 1163
- Joined: 25 Nov 2010, 22:38
- Has thanked: 186 times
- Been thanked: 267 times
Re: Card Development - talk about cards code here
by etphonehome » 01 Feb 2023, 00:15
Tried to code Silversmote Ghoul, but after gaining 7 life the trigger effect doesn't happen, Added 13 to CC[2] but it probably needs a 2 as it is a triggered ability in the graveyard.
- Code: Select all
int card_silversmote_ghoul(int player, int card, event_t event) {
/* CARD_ID_SILVERSMOTE_GHOUL 21668
Silversmote Ghoul |2|B
Creature - Zombie Vampire 3/1
At the beginning of your end step, if you gained 3 or more life this turn, return ~ from your graveyard to the battlefield tapped.
|1|B, Sacrifice ~: Draw a card. */
if (get_trap_condition(player, TRAP_LIFE_GAINED) > 4 && eot_trigger(player, card, event)){
return GA_RETURN_TO_PLAY_MODIFIED;
}
if (event == EVENT_RETURN_TO_PLAY_FROM_GRAVE_MODIFIED) {
add_state(player, card, STATE_TAPPED);
}
if (!IS_GAA_EVENT(event)) {
return 0;
}
if (event == EVENT_RESOLVE_ACTIVATION) {
draw_a_card(player);
}
return generic_activated_ability(player, card, event, GAA_SACRIFICE_ME, MANACOST_XB(1, 1), 0, NULL, NULL);
}
- etphonehome
- Posts: 299
- Joined: 21 May 2020, 12:50
- Has thanked: 270 times
- Been thanked: 39 times
Re: Card Development - talk about cards code here
by drool66 » 01 Feb 2023, 07:06
So you need to use two cc[2] values - 13 for the trap and 28 for the eot trigger from the grave. The way to do this is to special case the id in the rules engine. Go to rules_engine.c and search for "check_card_for_rules_engine" and add CARD_ID_SILVERSMOTE_GHOUL under either the cc[2] == 13 section, or the cc[2] == 28 section, then set the other cc[2] value to the card in ct_all. I recommend adding the id to the 13 section (so under CARD_ID_SWEET_GUM_RECLUSE), and giving the Silversmote Ghoul a cc[2] value of 28. I say do it that way because 13 already has several special cases and so far 28 has none.
Also, GAA_ means "Graveyard Activated Ability" and this is a triggered ability. The two work differently. You can track what happens in rules_engine.c::resolve_graveyard_eot_triggers(), but the gist is you'll have an invisible copy of the card in your hand, and you have the card put itself into play while responding to EVENT_GRAVEYARD_ABILITY_EOT. See jumpstart.c::card_lightning_phoenix() for how it works, but it'll look like this:
Also, GAA_ means "Graveyard Activated Ability" and this is a triggered ability. The two work differently. You can track what happens in rules_engine.c::resolve_graveyard_eot_triggers(), but the gist is you'll have an invisible copy of the card in your hand, and you have the card put itself into play while responding to EVENT_GRAVEYARD_ABILITY_EOT. See jumpstart.c::card_lightning_phoenix() for how it works, but it'll look like this:
- Code: Select all
if( event == EVENT_GRAVEYARD_ABILITY_EOT ){
if( get_trap_condition(player, TRAP_LIFE_GAINED) >= 5 ){
if( ! grafdiggers_cages(player, TYPE_CREATURE, TUTOR_FROM_GRAVE) ){
add_state(player, card, STATE_TAPPED);
remove_state(player, card, STATE_INVISIBLE);
put_into_play(player, card);
return -1;
}
}
}
The latest images for Manalink will be here.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
-
drool66 - Programmer
- Posts: 1163
- Joined: 25 Nov 2010, 22:38
- Has thanked: 186 times
- Been thanked: 267 times
Who is online
Users browsing this forum: No registered users and 31 guests