void player_reload_with_str(object *obj, const char* custom_str) { // Free and reload parser sd_script_free(&obj->animation_state.parser); sd_script_create(&obj->animation_state.parser); int ret; int err_pos; ret = sd_script_decode(&obj->animation_state.parser, custom_str, &err_pos); if(ret != SD_SUCCESS) { PERROR("Decoder error %s at position %d in string \"%s\"", sd_get_error(ret), err_pos, custom_str); } // Set player state player_reset(obj); obj->animation_state.reverse = 0; obj->slide_state.timer = 0; obj->slide_state.vel = vec2f_create(0,0); obj->enemy_slide_state.timer = 0; obj->enemy_slide_state.dest = vec2i_create(0,0); obj->enemy_slide_state.duration = 0; obj->hit_frames = 0; obj->can_hit = 0; }
vec2i spawn_position(int index, int scientist) { switch (index) { case 0: // top left gantry if (scientist) { return vec2i_create(90,80); } switch (rand_int(3)) { case 0: // middle return vec2i_create(90,80); case 1: // left arm return vec2i_create(30,80); case 2: // right arm return vec2i_create(120,80); } case 1: // top right gantry if (scientist) { return vec2i_create(230,80); } switch (rand_int(3)) { case 0: // middle return vec2i_create(230,80); case 1: // left arm return vec2i_create(200,80); case 2: //right arm return vec2i_create(260,80); } case 2: // middle left gantry return vec2i_create(90, 118); case 3: // middle right gantry return vec2i_create(230,118); //return vec2i_create(280,118); // only welder can use the following case 4: // bottom left gantry return vec2i_create(90,150); case 5: // bottom right gantry return vec2i_create(230,150); default: return vec2i_create(160, 200); } }
int vs_create(scene *scene) { // Init local data vs_local *local = malloc(sizeof(vs_local)); scene_set_userdata(scene, local); game_player *player1 = game_state_get_player(scene->gs, 0); game_player *player2 = game_state_get_player(scene->gs, 1); snprintf(local->vs_str, 128, "%s VS. %s", lang_get(20+player1->pilot_id), lang_get(20+player2->pilot_id)); animation *ani; palette *mpal = video_get_base_palette(); palette_set_player_color(mpal, 0, player1->colors[2], 0); palette_set_player_color(mpal, 0, player1->colors[1], 1); palette_set_player_color(mpal, 0, player1->colors[0], 2); palette_set_player_color(mpal, 1, player2->colors[2], 0); palette_set_player_color(mpal, 1, player2->colors[1], 1); palette_set_player_color(mpal, 1, player2->colors[0], 2); video_force_pal_refresh(); // HAR ani = &bk_get_info(&scene->bk_data, 5)->ani; object_create(&local->player1_har, scene->gs, vec2i_create(160,0), vec2f_create(0, 0)); object_set_animation(&local->player1_har, ani); object_select_sprite(&local->player1_har, player1->har_id); object_create(&local->player2_har, scene->gs, vec2i_create(160,0), vec2f_create(0, 0)); object_set_animation(&local->player2_har, ani); object_select_sprite(&local->player2_har, player2->har_id); object_set_direction(&local->player2_har, OBJECT_FACE_LEFT); object_set_pal_offset(&local->player2_har, 48); // PLAYER ani = &bk_get_info(&scene->bk_data, 4)->ani; object_create(&local->player1_portrait, scene->gs, vec2i_create(-10,150), vec2f_create(0, 0)); object_set_animation(&local->player1_portrait, ani); object_select_sprite(&local->player1_portrait, player1->pilot_id); object_create(&local->player2_portrait, scene->gs, vec2i_create(330,150), vec2f_create(0, 0)); object_set_animation(&local->player2_portrait, ani); object_select_sprite(&local->player2_portrait, player2->pilot_id); object_set_direction(&local->player2_portrait, OBJECT_FACE_LEFT); // clone the left side of the background image // Note! We are touching the scene-wide background surface! surface_sub(&scene->bk_data.background, // DST Surface &scene->bk_data.background, // SRC Surface 160, 0, // DST 0, 0, // SRC 160, 200, // Size SUB_METHOD_MIRROR); // Flip the right side horizontally if (player2->selectable) { // player1 gets to choose, start at arena 0 local->arena = 0; } else { // pick a random arena for 1 player mode local->arena = rand_int(5); // srand was done in melee } // Arena if(player2->selectable) { ani = &bk_get_info(&scene->bk_data, 3)->ani; object_create(&local->arena_select, scene->gs, vec2i_create(59,155), vec2f_create(0, 0)); object_set_animation(&local->arena_select, ani); object_select_sprite(&local->arena_select, local->arena); } // SCIENTIST int scientistpos = rand_int(4); vec2i scientistcoord = spawn_position(scientistpos, 1); if (scientistpos % 2) { scientistcoord.x += 50; } else { scientistcoord.x -= 50; } object *o_scientist = malloc(sizeof(object)); ani = &bk_get_info(&scene->bk_data, 8)->ani; object_create(o_scientist, scene->gs, scientistcoord, vec2f_create(0, 0)); object_set_animation(o_scientist, ani); object_select_sprite(o_scientist, 0); object_set_direction(o_scientist, scientistpos % 2 ? OBJECT_FACE_LEFT : OBJECT_FACE_RIGHT); game_state_add_object(scene->gs, o_scientist, RENDER_LAYER_MIDDLE, 0, 0); // WELDER int welderpos = rand_int(6); // welder can't be on the same gantry or the same *side* as the scientist // he also can't be on the same 'level' // but he has 10 possible starting positions while ((welderpos % 2) == (scientistpos % 2) || (scientistpos < 2 && welderpos < 2) || (scientistpos > 1 && welderpos > 1 && welderpos < 4)) { welderpos = rand_int(6); } object *o_welder = malloc(sizeof(object)); ani = &bk_get_info(&scene->bk_data, 7)->ani; object_create(o_welder, scene->gs, spawn_position(welderpos, 0), vec2f_create(0, 0)); object_set_animation(o_welder, ani); object_select_sprite(o_welder, 0); object_set_spawn_cb(o_welder, cb_vs_spawn_object, (void*)scene); object_set_destroy_cb(o_welder, cb_vs_destroy_object, (void*)scene); object_set_direction(o_welder, welderpos % 2 ? OBJECT_FACE_LEFT : OBJECT_FACE_RIGHT); game_state_add_object(scene->gs, o_welder, RENDER_LAYER_MIDDLE, 0, 0); // GANTRIES object *o_gantry_a = malloc(sizeof(object)); ani = &bk_get_info(&scene->bk_data, 11)->ani; object_create(o_gantry_a, scene->gs, vec2i_create(0,0), vec2f_create(0, 0)); object_set_animation(o_gantry_a, ani); object_select_sprite(o_gantry_a, 0); game_state_add_object(scene->gs, o_gantry_a, RENDER_LAYER_TOP, 0, 0); object *o_gantry_b = malloc(sizeof(object)); object_create(o_gantry_b, scene->gs, vec2i_create(320,0), vec2f_create(0, 0)); object_set_animation(o_gantry_b, ani); object_select_sprite(o_gantry_b, 0); object_set_direction(o_gantry_b, OBJECT_FACE_LEFT); game_state_add_object(scene->gs, o_gantry_b, RENDER_LAYER_TOP, 0, 0); // Background tex menu_background2_create(&local->arena_select_bg, 211, 50); // Quit Dialog dialog_create(&local->quit_dialog, DIALOG_STYLE_YES_NO, "ARE YOU SURE YOU WANT TO QUIT THIS GAME?", 72, 60); local->quit_dialog.userdata = scene; local->quit_dialog.clicked = vs_quit_dialog_clicked; // Too Pathetic Dialog char insult[512]; snprintf(insult, 512, lang_get(748), "Veteran", "Major Kreissack"); dialog_create(&local->too_pathetic_dialog, DIALOG_STYLE_OK, insult, 72, 60); local->too_pathetic_dialog.userdata = scene; local->too_pathetic_dialog.clicked = vs_too_pathetic_dialog_clicked; if (player2->pilot_id == 10 && settings_get()->gameplay.difficulty < 2) { // kriessack, but not on Veteran or higher dialog_show(&local->too_pathetic_dialog, 1); } // Callbacks scene_set_render_cb(scene, vs_render); scene_set_render_overlay_cb(scene, vs_render_overlay); scene_set_input_poll_cb(scene, vs_input_tick); scene_set_dynamic_tick_cb(scene, vs_dynamic_tick); scene_set_static_tick_cb(scene, vs_static_tick); scene_set_free_cb(scene, vs_free); // Pick renderer video_select_renderer(VIDEO_RENDERER_HW); return 0; }
void player_run(object *obj) { // Some vars for easier life player_animation_state *state = &obj->animation_state; player_sprite_state *rstate = &obj->sprite_state; if(state->finished) return; // Handle slide operation if(obj->slide_state.timer > 0) { obj->pos.x += obj->slide_state.vel.x; obj->pos.y += obj->slide_state.vel.y; obj->slide_state.timer--; } // Not sure what this does int run_ret; if(state->end_frame == UINT32_MAX) { run_ret = sd_stringparser_run( state->parser, state->ticks - 1); } else { run_ret = sd_stringparser_run_frames( state->parser, state->ticks - 1, state->end_frame); } // Handle frame if(run_ret == 0) { // Handle frame switch sd_stringparser_frame *param = &state->parser->current_frame; sd_stringparser_frame n_param; sd_stringparser_frame *f = param; sd_stringparser_frame *n = &n_param; int real_frame = param->letter - 65; // Do something if animation is finished! if(param->is_animation_end) { if(state->repeat) { player_reset(obj); sd_stringparser_run(state->parser, state->ticks - 1); real_frame = param->letter - 65; } else if(obj->finish != NULL) { obj->cur_sprite = NULL; obj->finish(obj); return; } else { obj->cur_sprite = NULL; state->finished = 1; return; } } // If frame changed, do something if(param->id != state->previous) { player_clear_frame(obj); // Tick management if(isset(f, "d")) { cmd_tickjump(obj, get(f, "d")); sd_stringparser_reset(state->parser); } // Animation management if(isset(f, "m") && state->spawn != NULL) { int mx = isset(f, "mx") ? get(f, "mx") : 0; int my = isset(f, "my") ? get(f, "my") : 0; int mg = isset(f, "mg") ? get(f, "mg") : 0; DEBUG("Spawning %d, with g = %d, pos = (%d,%d)", get(f, "m"), mg, mx, my); state->spawn( obj, get(f, "m"), vec2i_create(mx, my), mg, state->spawn_userdata); } if(isset(f, "md") && state->destroy != NULL) { state->destroy(obj, get(f, "md"), state->destroy_userdata); } // Music playback if(isset(f, "smo")) { cmd_music_on(get(f, "smo")); } if(isset(f, "smf")) { cmd_music_off(); } // Sound playback if(isset(f, "s")) { float pitch = PITCH_DEFAULT; float volume = VOLUME_DEFAULT * (settings_get()->sound.sound_vol/10.0f); float panning = PANNING_DEFAULT; if(isset(f, "sf")) { int p = clamp(get(f, "sf"), -16, 239); pitch = clampf((p/239.0f)*3.0f + 1.0f, PITCH_MIN, PITCH_MAX); } if(isset(f, "l")) { int v = clamp(get(f, "l"), 0, 100); volume = (v / 100.0f) * (settings_get()->sound.sound_vol/10.0f); } if(isset(f, "sb")) { panning = clamp(get(f, "sb"), -100, 100) / 100.0f; } int sound_id = obj->sound_translation_table[get(f, "s")] - 1; sound_play(sound_id, volume, panning, pitch); } // Blend mode stuff if(isset(f, "b1")) { rstate->method_flags &= 0x2000; } if(isset(f, "b2")) { rstate->method_flags &= 0x4000; } if(isset(f, "bb")) { rstate->method_flags &= 0x0010; rstate->blend_finish = get(f, "bb"); } if(isset(f, "be")) { rstate->method_flags &= 0x0800; } if(isset(f, "bf")) { rstate->method_flags &= 0x0001; rstate->blend_finish = get(f, "bf"); } if(isset(f, "bh")) { rstate->method_flags &= 0x0040; } if(isset(f, "bl")) { rstate->method_flags &= 0x0008; rstate->blend_finish = get(f, "bl"); } if(isset(f, "bm")) { rstate->method_flags &= 0x0100; rstate->blend_finish = get(f, "bm"); } if(isset(f, "bj")) { rstate->method_flags &= 0x0400; rstate->blend_finish = get(f, "bj"); } if(isset(f, "bs")) { rstate->blend_start = get(f, "bs"); } if(isset(f, "bu")) { rstate->method_flags &= 0x8000; } if(isset(f, "bw")) { rstate->method_flags &= 0x0080; } if(isset(f, "bx")) { rstate->method_flags &= 0x0002; } // Palette tricks if(isset(f, "bpd")) { rstate->pal_ref_index = get(f, "bpd"); } if(isset(f, "bpn")) { rstate->pal_entry_count = get(f, "bpn"); } if(isset(f, "bps")) { rstate->pal_start_index = get(f, "bps"); } if(isset(f, "bpb")) { rstate->pal_begin = get(f, "bpb"); } if(isset(f, "bpd")) { rstate->pal_end = get(f, "bpd"); } if(isset(f, "bz")) { rstate->pal_tint = get(f, "bz"); } // Handle movement if (isset(f, "v")) { int x = 0, y = 0; if(isset(f, "y-")) { y = get(f, "y-") * -1; } else if(isset(f, "y+")) { y = get(f, "y+"); } if(isset(f, "x-")) { x = get(f, "x-") * -1 * object_get_direction(obj); } else if(isset(f, "x+")) { x = get(f, "x+") * object_get_direction(obj); } if (x || y) { obj->vel.x += x; obj->vel.y += y; } } // handle scaling on the Y axis if(isset(f, "y")) { obj->y_percent = get(f, "y") / 100.0f; } if (isset(f, "e")) { // x,y relative to *enemy's* position int x = 0, y = 0; if(isset(f, "y-")) { y = get(f, "y-") * -1; } else if(isset(f, "y+")) { y = get(f, "y+"); } if(isset(f, "x-")) { x = get(f, "x-") * -1 * object_get_direction(obj); } else if(isset(f, "x+")) { x = get(f, "x+") * object_get_direction(obj); } float x_dist = dist(obj->pos.x, state->enemy_x + x); float y_dist = dist(obj->pos.y, state->enemy_y + y); obj->slide_state.timer = param->duration; obj->slide_state.vel.x = x_dist / (float)param->duration; obj->slide_state.vel.y = y_dist / (float)param->duration; DEBUG("Slide object %d for (x,y) = (%f,%f) for %d ticks.", obj->cur_animation->id, obj->slide_state.vel.x, obj->slide_state.vel.y, param->duration); } if (isset(f, "v") == 0 && isset(f, "e") == 0 && (isset(f, "x+") || isset(f, "y+") || isset(f, "x-") || isset(f, "y-"))) { // check for relative X interleaving int x = 0, y = 0; if(isset(f, "y-")) { y = get(f, "y-") * -1; } else if(isset(f, "y+")) { y = get(f, "y+"); } if(isset(f, "x-")) { x = get(f, "x-") * -1 * object_get_direction(obj); } else if(isset(f, "x+")) { x = get(f, "x+") * object_get_direction(obj); } obj->slide_state.timer = param->duration; obj->slide_state.vel.x = (float)x / (float)param->duration; obj->slide_state.vel.y = (float)y / (float)param->duration; DEBUG("Slide object %d for (x,y) = (%f,%f) for %d ticks.", obj->cur_animation->id, obj->slide_state.vel.x, obj->slide_state.vel.y, param->duration); } // Check if next frame contains X=nnn or Y=nnn if(!param->is_final_frame) { sd_stringparser_peek(state->parser, param->id + 1, &n_param); int slide = 0; float xpos = obj->pos.x; float ypos = obj->pos.y; if(isset(n, "x=") || isset(n, "y=")) { obj->slide_state.vel = vec2f_create(0,0); } if(isset(n, "x=")) { slide = get(n, "x="); if(object_get_direction(obj) == OBJECT_FACE_LEFT) { // if the sprite is flipped horizontally, adjust the X coordinates slide = 320 - slide; } if(slide != xpos) { obj->slide_state.vel.x = dist(xpos, slide) / (float)param->duration; obj->slide_state.timer = param->duration; DEBUG("Slide object %d for X = %f for a total of %d ticks.", obj->cur_animation->id, obj->slide_state.vel.x, param->duration); } } if(isset(n, "y=")) { slide = get(n, "y="); if(slide != ypos) { obj->slide_state.vel.y = dist(ypos, slide) / (float)param->duration; obj->slide_state.timer = param->duration; DEBUG("Slide object %d for Y = %f for a total of %d ticks.", obj->cur_animation->id, obj->slide_state.vel.y, param->duration); } } } // Set render settings if(real_frame < 25) { object_select_sprite(obj, real_frame); if(obj->cur_sprite != NULL) { rstate->duration = param->duration; rstate->blendmode = isset(f, "br") ? BLEND_ADDITIVE : BLEND_ALPHA; if(isset(f, "r")) { rstate->flipmode ^= FLIP_HORIZONTAL; } if(isset(f, "f")) { rstate->flipmode ^= FLIP_VERTICAL; } } } else { obj->cur_sprite = NULL; } } state->previous = param->id; } // Animation ticks if(state->reverse) { state->ticks--; } else { state->ticks++; } // Sprite ticks rstate->timer++; // All done. return; }
// Init mechlab int mechlab_create(scene *scene) { // Alloc mechlab_local *local = malloc(sizeof(mechlab_local)); memset(local, 0, sizeof(mechlab_local)); animation *bg_ani[3]; // Init the background for(int i = 0; i < sizeof(bg_ani)/sizeof(animation*); i++) { sprite *spr = sprite_copy(animation_get_sprite(&bk_get_info(&scene->bk_data, 14)->ani, i)); bg_ani[i] = create_animation_from_single(spr, spr->pos); object_create(&local->bg_obj[i], scene->gs, vec2i_create(0,0), vec2f_create(0,0)); object_set_animation(&local->bg_obj[i], bg_ani[i]); object_select_sprite(&local->bg_obj[i], 0); object_set_repeat(&local->bg_obj[i], 1); object_set_animation_owner(&local->bg_obj[i], OWNER_OBJECT); } // Find last saved game ... game_player *p1 = game_state_get_player(scene->gs, 0); const char* last_name = settings_get()->tournament.last_name; if(last_name == NULL || strlen(last_name) == 0) { last_name = NULL; } // ... and attempt to load it, if one was found. if(last_name != NULL) { int ret = sg_load(&p1->pilot, last_name); if(ret != SD_SUCCESS) { PERROR("Could not load saved game for playername '%s': %s!", last_name, sd_get_error(ret)); last_name = NULL; } else { DEBUG("Loaded savegame for playername '%s'.", last_name); } } // Either initialize a new tournament if no savegame is found, // or just show old savegame stats directly if it was. local->dashtype = DASHBOARD_NONE; if(last_name == NULL) { DEBUG("No previous savegame found"); } else { DEBUG("Previous savegame found; loading as default."); } mechlab_select_dashboard(scene, local, DASHBOARD_STATS); // Create main menu local->frame = guiframe_create(0, 0, 320, 200); guiframe_set_root(local->frame, lab_menu_main_create(scene)); guiframe_layout(local->frame); // Load HAR animation *initial_har_ani = &bk_get_info(&scene->bk_data, 15 + p1->pilot.har_id)->ani; local->mech = malloc(sizeof(object)); object_create(local->mech, scene->gs, vec2i_create(0,0), vec2f_create(0,0)); object_set_animation(local->mech, initial_har_ani); object_set_repeat(local->mech, 1); object_dynamic_tick(local->mech); // Set callbacks scene_set_userdata(scene, local); scene_set_input_poll_cb(scene, mechlab_input_tick); scene_set_event_cb(scene, mechlab_event); scene_set_render_cb(scene, mechlab_render); scene_set_free_cb(scene, mechlab_free); scene_set_dynamic_tick_cb(scene, mechlab_tick); // Pick renderer video_select_renderer(VIDEO_RENDERER_HW); return 0; }
int cutscene_create(scene *scene) { cutscene_local *local = malloc(sizeof(cutscene_local)); game_player *p1 = game_state_get_player(scene->gs, 0); const char *text = ""; switch (scene->id) { case SCENE_END: cutscene_music(PSM_END); text = lang_get(END_TEXT); local->text_x = 10; local->text_y = 5; local->text_width = 300; local->color = COLOR_YELLOW; break; case SCENE_END1: text = lang_get(END1_TEXT+p1->pilot_id); local->text_x = 10; local->text_y = 160; local->text_width = 300; local->color = COLOR_RED; // Pilot face animation *ani = &bk_get_info(&scene->bk_data, 3)->ani; object *obj = malloc(sizeof(object)); object_create(obj, scene->gs, vec2i_create(0,0), vec2f_create(0, 0)); object_set_animation(obj, ani); object_select_sprite(obj, p1->pilot_id); obj->halt=1; game_state_add_object(scene->gs, obj, RENDER_LAYER_TOP); // Face effects ani = &bk_get_info(&scene->bk_data, 10+p1->pilot_id)->ani; obj = malloc(sizeof(object)); object_create(obj, scene->gs, vec2i_create(0,0), vec2f_create(0, 0)); object_set_animation(obj, ani); game_state_add_object(scene->gs, obj, RENDER_LAYER_TOP); break; case SCENE_END2: text = lang_get(END2_TEXT+p1->pilot_id); local->text_x = 10; local->text_y = 160; local->text_width = 300; local->color = COLOR_GREEN; break; } local->len = strlen(text)-1; local->pos = 0; local->text = malloc(strlen(text)+1); strcpy(local->text, text); local->current = local->text; char *p; if ((p = strchr(local->text, '\n'))) { // null out the byte *p = '\0'; } // Callbacks scene_set_userdata(scene, local); scene_set_free_cb(scene, cutscene_free); scene_set_event_cb(scene, cutscene_event); scene_set_startup_cb(scene, cutscene_startup); scene_set_render_overlay_cb(scene, cutscene_render_overlay); // Pick renderer video_select_renderer(VIDEO_RENDERER_HW); return 0; }
void sprite_create(sprite *sp, void *src, int id) { sd_sprite *sdsprite = (sd_sprite*)src; sp->id = id; sp->raw_sprite = (void*)sd_sprite_vga_decode(sdsprite->img); sp->pos = vec2i_create(sdsprite->pos_x, sdsprite->pos_y); }
void player_run(object *obj) { // Some vars for easier life player_animation_state *state = &obj->animation_state; player_sprite_state *rstate = &obj->sprite_state; if(state->finished) return; // Handle slide operation if(obj->slide_state.timer > 0) { obj->pos.x += obj->slide_state.vel.x; obj->pos.y += obj->slide_state.vel.y; obj->slide_state.timer--; } if(obj->enemy_slide_state.timer > 0) { obj->enemy_slide_state.duration++; obj->pos.x = state->enemy->pos.x + obj->enemy_slide_state.dest.x; obj->pos.y = state->enemy->pos.y + obj->enemy_slide_state.dest.y; obj->enemy_slide_state.timer--; } // Not sure what this does const sd_script_frame *frame = sd_script_get_frame_at(&state->parser, state->current_tick); // Animation has ended ? if(frame == NULL) { if(state->repeat) { player_reset(obj); frame = sd_script_get_frame_at(&state->parser, state->current_tick); } else if(obj->finish != NULL) { obj->cur_sprite = NULL; obj->finish(obj); return; } else { obj->cur_sprite = NULL; state->finished = 1; return; } } // Handle frame state->entered_frame = 0; if(frame == NULL) { DEBUG("Something went wery wrong!"); // We shouldn't really get here, unless stringparser messes something up badly } else { // If frame changed, do something if(sd_script_frame_changed(&state->parser, state->previous_tick, state->current_tick)) { state->entered_frame = 1; player_clear_frame(obj); // Tick management if(sd_script_isset(frame, "d")) { if(!obj->animation_state.disable_d) { state->previous_tick = sd_script_get(frame, "d")-1; state->current_tick = sd_script_get(frame, "d"); } } // Hover flag if(sd_script_isset(frame, "h")) { rstate->disable_gravity = 1; } else { rstate->disable_gravity = 0; } if(sd_script_isset(frame, "ua")) { obj->animation_state.enemy->sprite_state.disable_gravity = 1; } // Animation creation command if(sd_script_isset(frame, "m") && state->spawn != NULL) { int mx = 0; if (sd_script_isset(frame, "mrx")) { int mrx = sd_script_get(frame, "mrx"); int mm = sd_script_isset(frame, "mm") ? sd_script_get(frame, "mm") : mrx; mx = random_int(&obj->rand_state, 320 - 2*mm) + mrx; DEBUG("randomized mx as %d", mx); } else if(sd_script_isset(frame, "mx")) { mx = obj->start.x + (sd_script_get(frame, "mx") * object_get_direction(obj)); } int my = 0; if (sd_script_isset(frame, "mry")) { int mry = sd_script_get(frame, "mry"); int mm = sd_script_isset(frame, "mm") ? sd_script_get(frame, "mm") : mry; my = random_int(&obj->rand_state, 320 - 2*mm) + mry; DEBUG("randomized my as %d", my); } else if(sd_script_isset(frame, "my")) { my = obj->start.y + sd_script_get(frame, "my"); } int mg = sd_script_isset(frame, "mg") ? sd_script_get(frame, "mg") : 0; state->spawn( obj, sd_script_get(frame, "m"), vec2i_create(mx, my), mg, state->spawn_userdata); } // Animation deletion if(sd_script_isset(frame, "md") && state->destroy != NULL) { state->destroy(obj, sd_script_get(frame, "md"), state->destroy_userdata); } // Music playback if(sd_script_isset(frame, "smo")) { if(sd_script_get(frame, "smo") == 0) { music_stop(); return; } music_play(PSM_END + (sd_script_get(frame, "smo") - 1)); } if(sd_script_isset(frame, "smf")) { music_stop(); } // Sound playback if(sd_script_isset(frame, "s")) { float pitch = PITCH_DEFAULT; float volume = VOLUME_DEFAULT * (settings_get()->sound.sound_vol/10.0f); float panning = PANNING_DEFAULT; if(sd_script_isset(frame, "sf")) { int p = clamp(sd_script_get(frame, "sf"), -16, 239); pitch = clampf((p/239.0f)*3.0f + 1.0f, PITCH_MIN, PITCH_MAX); } if(sd_script_isset(frame, "l")) { int v = clamp(sd_script_get(frame, "l"), 0, 100); volume = (v / 100.0f) * (settings_get()->sound.sound_vol/10.0f); } if(sd_script_isset(frame, "sb")) { panning = clamp(sd_script_get(frame, "sb"), -100, 100) / 100.0f; } int sound_id = obj->sound_translation_table[sd_script_get(frame, "s")] - 1; sound_play(sound_id, volume, panning, pitch); } // Blend mode stuff if(sd_script_isset(frame, "b1")) { rstate->method_flags &= 0x2000; } if(sd_script_isset(frame, "b2")) { rstate->method_flags &= 0x4000; } if(sd_script_isset(frame, "bb")) { rstate->method_flags &= 0x0010; rstate->blend_finish = sd_script_get(frame, "bb"); rstate->screen_shake_vertical = sd_script_get(frame, "bb"); } if(sd_script_isset(frame, "be")) { rstate->method_flags &= 0x0800; } if(sd_script_isset(frame, "bf")) { rstate->method_flags &= 0x0001; rstate->blend_finish = sd_script_get(frame, "bf"); } if(sd_script_isset(frame, "bh")) { rstate->method_flags &= 0x0040; } if(sd_script_isset(frame, "bl")) { rstate->method_flags &= 0x0008; rstate->blend_finish = sd_script_get(frame, "bl"); rstate->screen_shake_horizontal = sd_script_get(frame, "bl"); } if(sd_script_isset(frame, "bm")) { rstate->method_flags &= 0x0100; rstate->blend_finish = sd_script_get(frame, "bm"); } if(sd_script_isset(frame, "bj")) { rstate->method_flags &= 0x0400; rstate->blend_finish = sd_script_get(frame, "bj"); } if(sd_script_isset(frame, "bs")) { rstate->blend_start = sd_script_get(frame, "bs"); } if(sd_script_isset(frame, "bu")) { rstate->method_flags &= 0x8000; } if(sd_script_isset(frame, "bw")) { rstate->method_flags &= 0x0080; } if(sd_script_isset(frame, "bx")) { rstate->method_flags &= 0x0002; } // Palette tricks if(sd_script_isset(frame, "bpd")) { rstate->pal_ref_index = sd_script_get(frame, "bpd"); } if(sd_script_isset(frame, "bpn")) { rstate->pal_entry_count = sd_script_get(frame, "bpn"); } if(sd_script_isset(frame, "bps")) { rstate->pal_start_index = sd_script_get(frame, "bps"); } if(sd_script_isset(frame, "bpf")) { // Exact values come from master.dat if(game_state_get_player(obj->gs, 0)->har == obj) { rstate->pal_start_index = 1; rstate->pal_entry_count = 47; } else { rstate->pal_start_index = 48; rstate->pal_entry_count = 48; } } if(sd_script_isset(frame, "bpp")) { rstate->pal_end = sd_script_get(frame, "bpp") * 4; rstate->pal_begin = sd_script_get(frame, "bpp") * 4; } if(sd_script_isset(frame, "bpb")) { rstate->pal_begin = sd_script_get(frame, "bpb") * 4; } if(sd_script_isset(frame, "bz")) { rstate->pal_tint = 1; } // The following is a hack. We don't REALLY know what these tags do. // However, they are only used in CREDITS.BK, so we can just interpret // then as we see fit, as long as stuff works. if(sd_script_isset(frame, "bc") && frame->tick_len >= 50) { rstate->blend_start = 0; } else if(sd_script_isset(frame, "bd") && frame->tick_len >= 30) { rstate->blend_finish = 0; } // Handle movement if(sd_script_isset(frame, "ox")) { DEBUG("changing X from %f to %f", obj->pos.x, obj->pos.x+sd_script_get(frame, "ox")); /*obj->pos.x += sd_script_get(frame, "ox");*/ } if(sd_script_isset(frame, "oy")) { DEBUG("changing Y from %f to %f", obj->pos.y, obj->pos.y+sd_script_get(frame, "oy")); /*obj->pos.y += sd_script_get(frame, "oy");*/ } if (sd_script_isset(frame, "bm")) { // hack because we don't have 'walk to other HAR' implemented obj->pos.x = state->enemy->pos.x; obj->pos.y = state->enemy->pos.y; player_next_frame(state->enemy); } if (sd_script_isset(frame, "v")) { int x = 0, y = 0; if(sd_script_isset(frame, "y-")) { y = sd_script_get(frame, "y-") * -1; } else if(sd_script_isset(frame, "y+")) { y = sd_script_get(frame, "y+"); } if(sd_script_isset(frame, "x-")) { x = sd_script_get(frame, "x-") * -1 * object_get_direction(obj); } else if(sd_script_isset(frame, "x+")) { x = sd_script_get(frame, "x+") * object_get_direction(obj); } if (x || y) { DEBUG("x vel %d, y vel %d", x, y); obj->vel.x += x; obj->vel.y += y; } } if (sd_script_isset(frame, "bu") && obj->vel.y < 0.0f) { float x_dist = dist(obj->pos.x, 160); // assume that bu is used in conjunction with 'vy-X' and that we want to land in the center of the arena obj->slide_state.vel.x = x_dist / (obj->vel.y*-2); obj->slide_state.timer = obj->vel.y*-2; } // handle scaling on the Y axis if(sd_script_isset(frame, "y")) { obj->y_percent = sd_script_get(frame, "y") / 100.0f; } if (sd_script_isset(frame, "e")) { // x,y relative to *enemy's* position int x = 0, y = 0; if(sd_script_isset(frame, "y-")) { y = sd_script_get(frame, "y-") * -1; } else if(sd_script_isset(frame, "y+")) { y = sd_script_get(frame, "y+"); } if(sd_script_isset(frame, "x-")) { x = sd_script_get(frame, "x-") * -1 * object_get_direction(obj); } else if(sd_script_isset(frame, "x+")) { x = sd_script_get(frame, "x+") * object_get_direction(obj); } if (x || y) { obj->enemy_slide_state.timer = frame->tick_len; obj->enemy_slide_state.duration = 0; obj->enemy_slide_state.dest.x = x; obj->enemy_slide_state.dest.y = y; /*DEBUG("ENEMY Slide object %d for (x,y) = (%f,%f) for %d ticks. (%d,%d)", obj->cur_animation->id, obj->enemy_slide_state.dest.x, obj->enemy_slide_state.dest.y, param->duration, x, y);*/ } } if (sd_script_isset(frame, "v") == 0 && sd_script_isset(frame, "e") == 0 && (sd_script_isset(frame, "x+") || sd_script_isset(frame, "y+") || sd_script_isset(frame, "x-") || sd_script_isset(frame, "y-"))) { // check for relative X interleaving int x = 0, y = 0; if(sd_script_isset(frame, "y-")) { y = sd_script_get(frame, "y-") * -1; } else if(sd_script_isset(frame, "y+")) { y = sd_script_get(frame, "y+"); } if(sd_script_isset(frame, "x-")) { x = sd_script_get(frame, "x-") * -1 * object_get_direction(obj); } else if(sd_script_isset(frame, "x+")) { x = sd_script_get(frame, "x+") * object_get_direction(obj); } obj->slide_state.timer = frame->tick_len; obj->slide_state.vel.x = (float)x; obj->slide_state.vel.y = (float)y; /*DEBUG("Slide object %d for (x,y) = (%f,%f) for %d ticks.",*/ /*obj->cur_animation->id,*/ /*obj->slide_state.vel.x, */ /*obj->slide_state.vel.y, */ /*param->duration);*/ } if(sd_script_isset(frame, "x=") || sd_script_isset(frame, "y=")) { obj->slide_state.vel = vec2f_create(0,0); } if(sd_script_isset(frame, "x=")) { obj->pos.x = obj->start.x + (sd_script_get(frame, "x=") * object_get_direction(obj)); // Find frame ID by tick int frame_id = sd_script_next_frame_with_tag(&state->parser, "x=", state->current_tick); // Handle it! if(frame_id >= 0) { int mr = sd_script_get_tick_pos_at_frame(&state->parser, frame_id); int r = mr - state->current_tick; int next_x = sd_script_get(sd_script_get_frame(&state->parser, frame_id), "x="); int slide = obj->start.x + (next_x * object_get_direction(obj)); if(slide != obj->pos.x) { obj->slide_state.vel.x = dist(obj->pos.x, slide) / (float)(frame->tick_len + r); obj->slide_state.timer = frame->tick_len + r; /*DEBUG("Slide object %d for X = %f for a total of %d ticks.",*/ /*obj->cur_animation->id,*/ /*obj->slide_state.vel.x,*/ /*param->duration + r);*/ } } } if(sd_script_isset(frame, "y=")) { obj->pos.y = obj->start.y + sd_script_get(frame, "y="); // Find frame ID by tick int frame_id = sd_script_next_frame_with_tag(&state->parser, "y=", state->current_tick); // handle it! if(frame_id >= 0) { int mr = sd_script_get_tick_pos_at_frame(&state->parser, frame_id); int r = mr - state->current_tick; int next_y = sd_script_get(sd_script_get_frame(&state->parser, frame_id), "y="); int slide = next_y + obj->start.y; if(slide != obj->pos.y) { obj->slide_state.vel.y = dist(obj->pos.y, slide) / (float)(frame->tick_len + r); obj->slide_state.timer = frame->tick_len + r; /*DEBUG("Slide object %d for Y = %f for a total of %d ticks.",*/ /*obj->cur_animation->id,*/ /*obj->slide_state.vel.y,*/ /*param->duration + r);*/ } } } if(sd_script_isset(frame, "as")) { // make the object move around the screen in a circular motion until end of frame obj->orbit = 1; } else { obj->orbit = 0; } if(sd_script_isset(frame, "q")) { // Enable hit on the current and the next n-1 frames. obj->hit_frames = sd_script_get(frame, "q"); } if(obj->hit_frames > 0) { obj->can_hit = 1; obj->hit_frames--; } if(sd_script_isset(frame, "at")) { // set the object's X position to be behind the opponent obj->pos.x = obj->animation_state.enemy->pos.x + (15 * object_get_direction(obj)); } if(sd_script_isset(frame, "ar")) { DEBUG("flipping direction %d -> %d", object_get_direction(obj), object_get_direction(obj) *-1); // reverse direction object_set_direction(obj, object_get_direction(obj) * -1); DEBUG("flipping direction now %d", object_get_direction(obj)); } // Set render settings if(frame->sprite < 25) { object_select_sprite(obj, frame->sprite); if(obj->cur_sprite != NULL) { rstate->duration = frame->tick_len; rstate->blendmode = sd_script_isset(frame, "br") ? BLEND_ADDITIVE : BLEND_ALPHA; if(sd_script_isset(frame, "r")) { rstate->flipmode ^= FLIP_HORIZONTAL; } if(sd_script_isset(frame, "f")) { rstate->flipmode ^= FLIP_VERTICAL; } } } else { object_select_sprite(obj, -1); } } } // Animation ticks state->previous_tick = state->current_tick; if(state->reverse) { state->current_tick--; } else { state->current_tick++; } // Sprite ticks rstate->timer++; // All done. return; }
int melee_create(scene *scene) { char bitmap[51*36*4]; // Init local data melee_local *local = malloc(sizeof(melee_local)); memset(local, 0, sizeof(melee_local)); scene_set_userdata(scene, local); game_player *player1 = game_state_get_player(scene->gs, 0); game_player *player2 = game_state_get_player(scene->gs, 1); controller *player1_ctrl = game_player_get_ctrl(player1); controller *player2_ctrl = game_player_get_ctrl(player2); palette *mpal = video_get_base_palette(); palette_set_player_color(mpal, 0, 8, 0); palette_set_player_color(mpal, 0, 8, 1); palette_set_player_color(mpal, 0, 8, 2); video_force_pal_refresh(); memset(&bitmap, 255, 51*36*4); local->ticks = 0; local->pulsedir = 0; local->selection = 0; local->row_a = 0; local->column_a = 0; local->row_b = 0; local->column_b = 4; local->done_a = 0; local->done_b = 0; menu_background2_create(&local->feh, 90, 61); menu_background2_create(&local->bleh, 160, 43); surface_create_from_data(&local->select_hilight, SURFACE_TYPE_RGBA, 51, 36, bitmap); // set up the magic controller hooks if(player1_ctrl && player2_ctrl) { if(player1_ctrl->type == CTRL_TYPE_NETWORK) { controller_add_hook(player2_ctrl, player1_ctrl, player1_ctrl->controller_hook); } if (player2_ctrl->type == CTRL_TYPE_NETWORK) { controller_add_hook(player1_ctrl, player2_ctrl, player2_ctrl->controller_hook); } } animation *ani; sprite *spr; for(int i = 0; i < 10; i++) { ani = &bk_get_info(&scene->bk_data, 3)->ani; object_create(&local->pilots[i], scene->gs, vec2i_create(0,0), vec2f_create(0, 0)); object_set_animation(&local->pilots[i], ani); object_select_sprite(&local->pilots[i], i); ani = &bk_get_info(&scene->bk_data, 18+i)->ani; object_create(&local->har_player1[i], scene->gs, vec2i_create(110,95), vec2f_create(0, 0)); object_set_animation(&local->har_player1[i], ani); object_select_sprite(&local->har_player1[i], 0); object_set_repeat(&local->har_player1[i], 1); int row = i / 5; int col = i % 5; spr = sprite_copy(animation_get_sprite(&bk_get_info(&scene->bk_data, 1)->ani, 0)); mask_sprite(spr->data, 62*col, 42*row, 51, 36); ani = create_animation_from_single(spr, spr->pos); object_create(&local->harportraits_player1[i], scene->gs, vec2i_create(0, 0), vec2f_create(0, 0)); object_set_animation(&local->harportraits_player1[i], ani); object_select_sprite(&local->harportraits_player1[i], 0); object_set_animation_owner(&local->harportraits_player1[i], OWNER_OBJECT); if (player2->selectable) { spr = sprite_copy(animation_get_sprite(&bk_get_info(&scene->bk_data, 1)->ani, 0)); mask_sprite(spr->data, 62*col, 42*row, 51, 36); ani = create_animation_from_single(spr, spr->pos); object_create(&local->harportraits_player2[i], scene->gs, vec2i_create(0, 0), vec2f_create(0, 0)); object_set_animation(&local->harportraits_player2[i], ani); object_select_sprite(&local->harportraits_player2[i], 0); object_set_animation_owner(&local->harportraits_player2[i], OWNER_OBJECT); object_set_pal_offset(&local->harportraits_player2[i], 48); ani = &bk_get_info(&scene->bk_data, 18+i)->ani; object_create(&local->har_player2[i], scene->gs, vec2i_create(210,95), vec2f_create(0, 0)); object_set_animation(&local->har_player2[i], ani); object_select_sprite(&local->har_player2[i], 0); object_set_repeat(&local->har_player2[i], 1); object_set_direction(&local->har_player2[i], OBJECT_FACE_LEFT); object_set_pal_offset(&local->har_player2[i], 48); } } ani = &bk_get_info(&scene->bk_data, 4)->ani; object_create(&local->bigportrait1, scene->gs, vec2i_create(0,0), vec2f_create(0, 0)); object_set_animation(&local->bigportrait1, ani); object_select_sprite(&local->bigportrait1, 0); if (player2->selectable) { object_create(&local->bigportrait2, scene->gs, vec2i_create(320,0), vec2f_create(0, 0)); object_set_animation(&local->bigportrait2, ani); object_select_sprite(&local->bigportrait2, 4); object_set_direction(&local->bigportrait2, OBJECT_FACE_LEFT); } ani = &bk_get_info(&scene->bk_data, 5)->ani; object_create(&local->player2_placeholder, scene->gs, vec2i_create(0,0), vec2f_create(0, 0)); object_set_animation(&local->player2_placeholder, ani); if (player2->selectable) { object_select_sprite(&local->player2_placeholder, 0); } else { object_select_sprite(&local->player2_placeholder, 1); } spr = sprite_copy(animation_get_sprite(&bk_get_info(&scene->bk_data, 1)->ani, 0)); surface_convert_to_rgba(spr->data, video_get_pal_ref(), 0); ani = create_animation_from_single(spr, spr->pos); object_create(&local->unselected_har_portraits, scene->gs, vec2i_create(0,0), vec2f_create(0, 0)); object_set_animation(&local->unselected_har_portraits, ani); object_select_sprite(&local->unselected_har_portraits, 0); object_set_animation_owner(&local->unselected_har_portraits, OWNER_OBJECT); for(int i = 0; i < 2; i++) { local->bar_power[i] = progressbar_create(PROGRESSBAR_THEME_MELEE, PROGRESSBAR_LEFT, 50); local->bar_agility[i] = progressbar_create(PROGRESSBAR_THEME_MELEE, PROGRESSBAR_LEFT, 50); local->bar_endurance[i] = progressbar_create(PROGRESSBAR_THEME_MELEE, PROGRESSBAR_LEFT, 50); } component_layout(local->bar_power[0], 74, 12, 20*4, 8); component_layout(local->bar_agility[0], 74, 30, 20*4, 8); component_layout(local->bar_endurance[0], 74, 48, 20*4, 8); component_layout(local->bar_power[1], 320-66-local->feh.w, 12, 20*4, 8); component_layout(local->bar_agility[1], 320-66-local->feh.w, 30, 20*4, 8); component_layout(local->bar_endurance[1], 320-66-local->feh.w, 48, 20*4, 8); refresh_pilot_stats(local); // initialize nova selection cheat memset(local->har_selected, 0, sizeof(local->har_selected)); memset(local->katana_down_count, 0, sizeof(local->katana_down_count)); // Set callbacks scene_set_input_poll_cb(scene, melee_input_tick); scene_set_render_cb(scene, melee_render); scene_set_free_cb(scene, melee_free); scene_set_dynamic_tick_cb(scene, melee_tick); // Play correct music music_play(PSM_MENU); // Pick renderer video_select_renderer(VIDEO_RENDERER_HW); // All done return 0; }