/// Stage 1 midboss /// --------------- #pragma option -zPmain_03 #include "platform.h" #include "pc98.h" #include "master.hpp" #include "th01/math/subpixel.hpp" #include "th04/math/motion.hpp" extern "C" { #include "th04/math/randring.hpp" #include "th04/math/vector.hpp" #include "th04/snd/snd.h" #include "th04/main/homing.hpp" #include "th04/main/phase.hpp" #include "th04/main/playfld.hpp" #include "th04/main/bullet/bullet.hpp" } #include "th04/main/spark.hpp" #include "th04/main/bullet/clearzap.hpp" #include "th04/main/item/item.hpp" #include "th04/main/midboss/midboss.hpp" #include "th04/main/boss/boss.hpp" #include "th04/main/hud/hud.hpp" #include "th05/sprites/main_pat.h" // Constants // --------- static const subpixel_t MIDBOSS1_W = TO_SP(32); static const subpixel_t MIDBOSS1_H = TO_SP(32); static const int HP_TOTAL = 1000; // --------- // State // ----- // Using a boss_statebyte would have been nicer than repurposing *that*... #define bullet_angle boss.angle // MODDERS: Turn into a parameter of midboss1_move(). #define distance_from_center midboss.pos.velocity.x // ----- void near midboss1_move(void) { midboss.pos.prev.x = midboss.pos.cur.x; midboss.pos.prev.y = midboss.pos.cur.y; midboss.pos.cur.x.v = vector1_at( to_sp(playfield_fraction_x(1 / 2.0f)), distance_from_center, CosTable8[midboss.angle] ); midboss.pos.cur.y.v = vector1_at( to_sp(playfield_fraction_y(6 / 23.0f)), distance_from_center, SinTable8[midboss.angle] ); midboss.angle -= 0x02; } void near midboss1_pattern(void) { int interval = 16; if(midboss.hp <= 200) { interval = 12; } if((midboss.phase_frame % interval) == 0) { bullet_template.spawn_type = BST_NORMAL; bullet_template.patnum = 0; bullet_template.speed.set(2.0f); bullet_template.group = BG_SPREAD; bullet_template.special_motion = BSM_EXACT_LINEAR; bullet_template.set_spread(4, 0x02); bullet_template.angle = bullet_angle; bullet_angle += 0x14; bullet_template_tune(); bullets_add_special(); bullet_template.group = BG_SINGLE; bullet_template.spawn_type = BST_CLOUD_FORWARDS; bullet_template.speed.set(1.5f); bullet_template.patnum = PAT_BULLET16_N_BLUE; bullet_template_tune(); bullet_template.angle = randring2_next16(); bullet_template.origin.x.v = vector1_at( midboss.pos.cur.x, MIDBOSS1_W, CosTable8[bullet_template.angle] ); bullet_template.origin.y.v = vector1_at( midboss.pos.cur.y, MIDBOSS1_H, SinTable8[bullet_template.angle] ); bullets_add_regular(); } } #pragma option -a2 void pascal midboss1_update(void) { bullet_template.origin = midboss.pos.cur; midboss.phase_frame++; switch(midboss.phase) { case 0: // Timeout condition if(midboss.phase_frame >= (HUD_HP_FILL_FRAMES + 128)) { midboss.phase++; midboss.phase_frame = 0; midboss.sprite = PAT_MIDBOSS1; } break; case 1: case 2: midboss_hittest_shots_invincible( ((MIDBOSS1_W / 2) - (MIDBOSS1_W / 8)), ((MIDBOSS1_H / 2) - (MIDBOSS1_H / 8)) ); // Timeout condition if(midboss.phase_frame >= 64) { midboss.phase++; midboss.phase_frame = 0; distance_from_center.set(0.0f); bullet_angle = -0x20; } break; case 3: midboss1_pattern(); midboss_hittest_shots( (MIDBOSS1_W - (MIDBOSS1_W / 4)), (MIDBOSS1_H - (MIDBOSS1_H / 4)) ); // Or, alternatively, (((HP_TOTAL - midboss.hp) / HP_TOTAL) * 64.0f). distance_from_center.v = ( ((HP_TOTAL - midboss.hp) * 64lu * SUBPIXEL_FACTOR) / HP_TOTAL ); midboss1_move(); // Timeout condition if(midboss.phase_frame < 1500) { if(midboss.hp > 0) { break; } bullet_zap.active = true; midboss_score_bonus(5); items_add(midboss.pos.cur.x, midboss.pos.cur.y, IT_BIGPOWER); } midboss.phase = PHASE_EXPLODE_BIG; midboss.sprite = PAT_ENEMY_KILL; midboss.phase_frame = 0; sparks_add_circle( midboss.pos.cur.x, midboss.pos.cur.y, (MIDBOSS1_W / 4), 48 ); snd_se_play(12); break; default: midboss_defeat_update(); hud_hp_update_and_render(midboss.hp, HP_TOTAL); return; } hud_hp_update_and_render(midboss.hp, HP_TOTAL); homing_target.x = midboss.pos.cur.x; homing_target.y = midboss.pos.cur.y; }