[fixed]Collective Brutality escalate issue
Moderators: BAgate, drool66, Aswan jaguar, gmzombie, stassy, CCGHQ Admins
[fixed]Collective Brutality escalate issue
by Aswan jaguar » 23 Aug 2020, 16:29
Describe the Bug:
Collective Brutality has an issue when you escalate for second time in a raw to select all 3 modes. When the submenu with cards in your hand appears there is still with the same number of cards there was when you escalated the first time (the previous selected card is not there but in it's place there is a card not even in deck) and that card can be chosen again as a result you can discard only one card if you select the substitute card. If you don't then correctly it will discard the two chosen cards.
Which card did behave improperly?
Collective Brutality
Which update are you using? (date, name)Which type? (duel, gauntlet, sealed deck)
dev
What exactly should be the correct behavior/interaction?
Collective Brutality should either mark the selected card so it can't be chosen again if you escalate it again or remove the first selected card to be discarded from 2nd selection submenu.
Are any other cards possibly affected by this bug?
-
Collective Brutality has an issue when you escalate for second time in a raw to select all 3 modes. When the submenu with cards in your hand appears there is still with the same number of cards there was when you escalated the first time (the previous selected card is not there but in it's place there is a card not even in deck) and that card can be chosen again as a result you can discard only one card if you select the substitute card. If you don't then correctly it will discard the two chosen cards.
Which card did behave improperly?
Collective Brutality
Which update are you using? (date, name)Which type? (duel, gauntlet, sealed deck)
dev
What exactly should be the correct behavior/interaction?
Collective Brutality should either mark the selected card so it can't be chosen again if you escalate it again or remove the first selected card to be discarded from 2nd selection submenu.
Are any other cards possibly affected by this bug?
-
Last edited by Aswan jaguar on 28 Sep 2020, 12:11, edited 2 times 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: 8129
- Joined: 13 May 2010, 12:17
- Has thanked: 748 times
- Been thanked: 477 times
Re: Collective Brutality escalate issue
by FastEddie » 20 Sep 2020, 15:37
I think that fixes it. This card had other issues beyond the escalate mechanism, namely that discard would end in a hanging game, same for choosing a creature for -2/-2.
I tested the following cases:
I tested the following cases:
- Opponent has instant or sorcery in hand
Opponent has no instant or sorcery in hand (no save game for this attached)
At least one creature in play
No creature in play
Player has no hand after casting Collective Brutality
Opponent has shroud
- Code: Select all
int card_collective_brutality(int player, int card, event_t event){
/* Collective Brutality |1|B 0x200ef6c
* Sorcery
* Escalate-Discard a card.
* Choose one or more -
* * Target opponent reveals his or her hand. You choose an instant or sorcery card from it. That player discards that card.
* * Target creature gets -2/-2 until end of turn.
* * Target opponent loses 2 life and you gain 2 life. */
if( ! IS_GS_EVENT(player, card, event) ){
return 0;
}
enum
{
CHOICE_DURESS = 1<<0,
CHOICE_WEAKEN = 1<<1,
CHOICE_SUCK_LIFE = 1<<2,
CHOICE_MASK = CHOICE_DURESS | CHOICE_WEAKEN | CHOICE_SUCK_LIFE,
};
target_definition_t td_creature;
default_target_definition(player, card, &td_creature, TYPE_CREATURE );
td_creature.preferred_controller = player;
target_definition_t td_opp;
default_target_definition(player, card, &td_opp, 0);
td_opp.zone = TARGET_ZONE_PLAYERS;
card_instance_t *instance = get_card_instance(player, card);
if( event == EVENT_CAN_CAST ){
if( basic_spell(player, card, event) ){
return would_validate_arbitrary_target(&td_opp, 1-player, -1) || can_target(&td_creature);
}
}
if( event == EVENT_CAST_SPELL && affect_me(player, card) ){
int i;
int to_discard[2];
int td_count = 0;
if( ! check_special_flags2(player, card, SF2_COPIED_FROM_STACK) ){
instance->info_slot = 0;
int remaining_choices = 3;
if ( !would_validate_arbitrary_target(&td_opp, 1-player, -1) ) {
// Opponent can't be targeted
remaining_choices -= 2;
}
if ( !can_target(&td_creature) ) {
// No creatures in play
remaining_choices--;
}
int hand_backup[2][hand_count[player]];
int hand_backup_count = 0;
for(i=0; i<active_cards_count[player]; i++){
if( in_hand(player, i) ){
hand_backup[0][hand_backup_count] = get_original_internal_card_id(player, i);
hand_backup[1][hand_backup_count] = i;
hand_backup_count++;
}
}
while( ((instance->info_slot & CHOICE_MASK) != CHOICE_MASK) && (remaining_choices > 0) ){
int can_discard = !(instance->info_slot & CHOICE_DURESS) && would_validate_arbitrary_target(&td_opp, 1-player, -1);
int can_target_crit = !(instance->info_slot & CHOICE_WEAKEN) && can_target(&td_creature);
int can_suck = !(instance->info_slot & CHOICE_SUCK_LIFE) && would_validate_arbitrary_target(&td_opp, 1-player, -1);
int choice = DIALOG(player, card, event, DLG_NO_STORAGE, DLG_RANDOM,
"Opponent discards", can_discard, 15,
"Target creature gets -2/-2", can_target_crit, 10,
"Drain opponent 2 life", can_suck, life[1-player] <= 2 ? 20 : 5);
if( ! choice ){
spell_fizzled = 1;
return 0;
}
remaining_choices--;
// Convert choice number 1, 2, 3 in choice bits 001, 010, 100
instance->info_slot |= 1<<(choice-1);
if( (hand_count[player] > td_count) && (remaining_choices > 0) ){
int choice2 = DIALOG(player, card, event, DLG_NO_STORAGE, DLG_NO_CANCEL,
"Escalate", 1, 10,
"Decline", 1, 1);
if( choice2 == 1 ){
test_definition_t test;
new_default_test_definition(&test, TYPE_ANY, "Select a card to discard.");
test.id_flag = DOESNT_MATCH;
int selected = select_card_from_zone(player, player, hand_backup[0], hand_backup_count, 0, AI_MIN_VALUE, -1, &test);
if( selected != -1 ){
// Store selected card, will discard later
to_discard[td_count] = hand_backup[1][selected];
td_count++;
// Move cards right of selected one left to overwrite selected
for ( i=selected; i<hand_backup_count-1; i++ ) {
hand_backup[0][i] = hand_backup[0][i+1];
hand_backup[1][i] = hand_backup[1][i+1];
}
hand_backup_count--;
}
else{
break;
}
}
else{
break;
}
}
else{
break;
}
}
}
instance->number_of_targets = 0;
if( instance->info_slot & CHOICE_DURESS ){
instance->targets[0].player = 1-player;
instance->targets[0].card = -1;
instance->number_of_targets++;
}
if( instance->info_slot & CHOICE_WEAKEN ){
// new_pick_target stores the result in targets[] and increments number_of_targets
new_pick_target(&td_creature, "Select target creature (-2/-2).", -1, 1 | GS_LITERAL_PROMPT);
}
if( instance->info_slot & CHOICE_SUCK_LIFE ){
instance->targets[instance->number_of_targets].player = 1-player;
instance->targets[instance->number_of_targets].card = -1;
instance->number_of_targets++;
}
if( spell_fizzled != 1 ){
for(i=0; i<td_count; i++){
new_discard_card(player, to_discard[i], 0, player);
}
}
if (ai_is_speculating == 0) {
LOG_DEBUG("EVENT_CAST")
for (i=0; i<instance->number_of_targets; i++) {
LOG_DEBUG("targets[%d].player=%d, targets[%d].card=%d", i, instance->targets[i].player, i, instance->targets[i].card)
}
}
}
if( event == EVENT_RESOLVE_SPELL ){
if (ai_is_speculating == 0) {
LOG_DEBUG("EVENT_RESOLVE")
}
int targets_found = 0;
if( instance->info_slot & CHOICE_DURESS ){
if (ai_is_speculating == 0) {
LOG_DEBUG("CHOICE_DURESS")
}
if( validate_target(player, card, &td_opp, targets_found) ){
ec_definition_t ec;
// If duress has been chosen the player id is by definition in targets[0]
default_ec_definition(instance->targets[0].player, player, &ec);
test_definition_t this_test;
new_default_test_definition(&this_test, TYPE_INSTANT | TYPE_SORCERY, "Select an instant or sorcery card.");
this_test.type_flag = MATCH;
new_effect_coercion(&ec, &this_test);
}
targets_found++;
}
if( instance->info_slot & CHOICE_WEAKEN ){
if (ai_is_speculating == 0) {
LOG_DEBUG("CHOICE_WEAKEN")
}
if( validate_target(player, card, &td_creature, targets_found) ){
if (ai_is_speculating == 0) {
LOG_DEBUG("targets_found=%d, targets[targets_found].player=%d, targets[targets_found].card=%d", \
targets_found, instance->targets[targets_found].player, instance->targets[targets_found].card)
}
pump_until_eot(player, card, instance->targets[targets_found].player, instance->targets[targets_found].card, -2, -2);
}
targets_found++;
}
if( instance->info_slot & CHOICE_SUCK_LIFE ){
if (ai_is_speculating == 0) {
LOG_DEBUG("CHOICE_SUCK_LIFE")
}
if( validate_target(player, card, &td_opp, targets_found) ){
if (ai_is_speculating == 0) {
LOG_DEBUG("targets_found=%d, targets[targets_found].player=%d", targets_found, instance->targets[targets_found].player)
}
lose_life(instance->targets[targets_found].player, 2);
gain_life(player, 2);
}
}
kill_card(player, card, KILL_DESTROY);
}
return 0;
}
---
Argivian Archaeologist in the Library of Leng studying the Spells of the Ancients
Argivian Archaeologist in the Library of Leng studying the Spells of the Ancients
Re: [confirmed]Collective Brutality escalate issue
by FastEddie » 28 Sep 2020, 10:22
Committed in "[fasteddie 703385ba0] Fixed Collective Brutality."
---
Argivian Archaeologist in the Library of Leng studying the Spells of the Ancients
Argivian Archaeologist in the Library of Leng studying the Spells of the Ancients
3 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 18 guests