Add initial accept for gen 1 and 2

This commit is contained in:
Lorenzooone 2023-01-31 04:03:34 +01:00
parent 01296f8795
commit c1ed52c168
14 changed files with 476 additions and 82 deletions

View File

@ -80,15 +80,29 @@ u8 is_done_gen3;
u8 received_gen3[(sizeof(struct gen3_trade_data)>>4)+1];
void try_to_end_trade() {
syn_transmitted = 0;
trade_offer_out = CANCEL_VALUE;
trading_state = HAVE_OFFER;
}
void try_to_offer(u8 index) {
syn_transmitted = 0;
trade_offer_out = index;
trading_state = HAVE_OFFER;
}
void try_to_accept_offer() {
syn_transmitted = 0;
trade_offer_out = ACCEPT_VALUE;
trading_state = HAVE_ACCEPT;
}
void try_to_decline_offer() {
syn_transmitted = 0;
trade_offer_out = DECLINE_VALUE;
trading_state = HAVE_ACCEPT;
}
int get_received_trade_offer() {
if((trade_offer_in == CANCEL_VALUE) || (trade_offer_out == CANCEL_VALUE)) {
if(trade_offer_in == trade_offer_out)
@ -98,6 +112,12 @@ int get_received_trade_offer() {
return trade_offer_in;
}
int has_accepted_offer() {
if((trade_offer_in == DECLINE_VALUE) || (trade_offer_out == DECLINE_VALUE))
return 0;
return 1;
}
void set_start_state(enum START_TRADE_STATE new_val) {
start_state = new_val;
start_state_updated = 1;
@ -229,6 +249,15 @@ IWRAM_CODE u8 get_offer(u8 data, u8 trade_offer_start, u8 end_trade_value) {
return trade_offer_start + trade_offer_out;
}
IWRAM_CODE u8 get_accept(u8 data, u8 trade_offer_start) {
next_long_pause = 1;
if((data == (trade_offer_start + DECLINE_VALUE)) || (data == (trade_offer_start + ACCEPT_VALUE))) {
trade_offer_in = data - trade_offer_start;
trading_state = RECEIVED_ACCEPT;
}
return trade_offer_start + trade_offer_out;
}
IWRAM_CODE __attribute__((optimize(3))) void set_next_vcount_interrupt(void){
int next_stop = REG_VCOUNT + VCOUNT_WAIT_LINES;
if(next_stop >= 0xE4)
@ -380,10 +409,17 @@ IWRAM_CODE int process_data_arrived_gen1(u8 data, u8 is_master) {
return SEND_NO_INFO;
}
else {
// Do trading stuff here
// Space things out
if(syn_transmitted < MIN_WAIT_FOR_SYN) {
syn_transmitted++;
return SEND_NO_INFO;
}
// The actual trading menu logic
switch(trading_state) {
case HAVE_OFFER:
return get_offer(data, GEN1_TRADE_OFFER_START, END_TRADE_BYTE_GEN1);
case HAVE_ACCEPT:
return get_accept(data, GEN1_TRADE_OFFER_START);
default:
return SEND_NO_INFO;
}
@ -438,10 +474,17 @@ IWRAM_CODE int process_data_arrived_gen2(u8 data, u8 is_master) {
return SEND_NO_INFO;
}
else {
// Do trading stuff here
// Space things out
if(syn_transmitted < MIN_WAIT_FOR_SYN) {
syn_transmitted++;
return SEND_NO_INFO;
}
// The actual trading menu logic
switch(trading_state) {
case HAVE_OFFER:
return get_offer(data, GEN2_TRADE_OFFER_START, END_TRADE_BYTE_GEN2);
case HAVE_ACCEPT:
return get_accept(data, GEN2_TRADE_OFFER_START);
default:
return SEND_NO_INFO;
break;

View File

@ -27,6 +27,8 @@
#define GEN2_TRADE_OFFER_START 0x70
#define END_TRADE_BYTE_GEN2 (GEN2_TRADE_OFFER_START + CANCEL_VALUE)
#define END_TRADE_BYTE_GEN1 (GEN1_TRADE_OFFER_START + CANCEL_VALUE)
#define DECLINE_VALUE 1
#define ACCEPT_VALUE 2
#define WANTS_TO_CANCEL -1
#define TRADE_CANCELLED -2
@ -38,7 +40,10 @@ enum TRADING_STATE {NO_INFO, HAVE_OFFER, RECEIVED_OFFER, HAVE_ACCEPT, RECEIVED_A
void try_to_end_trade();
void try_to_offer(u8);
void try_to_accept_offer();
void try_to_decline_offer();
int get_received_trade_offer();
int has_accepted_offer();
void start_transfer(u8, u8);
void set_next_vcount_interrupt();
void stop_transfer(u8);

View File

@ -78,26 +78,66 @@ void read_game_data_trainer_info(int slot, struct game_data_t* game_data) {
}
}
void read_party(int slot, struct game_data_t* game_data) {
if(slot != 0)
slot = 1;
read_game_data_trainer_info(slot, game_data);
if(game_data->game_identifier.game_is_jp == UNDETERMINED) {
if(game_data->trainer_name[OT_NAME_JP_GEN3_SIZE+1] == 0)
game_data->game_identifier.game_is_jp = 1;
else
game_data->game_identifier.game_is_jp = 0;
void register_dex_entry(struct game_data_t* game_data, struct gen3_mon_data_unenc* data_src) {
u16 dex_index = get_dex_index_raw(data_src);
if(dex_index != NO_DEX_INDEX) {
u8 base_index = dex_index >> 3;
u8 rest_index = dex_index & 7;
game_data->pokedex_seen[base_index] |= (1 << rest_index);
game_data->pokedex_owned[base_index] |= (1 << rest_index);
}
u16 add_on = RSE_PARTY;
if(game_data->game_identifier.game_main_version == FRLG_MAIN_GAME_CODE)
add_on = FRLG_PARTY;
}
for(int i = 0; i < SECTION_TOTAL; i++)
if(read_section_id(slot, i) == SECTION_PARTY_INFO_ID) {
copy_save_to_ram((slot * SAVE_SLOT_SIZE) + (i * SECTION_SIZE) + add_on, (u8*)(&game_data->party_3), sizeof(struct gen3_party));
break;
void handle_mail_trade(struct game_data_t* game_data, u8 own_mon, u8 other_mon) {
u8 mail_id = get_mail_id_raw(&game_data[0].party_3_undec[own_mon]);
if((mail_id != GEN3_NO_MAIL) && (mail_id < PARTY_SIZE)) {
clean_mail_gen3(&game_data[0].mails_3[get_mail_id_raw(&game_data[0].party_3_undec[own_mon])], game_data[0].party_3_undec[own_mon].src);
}
mail_id = get_mail_id_raw(&game_data[1].party_3_undec[other_mon]);
if((mail_id != GEN3_NO_MAIL) && (mail_id < PARTY_SIZE)) {
u8 is_mail_free[PARTY_SIZE] = {1,1,1,1,1,1};
for(int i = 0; i < game_data[0].party_3.total; i++) {
u8 inner_mail_id = get_mail_id_raw(&game_data[0].party_3.mons[i]);
if((inner_mail_id != GEN3_NO_MAIL) && (inner_mail_id < PARTY_SIZE))
is_mail_free[inner_mail_id] = 0;
}
u8 target = PARTY_SIZE-1;
for(int i = 0; i < PARTY_SIZE; i++)
if(is_mail_free[i]) {
target = i;
break;
}
u8* dst = (u8*)&game_data[0].mails_3[target];
u8* src = (u8*)&game_data[1].mails_3[mail_id];
for(int i = 0; i < sizeof(struct mail_gen3); i++)
dst[i] = src[i];
game_data[1].party_3_undec[other_mon].src->mail_id = target;
}
}
u8 trade_mons(struct game_data_t* game_data, u8 own_mon, u8 other_mon, u16** learnset_ptr, u8 curr_gen) {
handle_mail_trade(game_data, own_mon, other_mon);
u8* dst = (u8*)&game_data[0].party_3.mons[own_mon];
u8* src = (u8*)&game_data[1].party_3.mons[other_mon];
for(int i = 0; i < sizeof(struct gen3_mon); i++)
dst[i] = src[i];
dst = (u8*)&game_data[0].party_3_undec[own_mon];
src = (u8*)&game_data[1].party_3_undec[other_mon];
for(int i = 0; i < sizeof(struct gen3_mon_data_unenc); i++)
dst[i] = src[i];
game_data[0].party_3_undec[own_mon].src = &game_data[0].party_3.mons[own_mon];
for(int i = 0; i < GIFT_RIBBONS; i++)
if(!game_data[0].giftRibbons[i])
game_data[0].giftRibbons[i] = game_data[1].giftRibbons[i];
register_dex_entry(&game_data[0], &game_data[0].party_3_undec[own_mon]);
u8 ret_val = trade_evolve(&game_data[0].party_3.mons[own_mon], &game_data[0].party_3_undec[own_mon], learnset_ptr, curr_gen);
if(ret_val)
register_dex_entry(&game_data[0], &game_data[0].party_3_undec[own_mon]);
return ret_val;
}
void process_party_data(struct game_data_t* game_data) {
if(game_data->party_3.total > PARTY_SIZE)
game_data->party_3.total = PARTY_SIZE;
u8 curr_slot = 0;
@ -128,6 +168,29 @@ void read_party(int slot, struct game_data_t* game_data) {
game_data->party_1.total = curr_slot;
}
void read_party(int slot, struct game_data_t* game_data) {
if(slot != 0)
slot = 1;
read_game_data_trainer_info(slot, game_data);
if(game_data->game_identifier.game_is_jp == UNDETERMINED) {
if(game_data->trainer_name[OT_NAME_JP_GEN3_SIZE+1] == 0)
game_data->game_identifier.game_is_jp = 1;
else
game_data->game_identifier.game_is_jp = 0;
}
u16 add_on = RSE_PARTY;
if(game_data->game_identifier.game_main_version == FRLG_MAIN_GAME_CODE)
add_on = FRLG_PARTY;
for(int i = 0; i < SECTION_TOTAL; i++)
if(read_section_id(slot, i) == SECTION_PARTY_INFO_ID) {
copy_save_to_ram((slot * SAVE_SLOT_SIZE) + (i * SECTION_SIZE) + add_on, (u8*)(&game_data->party_3), sizeof(struct gen3_party));
break;
}
process_party_data(game_data);
}
u32 read_slot_index(int slot) {
if(slot != 0)
slot = 1;
@ -194,4 +257,4 @@ void read_gen_3_data(struct game_data_t* game_data){
read_party(slot, game_data);
own_game_data_ptr = game_data;
}
}

View File

@ -24,6 +24,8 @@ struct game_data_t {
void init_game_data(struct game_data_t*);
void read_gen_3_data(struct game_data_t*);
void process_party_data(struct game_data_t* game_data);
struct game_data_t* get_own_game_data();
u8 trade_mons(struct game_data_t*, u8, u8, u16**, u8);
#endif
#endif

View File

@ -286,6 +286,27 @@ u8 handle_input_main_menu(u8* cursor_y_pos, u16 keys, u8* update, u8* target, u8
return 0;
}
u8 handle_input_offer_options(u16 keys, u8* cursor_y_pos, u8* cursor_x_pos) {
if(keys & KEY_B)
return 1 + 1;
if(keys & KEY_A) {
if(!(*cursor_x_pos))
return 1 + (*cursor_y_pos);
else
return OFFER_INFO_DISPLAY + (*cursor_y_pos);
}
if((keys & KEY_LEFT) || (keys & KEY_RIGHT))
*cursor_x_pos ^= 1;
if((keys & KEY_UP) || (keys & KEY_DOWN))
*cursor_y_pos ^= 1;
return 0;
}
u8 handle_input_trade_options(u16 keys, u8* cursor_x_pos) {
if(keys & KEY_B)

View File

@ -8,6 +8,7 @@
#define CANCEL_TRADING 0xFF
#define CANCEL_TRADE_START 0xFF
#define CANCEL_TRADE_OPTIONS 0xFF
#define OFFER_INFO_DISPLAY 0x12
#define START_MULTIBOOT 0x49
#define VIEW_OWN_PARTY 0x65
@ -19,6 +20,7 @@ u8 handle_input_info_menu(struct game_data_t*, u8*, u8, u16, u8*, u8, u8*);
u8 handle_input_trading_menu(u8*, u8*, u16, u8, u8);
u8 handle_input_main_menu(u8*, u16, u8*, u8*, u8*, u8*);
u8 handle_input_trade_options(u16, u8*);
u8 handle_input_offer_options(u16, u8*, u8*);
u8 handle_input_trade_setup(u16, u8);
#endif

View File

@ -30,9 +30,9 @@
#define MIN_WAITCYCLE 1
#define BASE_SCREEN 0
#define INFO_SCREEN 2
#define INFO_SCREEN 3
enum STATE {MAIN_MENU, MULTIBOOT, TRADING_MENU, INFO_MENU, START_TRADE, WAITING_DATA, TRADE_OPTIONS, NATURE_SETTING, OFFER_MENU};
enum STATE {MAIN_MENU, MULTIBOOT, TRADING_MENU, INFO_MENU, START_TRADE, WAITING_DATA, TRADE_OPTIONS, NATURE_SETTING, OFFER_MENU, TRADING_ANIMATION};
enum STATE curr_state;
u32 counter = 0;
u32 input_counter = 0;
@ -107,31 +107,78 @@ void cursor_update_main_menu(u8 cursor_y_pos) {
update_cursor_y(BASE_Y_CURSOR_MAIN_MENU + (BASE_Y_CURSOR_INCREMENT_MAIN_MENU * cursor_y_pos));
}
void waiting_init(u8 cancel, u8 cursor_y_pos) {
void cursor_update_trade_options(u8 cursor_x_pos) {
update_cursor_base_x(BASE_X_CURSOR_TRADE_OPTIONS + (cursor_x_pos * BASE_X_CURSOR_INCREMENT_TRADE_OPTIONS), counter);
}
void cursor_update_offer_options(u8 cursor_y_pos, u8 cursor_x_pos) {
update_cursor_base_x(BASE_X_CURSOR_OFFER_OPTIONS + (cursor_x_pos * BASE_X_CURSOR_INCREMENT_OFFER_OPTIONS), counter);
update_cursor_y(BASE_Y_CURSOR_OFFER_OPTIONS + (BASE_Y_CURSOR_INCREMENT_OFFER_OPTIONS * cursor_y_pos));
}
void offer_init(struct game_data_t* game_data, u8 own_mon, u8 other_mon, u8* cursor_y_pos, u8* cursor_x_pos) {
curr_state = OFFER_MENU;
set_screen(BASE_SCREEN);
reset_sprites_to_party();
disable_all_screens_but_current();
disable_all_cursors();
disable_all_sprites();
set_screen(OFFER_WINDOW_SCREEN);
print_offer_screen(game_data, own_mon, other_mon);
set_screen(OFFER_OPTIONS_WINDOW_SCREEN);
print_offer_options_screen(game_data, own_mon, other_mon);
enable_screen(OFFER_WINDOW_SCREEN);
enable_screen(OFFER_OPTIONS_WINDOW_SCREEN);
*cursor_x_pos = 0;
*cursor_y_pos = 0;
cursor_update_offer_options(*cursor_y_pos, *cursor_x_pos);
}
void waiting_init() {
curr_state = WAITING_DATA;
set_screen(WAITING_WINDOW_SCREEN);
reset_screen(BLANK_FILL);
init_waiting_window();
print_waiting();
enable_screen(WAITING_WINDOW_SCREEN);
}
void waiting_offer_init(u8 cancel, u8 cursor_y_pos) {
waiting_init();
if(cancel)
try_to_end_trade();
else
try_to_offer(cursor_y_pos);
curr_state = WAITING_DATA;
}
void check_bad_trade_received(u8 curr_gen, u8 own_menu) {
void waiting_accept_init(u8 decline) {
waiting_init();
if(decline)
try_to_decline_offer();
else
try_to_accept_offer();
}
void check_bad_trade_received(struct game_data_t* game_data, u8 target, u8 region, u8 master, u8 curr_gen, u8 own_menu, u8* cursor_y_pos) {
u8 useless = 0;
// Handle bad received / No valid mons
if(handle_input_trading_menu(&useless, &useless, 0, curr_gen, own_menu) == CANCEL_TRADING) {
if(own_menu)
main_menu_init(&game_data[0], target, region, master, &cursor_y_pos);
main_menu_init(&game_data[0], target, region, master, cursor_y_pos);
else
waiting_init(1, 0);
waiting_offer_init(1, 0);
}
}
void trade_menu_init(struct game_data_t* game_data, u8 curr_gen, u8 own_menu, u8* cursor_y_pos, u8* cursor_x_pos) {
void trade_options_init(u8 cursor_x_pos, u8* submenu_cursor_x_pos) {
curr_state = TRADE_OPTIONS;
set_screen(TRADE_OPTIONS_WINDOW_SCREEN);
print_trade_options(cursor_x_pos);
enable_screen(TRADE_OPTIONS_WINDOW_SCREEN);
*submenu_cursor_x_pos = 0;
cursor_update_trade_options(*submenu_cursor_x_pos);
update_cursor_y(BASE_Y_CURSOR_TRADE_OPTIONS);
}
void trade_menu_init(struct game_data_t* game_data, u8 target, u8 region, u8 master, u8 curr_gen, u8 own_menu, u8* cursor_y_pos, u8* cursor_x_pos) {
curr_state = TRADING_MENU;
*cursor_y_pos = 0;
*cursor_x_pos = 0;
@ -139,18 +186,18 @@ void trade_menu_init(struct game_data_t* game_data, u8 curr_gen, u8 own_menu, u8
print_trade_menu(game_data, 1, curr_gen, 1, own_menu);
set_party_sprite_counter();
cursor_update_trading_menu(*cursor_y_pos, *cursor_x_pos);
check_bad_trade_received(curr_gen, own_menu);
check_bad_trade_received(game_data, target, region, master, curr_gen, own_menu, cursor_y_pos);
}
void return_to_trade_menu(u8 cursor_y_pos, u8 cursor_x_pos, u8 curr_gen, u8 own_menu) {
void return_to_trade_menu(struct game_data_t* game_data, u8 target, u8 region, u8 master, u8 curr_gen, u8 own_menu, u8* cursor_y_pos, u8* cursor_x_pos) {
curr_state = TRADING_MENU;
set_screen(BASE_SCREEN);
reset_sprites_to_party();
disable_all_screens_but_current();
disable_all_cursors();
enable_all_valid_sprites();
cursor_update_trading_menu(cursor_y_pos, cursor_x_pos);
check_bad_trade_received(curr_gen, own_menu);
cursor_update_trading_menu(*cursor_y_pos, *cursor_x_pos);
check_bad_trade_received(game_data, target, region, master, curr_gen, own_menu, cursor_y_pos);
}
void main_menu_init(struct game_data_t* game_data, u8 target, u8 region, u8 master, u8* cursor_y_pos) {
@ -207,6 +254,8 @@ int main(void)
init_item_icon();
init_cursor();
u16** learnset_ptr = NULL;
u8 evolved = 0;
u8 returned_val;
u8 update = 0;
u8 target = 1;
@ -216,7 +265,7 @@ int main(void)
u8 own_menu = 0;
u8 cursor_y_pos = 0;
u8 cursor_x_pos = 0;
//u8 submenu_cursor_y_pos = 0;
u8 submenu_cursor_y_pos = 0;
u8 submenu_cursor_x_pos = 0;
u8 prev_val = 0;
u8 curr_mon = 0;
@ -239,8 +288,7 @@ int main(void)
if(get_start_state_raw() == START_TRADE_DON) {
read_comm_buffer(&game_data[1], curr_gen, region);
own_menu = 0;
trade_menu_init(game_data, curr_gen, own_menu, &cursor_y_pos, &cursor_x_pos);
trade_menu_init(game_data, target, region, master, curr_gen, own_menu, &cursor_y_pos, &cursor_x_pos);
}
else {
print_start_trade();
@ -254,21 +302,27 @@ int main(void)
main_menu_init(&game_data[0], target, region, master, &cursor_y_pos);
}
else if(result == WANTS_TO_CANCEL)
return_to_trade_menu(cursor_y_pos, cursor_x_pos, curr_gen, own_menu);
return_to_trade_menu(game_data, target, region, master, curr_gen, own_menu, &cursor_y_pos, &cursor_x_pos);
else {
if(game_data[1].party_3_undec[result].is_valid_gen3) {
// Print the offer menu here
other_mon = result;
curr_state = OFFER_MENU;
offer_init(game_data, curr_mon, other_mon, &submenu_cursor_y_pos, &submenu_cursor_x_pos);
}
else {
// Handle bad offer
curr_state = WAITING_DATA;
// TODO: Handle bad offer
return_to_trade_menu(game_data, target, region, master, curr_gen, own_menu, &cursor_y_pos, &cursor_x_pos);
waiting_accept_init(1);
}
}
}
else if(get_trading_state() == RECEIVED_ACCEPT) {
if(has_accepted_offer()) {
evolved = trade_mons(game_data, curr_mon, other_mon, learnset_ptr, curr_gen);
process_party_data(&game_data[0]);
curr_state = TRADING_ANIMATION;
}
else
return_to_trade_menu(game_data, target, region, master, curr_gen, own_menu, &cursor_y_pos, &cursor_x_pos);
}
}
}
@ -290,7 +344,7 @@ int main(void)
else if(returned_val > VIEW_OWN_PARTY && returned_val <= VIEW_OWN_PARTY + TOTAL_GENS) {
curr_gen = returned_val - VIEW_OWN_PARTY;
own_menu = 1;
trade_menu_init(game_data, curr_gen, own_menu, &cursor_y_pos, &cursor_x_pos);
trade_menu_init(game_data, target, region, master, curr_gen, own_menu, &cursor_y_pos, &cursor_x_pos);
}
else if(returned_val > 0 && returned_val <= TOTAL_GENS) {
curr_gen = returned_val;
@ -316,21 +370,12 @@ int main(void)
}
else {
if(returned_val == CANCEL_TRADING)
waiting_init(1, cursor_y_pos);
waiting_offer_init(1, cursor_y_pos);
else if(returned_val) {
if(cursor_x_pos && curr_gen ==3)
info_menu_init(game_data, cursor_x_pos, curr_mon, &curr_page);
else {
set_screen(TRADE_OPTIONS_WINDOW_SCREEN);
reset_screen(BLANK_FILL);
init_trade_options_window();
print_trade_options(cursor_x_pos);
enable_screen(TRADE_OPTIONS_WINDOW_SCREEN);
submenu_cursor_x_pos = 0;
update_cursor_base_x(BASE_X_CURSOR_TRADE_OPTIONS + (submenu_cursor_x_pos * BASE_X_CURSOR_INCREMENT_TRADE_OPTIONS), counter);
update_cursor_y(BASE_Y_CURSOR_TRADE_OPTIONS);
curr_state = TRADE_OPTIONS;
}
else
trade_options_init(cursor_x_pos, &submenu_cursor_x_pos);
}
}
break;
@ -338,7 +383,7 @@ int main(void)
prev_val = curr_mon;
returned_val = handle_input_info_menu(game_data, &cursor_y_pos, cursor_x_pos, keys, &curr_mon, curr_gen, &curr_page);
if(returned_val == CANCEL_INFO)
return_to_trade_menu(cursor_y_pos, cursor_x_pos, curr_gen, own_menu);
return_to_trade_menu(game_data, target, region, master, curr_gen, own_menu, &cursor_y_pos, &cursor_x_pos);
else
print_pokemon_pages(returned_val, curr_mon != prev_val, &game_data[cursor_x_pos].party_3_undec[curr_mon], curr_page);
break;
@ -356,27 +401,42 @@ int main(void)
returned_val = handle_input_trade_options(keys, &submenu_cursor_x_pos);
if(returned_val) {
if(returned_val == CANCEL_TRADE_OPTIONS)
return_to_trade_menu(cursor_y_pos, cursor_x_pos, curr_gen, own_menu);
return_to_trade_menu(game_data, target, region, master, curr_gen, own_menu, &cursor_y_pos, &cursor_x_pos);
else {
if(!submenu_cursor_x_pos)
info_menu_init(game_data, cursor_x_pos, curr_mon, &curr_page);
else if(!cursor_x_pos)
waiting_init(0, cursor_y_pos);
waiting_offer_init(0, cursor_y_pos);
else {
// Print the nature settings menu here
// TODO: Print the nature settings menu here
curr_state = NATURE_SETTING;
}
}
}
else
update_cursor_base_x(BASE_X_CURSOR_TRADE_OPTIONS + (submenu_cursor_x_pos * BASE_X_CURSOR_INCREMENT_TRADE_OPTIONS), counter);
cursor_update_trade_options(submenu_cursor_x_pos);
break;
case WAITING_DATA:
break;
case NATURE_SETTING:
// TODO: Nature settings
break;
case OFFER_MENU:
returned_val = handle_input_offer_options(keys, &submenu_cursor_y_pos, &submenu_cursor_x_pos);
if(returned_val) {
if(returned_val >= OFFER_INFO_DISPLAY) {
returned_val -= OFFER_INFO_DISPLAY;
if(returned_val)
returned_val = 1;
// TODO: Handle the summaries here
}
else
waiting_accept_init(returned_val-1);
}
else
cursor_update_offer_options(submenu_cursor_y_pos, submenu_cursor_x_pos);
break;
default:
main_menu_init(&game_data[0], target, region, master, &cursor_y_pos);

View File

@ -13,6 +13,8 @@
#define NUM_LINES 10
#define MAIN_MENU_DISTANCE_FROM_BORDER 2
#define SUMMARY_LINE_MAX_SIZE 18
const char* person_strings[] = {"You", "Other"};
const char* game_strings[] = {"RS", "FRLG", "E"};
const char* unidentified_string = "Unidentified";
@ -25,6 +27,7 @@ const char* target_strings[] = {"Gen 1", "Gen 2", "Gen 3"};
const char* stat_strings[] = {"Hp", "Atk", "Def", "SpA", "SpD", "Spe"};
const char* contest_strings[] = {"Coolness", "Beauty", "Cuteness", "Smartness", "Toughness", "Feel"};
const char* trade_start_state_strings[] = {"Unknown", "Entering Room", "Starting Trade", "Ending Trade", "Waiting Trade", "Trading Party Data", "Synchronizing", "Completed"};
const char* offer_strings[] = {" Sending ", "Receiving"};
const u8 ribbon_print_pos[NUM_LINES*2] = {0,1,2,3,4,5,6,7,8,9,14,15,13,16,10,0xFF,11,0xFF,12,0xFF};
@ -102,7 +105,98 @@ void print_trade_menu(struct game_data_t* game_data, u8 update, u8 curr_gen, u8
PRINT_FUNCTION(" Cancel");
}
void print_offer_screen(struct game_data_t* game_data, u8 own_mon, u8 other_mon) {
default_reset_screen();
init_offer_window();
u8 possible_mons[2] = {own_mon, other_mon};
for(int i = 0; i < 2; i++) {
struct gen3_mon_data_unenc* mon = &game_data[i].party_3_undec[possible_mons[i]];
u8 is_shiny = is_shiny_gen3_raw(mon, 0);
//u8 has_pokerus = has_pokerus_gen3_raw(mon);
//u8 is_jp = mon->src->language == JAPANESE_LANGUAGE;
u8 is_egg = mon->is_egg;
u8 curr_text_y = 0;
set_text_y(curr_text_y++);
set_text_x(3+(OFFER_WINDOW_X*i));
PRINT_FUNCTION("\x01", offer_strings[i]);
load_pokemon_sprite_raw(mon, BASE_Y_SPRITE_OFFER_MENU, (OFFER_WINDOW_X*8*i) + BASE_X_SPRITE_OFFER_MENU);
if(!is_egg) {
set_text_y(curr_text_y++);
set_text_x(4+(OFFER_WINDOW_X*i));
PRINT_FUNCTION("\x01", get_pokemon_name_raw(mon));
set_text_y(curr_text_y++);
set_text_x(4+(OFFER_WINDOW_X*i));
PRINT_FUNCTION("Lv. \x03 \x02", to_valid_level_gen3(mon->src), get_pokemon_gender_char_raw(mon));
if(is_shiny) {
set_text_y(curr_text_y++);
set_text_x(4+(OFFER_WINDOW_X*i));
PRINT_FUNCTION("Shiny");
}
else
curr_text_y++;
set_text_y(curr_text_y++);
set_text_x(OFFER_WINDOW_X*i);
PRINT_FUNCTION("\x01 Nature", get_nature_name(mon->src->pid));
set_text_y(curr_text_y++);
//set_text_x(OFFER_WINDOW_X*i);
//PRINT_FUNCTION("ITEM:");
set_text_y(curr_text_y++);
set_text_x(OFFER_WINDOW_X*i);
if(has_item_raw(mon))
PRINT_FUNCTION("\x01", get_item_name_raw(mon));
else
PRINT_FUNCTION("No Item");
//set_text_y(curr_text_y++);
//set_text_x(OFFER_WINDOW_X*i);
//PRINT_FUNCTION("ABILITY:");
//set_text_y(curr_text_y++);
//set_text_x(OFFER_WINDOW_X*i);
//PRINT_FUNCTION("\x01", get_ability_name_raw(mon));
set_text_y(curr_text_y++);
set_text_x(OFFER_WINDOW_X*i);
//PRINT_FUNCTION("MOVES:");
for(int j = 0; j < MOVES_SIZE; j++) {
set_text_y(curr_text_y++);
set_text_x(OFFER_WINDOW_X*i);
PRINT_FUNCTION("\x01", get_move_name_gen3(&mon->attacks, j));
}
}
else {
curr_text_y++;
set_text_y(curr_text_y++);
set_text_x(4+(OFFER_WINDOW_X*i));
PRINT_FUNCTION("\x01", get_pokemon_name_raw(mon));
}
}
}
void print_offer_options_screen(struct game_data_t* game_data, u8 own_mon, u8 other_mon) {
reset_screen(BLANK_FILL);
init_offer_options_window();
clear_offer_options_window();
set_text_y(OFFER_OPTIONS_WINDOW_Y);
set_text_x(OFFER_OPTIONS_WINDOW_X);
PRINT_FUNCTION("Trade \x01\n", get_pokemon_name_raw(&game_data[0].party_3_undec[own_mon]));
set_text_x(OFFER_OPTIONS_WINDOW_X);
PRINT_FUNCTION("for \x01?\n\n", get_pokemon_name_raw(&game_data[1].party_3_undec[other_mon]));
set_text_x(OFFER_OPTIONS_WINDOW_X+2);
PRINT_FUNCTION("Yes");
set_text_x(OFFER_OPTIONS_WINDOW_X + (OFFER_OPTIONS_WINDOW_X_SIZE - SUMMARY_LINE_MAX_SIZE));
PRINT_FUNCTION("Summary: Sending\n\n");
set_text_x(OFFER_OPTIONS_WINDOW_X+2);
PRINT_FUNCTION("No");
set_text_x(OFFER_OPTIONS_WINDOW_X + (OFFER_OPTIONS_WINDOW_X_SIZE - SUMMARY_LINE_MAX_SIZE));
PRINT_FUNCTION("Summary: Receiving");
}
void print_trade_options(u8 cursor_x_pos){
reset_screen(BLANK_FILL);
init_trade_options_window();
clear_trade_options_window();
set_text_y(TRADE_OPTIONS_WINDOW_Y);
set_text_x(TRADE_OPTIONS_WINDOW_X);
@ -115,6 +209,8 @@ void print_trade_options(u8 cursor_x_pos){
}
void print_waiting(){
reset_screen(BLANK_FILL);
init_waiting_window();
clear_waiting_window();
set_text_y(WAITING_WINDOW_Y);
set_text_x(WAITING_WINDOW_X);

View File

@ -13,6 +13,9 @@
#define BASE_Y_SPRITE_INFO_PAGE 0
#define BASE_X_SPRITE_INFO_PAGE 0
#define BASE_Y_SPRITE_OFFER_MENU 0
#define BASE_X_SPRITE_OFFER_MENU 0
void print_game_info(struct game_data_t*, int);
void print_trade_menu(struct game_data_t*, u8, u8, u8, u8);
void print_pokemon_pages(u8, u8, struct gen3_mon_data_unenc*, u8);
@ -20,6 +23,8 @@ void print_main_menu(u8, u8, u8, u8);
void print_multiboot(enum MULTIBOOT_RESULTS);
void print_start_trade();
void print_waiting();
void print_offer_screen(struct game_data_t*, u8, u8);
void print_offer_options_screen(struct game_data_t*, u8, u8);
void print_trade_options(u8 cursor_x_pos);
#endif

View File

@ -48,6 +48,7 @@
#include "learnset_evos_gen1_bin.h"
#include "learnset_evos_gen2_bin.h"
#include "learnset_evos_gen3_bin.h"
#include "dex_conversion_bin.h"
#define MF_7_1_INDEX 2
#define M_INDEX 1
@ -192,6 +193,21 @@ const u8* get_item_name(int index, u8 is_egg){
return get_table_pointer(item_names_bin, index);
}
u8 has_item_raw(struct gen3_mon_data_unenc* data_src){
if(!data_src->is_valid_gen3)
return 0;
u8 index = data_src->growth.item;
u8 is_egg = data_src->is_egg;
if(is_egg)
return 0;
if((!index) || (index > LAST_VALID_GEN_3_ITEM))
return 0;
return 1;
}
const u8* get_item_name_raw(struct gen3_mon_data_unenc* data_src){
if(!data_src->is_valid_gen3)
return get_item_name(0,0);
@ -325,7 +341,7 @@ void load_pokemon_sprite_raw(struct gen3_mon_data_unenc* data_src, u16 y, u16 x)
if(!data_src->is_valid_gen3)
return;
return load_pokemon_sprite(data_src->growth.species, data_src->src->pid, data_src->is_egg, data_src->deoxys_form, (data_src->growth.item > 0) && (data_src->growth.item <= LAST_VALID_GEN_3_ITEM), y, x);
return load_pokemon_sprite(data_src->growth.species, data_src->src->pid, data_src->is_egg, data_src->deoxys_form, has_item_raw(data_src), y, x);
}
const u8* get_move_name_gen3(struct gen3_mon_attacks* attacks, u8 slot){
@ -506,6 +522,30 @@ u8 is_shiny_gen2_raw(struct gen2_mon_data* src){
return is_shiny_gen2_unfiltered(src->ivs);
}
u8 has_mail(struct gen3_mon* src, struct gen3_mon_growth* growth) {
if(growth->item < INITIAL_MAIL_GEN3 || growth->item > LAST_MAIL_GEN3)
return 0;
if(src->mail_id == GEN3_NO_MAIL)
return 0;
return 1;
}
u8 get_mail_id(struct gen3_mon* src, struct gen3_mon_growth* growth) {
if(!has_mail(src, growth))
return GEN3_NO_MAIL;
return src->mail_id;
}
u8 get_mail_id_raw(struct gen3_mon_data_unenc* data_src) {
return get_mail_id(data_src->src, &data_src->growth);
}
u16 get_dex_index_raw(struct gen3_mon_data_unenc* data_src){
u16* dex_conversion_bin_16 = (u16*)dex_conversion_bin;
u16 mon_index = get_mon_index_raw(data_src);
return dex_conversion_bin_16[mon_index];
}
u8 decrypt_data(struct gen3_mon* src, u32* decrypted_dst) {
// Decrypt the data
u32 key = src->pid ^ src->ot_id;
@ -815,7 +855,7 @@ u8 validate_converting_mon_of_gen3(struct gen3_mon* src, struct gen3_mon_growth*
return 0;
// Item checks
if(growth->item >= INITIAL_MAIL_GEN3 && growth->item <= LAST_MAIL_GEN3)
if(has_mail(src, growth))
return 0;
// Validity checks
@ -1599,7 +1639,7 @@ u8 gen2_to_gen3(struct gen2_mon_data* src, struct gen3_mon_data_unenc* data_dst,
// Set base data
dst->has_species = 1;
dst->pokerus_rem = 0xFF;
dst->mail_id = GEN3_NO_MAIL;
data_dst->is_egg = is_egg;
if(is_jp)
@ -1652,8 +1692,6 @@ u8 gen2_to_gen3(struct gen2_mon_data* src, struct gen3_mon_data_unenc* data_dst,
convert_moves_to_gen3(&data_dst->attacks, &data_dst->growth, src->moves, src->pps, 1);
data_dst->misc.pokerus = src->pokerus;
if(!(data_dst->misc.pokerus & 0xF) && (data_dst->misc.pokerus>>4))
dst->pokerus_rem = 0;
// Special Mew handling
if(data_dst->growth.species == MEW_SPECIES)
@ -1691,7 +1729,7 @@ u8 gen1_to_gen3(struct gen1_mon_data* src, struct gen3_mon_data_unenc* data_dst,
// Set base data
dst->has_species = 1;
dst->pokerus_rem = 0xFF;
dst->mail_id = GEN3_NO_MAIL;
data_dst->is_egg = 0;
if(is_jp)
@ -1738,8 +1776,6 @@ u8 gen1_to_gen3(struct gen1_mon_data* src, struct gen3_mon_data_unenc* data_dst,
convert_moves_to_gen3(&data_dst->attacks, &data_dst->growth, src->moves, src->pps, 1);
data_dst->misc.pokerus = 0;
if(!(data_dst->misc.pokerus & 0xF) && (data_dst->misc.pokerus>>4))
dst->pokerus_rem = 0;
// Special Mew handling
if(data_dst->growth.species == MEW_SPECIES)
@ -1757,6 +1793,18 @@ u8 gen1_to_gen3(struct gen1_mon_data* src, struct gen3_mon_data_unenc* data_dst,
return 1;
}
void clean_mail_gen3(struct mail_gen3* mail, struct gen3_mon* mon){
for(int i = 0; i < MAIL_WORDS_SIZE; i++)
mail->words[i] = 0;
for(int i = 0; i < OT_NAME_GEN3_SIZE+1; i++)
mail->ot_name[i] = GEN3_EOL;
mail->ot_id = 0;
mail->species = BULBASAUR_SPECIES;
mail->item = 0;
mon->mail_id = GEN3_NO_MAIL;
}
u8 trade_evolve(struct gen3_mon* mon, struct gen3_mon_data_unenc* mon_data, u16** learnset_ptr, u8 curr_gen) {
*learnset_ptr = NULL;
const u16* learnsets = (const u16*)learnset_evos_gen3_bin;
@ -1816,4 +1864,4 @@ u8 trade_evolve(struct gen3_mon* mon, struct gen3_mon_data_unenc* mon_data, u16*
}
return 1;
}
}

View File

@ -14,10 +14,14 @@
#define GEN2_STATS_TOTAL 6
#define GEN1_STATS_TOTAL 5
#define NO_DEX_INDEX 0xFFFF
#define GEN3_NO_ITEM 0xFFFF
#define GEN2_NO_ITEM 0xFF
#define GEN2_MAIL 0xFE
#define GEN3_NO_MAIL 0xFF
#define M_GENDER 0
#define F_GENDER 1
#define U_GENDER 2
@ -48,22 +52,24 @@
#define COLOSSEUM_ALT 0x103
#define TRADE_MET 0xFE
#define NIDORAN_M_SPECIES 32
#define BULBASAUR_SPECIES 1
#define NIDORAN_F_SPECIES 29
#define NIDORAN_M_SPECIES 32
#define MR_MIME_SPECIES 122
#define MR_MIME_OLD_NAME_POS 445
#define MEW_SPECIES 151
#define UNOWN_SPECIES 201
#define UNOWN_REAL_NAME_POS 446
#define RAIKOU_SPECIES 243
#define SUICUNE_SPECIES 245
#define DEOXYS_SPECIES 410
#define DEOXYS_FORMS_POS 442
#define MR_MIME_OLD_NAME_POS 445
#define UNOWN_REAL_NAME_POS 446
#define DEOXYS_NORMAL 0
#define DEOXYS_ATK 1
#define DEOXYS_DEF 2
#define DEOXYS_SPE 3
#define DEOXYS_FORMS_POS 442
#define MEW_SPECIES 151
#define RAIKOU_SPECIES 243
#define SUICUNE_SPECIES 245
#define GEN2_DOT 0xE8
#define GEN1_DOT 0xF2
@ -203,7 +209,7 @@ struct gen3_mon {
u32 enc_data[ENC_DATA_SIZE>>2];
u32 status;
u8 level;
u8 pokerus_rem;
u8 mail_id;
u16 curr_hp;
u16 stats[GEN2_STATS_TOTAL];
} __attribute__ ((packed)) __attribute__ ((aligned(4)));
@ -287,6 +293,7 @@ u8 gen1_to_gen3(struct gen1_mon_data*, struct gen3_mon_data_unenc*, u8, u8*, u8*
const u8* get_pokemon_name_raw(struct gen3_mon_data_unenc*);
u16 get_mon_index_raw(struct gen3_mon_data_unenc*);
u8 has_item_raw(struct gen3_mon_data_unenc* data_src);
const u8* get_item_name_raw(struct gen3_mon_data_unenc*);
const u8* get_met_location_name_gen3_raw(struct gen3_mon_data_unenc*);
u8 get_met_level_gen3_raw(struct gen3_mon_data_unenc*);
@ -298,6 +305,8 @@ void load_pokemon_sprite_raw(struct gen3_mon_data_unenc*, u16, u16);
u8 get_pokemon_gender_raw(struct gen3_mon_data_unenc*);
char get_pokemon_gender_char_raw(struct gen3_mon_data_unenc*);
u8 is_shiny_gen3_raw(struct gen3_mon_data_unenc*, u32);
u16 get_dex_index_raw(struct gen3_mon_data_unenc*);
u8 get_mail_id_raw(struct gen3_mon_data_unenc*);
u8 to_valid_level_gen3(struct gen3_mon*);
u16 calc_stats_gen3_raw(struct gen3_mon_data_unenc*, u8);
u8 get_evs_gen3(struct gen3_mon_evs*, u8);
@ -315,6 +324,7 @@ u32 get_level_exp_mon_index(u16, u8);
u8 get_pokemon_gender_gen2(u8, u8, u8, u8);
u8 get_pokemon_gender_kind_gen3(int, u32, u8, u8);
u8 get_pokemon_gender_kind_gen2(u8, u8, u8);
void clean_mail_gen3(struct mail_gen3*, struct gen3_mon* mon);
u8 trade_evolve(struct gen3_mon*, struct gen3_mon_data_unenc*, u16**, u8);
#endif
#endif

View File

@ -16,6 +16,11 @@
#define BASE_X_CURSOR_INCREMENT_TRADE_OPTIONS 120
#define BASE_Y_CURSOR_TRADE_OPTIONS 152
#define BASE_X_CURSOR_OFFER_OPTIONS 10
#define BASE_Y_CURSOR_OFFER_OPTIONS 128
#define BASE_X_CURSOR_INCREMENT_OFFER_OPTIONS 64
#define BASE_Y_CURSOR_INCREMENT_OFFER_OPTIONS 16
void init_sprite_counter();
u8 get_sprite_counter();
void inc_sprite_counter();

View File

@ -25,6 +25,22 @@ void clear_waiting_window() {
reset_window(WAITING_WINDOW_X, WAITING_WINDOW_Y, WAITING_WINDOW_X_SIZE, WAITING_WINDOW_Y_SIZE, WAITING_WINDOW_SCREEN);
}
void init_offer_window() {
create_window(OFFER_WINDOW_X, OFFER_WINDOW_Y, OFFER_WINDOW_X_SIZE, OFFER_WINDOW_Y_SIZE, OFFER_WINDOW_SCREEN);
}
void clear_offer_window() {
reset_window(OFFER_WINDOW_X, OFFER_WINDOW_Y, OFFER_WINDOW_X_SIZE, OFFER_WINDOW_Y_SIZE, OFFER_WINDOW_SCREEN);
}
void init_offer_options_window() {
create_window(OFFER_OPTIONS_WINDOW_X, OFFER_OPTIONS_WINDOW_Y, OFFER_OPTIONS_WINDOW_X_SIZE, OFFER_OPTIONS_WINDOW_Y_SIZE, OFFER_OPTIONS_WINDOW_SCREEN);
}
void clear_offer_options_window() {
reset_window(OFFER_OPTIONS_WINDOW_X, OFFER_OPTIONS_WINDOW_Y, OFFER_OPTIONS_WINDOW_X_SIZE, OFFER_OPTIONS_WINDOW_Y_SIZE, OFFER_OPTIONS_WINDOW_SCREEN);
}
void create_window(u8 x, u8 y, u8 x_size, u8 y_size, u8 screen_num) {
u16* screen = get_screen(screen_num);

View File

@ -7,15 +7,33 @@
#define TRADE_OPTIONS_WINDOW_X_SIZE 0x1E
#define TRADE_OPTIONS_WINDOW_Y_SIZE 1
#define WAITING_WINDOW_SCREEN 2
#define WAITING_WINDOW_SCREEN 3
#define WAITING_WINDOW_X 5
#define WAITING_WINDOW_Y 0x8
#define WAITING_WINDOW_X_SIZE 10
#define WAITING_WINDOW_Y_SIZE 1
#define OFFER_WINDOW_SCREEN 1
#define OFFER_WINDOW_X 15
#define OFFER_WINDOW_Y 0
#define OFFER_WINDOW_X_SIZE (0x1E - OFFER_WINDOW_X)
#define OFFER_WINDOW_Y_SIZE (0x14)
#define OFFER_OPTIONS_WINDOW_SCREEN 2
#define OFFER_OPTIONS_WINDOW_X 1
#define OFFER_OPTIONS_WINDOW_Y 0xD
#define OFFER_OPTIONS_WINDOW_X_SIZE (0x1E - OFFER_OPTIONS_WINDOW_X - 1)
#define OFFER_OPTIONS_WINDOW_Y_SIZE (0x14 - OFFER_OPTIONS_WINDOW_Y - 1)
void init_trade_options_window();
void clear_trade_options_window();
void init_offer_window();
void clear_offer_window();
void init_offer_options_window();
void clear_offer_options_window();
void init_waiting_window();
void clear_waiting_window();