Implement cards held in hand effects (#205)
* Adapt existing Jokers to the Held Card mechanic + effect display location * Add suggestions from @ricfehr3 * Add suggestions from @MeirGavish --------- Co-authored-by: MathisMartin31 <mathis.martin31@gmail.com>
This commit is contained in:
+2
-2
@@ -6,8 +6,6 @@
|
||||
#define MAX_JOKERS_HELD_SIZE 5 // This doesn't account for negatives right now.
|
||||
#define MAX_SHOP_JOKERS 2 // TODO: Make this dynamic and allow for other items besides jokers
|
||||
#define MAX_SELECTION_SIZE 5
|
||||
#define MAX_CARD_SCORE_DIGITS 2 // Current digit limit for score received from cards including mult etc. from jokers
|
||||
#define MAX_CARD_SCORE_STR_LEN (MAX_CARD_SCORE_DIGITS + 1) // For the '+' or 'X'
|
||||
#define FRAMES(x) (((x) + game_speed - 1) / game_speed)
|
||||
|
||||
// TODO: Can make these dynamic to support interest-related jokers and vouchers
|
||||
@@ -53,7 +51,9 @@ enum HandState
|
||||
enum PlayState
|
||||
{
|
||||
PLAY_PLAYING,
|
||||
PLAY_BEFORE_SCORING,
|
||||
PLAY_SCORING_CARDS,
|
||||
PLAY_SCORING_HELD,
|
||||
PLAY_SCORING_JOKERS,
|
||||
PLAY_ENDING,
|
||||
PLAY_ENDED
|
||||
|
||||
+4
-4
@@ -49,9 +49,11 @@
|
||||
// Joker per Joker basis (see if it's there, then do something, e.g. Pareidolia, Baseball Card)
|
||||
enum JokerEvent
|
||||
{
|
||||
JOKER_EVENT_ON_HAND_PLAYED, // Triggers only once when the hand is played
|
||||
JOKER_EVENT_ON_JOKER_CREATED, // Triggers only once when the Joker is created, mainly used for data initialization
|
||||
JOKER_EVENT_ON_HAND_PLAYED, // Triggers only once when the hand is played and before the cards are scored
|
||||
JOKER_EVENT_ON_CARD_SCORED, // Triggers when a played card scores (e.g. Walkie Talkie, Fibonnacci...)
|
||||
JOKER_EVENT_ON_CARD_SCORED_END, // Triggers after the card has finishd scoring (e.g. retrigger Jokers)
|
||||
JOKER_EVENT_ON_CARD_HELD, // Triggers when going through held cards
|
||||
JOKER_EVENT_INDEPENDENT, // Joker will trigger normally, when Jokers are scored (e.g. base Joker)
|
||||
JOKER_EVENT_ON_HAND_SCORED_END, // Triggers when entire hand has finished scoring (e.g. food Jokers)
|
||||
JOKER_EVENT_ON_HAND_DISCARDED, // Triggers when discarding a hand
|
||||
@@ -105,12 +107,10 @@ typedef struct // These jokers are triggered after the played hand has finished
|
||||
} JokerEffect;
|
||||
|
||||
typedef JokerEffect (*JokerEffectFunc)(Joker *joker, Card *scored_card, enum JokerEvent joker_event);
|
||||
typedef void (*JokerCallbackOnCreated)(Joker *joker);
|
||||
typedef struct {
|
||||
u8 rarity;
|
||||
u8 base_value;
|
||||
JokerEffectFunc joker_effect;
|
||||
JokerCallbackOnCreated on_joker_created;
|
||||
} JokerInfo;
|
||||
const JokerInfo* get_joker_registry_entry(int joker_id);
|
||||
size_t get_joker_registry_size(void);
|
||||
@@ -129,7 +129,7 @@ JokerObject *joker_object_new(Joker *joker);
|
||||
void joker_object_destroy(JokerObject **joker_object);
|
||||
void joker_object_update(JokerObject *joker_object);
|
||||
void joker_object_shake(JokerObject *joker_object, mm_word sound_id); // This doesn't actually score anything, it just performs an animation and plays a sound effect
|
||||
bool joker_object_score(JokerObject *joker_object, Card* scored_card, enum JokerEvent joker_event, int *chips, int *mult, int *money, bool *retrigger); // This scores the joker and returns true if it was scored successfully (Card = NULL means the joker is independent and not scored by a card)
|
||||
bool joker_object_score(JokerObject *joker_object, CardObject* card_object, enum JokerEvent joker_event, int *chips, int *mult, int *money, bool *retrigger); // This scores the joker and returns true if it was scored successfully (Card = NULL means the joker is independent and not scored by a card)
|
||||
|
||||
void joker_object_set_selected(JokerObject* joker_object, bool selected);
|
||||
bool joker_object_is_selected(JokerObject* joker_object);
|
||||
|
||||
+55
-11
@@ -541,6 +541,7 @@ static const Rect TEMP_SCORE_RECT = {8, 64, 64, 72 };
|
||||
static const Rect SCORE_RECT = {32, 48, 64, 56 };
|
||||
|
||||
static const Rect PLAYED_CARDS_SCORES_RECT = {72, 48, 240, 56 };
|
||||
static const Rect HELD_CARDS_SCORES_RECT = {72, 108, 240, 116 };
|
||||
static const Rect BLIND_TOKEN_TEXT_RECT = {80, 72, 200, 160 };
|
||||
static const Rect MONEY_TEXT_RECT = {8, 120, 64, 128 };
|
||||
static const Rect CHIPS_TEXT_RECT = {8, 80, 32, 88 };
|
||||
@@ -2181,13 +2182,13 @@ static void cards_in_hand_update_loop(bool* discarded_card, int* played_selectio
|
||||
}
|
||||
|
||||
// returns true if a joker was scored, false otherwise
|
||||
static bool check_and_score_joker_for_event(ListItr* starting_joker_itr, Card* played_card, enum JokerEvent joker_event)
|
||||
static bool check_and_score_joker_for_event(ListItr* starting_joker_itr, CardObject* card_object, enum JokerEvent joker_event)
|
||||
{
|
||||
JokerObject* joker;
|
||||
|
||||
while((joker = list_itr_next(starting_joker_itr)))
|
||||
{
|
||||
if (joker_object_score(joker, played_card, joker_event, &chips, &mult, &money, &retrigger))
|
||||
if (joker_object_score(joker, card_object, joker_event, &chips, &mult, &money, &retrigger))
|
||||
{
|
||||
display_chips();
|
||||
display_mult();
|
||||
@@ -2231,8 +2232,9 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection
|
||||
|
||||
if (*played_selections == 0)
|
||||
{
|
||||
play_state = PLAY_SCORING_CARDS;
|
||||
_joker_scored_itr = list_itr_create(&_owned_jokers_list);
|
||||
timer = TM_ZERO;
|
||||
play_state = PLAY_BEFORE_SCORING;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2242,11 +2244,26 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection
|
||||
}
|
||||
break;
|
||||
|
||||
case PLAY_BEFORE_SCORING:
|
||||
|
||||
// Activate Jokers with an effect just before the hand is scored
|
||||
if (check_and_score_joker_for_event(&_joker_scored_itr, NULL, JOKER_EVENT_ON_HAND_PLAYED))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (card_object_is_selected(played[i]) && played_top - i >= *played_selections)
|
||||
{
|
||||
played_y -= int2fx(10);
|
||||
}
|
||||
|
||||
play_state = PLAY_SCORING_CARDS;
|
||||
break;
|
||||
|
||||
case PLAY_SCORING_CARDS:
|
||||
|
||||
if (i == 0 && (timer % FRAMES(30) == 0) && timer > FRAMES(40))
|
||||
{
|
||||
|
||||
// We are about to score played Cards, then Jokers.
|
||||
// If we need to retrigger, then we have scored a card previously
|
||||
// and thus have incremented scored_card_index by 1.
|
||||
@@ -2268,7 +2285,7 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection
|
||||
// Trigger all Jokers after each card scored
|
||||
if (*played_selections > 0)
|
||||
{
|
||||
if (check_and_score_joker_for_event(&_joker_scored_itr, played[*played_selections - 1]->card, JOKER_EVENT_ON_CARD_SCORED))
|
||||
if (check_and_score_joker_for_event(&_joker_scored_itr, played[*played_selections - 1], JOKER_EVENT_ON_CARD_SCORED))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -2276,7 +2293,7 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection
|
||||
// Trigger all Jokers that have an effect when a card finishes scoring
|
||||
// (e.g. retriggers) after activating all the other scored_card Jokers normally
|
||||
_joker_scored_itr = list_itr_create(&_owned_jokers_list);
|
||||
if (check_and_score_joker_for_event(&_joker_scored_itr, played[*played_selections - 1]->card, JOKER_EVENT_ON_CARD_SCORED_END))
|
||||
if (check_and_score_joker_for_event(&_joker_scored_itr, played[*played_selections - 1], JOKER_EVENT_ON_CARD_SCORED_END))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -2310,11 +2327,10 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection
|
||||
}
|
||||
}
|
||||
|
||||
// advance state after going past the last card (exited the loop without returning)
|
||||
play_state = PLAY_SCORING_JOKERS;
|
||||
play_state = PLAY_SCORING_HELD;
|
||||
// reuse these variables for held cards
|
||||
_joker_scored_itr = list_itr_create(&_owned_jokers_list);
|
||||
scored_card_index = 0; // reuse this variable for held cards
|
||||
return;
|
||||
scored_card_index = hand_top;
|
||||
}
|
||||
|
||||
if (card_object_is_selected(played[i]))
|
||||
@@ -2322,7 +2338,35 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection
|
||||
played_y -= int2fx(10);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case PLAY_SCORING_HELD:
|
||||
|
||||
if (i == 0 && (timer % FRAMES(30) == 0) && timer > FRAMES(40))
|
||||
{
|
||||
tte_erase_rect_wrapper(HELD_CARDS_SCORES_RECT);
|
||||
|
||||
// Go through all held cards and see if they activate Jokers
|
||||
for ( ; scored_card_index >= 0; scored_card_index--)
|
||||
{
|
||||
|
||||
if (check_and_score_joker_for_event(&_joker_scored_itr, hand[scored_card_index], JOKER_EVENT_ON_CARD_HELD))
|
||||
{
|
||||
card_object_shake(hand[scored_card_index], SFX_CARD_SELECT);
|
||||
return;
|
||||
}
|
||||
_joker_scored_itr = list_itr_create(&_owned_jokers_list);
|
||||
}
|
||||
scored_card_index = 0;
|
||||
|
||||
play_state = PLAY_SCORING_JOKERS;
|
||||
}
|
||||
|
||||
if (card_object_is_selected(played[i]))
|
||||
{
|
||||
played_y -= int2fx(10);
|
||||
}
|
||||
break;
|
||||
|
||||
// Score Jokers normally
|
||||
case PLAY_SCORING_JOKERS:
|
||||
|
||||
|
||||
+33
-15
@@ -14,6 +14,8 @@
|
||||
#include "pool.h"
|
||||
|
||||
#define JOKER_SCORE_TEXT_Y 48
|
||||
#define HELD_CARD_SCORE_TEXT_Y 108
|
||||
#define MAX_CARD_SCORE_STR_LEN 2
|
||||
#define NUM_JOKERS_PER_SPRITESHEET 2
|
||||
|
||||
static const unsigned int *joker_gfxTiles[] =
|
||||
@@ -144,7 +146,9 @@ Joker *joker_new(u8 id)
|
||||
joker->value = jinfo->base_value + edition_price_lut[joker->modifier];
|
||||
joker->rarity = jinfo->rarity;
|
||||
joker->data = 0;
|
||||
jinfo->on_joker_created(joker);
|
||||
|
||||
// initialize persistent Joker data if needed
|
||||
jinfo->joker_effect(joker, NULL, JOKER_EVENT_ON_JOKER_CREATED);
|
||||
|
||||
return joker;
|
||||
}
|
||||
@@ -158,7 +162,7 @@ void joker_destroy(Joker **joker)
|
||||
JokerEffect joker_get_score_effect(Joker *joker, Card *scored_card, enum JokerEvent joker_event)
|
||||
{
|
||||
const JokerInfo *jinfo = get_joker_registry_entry(joker->id);
|
||||
if (!jinfo || jinfo->joker_effect == NULL) return (JokerEffect){0};
|
||||
if (!jinfo) return (JokerEffect){0};
|
||||
|
||||
return jinfo->joker_effect(joker, scored_card, joker_event);
|
||||
}
|
||||
@@ -248,25 +252,25 @@ void joker_object_shake(JokerObject *joker_object, mm_word sound_id)
|
||||
sprite_object_shake(joker_object->sprite_object, sound_id);
|
||||
}
|
||||
|
||||
void set_and_shift_text(char* str, int* cursor_pos_x, int color_pb)
|
||||
void set_and_shift_text(char* str, int* cursor_pos_x, int* cursor_pos_y, int color_pb)
|
||||
{
|
||||
tte_set_pos(*cursor_pos_x, JOKER_SCORE_TEXT_Y);
|
||||
tte_set_pos(*cursor_pos_x, *cursor_pos_y);
|
||||
tte_set_special(color_pb * TTE_SPECIAL_PB_MULT_OFFSET);
|
||||
tte_write(str);
|
||||
|
||||
// + 1 For space
|
||||
const int joker_score_display_offset_px = (MAX_CARD_SCORE_STR_LEN + 1)*TTE_CHAR_SIZE;
|
||||
const int joker_score_display_offset_px = (MAX_CARD_SCORE_STR_LEN + 1) * TTE_CHAR_SIZE;
|
||||
*cursor_pos_x += joker_score_display_offset_px;
|
||||
}
|
||||
|
||||
bool joker_object_score(JokerObject *joker_object, Card* scored_card, enum JokerEvent joker_event, int *chips, int *mult, int *money, bool *retrigger)
|
||||
bool joker_object_score(JokerObject *joker_object, CardObject* card_object, enum JokerEvent joker_event, int *chips, int *mult, int *money, bool *retrigger)
|
||||
{
|
||||
if (joker_object == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
JokerEffect joker_effect = joker_get_score_effect(joker_object->joker, scored_card, joker_event);
|
||||
JokerEffect joker_effect = joker_get_score_effect(joker_object->joker, card_object->card, joker_event);
|
||||
|
||||
if (memcmp(&joker_effect, &(JokerEffect){0}, sizeof(JokerEffect)) == 0)
|
||||
{
|
||||
@@ -280,35 +284,49 @@ bool joker_object_score(JokerObject *joker_object, Card* scored_card, enum Joker
|
||||
*retrigger = joker_effect.retrigger;
|
||||
// joker_effect.message will have been set if the Joker had anything custom to say
|
||||
|
||||
int cursorPosX = fx2int(joker_object->sprite_object->x) + 8; // Offset of 16 pixels to center the text on the card
|
||||
int cursorPosX = TILE_SIZE; // Offset of one tile to better center the text on the card
|
||||
int cursorPosY = 0;
|
||||
if (joker_event == JOKER_EVENT_ON_CARD_HELD)
|
||||
{
|
||||
// display the text on top of the card instead of below the Joker for Held Cards effects
|
||||
// scored_card cannot be NULL here because of the joker event
|
||||
cursorPosX += fx2int(card_object->sprite_object->x);
|
||||
cursorPosY = HELD_CARD_SCORE_TEXT_Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursorPosX += fx2int(joker_object->sprite_object->x);
|
||||
cursorPosY = JOKER_SCORE_TEXT_Y;
|
||||
}
|
||||
|
||||
if (joker_effect.chips > 0)
|
||||
{
|
||||
char score_buffer[INT_MAX_DIGITS + 2]; // For '+' and null terminator
|
||||
snprintf(score_buffer, sizeof(score_buffer), "+%d", joker_effect.chips);
|
||||
set_and_shift_text(score_buffer, &cursorPosX, TTE_BLUE_PB);
|
||||
set_and_shift_text(score_buffer, &cursorPosX, &cursorPosY, TTE_BLUE_PB);
|
||||
}
|
||||
if (joker_effect.mult > 0)
|
||||
{
|
||||
char score_buffer[INT_MAX_DIGITS + 2];
|
||||
snprintf(score_buffer, sizeof(score_buffer), "+%d", joker_effect.mult);
|
||||
set_and_shift_text(score_buffer, &cursorPosX, TTE_RED_PB);
|
||||
set_and_shift_text(score_buffer, &cursorPosX, &cursorPosY, TTE_RED_PB);
|
||||
}
|
||||
if (joker_effect.xmult > 0)
|
||||
{
|
||||
char score_buffer[INT_MAX_DIGITS + 2];
|
||||
snprintf(score_buffer, sizeof(score_buffer), "X%d", joker_effect.xmult);
|
||||
set_and_shift_text(score_buffer, &cursorPosX, TTE_RED_PB);
|
||||
set_and_shift_text(score_buffer, &cursorPosX, &cursorPosY, TTE_RED_PB);
|
||||
}
|
||||
if (joker_effect.money > 0)
|
||||
{
|
||||
char score_buffer[INT_MAX_DIGITS + 2];
|
||||
snprintf(score_buffer, sizeof(score_buffer), "+%d", joker_effect.money);
|
||||
set_and_shift_text(score_buffer, &cursorPosX, TTE_YELLOW_PB);
|
||||
snprintf(score_buffer, sizeof(score_buffer), "%d$", joker_effect.money);
|
||||
set_and_shift_text(score_buffer, &cursorPosX, &cursorPosY, TTE_YELLOW_PB);
|
||||
}
|
||||
// custom message for Jokers (including retriggers where Jokers will say "Again!")
|
||||
if (joker_effect.message[0] != '\0') // Message is not empty
|
||||
if (joker_effect.message != NULL && joker_effect.message[0] != '\0') // Message is not empty
|
||||
{
|
||||
set_and_shift_text(joker_effect.message, &cursorPosX, TTE_WHITE_PB);
|
||||
set_and_shift_text(joker_effect.message, &cursorPosX, &cursorPosY, TTE_WHITE_PB);
|
||||
}
|
||||
if (joker_effect.expire)
|
||||
{
|
||||
|
||||
+106
-124
@@ -20,6 +20,11 @@ if (checked_event != restricted_event) \
|
||||
|
||||
// Joker Effect functions
|
||||
|
||||
static JokerEffect joker_effect_noop(Joker *joker, Card *scored_card, enum JokerEvent joker_event)
|
||||
{
|
||||
return (JokerEffect){0};
|
||||
}
|
||||
|
||||
static JokerEffect default_joker_effect(Joker *joker, Card *scored_card, enum JokerEvent joker_event)
|
||||
{
|
||||
JokerEffect effect = {0};
|
||||
@@ -399,23 +404,41 @@ static JokerEffect blue_joker_effect(Joker *joker, Card *scored_card, enum Joker
|
||||
static JokerEffect raised_fist_joker_effect(Joker *joker, Card *scored_card, enum JokerEvent joker_event)
|
||||
{
|
||||
JokerEffect effect = {0};
|
||||
|
||||
SCORE_ON_EVENT_ONLY(JOKER_EVENT_INDEPENDENT, joker_event, effect)
|
||||
|
||||
// Find the lowest rank card in hand
|
||||
// Aces are always considered high value, even in an ace-low straight
|
||||
u8 lowest_value = IMPOSSIBLY_HIGH_CARD_VALUE;
|
||||
CardObject** hand = get_hand_array();
|
||||
int hand_size = hand_get_size();
|
||||
for (int i = 0; i < hand_size; i++ )
|
||||
s32* p_lowest_value_index = &(joker->data);
|
||||
|
||||
switch (joker_event)
|
||||
{
|
||||
u8 value = card_get_value(hand[i]->card);
|
||||
if (lowest_value > value)
|
||||
lowest_value = value;
|
||||
}
|
||||
// Use this event to compute the index of the lowest value card only once.
|
||||
// Aces are always considered high value, even in an ace-low straight
|
||||
case JOKER_EVENT_ON_HAND_PLAYED:
|
||||
// index initialized at 0 but accessed only if
|
||||
// hand_size > 0 so we're never out of bounds
|
||||
*p_lowest_value_index = 0;
|
||||
u8 lowest_value = IMPOSSIBLY_HIGH_CARD_VALUE;
|
||||
CardObject** hand = get_hand_array();
|
||||
int hand_size = hand_get_size();
|
||||
for (int i = 0; i < hand_size; i++ )
|
||||
{
|
||||
u8 value = card_get_value(hand[i]->card);
|
||||
if (lowest_value > value)
|
||||
{
|
||||
*p_lowest_value_index = i;
|
||||
lowest_value = value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
if (lowest_value != IMPOSSIBLY_HIGH_CARD_VALUE)
|
||||
effect.mult = lowest_value * 2;
|
||||
case JOKER_EVENT_ON_CARD_HELD:
|
||||
if (get_scored_card_index() == *p_lowest_value_index)
|
||||
{
|
||||
effect.mult = 2 * card_get_value(scored_card);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return effect;
|
||||
}
|
||||
@@ -424,17 +447,11 @@ static JokerEffect reserved_parking_joker_effect(Joker *joker, Card *scored_card
|
||||
{
|
||||
JokerEffect effect = {0};
|
||||
|
||||
// TODO: switch from INDEPENDENT to CARD_HELD when it's implemented
|
||||
SCORE_ON_EVENT_ONLY(JOKER_EVENT_INDEPENDENT, joker_event, effect)
|
||||
SCORE_ON_EVENT_ONLY(JOKER_EVENT_ON_CARD_HELD, joker_event, effect)
|
||||
|
||||
CardObject** hand = get_hand_array();
|
||||
int hand_size = hand_get_size();
|
||||
for (int i = 0; i < hand_size; i++ )
|
||||
if ((random() % 2 == 0) && card_is_face(scored_card))
|
||||
{
|
||||
if ((random() % 2 == 0) && card_is_face(hand[i]->card))
|
||||
{
|
||||
effect.money += 1;
|
||||
}
|
||||
effect.money++;
|
||||
}
|
||||
|
||||
return effect;
|
||||
@@ -583,7 +600,7 @@ static JokerEffect hanging_chad_joker_effect(Joker *joker, Card *scored_card, en
|
||||
|
||||
switch (joker_event)
|
||||
{
|
||||
case JOKER_EVENT_ON_HAND_SCORED_END:
|
||||
case JOKER_EVENT_ON_HAND_PLAYED:
|
||||
*p_remaining_retriggers = 2;
|
||||
break;
|
||||
|
||||
@@ -724,17 +741,11 @@ static JokerEffect shoot_the_moon_joker_effect(Joker *joker, Card *scored_card,
|
||||
{
|
||||
JokerEffect effect = {0};
|
||||
|
||||
// TODO: switch from CARD_SCORED to CARD_HELD when triggering held cards is implemented
|
||||
SCORE_ON_EVENT_ONLY(JOKER_EVENT_INDEPENDENT, joker_event, effect)
|
||||
SCORE_ON_EVENT_ONLY(JOKER_EVENT_ON_CARD_HELD, joker_event, effect)
|
||||
|
||||
CardObject** hand = get_hand_array();
|
||||
int hand_size = hand_get_size();
|
||||
for (int i = 0; i < hand_size; i++ )
|
||||
if (scored_card->rank == QUEEN)
|
||||
{
|
||||
if (hand[i]->card->rank == QUEEN)
|
||||
{
|
||||
effect.mult += 13;
|
||||
}
|
||||
effect.mult += 13;
|
||||
}
|
||||
|
||||
return effect;
|
||||
@@ -749,7 +760,7 @@ static JokerEffect photograph_joker_effect(Joker *joker, Card *scored_card, enum
|
||||
|
||||
switch (joker_event)
|
||||
{
|
||||
case JOKER_EVENT_ON_HAND_SCORED_END:
|
||||
case JOKER_EVENT_ON_HAND_PLAYED:
|
||||
*p_first_face_index = UNDEFINED;
|
||||
break;
|
||||
|
||||
@@ -801,7 +812,7 @@ static JokerEffect dusk_joker_effect(Joker *joker, Card *scored_card, enum Joker
|
||||
|
||||
switch (joker_event)
|
||||
{
|
||||
case JOKER_EVENT_ON_HAND_SCORED_END:
|
||||
case JOKER_EVENT_ON_HAND_PLAYED:
|
||||
*p_last_retriggered_index = UNDEFINED;
|
||||
break;
|
||||
|
||||
@@ -880,7 +891,7 @@ static JokerEffect hack_joker_effect(Joker *joker, Card *scored_card, enum Joker
|
||||
|
||||
switch (joker_event)
|
||||
{
|
||||
case JOKER_EVENT_ON_HAND_SCORED_END:
|
||||
case JOKER_EVENT_ON_HAND_PLAYED:
|
||||
*p_last_retriggered_index = UNDEFINED;
|
||||
break;
|
||||
|
||||
@@ -920,8 +931,15 @@ static JokerEffect seltzer_joker_effect(Joker *joker, Card *scored_card, enum Jo
|
||||
|
||||
switch (joker_event)
|
||||
{
|
||||
case JOKER_EVENT_ON_HAND_SCORED_END:
|
||||
case JOKER_EVENT_ON_JOKER_CREATED:
|
||||
*p_hands_left_until_exp = 10; // remaining retriggered hands
|
||||
break;
|
||||
|
||||
case JOKER_EVENT_ON_HAND_PLAYED:
|
||||
*p_last_retriggered_idx = UNDEFINED;
|
||||
break;
|
||||
|
||||
case JOKER_EVENT_ON_HAND_SCORED_END:
|
||||
*p_hands_left_until_exp -= 1;
|
||||
if (*p_hands_left_until_exp <= 0)
|
||||
{
|
||||
@@ -962,7 +980,7 @@ static JokerEffect sock_and_buskin_joker_effect(Joker *joker, Card *scored_card,
|
||||
|
||||
switch (joker_event)
|
||||
{
|
||||
case JOKER_EVENT_ON_HAND_SCORED_END:
|
||||
case JOKER_EVENT_ON_HAND_PLAYED:
|
||||
*p_last_retriggered_face_index = UNDEFINED;
|
||||
break;
|
||||
|
||||
@@ -983,42 +1001,6 @@ static JokerEffect sock_and_buskin_joker_effect(Joker *joker, Card *scored_card,
|
||||
return effect;
|
||||
}
|
||||
|
||||
// ON JOKER CREATED Callbacks
|
||||
|
||||
// For Jokers that don't need to do anything when created
|
||||
void on_joker_created_noop(Joker *joker) {}
|
||||
|
||||
void hanging_chad_on_joker_created(Joker *joker)
|
||||
{
|
||||
joker->data = 2; // retriggers left, reset to 2 at round end
|
||||
}
|
||||
|
||||
void dusk_on_joker_created(Joker *joker)
|
||||
{
|
||||
joker->data = UNDEFINED; // previously retriggered card index
|
||||
}
|
||||
|
||||
void hack_on_joker_created(Joker *joker)
|
||||
{
|
||||
joker->data = UNDEFINED; // previously retriggered card index
|
||||
}
|
||||
|
||||
void photograph_on_joker_created(Joker *joker)
|
||||
{
|
||||
joker->data = UNDEFINED; // First scoring face card index
|
||||
}
|
||||
|
||||
void sock_and_buskin_on_joker_created(Joker *joker)
|
||||
{
|
||||
joker->data = UNDEFINED; // previously retriggered face card index
|
||||
}
|
||||
|
||||
void seltzer_on_joker_created(Joker *joker)
|
||||
{
|
||||
joker->halves.data0 = UNDEFINED; // previously retriggered card index
|
||||
joker->halves.data1 = 10; // remaining retriggered hands
|
||||
}
|
||||
|
||||
|
||||
/* The index of a joker in the registry matches its ID.
|
||||
* The joker sprites are matched by ID so the position in the registry
|
||||
@@ -1030,57 +1012,57 @@ void seltzer_on_joker_created(Joker *joker)
|
||||
* Otherwise the order is similar to the wiki.
|
||||
*/
|
||||
const JokerInfo joker_registry[] = {
|
||||
{ COMMON_JOKER, 2, default_joker_effect, on_joker_created_noop }, // DEFAULT_JOKER_ID = 0
|
||||
{ COMMON_JOKER, 5, greedy_joker_effect, on_joker_created_noop }, // GREEDY_JOKER_ID = 1
|
||||
{ COMMON_JOKER, 5, lusty_joker_effect, on_joker_created_noop }, // etc... 2
|
||||
{ COMMON_JOKER, 5, wrathful_joker_effect, on_joker_created_noop }, // 3
|
||||
{ COMMON_JOKER, 5, gluttonous_joker_effect, on_joker_created_noop }, // 4
|
||||
{ COMMON_JOKER, 3, jolly_joker_effect, on_joker_created_noop }, // 5
|
||||
{ COMMON_JOKER, 4, zany_joker_effect, on_joker_created_noop }, // 6
|
||||
{ COMMON_JOKER, 4, mad_joker_effect, on_joker_created_noop }, // 7
|
||||
{ COMMON_JOKER, 4, crazy_joker_effect, on_joker_created_noop }, // 8
|
||||
{ COMMON_JOKER, 4, droll_joker_effect, on_joker_created_noop }, // 9
|
||||
{ COMMON_JOKER, 3, sly_joker_effect, on_joker_created_noop }, // 10
|
||||
{ COMMON_JOKER, 4, wily_joker_effect, on_joker_created_noop }, // 11
|
||||
{ COMMON_JOKER, 4, clever_joker_effect, on_joker_created_noop }, // 12
|
||||
{ COMMON_JOKER, 4, devious_joker_effect, on_joker_created_noop }, // 13
|
||||
{ COMMON_JOKER, 4, crafty_joker_effect, on_joker_created_noop }, // 14
|
||||
{ COMMON_JOKER, 5, half_joker_effect, on_joker_created_noop }, // 15
|
||||
{ UNCOMMON_JOKER, 8, joker_stencil_effect, on_joker_created_noop }, // 16
|
||||
{ COMMON_JOKER, 5, banner_joker_effect, on_joker_created_noop }, // 17
|
||||
{ COMMON_JOKER, 4, walkie_talkie_joker_effect, on_joker_created_noop }, // 18
|
||||
{ UNCOMMON_JOKER, 8, fibonnaci_joker_effect, on_joker_created_noop }, // 19
|
||||
{ UNCOMMON_JOKER, 6, blackboard_joker_effect, on_joker_created_noop }, // 20
|
||||
{ COMMON_JOKER, 5, mystic_summit_joker_effect, on_joker_created_noop }, // 21
|
||||
{ COMMON_JOKER, 4, misprint_joker_effect, on_joker_created_noop }, // 22
|
||||
{ COMMON_JOKER, 4, even_steven_joker_effect, on_joker_created_noop }, // 23
|
||||
{ COMMON_JOKER, 5, blue_joker_effect, on_joker_created_noop }, // 24
|
||||
{ COMMON_JOKER, 4, odd_todd_joker_effect, on_joker_created_noop }, // 25
|
||||
{ UNCOMMON_JOKER, 7, NULL, /* Shortcut */ on_joker_created_noop }, // 26
|
||||
{ COMMON_JOKER, 4, business_card_joker_effect, on_joker_created_noop }, // 27
|
||||
{ COMMON_JOKER, 2, default_joker_effect }, // DEFAULT_JOKER_ID = 0
|
||||
{ COMMON_JOKER, 5, greedy_joker_effect }, // GREEDY_JOKER_ID = 1
|
||||
{ COMMON_JOKER, 5, lusty_joker_effect }, // etc... 2
|
||||
{ COMMON_JOKER, 5, wrathful_joker_effect }, // 3
|
||||
{ COMMON_JOKER, 5, gluttonous_joker_effect }, // 4
|
||||
{ COMMON_JOKER, 3, jolly_joker_effect }, // 5
|
||||
{ COMMON_JOKER, 4, zany_joker_effect }, // 6
|
||||
{ COMMON_JOKER, 4, mad_joker_effect }, // 7
|
||||
{ COMMON_JOKER, 4, crazy_joker_effect }, // 8
|
||||
{ COMMON_JOKER, 4, droll_joker_effect }, // 9
|
||||
{ COMMON_JOKER, 3, sly_joker_effect }, // 10
|
||||
{ COMMON_JOKER, 4, wily_joker_effect }, // 11
|
||||
{ COMMON_JOKER, 4, clever_joker_effect }, // 12
|
||||
{ COMMON_JOKER, 4, devious_joker_effect }, // 13
|
||||
{ COMMON_JOKER, 4, crafty_joker_effect }, // 14
|
||||
{ COMMON_JOKER, 5, half_joker_effect }, // 15
|
||||
{ UNCOMMON_JOKER, 8, joker_stencil_effect }, // 16
|
||||
{ COMMON_JOKER, 5, banner_joker_effect }, // 17
|
||||
{ COMMON_JOKER, 4, walkie_talkie_joker_effect }, // 18
|
||||
{ UNCOMMON_JOKER, 8, fibonnaci_joker_effect }, // 19
|
||||
{ UNCOMMON_JOKER, 6, blackboard_joker_effect }, // 20
|
||||
{ COMMON_JOKER, 5, mystic_summit_joker_effect }, // 21
|
||||
{ COMMON_JOKER, 4, misprint_joker_effect }, // 22
|
||||
{ COMMON_JOKER, 4, even_steven_joker_effect }, // 23
|
||||
{ COMMON_JOKER, 5, blue_joker_effect }, // 24
|
||||
{ COMMON_JOKER, 4, odd_todd_joker_effect }, // 25
|
||||
{ UNCOMMON_JOKER, 7, joker_effect_noop, }, // 26 Shortcut
|
||||
{ COMMON_JOKER, 4, business_card_joker_effect }, // 27
|
||||
// Business card should be paired with Shortcut for palette optimization when it's added
|
||||
{ COMMON_JOKER, 4, scary_face_joker_effect, on_joker_created_noop }, // 28
|
||||
{ UNCOMMON_JOKER, 7, bootstraps_joker_effect, on_joker_created_noop }, // 29
|
||||
{ UNCOMMON_JOKER, 5, NULL, on_joker_created_noop }, // 30 Pareidolia
|
||||
{ COMMON_JOKER, 6, reserved_parking_joker_effect, on_joker_created_noop }, // 31
|
||||
{ COMMON_JOKER, 4, abstract_joker_effect, on_joker_created_noop }, // 32
|
||||
{ UNCOMMON_JOKER, 6, bull_joker_effect, on_joker_created_noop }, // 33
|
||||
{ RARE_JOKER, 8, the_duo_joker_effect, on_joker_created_noop }, // 34
|
||||
{ RARE_JOKER, 8, the_trio_joker_effect, on_joker_created_noop }, // 35
|
||||
{ RARE_JOKER, 8, the_family_joker_effect, on_joker_created_noop }, // 36
|
||||
{ RARE_JOKER, 8, the_order_joker_effect, on_joker_created_noop }, // 37
|
||||
{ RARE_JOKER, 8, the_tribe_joker_effect, on_joker_created_noop }, // 38
|
||||
{ RARE_JOKER, 10, blueprint_joker_effect, on_joker_created_noop }, // 39
|
||||
{ RARE_JOKER, 10, brainstorm_joker_effect, on_joker_created_noop }, // 40
|
||||
{ COMMON_JOKER, 5, raised_fist_joker_effect, on_joker_created_noop }, // 41
|
||||
{ COMMON_JOKER, 4, smiley_face_joker_effect, on_joker_created_noop }, // 42
|
||||
{ UNCOMMON_JOKER, 6, acrobat_joker_effect, on_joker_created_noop }, // 43
|
||||
{ UNCOMMON_JOKER, 5, dusk_joker_effect, dusk_on_joker_created }, // 44
|
||||
{ UNCOMMON_JOKER, 6, sock_and_buskin_joker_effect, sock_and_buskin_on_joker_created }, // 45
|
||||
{ UNCOMMON_JOKER, 6, hack_joker_effect, hack_on_joker_created }, // 46
|
||||
{ COMMON_JOKER, 4, hanging_chad_joker_effect, hanging_chad_on_joker_created }, // 47
|
||||
{ UNCOMMON_JOKER, 7, NULL,/* Four Fingers */ on_joker_created_noop }, // 48
|
||||
{ COMMON_JOKER, 4, scholar_joker_effect, on_joker_created_noop }, // 49
|
||||
{ COMMON_JOKER, 4, scary_face_joker_effect }, // 28
|
||||
{ UNCOMMON_JOKER, 7, bootstraps_joker_effect }, // 29
|
||||
{ UNCOMMON_JOKER, 5, joker_effect_noop }, // 30 Pareidolia
|
||||
{ COMMON_JOKER, 6, reserved_parking_joker_effect }, // 31
|
||||
{ COMMON_JOKER, 4, abstract_joker_effect }, // 32
|
||||
{ UNCOMMON_JOKER, 6, bull_joker_effect }, // 33
|
||||
{ RARE_JOKER, 8, the_duo_joker_effect }, // 34
|
||||
{ RARE_JOKER, 8, the_trio_joker_effect }, // 35
|
||||
{ RARE_JOKER, 8, the_family_joker_effect }, // 36
|
||||
{ RARE_JOKER, 8, the_order_joker_effect }, // 37
|
||||
{ RARE_JOKER, 8, the_tribe_joker_effect }, // 38
|
||||
{ RARE_JOKER, 10, blueprint_joker_effect }, // 39
|
||||
{ RARE_JOKER, 10, brainstorm_joker_effect }, // 40
|
||||
{ COMMON_JOKER, 5, raised_fist_joker_effect }, // 41
|
||||
{ COMMON_JOKER, 4, smiley_face_joker_effect }, // 42
|
||||
{ UNCOMMON_JOKER, 6, acrobat_joker_effect }, // 43
|
||||
{ UNCOMMON_JOKER, 5, dusk_joker_effect }, // 44
|
||||
{ UNCOMMON_JOKER, 6, sock_and_buskin_joker_effect }, // 45
|
||||
{ UNCOMMON_JOKER, 6, hack_joker_effect }, // 46
|
||||
{ COMMON_JOKER, 4, hanging_chad_joker_effect }, // 47
|
||||
{ UNCOMMON_JOKER, 7, joker_effect_noop, }, // 48 Four Fingers
|
||||
{ COMMON_JOKER, 4, scholar_joker_effect }, // 49
|
||||
|
||||
// The following jokers don't have sprites yet,
|
||||
// uncomment them when their sprites are added.
|
||||
|
||||
Reference in New Issue
Block a user