13#include "skip_tags_gfx.h"
22#define MAX_NON_OVERLAPING_TAG_SPRITES 5
23#define SKIP_TAG_HIDE_X_OFFSET 20
25#define SKIP_TAG_GET_BOUNCE_STRENGTH (float2fx(-0.3f))
26#define SKIP_TAG_TRIGGER_BOUNCE_STRENGTH (float2fx(-0.4f))
30static const BG_POINT OWNED_SKIP_TAGS_BASE_POS = {219, 97};
32static const int OWNED_SKIP_TAGS_STACK_HEIGHT = 64;
33static const int OWNED_SKIP_TAGS_SPACING = 12;
40#define NB_ANTE1_SKIP_TAGS 7
46#define NB_SKIP_TAG_TYPES 10
51 SKIP_TAG_TYPE_INVESTMENT,
62 SKIP_TAG_TYPE_INVESTMENT,
65 SKIP_TAG_TYPE_GARBAGE,
74static List s_owned_skip_tags;
78 return &s_owned_skip_tags;
99 static bool pb_init =
false;
102 GRIT_CPY(&pal_obj_mem[PAL_ROW_LEN * SKIP_TAGS_PB], skip_tags_gfxPal);
109 &skip_tags_gfxTiles[tag->type * SKIP_TAG_SPRITE_TILES *
TILE_SIZE],
119 ATTR0_SQUARE | ATTR0_4BPP | ATTR0_AFF,
131 if (tag == NULL || *tag == NULL)
146 int2fx(OWNED_SKIP_TAGS_BASE_POS.x + (move_offscreen ? SKIP_TAG_HIDE_X_OFFSET : 0));
157 if (g_game_vars.ante == 1)
169static inline int get_skip_tag_sprites_spacing(
void)
172 return (nb_owned_tags <= MAX_NON_OVERLAPING_TAG_SPRITES)
173 ? OWNED_SKIP_TAGS_SPACING
174 : OWNED_SKIP_TAGS_STACK_HEIGHT / nb_owned_tags;
177static void rearrange_skip_tag_sprites(
int nb_owned_tags,
int tag_spacing)
179 for (
int idx = 0; idx < nb_owned_tags; idx++)
186 BG_POINT dest_pos = {
187 OWNED_SKIP_TAGS_BASE_POS.x,
188 OWNED_SKIP_TAGS_BASE_POS.y - idx * tag_spacing
204 if (tag->type == tag_type)
221 if (tag->type == tag_type)
241 if (nb_owned_tags >= MAX_SKIP_TAGS - NB_SKIPPABLE_BLINDS)
243 MGBA_FUNC_WARN(
"Memory pool limit reached, cannot obtain more Skip Tags");
250 BG_POINT new_tag_pos = OWNED_SKIP_TAGS_BASE_POS;
254 if (nb_owned_tags <= MAX_NON_OVERLAPING_TAG_SPRITES)
256 new_tag_pos.y -= (nb_owned_tags - 1) * OWNED_SKIP_TAGS_SPACING;
262 int even_spacing = get_skip_tag_sprites_spacing();
265 rearrange_skip_tag_sprites(nb_owned_tags - 1, even_spacing);
266 new_tag_pos.y -= even_spacing * (nb_owned_tags - 1);
286 rearrange_skip_tag_sprites(
list_get_len(&s_owned_skip_tags), get_skip_tag_sprites_spacing());
302enum SkipTagProcessState
304 SKIP_TAG_PROCESS_STATE_SEARCH,
305 SKIP_TAG_PROCESS_STATE_TRIGGER,
306 SKIP_TAG_PROCESS_STATE_REMOVE,
307 SKIP_TAG_PROCESS_STATE_MAX
310static void skip_tag_search_for_event(
void);
311static void skip_tag_trigger_for_event(
void);
312static void skip_tag_remove_for_event(
void);
314static StateInfo tag_process_state_fn[SKIP_TAG_PROCESS_STATE_MAX] = {
315 STATE_INFO_UPDATE_FN_ONLY(skip_tag_search_for_event),
316 STATE_INFO_UPDATE_FN_ONLY(skip_tag_trigger_for_event),
317 STATE_INFO_UPDATE_FN_ONLY(skip_tag_remove_for_event)
321 STATE_MACHINE_DEFINE(tag_process_state_fn, SKIP_TAG_PROCESS_STATE_MAX);
327 enum SkipTagProcessState tag_process_state;
328 enum SkipTagEvent tag_event;
329 enum SkipTagProcStage tag_proc_stage;
333 .tags_timer = TM_ZERO,
334 .tag_process_state = SKIP_TAG_PROCESS_STATE_MAX,
335 .tag_event = SKIP_TAG_EVENT_NONE,
336 .tag_proc_stage = SKIP_TAG_PROCESS_STAGE_NONE,
341 return s_tag_process_info.tag_proc_stage;
349 s_tag_process_info.tags_timer = TM_ZERO;
350 s_tag_process_info.tag_process_state = SKIP_TAG_PROCESS_STATE_SEARCH;
351 s_tag_process_info.tag_event = checked_tag_event;
352 s_tag_process_info.tag_proc_stage = SKIP_TAG_PROCESS_STAGE_NONE;
361 s_tag_process_info.tag_process_state = tag_process_sm.
state;
362 s_tag_process_info.tags_timer = TM_ZERO;
368 if (s_tag_process_info.tag_process_state >= SKIP_TAG_PROCESS_STATE_MAX)
382static SkipTag* s_consumed_tag = NULL;
383static int s_consumed_tag_idx = 0;
384static SkipTagCallback s_consumed_tag_effect_func = NULL;
386static void skip_tag_search_for_event(
void)
388 s_tag_process_info.tag_proc_stage = SKIP_TAG_PROCESS_STAGE_NONE;
389 s_tag_process_info.tags_timer++;
393 for (; s_consumed_tag_idx < nb_owned_tags; s_consumed_tag_idx++)
395 s_consumed_tag =
list_get_at_idx(&s_owned_skip_tags, s_consumed_tag_idx);
397 if (s_consumed_tag == NULL)
402 if (info == NULL || info->event_type != s_tag_process_info.tag_event)
406 if (info->tag_condition_func())
408 s_consumed_tag_effect_func = info->tag_effect_func;
409 s_tag_process_info.tag_proc_stage = SKIP_TAG_PROCESS_STAGE_NONE;
415 s_consumed_tag_idx = 0;
416 s_tag_process_info.tag_proc_stage = SKIP_TAG_PROCESS_STAGE_END;
417 s_tag_process_info.tag_process_state = SKIP_TAG_PROCESS_STATE_MAX;
421static void skip_tag_trigger_for_event(
void)
423 s_tag_process_info.tag_proc_stage = SKIP_TAG_PROCESS_STAGE_NONE;
424 if (s_tag_process_info.tags_timer++ % FRAMES(TM_SKIP_TAG_ANIM_DURATION) != TM_ZERO)
427 BG_POINT tag_pos = {fx2int(s_consumed_tag->x), fx2int(s_consumed_tag->y)};
430 s_consumed_tag->type += MAX_SKIP_TAG_TYPES;
436 s_consumed_tag->rotation = 0;
437 s_consumed_tag->vrotation = 0;
441 s_tag_process_info.tag_proc_stage = SKIP_TAG_PROCESS_STAGE_TRIGGER;
447 (*s_consumed_tag_effect_func)();
448 s_consumed_tag = NULL;
449 s_consumed_tag_effect_func = NULL;
452static void skip_tag_remove_for_event(
void)
454 s_tag_process_info.tag_proc_stage = SKIP_TAG_PROCESS_STAGE_NONE;
455 if (s_tag_process_info.tags_timer++ % FRAMES(TM_SKIP_TAG_ANIM_DURATION) != TM_ZERO)
Utilities for using maxmod to play sound effects.
#define MM_BASE_PITCH_RATE
The default pitch rate for the sound effect played.
void play_sfx(mm_word id, mm_word rate, mm_byte volume)
Play a sound effect, wrapper for mmEffectEx() See https://maxmod.org/ref/functions/mm_sound_effect....
#define SFX_DEFAULT_VOLUME
Default volume for sound effects.
Blind select state functions.
Game global game variables struct definition.
#define TILE_SIZE
Tile size in pixels, both height and width as tiles are square.
#define TILE_MEM_OBJ_CHARBLOCK0_IDX
The index for the first charblock of the object memory in tonc's tile_mem.
Functions relative to the handling of Jokers.
void * list_get_at_idx(List *list, unsigned int idx)
int list_get_len(const List *list)
ListItr rev_list_itr_create(List *list)
void list_clear(List *list)
void * list_itr_next(ListItr *itr)
bool list_remove_at_idx(List *list, unsigned int idx)
void list_push_back(List *list, void *data)
ListItr list_itr_create(List *list)
Interface to interact with the mgba logger.
u32 rng_get_u32(enum RngSequence key)
Get the next "randomly" generated number in the sequence corresponding to the given type.
void remove_skip_tag(int tag_idx)
Pops the Tag at index in owned list, destroys it and rearranges the remaining Tags' sprites.
void set_owned_skip_tags_moved_offscreen(bool move_offscreen)
Show or hide the owned SkipTag sprites by moving them offscreen to the right.
void skip_tag_process_pause(void)
Suspend the processing of Skip Tags.
#define NB_ANTE1_SKIP_TAGS
Number of implemented Skip Tags available from Ante 1.
void skip_tag_set_sprite(SkipTag *tag, s16 layer)
Set the sprite for the given SkipTag, according to its internal ID.
void skip_tag_destroy(SkipTag **tag)
Destroy the given SkipTag, invalidate it in the corresponding memory pool and set the pointer provide...
SkipTag * roll_skip_tag(void)
Create a new SkipTag with a random ID, picked by taking the Ante into account, as some Tags only appe...
void skip_tag_process_start(enum SkipTagEvent checked_tag_event)
Start Skip Tag processing for the specified event.
enum SkipTagProcStage skip_tag_process_get_proc_stage(void)
Recover the current stage of the Tag processing.
void skip_tag_process_resume(void)
Resume the processing of Skip Tags.
void add_skip_tag(SkipTag **blind_tag)
Adds the SkipTag to the owned list, snaps it into position and sets the original pointer to NULL.
GBAL_UNUSED bool skip_tag_is_owned(enum SkipTagTypes tag_type)
Checks if the given tag type is present in owned Tags list.
void remove_all_skip_tags(void)
Delete all owned Skip Tags.
#define NB_SKIP_TAG_TYPES
Number of implemented Skip Tags.
SkipTag * skip_tag_new(enum SkipTagTypes tag_type)
Create a new Skip Tag object for the given Tag ID and allocates space for it in the corresponding mem...
int skip_tag_count(enum SkipTagTypes tag_type)
Counts how many tags of a certain type we own.
List * get_owned_skip_tags(void)
Get the owned skip tags list.
Data structures and functions related to the handling of Skip Tags.
SkipTagTypes
List of all Skip Tags, in the order they are in on their spritesheet. Not all of them are implemented...
const SkipTagInfo * get_skip_tag_registry_entry(enum SkipTagTypes tag_type)
Get the registry entry info for the given Skip Tag type.
void sprite_object_init(SpriteObject *sprite_object)
Initialize a SpriteObject to a default state. Must be called only once per SpriteObject when it is cr...
void sprite_object_destroy(SpriteObject *sprite_object)
Destroy SpriteObject.
int sprite_get_tid(enum SpriteType sprite_type, s16 layer)
Get the tile index of a certain SpriteType at a certain layer.
void sprite_object_bounce(SpriteObject *sprite_object, FIXED strength)
Make SpriteObject bounce by slightly increasing its size in an elastic way.
void sprite_object_set_sprite(SpriteObject *sprite_object, Sprite *sprite)
Register a Sprite to an associated SpriteObject.
void sprite_object_set_target(SpriteObject *sprite_object, BG_POINT to)
Set a SpriteObject's target position so that is slides across the screen between from the current pos...
INLINE void sprite_object_position(SpriteObject *sprite_object, int x, int y)
Set sprite_object position. Inlined for efficiency.
Sprite * sprite_new(u16 a0, u16 a1, u32 tid, u32 pb, s16 sprite_index)
Allocate and retrieve a pointer to a valid Sprite.
void sprite_destroy(Sprite **sprite)
Destroy Sprite.
int sprite_get_starting_layer(enum SpriteType sprite_type)
Get the starting layer of a certain type of sprite.
void sprite_object_sway(SpriteObject *sprite_object)
Make SpriteObject sway by slightly rotating on screen.
void state_machine_remove(StateMachine *state_machine)
Remove a statemachine's update function.
void state_machine_register(StateMachine *state_machine)
Register a statemachine to run it's update function once per frame.
void state_machine_change_state(StateMachine *state_machine, int new_state)
Calls the current state's on_exit, the new state's on_init, and sets the active update fn.
Data structure containing the info about a Skip Tag, namely:
A sprite object is a sprite that is focusable and movable in animation.
Sprite struct for GBA hardware specifics.
bool registered
Flag to determine if statemachine is already running it's active_update function.
int state
The current state of the state machine, the offset into state_infos.
Utilities relating around number string representation and protected arithmatic helper functions.
#define GBAL_RETURN_IF_NULL(param, ret_val)
Returns ret_val and prints a default error message if param is equal to NULL. Useful for checking arg...
#define GBAL_UNUSED
Wrapper around the "unused" attribute.
#define RET_NONE
An empty return value for RETURN_IF macros when used in void functions Expands to nothing because mac...