diff --git a/src/deh_tables.c b/src/deh_tables.c index 9d1e8c638..9603ce86e 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -303,6 +303,9 @@ actionpointer_t actionpointers[] = {{A_SpawnItemDebrisCloud}, "A_SPAWNITEMDEBRISCLOUD"}, {{A_RingShooterFace}, "A_RINGSHOOTERFACE"}, {{A_SpawnSneakerPanel}, "A_SPAWNSNEAKERPANEL"}, + {{A_MakeSSCandle}, "A_MAKESSCANDLE"}, + {{A_HologramRandomTranslucency}, "A_HOLOGRAMRANDOMTRANSLUCENCY"}, + {{A_SSChainShatter}, "A_SSCHAINSHATTER"}, {{NULL}, "NONE"}, @@ -4948,6 +4951,70 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi // MT_WATERFALLPARTICLESPAWNER "S_WATERFALLPARTICLE", + + // Sealed Stars + // MT_SSCANDLE + "S_SSCANDLE_INIT", + "S_SSCANDLE", + + // MT_SSCANDLE_SIDE + "S_SSCANDLE_SIDE", + + // MT_SSCANDLE_FLAME + "S_SSCANDLE_FLAME", + + // MT_SS_HOLOGRAM + "S_HOLOGRAM_BIRD", + "S_HOLOGRAM_CRAB", + "S_HOLOGRAM_FISH", + "S_HOLOGRAM_SQUID", + + // MT_SS_COIN + "S_SS_COIN", + + // MT_SS_GOBLET + "S_SS_GOBLET", + + // MT_SS_LAMP + "S_SS_LAMP", + + // MT_SS_LAMP_BULB + "S_SS_LAMP_BULB", + "S_SS_LAMP_AURA", + + // MT_SSWINDOW + "S_SSWINDOW_INIT", + "S_SSWINDOW", + + // MT_SSWINDOW_SHINE + "S_SSWINDOW_SHINE", + + // MT_SSCHAINSOUND + "S_SSCHAINSOUND", + + // MT_SEALEDSTAR_BUMPER + "S_SEALEDSTAR_BUMPER", + "S_SEALEDSTAR_BUMPERHIT", + + // MT_SSCHAIN_SPAWNER + "S_SSCHAIN_SPAWNER_SHATTER", + + // MT_SSCHAIN + "S_SSCHAIN1", + + // MT_GACHATARGET + "S_GACHATARGET", + "S_GACHATARGETSPIN", + "S_GACHATARGETOK", + + // MT_CABOTRON + "S_CABOTRON", + + // MT_CABOTRONSTAR + "S_CABOTRONSTAR", + + // MT_STARSTREAM + "S_STARSTREAM", }; // RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1", @@ -6232,6 +6299,29 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_TRICKBALLOON_YELLOW_POINT", "MT_WATERFALLPARTICLESPAWNER", + + "MT_SSCANDLE", + "MT_SSCANDLE_SIDE", + "MT_SSCANDLE_FLAME", + "MT_SS_HOLOGRAM", + "MT_SS_HOLOGRAM_ROTATOR", + "MT_SS_COIN", + "MT_SS_COIN_CLOUD", + "MT_SS_GOBLET", + "MT_SS_GOBLET_CLOUD", + "MT_SS_LAMP", + "MT_SS_LAMP_BULB", + "MT_SSWINDOW", + "MT_SSWINDOW_SHINE", + "MT_SSCHAINSOUND", + "MT_SLSTMACE", + "MT_SEALEDSTAR_BUMPER", + "MT_SSCHAIN_SPAWNER", + "MT_SSCHAIN", + "MT_GACHATARGET", + "MT_CABOTRON", + "MT_CABOTRONSTAR", + "MT_STARSTREAM", }; const char *const MOBJFLAG_LIST[] = { diff --git a/src/info.c b/src/info.c index 5d2fb36af..4ed3520e2 100644 --- a/src/info.c +++ b/src/info.c @@ -1037,6 +1037,25 @@ char sprnames[NUMSPRITES + 1][5] = // Waterfall particles "WTRP", + // Sealed Stars + "SCND", + "SCNF", + "SSBI", + "SSCR", + "SSFI", + "SSSQ", + "SSCO", + "SGOB", + "SSLA", + "SWIN", + "SWIS", + "SBMP", + "SSCH", + "GCTA", + "SENB", + "SENC", + "SEAS", + // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later "VIEW", }; @@ -5848,6 +5867,69 @@ state_t states[NUMSTATES] = // MT_WATERFALLPARTICLESPAWNER {SPR_WTRP, FF_ANIMATE, 32, {NULL}, 31, 1, S_NULL}, + + // MT_SSCANDLE + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_SSCANDLE}, // S_SSCANDLE_INIT + {SPR_NULL, 0, -1, {A_MakeSSCandle}, 0, 0, S_SSCANDLE}, // S_SSCANDLE + + // MT_SSCANDLE_SIDE + {SPR_SCND, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_SSCANDLE_SIDE}, // S_SSCANDLE_SIDE + + // MT_SSCANDLE_FLAME + {SPR_SCNF, FF_ANIMATE|FF_FULLBRIGHT|FF_ADD|FF_RANDOMANIM|0, -1, {NULL}, 15, 4, S_SSCANDLE_FLAME}, // S_SSCANDLE_FLAME + + // MT_SS_HOLOGRAM + {SPR_SSBI, FF_PAPERSPRITE|FF_ANIMATE|FF_ADD|0, -1, {A_HologramRandomTranslucency}, 15, 1, S_NULL}, // S_HOLOGRAM_BIRD + {SPR_SSCR, FF_PAPERSPRITE|FF_ANIMATE|FF_ADD|0, -1, {A_HologramRandomTranslucency}, 15, 1, S_NULL}, // S_HOLOGRAM_CRAB + {SPR_SSFI, FF_PAPERSPRITE|FF_ANIMATE|FF_ADD|0, -1, {A_HologramRandomTranslucency}, 15, 1, S_NULL}, // S_HOLOGRAM_FISH + {SPR_SSSQ, FF_PAPERSPRITE|FF_ANIMATE|FF_ADD|0, -1, {A_HologramRandomTranslucency}, 15, 1, S_NULL}, // S_HOLOGRAM_SQUID + + // MT_SS_COIN + {SPR_SSCO, 0, 0, {NULL}, 0, 0, S_NULL}, // S_SS_COIN + + // MT_SS_GOBLET + {SPR_SGOB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SS_GOBLET + + // MT_SS_LAMP + {SPR_SSLA, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SS_LAMP + + // MT_SS_LAMP_BULB + {SPR_SSLA, 1|FF_PAPERSPRITE|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_SS_LAMP_BULB + {SPR_SSLA, 3|FF_ANIMATE|FF_FULLBRIGHT|FF_ADD, -1, {NULL}, 1, 1, S_NULL}, // S_SS_LAMP_AURA + + // MT_SSWINDOW + {SPR_SWIN, FF_PAPERSPRITE|FF_FULLBRIGHT|FF_TRANS30|0, 1, {A_ChangeAngleRelative}, -90, -90, S_SSWINDOW}, // S_SSWINDOW_INIT + {SPR_SWIN, FF_PAPERSPRITE|FF_ANIMATE|FF_FULLBRIGHT|FF_TRANS30|0, -1, {NULL}, 31, 4, S_SSWINDOW}, // S_SSWINDOW + + // MT_SSWINDOW_SHINE + {SPR_SWIS, FF_PAPERSPRITE|FF_ANIMATE|FF_FULLBRIGHT|FF_ADD|FF_RANDOMANIM|0, -1, {NULL}, 31, 3, S_SSWINDOW_SHINE}, // S_SSWINDOW_SHINE + + // MT_SSCHAINSOUND + {SPR_NULL, 0, 16, {A_PlaySound}, sfx_ssthnk, 1, S_SSCHAINSOUND}, // S_SSCHAINSOUND + + // MT_SEALEDSTAR_BUMPER + {SPR_SBMP, 0|FF_FULLBRIGHT, -1, {NULL}, 2, 8, S_SEALEDSTAR_BUMPER}, // S_SEALEDSTAR_BUMPER + {SPR_SBMP, 1|FF_ANIMATE|FF_FULLBRIGHT, 8, {NULL}, 1, 2, S_SEALEDSTAR_BUMPER}, // S_SEALEDSTAR_BUMPERHIT + + // MT_SSCHAIN_SPAWNER + {SPR_NULL, 0, 2, {A_SSChainShatter}, 0, 0, S_NULL}, // S_SSCHAIN_SPAWNER_SHATTER + + // MT_SSCHAIN + {SPR_SSCH, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SSCHAIN1 + + // MT_GACHATARGET + {SPR_GCTA, FF_PAPERSPRITE|FF_FULLBRIGHT|0, -1, {NULL}, 0, 0, S_NULL}, // S_GACHATARGET + {SPR_GCTA, FF_PAPERSPRITE|FF_ANIMATE|FF_FULLBRIGHT|0, 12, {NULL}, 3, 4, S_GACHATARGETOK}, // S_GACHATARGETSPIN + {SPR_GCTA, FF_PAPERSPRITE|FF_FULLBRIGHT|5, -1, {NULL}, 0, 0, S_NULL}, // S_GACHATARGETOK + + // MT_CABOTRON + {SPR_SENB, 0|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_CABOTRON}, // S_CABOTRON + + // MT_CABOTRONSTAR + {SPR_SENC, 0|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_CABOTRONSTAR}, // S_CABOTRONSTAR + + // MT_STARSTREAM + {SPR_SEAS, FF_ANIMATE|0, 30, {NULL}, 29, 1, S_NULL}, // S_STARSTREAM }; mobjinfo_t mobjinfo[NUMMOBJTYPES] = @@ -33553,6 +33635,578 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = MF_NOGRAVITY, // flags S_NULL // raisestate }, + { // MT_SSCANDLE + 3492, // doomednum + S_SSCANDLE_INIT, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 256*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_RUNSPAWNFUNC|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SSCANDLE_SIDE + -1, // doomednum + S_SSCANDLE_SIDE, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 256*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOGRAVITY|MF_NOTHINK, // flags + S_NULL // raisestate + }, + { // MT_SSCANDLE_FLAME + -1, // doomednum + S_SSCANDLE_FLAME, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 32*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SS_HOLOGRAM + 3475, // doomednum + S_HOLOGRAM_CRAB, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 3, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 128*FRACUNIT, // radius + 256*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SS_HOLOGRAM_ROTATOR + 3476, // doomednum + S_INVISIBLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 0, // radius + 0, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SS_COIN + -1, // doomednum + S_SS_COIN, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 18*FRACUNIT, // radius + 37*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SS_COIN_CLOUD + 3474, // doomednum + S_INVISIBLE, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 0, // radius + 0, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SS_GOBLET + -1, // doomednum + S_SS_GOBLET, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 64*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SS_GOBLET_CLOUD + 3478, // doomednum + S_INVISIBLE, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 0, // radius + 0, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SS_LAMP + 3477, // doomednum + S_SS_LAMP, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 12*FRACUNIT, // radius + 369*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DRAWFROMFARAWAY, // flags + S_NULL // raisestate + }, + { // MT_SS_LAMP_BULB + -1, // doomednum + S_SS_LAMP_BULB, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 85*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DRAWFROMFARAWAY, // flags + S_NULL // raisestate + }, + { // MT_SSWINDOW + 3493, // doomednum + S_SSWINDOW_INIT, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 192*FRACUNIT, // radius + 512*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_RUNSPAWNFUNC|MF_NOGRAVITY|MF_NOCLIP, // flags + S_NULL // raisestate + }, + { // MT_SSWINDOW_SHINE + -1, // doomednum + S_SSWINDOW_SHINE, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 192*FRACUNIT, // radius + 512*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOGRAVITY|MF_NOCLIP, // flags + S_NULL // raisestate + }, + { // MT_SSCHAINSOUND + 3494, // doomednum + S_SSCHAINSOUND, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 1*FRACUNIT, // radius + 1*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIP, // flags + S_NULL // raisestate + }, + { // MT_SLSTMACE + -1, // doomednum + S_INVISIBLE, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 1*FRACUNIT, // radius + 1*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + 0, // flags + S_NULL // raisestate + }, + { // MT_SEALEDSTAR_BUMPER + 2461, // doomednum + S_SEALEDSTAR_BUMPER, // spawnstate + 1, // spawnhealth + S_SEALEDSTAR_BUMPERHIT, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_ssbmpr, // deathsound + 0, // speed + 24*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SSCHAIN_SPAWNER + 3479, // doomednum + S_INVISIBLE, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 1*FRACUNIT, // radius + 1*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SSCHAIN + -1, // doomednum + S_SSCHAIN1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 1*FRACUNIT, // radius + 1*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOSQUISH, // flags + S_NULL // raisestate + }, + { // MT_GACHATARGET + 3739, // doomednum + S_GACHATARGET, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_GACHATARGETSPIN, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 32*4*FRACUNIT,// radius + 64*4*FRACUNIT,// height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_ENEMY|MF_SHOOTABLE|MF_NOHITLAGFORME, // flags + S_NULL // raisestate + }, + { // MT_CABOTRON + 3738, // doomednum + S_CABOTRON, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + MT_CABOTRONSTAR, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 2, // speed + 32*FRACUNIT, // radius + 64*FRACUNIT, // height + 0, // dispoffset + 8*FRACUNIT, // mass + 5, // damage + sfx_None, // activesound + MF_SPECIAL|MF_ENEMY|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_CABOTRONSTAR + -1, // doomednum + S_CABOTRONSTAR, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 32*FRACUNIT, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 4*FRACUNIT, // speed + 26*FRACUNIT, // radius + 52*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 8, // damage + sfx_None, // activesound + MF_PAIN|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + { // MT_STARSTREAM + -1, // doomednum + S_STARSTREAM, // spawnstate + 10000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 4*FRACUNIT, // radius + 4*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 8, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, }; diff --git a/src/info.h b/src/info.h index c36ccf111..09f34a692 100644 --- a/src/info.h +++ b/src/info.h @@ -297,6 +297,9 @@ enum actionnum A_RINGSHOOTERFACE, A_SPAWNSNEAKERPANEL, A_BLENDEYEPUYOHACK, + A_MAKESSCANDLE, + A_HOLOGRAMRANDOMTRANSLUCENCY, + A_SSCHAINSHATTER, NUMACTIONS }; @@ -574,6 +577,9 @@ void A_SpawnItemDebrisCloud(); void A_RingShooterFace(); void A_SpawnSneakerPanel(); void A_BlendEyePuyoHack(); +void A_MakeSSCandle(); +void A_HologramRandomTranslucency(); +void A_SSChainShatter(); extern boolean actionsoverridden[NUMACTIONS]; @@ -1591,6 +1597,25 @@ typedef enum sprite // Waterfall particles SPR_WTRP, + // Sealed Stars + SPR_SCND, // Candle + SPR_SCNF, // Candle Flame + SPR_SSBI, // Hologram Bird + SPR_SSCR, // Hologram Crab + SPR_SSFI, // Hologram Fish + SPR_SSSQ, // Hologram Squid + SPR_SSCO, // Coin + SPR_SGOB, // Goblet + SPR_SSLA, // Lamp + SPR_SWIN, // Window + SPR_SWIS, // Window Shine + SPR_SBMP, // Bumper + SPR_SSCH, // Chain + SPR_GCTA, // Gachatarget + SPR_SENB, // Cabotron + SPR_SENC, // Cabotron + SPR_SEAS, // Starstream + // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later SPR_VIEW, @@ -6273,6 +6298,70 @@ typedef enum state // MT_WATERFALLPARTICLESPAWNER S_WATERFALLPARTICLE, + // Sealed Stars + // MT_SSCANDLE + S_SSCANDLE_INIT, + S_SSCANDLE, + + // MT_SSCANDLE_SIDE + S_SSCANDLE_SIDE, + + // MT_SSCANDLE_FLAME + S_SSCANDLE_FLAME, + + // MT_SS_HOLOGRAM + S_HOLOGRAM_BIRD, + S_HOLOGRAM_CRAB, + S_HOLOGRAM_FISH, + S_HOLOGRAM_SQUID, + + // MT_SS_COIN + S_SS_COIN, + + // MT_SS_GOBLET + S_SS_GOBLET, + + // MT_SS_LAMP + S_SS_LAMP, + + // MT_SS_LAMP_BULB + S_SS_LAMP_BULB, + S_SS_LAMP_AURA, + + // MT_SSWINDOW + S_SSWINDOW_INIT, + S_SSWINDOW, + + // MT_SSWINDOW_SHINE + S_SSWINDOW_SHINE, + + // MT_SSCHAINSOUND + S_SSCHAINSOUND, + + // MT_SEALEDSTAR_BUMPER + S_SEALEDSTAR_BUMPER, + S_SEALEDSTAR_BUMPERHIT, + + // MT_SSCHAIN_SPAWNER + S_SSCHAIN_SPAWNER_SHATTER, + + // MT_SSCHAIN + S_SSCHAIN1, + + // MT_GACHATARGET + S_GACHATARGET, + S_GACHATARGETSPIN, + S_GACHATARGETOK, + + // MT_CABOTRON + S_CABOTRON, + + // MT_CABOTRONSTAR + S_CABOTRONSTAR, + + // MT_STARSTREAM + S_STARSTREAM, + S_FIRSTFREESLOT, S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1, NUMSTATES @@ -7579,6 +7668,29 @@ typedef enum mobj_type MT_WATERFALLPARTICLESPAWNER, + MT_SSCANDLE, + MT_SSCANDLE_SIDE, + MT_SSCANDLE_FLAME, + MT_SS_HOLOGRAM, + MT_SS_HOLOGRAM_ROTATOR, + MT_SS_COIN, + MT_SS_COIN_CLOUD, + MT_SS_GOBLET, + MT_SS_GOBLET_CLOUD, + MT_SS_LAMP, + MT_SS_LAMP_BULB, + MT_SSWINDOW, + MT_SSWINDOW_SHINE, + MT_SSCHAINSOUND, + MT_SLSTMACE, + MT_SEALEDSTAR_BUMPER, + MT_SSCHAIN_SPAWNER, + MT_SSCHAIN, + MT_GACHATARGET, + MT_CABOTRON, + MT_CABOTRONSTAR, + MT_STARSTREAM, + MT_FIRSTFREESLOT, MT_LASTFREESLOT = MT_FIRSTFREESLOT + NUMMOBJFREESLOTS - 1, NUMMOBJTYPES diff --git a/src/k_objects.h b/src/k_objects.h index db04e0b8c..48ec573ae 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -369,6 +369,28 @@ void Obj_BulbTouched(mobj_t *special, mobj_t *toucher); /* Waterfall Particles Spawner */ void Obj_WaterfallParticleThink(mobj_t *mo); +/* Sealed Star objects */ +void Obj_SSCandleMobjThink(mobj_t* mo); +void Obj_SSHologramRotatorMapThingSpawn(mobj_t* mo, mapthing_t* mt); +void Obj_SSHologramRotatorMobjThink(mobj_t* mo); +void Obj_SSHologramMobjSpawn(mobj_t* mo); +void Obj_SSHologramMobjFuse(mobj_t* mo); +void Obj_SSHologramMapThingSpawn(mobj_t* mo, mapthing_t* mt); +void Obj_SSCoinCloudMapThingSpawn(mobj_t* mo, mapthing_t* mt); +void Obj_SSCoinMobjThink(mobj_t* mo); +void Obj_SSGobletCloudMapThingSpawn(mobj_t* mo, mapthing_t* mt); +void Obj_SSGobletMobjThink(mobj_t* mo); +void Obj_SSLampMapThingSpawn(mobj_t* mo, mapthing_t* mt); +void Obj_SSWindowMapThingSpawn(mobj_t* mo, mapthing_t* mt); +void Obj_SLSTMaceMobjThink(mobj_t* mo); +void Obj_SSBumperTouchSpecial(mobj_t* special, mobj_t* toucher); +void Obj_SSBumperMobjSpawn(mobj_t* mo); +void Obj_SSChainMobjThink(mobj_t* mo); +void Obj_SSGachaTargetMobjSpawn(mobj_t* mo); +void Obj_SSCabotronMobjSpawn(mobj_t* mo); +void Obj_SSCabotronMobjThink(mobj_t* mo); +void Obj_SSCabotronStarMobjThink(mobj_t* mo); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index b32ae5cec..31c92d74f 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -52,6 +52,7 @@ target_sources(SRB2SDL2 PRIVATE trick-balloon.c cloud.c waterfall-particle.c + sealed-star.c ) add_subdirectory(versus) diff --git a/src/objects/sealed-star.c b/src/objects/sealed-star.c new file mode 100644 index 000000000..bf7b9c342 --- /dev/null +++ b/src/objects/sealed-star.c @@ -0,0 +1,667 @@ +// DR. ROBOTNIK'S RING RACERS +//------------------------------- +// Copyright (C) 2024 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \brief Sealed Star objects + +#include + +#include "../info.h" +#include "../doomdef.h" +#include "../g_game.h" +#include "../p_local.h" +#include "../m_fixed.h" +#include "../m_random.h" +#include "../k_kart.h" +#include "../k_objects.h" +#include "../r_main.h" +#include "../s_sound.h" + +static const INT32 kMinTranslucency = 0; +static const INT32 kMaxTranslucency = 10; + +void Obj_SSCandleMobjThink(mobj_t* mo) +{ + mo->extravalue1 = (mo->extravalue1 + 3) % 360; + mo->z += FSIN(mo->extravalue1 * ANG1) / 4; + if (mo->tracer) + { + mo->tracer->z = mo->z + (256*FRACUNIT); + } +} + +void Obj_SSHologramRotatorMapThingSpawn(mobj_t* mo, mapthing_t* mt) +{ + INT32 numStates = 0; + statenum_t mystates[32] = {0}; + char stringarg[256]; + char *token; + int i; + INT32 speed = 8; + INT32 radius = 256; + INT32 amplitude = mt->thing_args[2]; + INT32 frequency = mt->thing_args[3]; + angle_t angDiff; + mobj_t* part; + fixed_t circumference; + + // This is probably dangerously unsafe but what code written in C isn't + // Christ, parsing strings in C is heinous + // strtok is a nightmare so let's try to avoid that + + if (mt->thing_stringargs[0] == NULL) + { + CONS_Alert(CONS_WARNING, "MT_HOLOGRAM_ROTATOR %d: stringarg 0 is NULL\n", mt->tid); + return; + } + + memset(stringarg, 0, sizeof(stringarg)); + strlcpy(stringarg, mt->thing_stringargs[0], sizeof(stringarg)); + for (i = 0; i < (int)(sizeof(stringarg)); i++) + { + if (stringarg[i] == ' ' || stringarg[i] == ',') + { + stringarg[i] = 0; + } + } + stringarg[sizeof(stringarg) - 1] = 0; + + for (token = stringarg; token < stringarg + sizeof(stringarg) && numStates < 32; ) + { + char *next = token + strlen(token) + 1; + + if (stricmp(token, "bird") == 0) + { + mystates[numStates] = S_HOLOGRAM_BIRD; + numStates += 1; + } + else if (stricmp(token, "fish") == 0) + { + mystates[numStates] = S_HOLOGRAM_FISH; + numStates += 1; + } + else if (stricmp(token, "crab") == 0) + { + mystates[numStates] = S_HOLOGRAM_CRAB; + numStates += 1; + } + else if (stricmp(token, "squid") == 0) + { + mystates[numStates] = S_HOLOGRAM_SQUID; + numStates += 1; + } + + token = next; + } + + if (numStates == 0) + { + CONS_Alert(CONS_WARNING, "MT_HOLOGRAM_ROTATOR %d: stringarg 0 consists exclusively of unrecognised creatures\n", mt->tid); + return; + } + + if (mt->thing_args[0]) + { + speed = mt->thing_args[0]; + } + if (mt->thing_args[1]) + { + radius = mt->thing_args[1]; + } + + // adjust for quarter-scale default + radius *= 4; + amplitude *= 2; + + angDiff = FixedAngle(360 * FRACUNIT/numStates); + part = mo; + circumference = 2 * M_PI_FIXED * radius; + + mo->cusval = abs(speed * mo->scale); + mo->movedir = FixedAngle(FixedDiv(360 * speed * FRACUNIT, circumference)); + mo->movefactor = radius * mo->scale; + + if (amplitude > 0 && frequency > 0) + { + mo->extravalue1 = amplitude * mo->scale; + mo->extravalue2 = frequency * ANG1 / 2; + } + else + { + mo->extravalue1 = 0; + mo->extravalue2 = 0; + } + + for (i = 0; i < numStates; i++) + { + statenum_t thisstate = mystates[i]; + P_SetTarget(&part->hnext, P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_SS_HOLOGRAM)); + P_SetTarget(&part->hnext->hprev, part); + part = part->hnext; + P_SetTarget(&part->target, mo); + P_SetMobjState(part, thisstate); + part->angle = angDiff * i; + if (speed < 0) + { + part->renderflags ^= RF_HORIZONTALFLIP; + } + } +} + +void Obj_SSHologramRotatorMobjThink(mobj_t* mo) +{ + mobj_t* part = mo; + + while (part->hnext) + { + fixed_t oldZ, z; + + part = part->hnext; + oldZ = part->z; + + if (mo->extravalue1) + { + z = mo->z + mo->extravalue1 + FixedMul(mo->extravalue1, FSIN(mo->extravalue2 * (part->extravalue2 + leveltime))); + } + else + { + z = oldZ; + } + + part->angle += mo->movedir; + P_MoveOrigin( + part, + mo->x + FixedMul(mo->movefactor, FCOS(part->angle - ANGLE_90)), + mo->y + FixedMul(mo->movefactor, FSIN(part->angle - ANGLE_90)), + z + ); + + part->rollangle = R_PointToAngle2(0, 0, mo->cusval, z - oldZ); + } +} + +void Obj_SSHologramMobjSpawn(mobj_t* mo) +{ + mo->fuse = mo->reactiontime; + mo->threshold = -1 + P_RandomKey(PR_UNDEFINED, 2) * 2; + mo->extravalue2 = P_RandomFixed(PR_UNDEFINED); +} + +void Obj_SSHologramMapThingSpawn(mobj_t* mo, mapthing_t* mt) +{ + char* stringarg0 = mt->thing_stringargs[0]; + + if (stringarg0 == NULL) + { + P_SetMobjState(mo, S_HOLOGRAM_CRAB); + } + else if (stricmp(stringarg0, "bird")) + { + P_SetMobjState(mo, S_HOLOGRAM_BIRD); + } + else if (stricmp(stringarg0, "crab") == 0) + { + P_SetMobjState(mo, S_HOLOGRAM_CRAB); + } + else if (stricmp(stringarg0, "fish") == 0) + { + P_SetMobjState(mo, S_HOLOGRAM_FISH); + } + else if (stricmp(stringarg0, "squid") == 0) + { + P_SetMobjState(mo, S_HOLOGRAM_SQUID); + } + + if (mt->thing_args[0]) + { + mo->renderflags ^= RF_HORIZONTALFLIP; + } +} + +void Obj_SSHologramMobjFuse(mobj_t* mo) +{ + INT32 trans = (mo->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; + + if (trans >= kMaxTranslucency) + { + mo->threshold = -1; + } + else if (trans <= kMinTranslucency) + { + mo->threshold = 1; + } + + trans += mo->threshold; + mo->frame = (mo->frame & ~FF_TRANSMASK) | (trans << FF_TRANSSHIFT); + + if (trans >= kMaxTranslucency) + { + mo->fuse = 24; + } + else + { + mo->fuse = mo->reactiontime; + } +} + +static struct { + INT32 t; + INT32 x; + INT32 y; + INT32 z; + INT32 w; + INT32 xx; + INT32 yy; + INT32 zz; + INT32 ww; +} srng_state = {0, 5197528, 3154710, 9406548, 1028369, 0, 0, 0, 0}; + +static void set_srng_seed(INT32 seed) +{ + srng_state.t = seed; + srng_state.xx = srng_state.x; + srng_state.yy = srng_state.y; + srng_state.zz = srng_state.z; + srng_state.ww = srng_state.w; +} + +static INT32 srng_random(void) +{ + srng_state.xx = srng_state.yy; + srng_state.yy = srng_state.zz; + srng_state.zz = srng_state.ww; + srng_state.ww = srng_state.ww ^ (srng_state.ww >> 19) ^ srng_state.t ^ (srng_state.t >> 8); + srng_state.t = srng_state.xx ^ (srng_state.xx << 11); + return srng_state.ww; +} + +static INT32 srng_RandomRange(INT32 a, INT32 b) +{ + return a + abs(srng_random() % (b - a + 1)); +} + +static fixed_t srng_RandomFixed(void) +{ + return (fixed_t)(srng_RandomRange(0, FRACUNIT)); +} + +static boolean srng_RandomChance(INT32 chance) +{ + return srng_RandomFixed() < chance; +} + +// spinning-related values +#define COIN_FRAMES (4) // number of frames the coin has +#define MIN_SPIN_TICS (3) // fastest speed with which a coin can animate +#define MAX_SPIN_TICS (10) // slowest speed with which a coin can animate + +// spawning-related values +#define SPAWNS_PER_MAPTHINGS (10) // number of coins to spawn per spawner +#define COIN_SCALE (2*FRACUNIT) // upscales coins by this factor +#define SPAWN_RANGE (256*FRACUNIT*4) // cubed range over which coins should spawn +#define MIN_SPACING (64*FRACUNIT*4) // minimum spherical space between each coin +// IMPORTANT not to make the spacing too large relative to the spawn range, or spawn attempts could potentially escalate and impact load times or even cause a softlock + +// eidolon hardcoder note: this should probably have been implemented +// with a statistical distribution instead of a linear search, +// but this was hardcoded to copy the exact behavior of the Lua + +static boolean cloud_CheckDistribution(mobj_t **coins, INT32 coin_count, fixed_t x, fixed_t y, fixed_t z, fixed_t scale) +{ + fixed_t spacing = FixedMul(MIN_SPACING, scale); + int i; + x = FixedMul(x, scale); + y = FixedMul(y, scale); + z = FixedMul(z, scale); + + for (i = 0; i < coin_count; i++) + { + mobj_t *coin = coins[i]; + if (FixedHypot(FixedHypot(coin->x - x, coin->y - y), coin->z - z) < spacing) + { + return false; + } + } + + return true; +} + +static void CoinCloudSpawn(mobj_t *mo, INT32 seed, mobjtype_t ty) +{ + fixed_t x, y, z; + mobj_t *coins[SPAWNS_PER_MAPTHINGS]; + mobj_t *coin; + int i; + + set_srng_seed(seed); + for (i = 0; i < SPAWNS_PER_MAPTHINGS; i++) + { + // as mentioned... this is a really goofy way to implement a statistical distribution + do { + x = FixedMul(SPAWN_RANGE, srng_RandomFixed()) - (SPAWN_RANGE >> 1); + y = FixedMul(SPAWN_RANGE, srng_RandomFixed()) - (SPAWN_RANGE >> 1); + z = FixedMul(SPAWN_RANGE, srng_RandomFixed()); + } while (!cloud_CheckDistribution(coins, i, x, y, z, mo->scale)); + + coin = P_SpawnMobjFromMobj(mo, x, y, z, ty); + coin->scale = coin->destscale = FixedMul(coin->scale, COIN_SCALE); + + // initial angle & frame + coin->angle = FixedAngle(360 * srng_RandomFixed()); + coin->frame = (coin->frame & ~FF_FRAMEMASK) | srng_RandomRange(0, COIN_FRAMES - 1); + + // random animation speed + coin->extravalue1 = srng_RandomRange(MIN_SPIN_TICS, MAX_SPIN_TICS); + coin->extravalue2 = coin->extravalue1; + + coins[i] = coin; + } +} + +void Obj_SSCoinCloudMapThingSpawn(mobj_t* mo, mapthing_t* mt) +{ + CoinCloudSpawn(mo, mt->thing_args[0], MT_SS_COIN); +} + +void Obj_SSCoinMobjThink(mobj_t* mo) +{ + mo->extravalue2 -= 1; + if (mo->extravalue2 <= 0) + { + mo->extravalue2 = mo->extravalue1; + mo->frame = (mo->frame & ~FF_FRAMEMASK) | ((mo->frame + 1) % COIN_FRAMES); + } +} + +// spinning-related values +#define GOBLET_FRAMES (8) // number of frames the goblet has +#define MIN_VERTICAL_SPIN_TICS (3) // fastest speed with which a goblet can animate (frame) +#define MAX_VERTICAL_SPIN_TICS (10) // slowest speed with which a goblet can animate (frame) +#define MIN_HORIZONTAL_SPIN_SPEED (ANG1 * 1) // slowest speed with which a goblet can rotate (angle) +#define MAX_HORIZONTAL_SPIN_SPEED (ANG1 * 3) // fastest speed with which a goblet can rotate (angle) + +// spawning-related values +#define GOBLET_SPAWNS_PER_MAPTHING (5) // number of goblets to spawn per spawner +#define GOBLET_SCALE (2*FRACUNIT) // upscales goblets by this factor +#define GOBLET_SPAWN_RANGE (256*FRACUNIT*4) // cubed range over which goblets should spawn +#define GOBLET_MIN_SPACING (64*FRACUNIT*4) // minimum spherical space between each goblet +// IMPORTANT not to make the spacing too large relative to the spawn range, or spawn attempts could potentially escalate and impact load times or even cause a softlock + +#define GOBLET_SEED_OFFSET (1267491679) // I'm setting a garbage seed offset here so that seed 0 clouds are markedly different to their coin counterparts + +static void GobletCloudSpawn(mobj_t *mo, INT32 seed, mobjtype_t ty) +{ + fixed_t x, y, z; + mobj_t *coins[GOBLET_SPAWNS_PER_MAPTHING]; + mobj_t *coin; + int i; + + set_srng_seed(seed + GOBLET_SEED_OFFSET); + for (i = 0; i < GOBLET_SPAWNS_PER_MAPTHING; i++) + { + // as mentioned... this is a really goofy way to implement a statistical distribution + do { + x = FixedMul(GOBLET_SPAWN_RANGE, srng_RandomFixed()) - (GOBLET_SPAWN_RANGE >> 1); + y = FixedMul(GOBLET_SPAWN_RANGE, srng_RandomFixed()) - (GOBLET_SPAWN_RANGE >> 1); + z = FixedMul(GOBLET_SPAWN_RANGE, srng_RandomFixed()); + } while (!cloud_CheckDistribution(coins, i, x, y, z, mo->scale)); + + coin = P_SpawnMobjFromMobj(mo, x, y, z, ty); + coin->scale = coin->destscale = FixedMul(coin->scale, GOBLET_SCALE); + + // initial angle & frame + coin->angle = FixedAngle(360 * srng_RandomFixed()); + coin->frame = (coin->frame & ~FF_FRAMEMASK) | srng_RandomRange(0, GOBLET_FRAMES - 1); + + // random animation speed + coin->extravalue1 = srng_RandomRange(MIN_VERTICAL_SPIN_TICS, MAX_VERTICAL_SPIN_TICS); + coin->extravalue2 = coin->extravalue1; + + // random angle speed + coin->movedir = MIN_HORIZONTAL_SPIN_SPEED + FixedMul(srng_RandomFixed(), MAX_HORIZONTAL_SPIN_SPEED - MIN_HORIZONTAL_SPIN_SPEED); + if (srng_RandomChance(FRACUNIT/2)) + { + coin->movedir = -coin->movedir; + } + + coins[i] = coin; + } +} + +void Obj_SSGobletCloudMapThingSpawn(mobj_t* mo, mapthing_t* mt) +{ + GobletCloudSpawn(mo, mt->thing_args[0], MT_SS_GOBLET); +} + +void Obj_SSGobletMobjThink(mobj_t* mo) +{ + mo->angle += mo->movedir; + mo->extravalue2 -= 1; + if (mo->extravalue2 <= 0) + { + mo->extravalue2 = mo->extravalue1; + mo->frame = (mo->frame & ~FF_FRAMEMASK) | ((mo->frame + 1) % GOBLET_FRAMES); + } +} + +#define LAMP_SCALE (4 * FRACUNIT) +#define BULB_HORIZONTAL_OFFSET (124 * FRACUNIT) +#define BULB_VERTICAL_OFFSET (243 * FRACUNIT) + +void Obj_SSLampMapThingSpawn(mobj_t* mo, mapthing_t* mt) +{ + int i; + angle_t angle = FixedAngle(mt->angle * FRACUNIT); + fixed_t bulbX = FixedMul(BULB_HORIZONTAL_OFFSET, FCOS(angle)); + fixed_t bulbY = FixedMul(BULB_HORIZONTAL_OFFSET, FSIN(angle)); + mobj_t *core, *part; + + mo->scale = mo->destscale = FixedMul(mo->scale, LAMP_SCALE); + + // INVISIBLE (BUT RENDERERED) CORE + // we need this because linkdrawing to a papersprite results in all linked mobjs becoming invisible when the papersprite is viewed parallel to its angle + core = P_SpawnMobjFromMobj(mo, bulbX, bulbY, BULB_VERTICAL_OFFSET, MT_SS_LAMP_BULB); + P_SetTarget(&core->tracer, mo); + P_SetMobjState(core, S_SHADOW); + + // parallel bulb + part = P_SpawnMobjFromMobj(core, 0, 0, 0, MT_SS_LAMP_BULB); + part->angle = angle; + part->flags2 |= MF2_LINKDRAW; + P_SetTarget(&part->tracer, core); + + // perpendicular bulb (as 2 minecraft cross parts) + angle += ANGLE_90; + bulbX = FixedMul(core->info->radius, FCOS(angle)); + bulbY = FixedMul(core->info->radius, FSIN(angle)); + part = core; + for (i = 0; i < 1; i++) + { + P_SetTarget(&part->hnext, P_SpawnMobjFromMobj(core, bulbX, bulbY, 0, MT_SS_LAMP_BULB)); + P_SetTarget(&part->hnext->hprev, part); + part = part->hnext; + part->angle = angle; + part->frame = (part->frame & ~FF_FRAMEMASK) | 2; + + part->flags2 |= MF2_LINKDRAW; + P_SetTarget(&part->tracer, core); + part->dispoffset = 1; + angle += ANGLE_180; + bulbX = -bulbX; + bulbY = -bulbY; + } + + // aura + part = P_SpawnMobjFromMobj(core, 0, 0, 0, MT_SS_LAMP_BULB); + P_SetMobjState(part, S_SS_LAMP_AURA); + part->dispoffset -= 1; +} + +void Obj_SSWindowMapThingSpawn(mobj_t* mo, mapthing_t* mt) +{ + angle_t angle; + fixed_t co, si, x, y, xofs, yofs; + mobj_t *shinel, *shinem, *shiner; + + mo->scale = mo->destscale = FRACUNIT; + angle = FixedAngle(mt->angle * FRACUNIT); + + co = FCOS(angle); + si = FSIN(angle); + + x = 192 * co; + y = 192 * si; + + xofs = 128 * si; + yofs = -128 * co; + + shinel = P_SpawnMobjFromMobj(mo, x + xofs, y + yofs, 0, MT_SSWINDOW_SHINE); + shinem = P_SpawnMobjFromMobj(mo, x, y, 64*FRACUNIT, MT_SSWINDOW_SHINE); + shiner = P_SpawnMobjFromMobj(mo, x - xofs, y - yofs, 0, MT_SSWINDOW_SHINE); + + shinel->angle = angle; + shinem->angle = angle; + shiner->angle = angle; + + shinel->scale = mo->destscale = FRACUNIT; + shinem->scale = mo->destscale = FRACUNIT; + shiner->scale = mo->destscale = FRACUNIT; +} + +void Obj_SLSTMaceMobjThink(mobj_t* mo) +{ + if (leveltime % 2 == 0) + { + var1 = 9; + var2 = 0; + A_GhostMe(mo); + } +} + +#define BUMPER_STRENGTH (56) + +void Obj_SSBumperTouchSpecial(mobj_t* special, mobj_t* toucher) +{ + angle_t hang; + angle_t vang; + fixed_t str; + int i; + + hang = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y); + vang = 0; + + if (P_IsObjectOnGround(toucher) == false) + { + vang = R_PointToAngle2( + FixedHypot(special->x, special->y), special->z + (special->height >> 1), + FixedHypot(toucher->x, toucher->y), toucher->z + (toucher->height >> 1) + ); + } + + str = (BUMPER_STRENGTH * special->scale) >> 1; + + toucher->momx = FixedMul(FixedMul(str, FCOS(hang)), abs(FCOS(vang))); + toucher->momy = FixedMul(FixedMul(str, FSIN(hang)), abs(FCOS(vang))); + toucher->momz = FixedMul(str, FSIN(vang)); + + if (toucher->player) + { + if (toucher->player->tiregrease == 0) + { + for (i = 0; i < 2; i++) + { + mobj_t *grease = P_SpawnMobjFromMobj(toucher, 0, 0, 0, MT_TIREGREASE); + P_SetTarget(&grease->target, toucher); + grease->angle = toucher->angle; + grease->extravalue1 = i; + } + } + + if (toucher->player->tiregrease < 2*TICRATE) // greasetics + { + toucher->player->tiregrease = 2*TICRATE; + } + } + + if (special->state != &states[special->info->seestate]) + { + S_StartSound(special, special->info->deathsound); + P_SetMobjState(special, special->info->seestate); + } +} + +void Obj_SSBumperMobjSpawn(mobj_t* mo) +{ + mo->shadowscale = FRACUNIT; + mo->destscale <<= 1; + P_SetScale(mo, mo->destscale); +} + +void Obj_SSChainMobjThink(mobj_t* mo) +{ + mo->angle += ANGLE_22h; + + if (mo->momx == 0 && P_IsObjectOnGround(mo)) + { + P_RemoveMobj(mo); + } +} + +void Obj_SSGachaTargetMobjSpawn(mobj_t* mo) +{ + mo->scale *= 4; + mo->destscale = mo->scale; +} + +void Obj_SSCabotronMobjSpawn(mobj_t* mo) +{ + int i; + mobj_t *ball; + + for (i = 0; i < 4; i++) + { + ball = P_SpawnMobj(mo->x, mo->y, mo->z, MT_CABOTRONSTAR); + ball->destscale = mo->scale; + P_SetScale(ball, mo->scale); + P_SetTarget(&ball->target, mo); + + ball->movedir = FixedAngle(FixedMul(FixedDiv(i<threshold = ball->radius + mo->radius + FixedMul(11*FRACUNIT, ball->scale); + } + + mo->scale *= 2; + mo->destscale = mo->scale; +} + +void Obj_SSCabotronMobjThink(mobj_t* mo) +{ + angle_t xdir = FSIN(mo->angle - ANGLE_90); + angle_t ydir = FCOS(mo->angle + ANGLE_90); + boolean didMove; + + didMove = P_TryMove(mo, mo->x - (xdir * mo->info->speed), mo->y - (ydir * mo->info->speed), false, NULL); + if (!didMove) + { + // --print("Flipping sawblade") + mo->angle += ANGLE_180; + } +} + +void Obj_SSCabotronStarMobjThink(mobj_t* mo) +{ + if (mo->target) + { + // "but ang just call the action in the soc :))))" + var1 = 0; + var2 = 0; + A_UnidusBall(mo); + // how about no because for some reason it will call the func ONCE and never again in its pitiful aimless life + + // and let's just hack FF_ANIMATE too shall we; since var1 is being used to make sure the fucking balls don't fly off the handle which means frame anims can't be handled by the soc + // this game is popsicle sticks and i am out of glue. + } +} diff --git a/src/p_enemy.c b/src/p_enemy.c index 649f683e0..f5efa02bb 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -329,6 +329,9 @@ void A_SpawnItemDebrisCloud(mobj_t *actor); void A_RingShooterFace(mobj_t *actor); void A_SpawnSneakerPanel(mobj_t *actor); void A_BlendEyePuyoHack(mobj_t *actor); +void A_MakeSSCandle(mobj_t *actor); +void A_HologramRandomTranslucency(mobj_t *actor); +void A_SSChainShatter(mobj_t *actor); //for p_enemy.c @@ -3819,7 +3822,7 @@ void A_AttractChase(mobj_t *actor) // Base add is 3 tics for 9,9, adds 1 tic for each point closer to the 1,1 end actor->target->player->ringboost += K_GetKartRingPower(actor->target->player, true) + 3; - + S_ReducedVFXSoundAtVolume(actor->target, sfx_s1b5, actor->target->player->ringvolume, NULL); actor->target->player->ringvolume -= RINGVOLUMEUSEPENALTY; @@ -13801,3 +13804,56 @@ void A_BlendEyePuyoHack(mobj_t *actor) actor->frame = 7; } } + +void A_MakeSSCandle(mobj_t* actor) +{ + int i; + + fixed_t dist = ((4 * actor->scale * 6) * 4) + (7 * FRACUNIT) / 2; + + // Flame + mobj_t* fire = P_SpawnMobjFromMobj(actor, 0, 0, (256 * FRACUNIT) * 4, MT_SSCANDLE_FLAME); + fire->scale = fire->destscale = FRACUNIT; + P_SetTarget(&actor->tracer, fire); + + // Sides + for (i = 0; i < 5; i++) + { + fixed_t a = FixedAngle(60 * FRACUNIT) * i; + fixed_t offsetx = actor->x + FixedMul(dist, FCOS(a)); + fixed_t offsety = actor->y + FixedMul(dist, FSIN(a)); + + mobj_t* side = P_SpawnMobj(offsetx, offsety, actor->z, MT_SSCANDLE_SIDE); + side->angle = a + FixedAngle(90 * FRACUNIT); + side->scale = side->destscale = FRACUNIT; + } +} + +void A_HologramRandomTranslucency(mobj_t* actor) +{ + actor->frame = (actor->frame & ~FF_TRANSMASK) | (P_RandomRange(PR_UNDEFINED, 0, 10) << FF_TRANSSHIFT); +} + +static void A_SSChainShatter_link(mobj_t* actor, angle_t angle) +{ + mobj_t *x; + + x = P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_SSCHAIN); + + P_InstaThrust(x, angle, 20 * mapobjectscale); + x->momx = 10 * mapobjectscale * P_MobjFlip(x); +} + +void A_SSChainShatter(mobj_t* actor) +{ + angle_t angle = P_RandomKey(PR_UNDEFINED, 360) * ANG1; + + actor->scale *= 4; + + A_SSChainShatter_link(actor, angle); + A_SSChainShatter_link(actor, angle + ANGLE_180); + + S_StartSound(NULL, sfx_chcrun); + + actor->fuse = 1; +} diff --git a/src/p_inter.c b/src/p_inter.c index 2b413dd3e..7655d8d3d 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1031,6 +1031,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) Obj_TrickBalloonTouchSpecial(special, toucher); return; + case MT_SEALEDSTAR_BUMPER: + Obj_SSBumperTouchSpecial(special, toucher); + return; + default: // SOC or script pickup P_SetTarget(&special->target, toucher); break; diff --git a/src/p_mobj.c b/src/p_mobj.c index 0e5dc14bf..b6990759c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6933,6 +6933,38 @@ static void P_MobjSceneryThink(mobj_t *mobj) Obj_EMZRainGenerator(mobj); return; } + case MT_SSCANDLE: + { + Obj_SSCandleMobjThink(mobj); + return; + } + case MT_SS_HOLOGRAM_ROTATOR: + { + Obj_SSHologramRotatorMobjThink(mobj); + return; + } + case MT_SS_HOLOGRAM: + { + if (mobj->fuse) + { + mobj->fuse--; + } + if (!mobj->fuse) + { + Obj_SSHologramMobjFuse(mobj); + } + return; + } + case MT_SS_COIN: + { + Obj_SSCoinMobjThink(mobj); + return; + } + case MT_SS_GOBLET: + { + Obj_SSGobletMobjThink(mobj); + return; + } case MT_VWREF: case MT_VWREB: { @@ -10358,6 +10390,30 @@ static boolean P_MobjRegularThink(mobj_t *mobj) break; } + case MT_SLSTMACE: + { + Obj_SLSTMaceMobjThink(mobj); + break; + } + + case MT_SSCHAIN: + { + Obj_SSChainMobjThink(mobj); + break; + } + + case MT_CABOTRON: + { + Obj_SSCabotronMobjThink(mobj); + break; + } + + case MT_CABOTRONSTAR: + { + Obj_SSCabotronStarMobjThink(mobj); + break; + } + default: // check mobj against possible water content, before movement code P_MobjCheckWater(mobj); @@ -11880,6 +11936,18 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_TRICKBALLOON_YELLOW: Obj_TrickBalloonMobjSpawn(mobj); break; + case MT_SS_HOLOGRAM: + Obj_SSHologramMobjSpawn(mobj); + break; + case MT_SEALEDSTAR_BUMPER: + Obj_SSBumperMobjSpawn(mobj); + break; + case MT_GACHATARGET: + Obj_SSGachaTargetMobjSpawn(mobj); + break; + case MT_CABOTRON: + Obj_SSCabotronMobjSpawn(mobj); + break; default: break; } @@ -14667,6 +14735,36 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj) Obj_FuelCanisterEmitterInit(mobj); break; } + case MT_SS_HOLOGRAM_ROTATOR: + { + Obj_SSHologramRotatorMapThingSpawn(mobj, mthing); + break; + } + case MT_SS_HOLOGRAM: + { + Obj_SSHologramMapThingSpawn(mobj, mthing); + break; + } + case MT_SS_COIN_CLOUD: + { + Obj_SSCoinCloudMapThingSpawn(mobj, mthing); + break; + } + case MT_SS_GOBLET_CLOUD: + { + Obj_SSGobletCloudMapThingSpawn(mobj, mthing); + break; + } + case MT_SS_LAMP: + { + Obj_SSLampMapThingSpawn(mobj, mthing); + break; + } + case MT_SSWINDOW: + { + Obj_SSWindowMapThingSpawn(mobj, mthing); + break; + } default: break; } diff --git a/src/sounds.c b/src/sounds.c index b40efa6a9..828f67242 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1242,7 +1242,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"ridr1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Boarding Rideroid"}, // Rideroid Activation {"ridr2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Rideroid Diveroll {"ridr3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Rideroid Loop - {"ridr4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Leaving Rideroid + {"ridr4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Leaving Rideroid {"befan1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Whisking"}, // Blend Eye whisk startup {"befan2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Whisking"}, // Blend Eye whisk @@ -1256,6 +1256,13 @@ sfxinfo_t S_sfx[NUMSFX] = {"lcfuel", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Fuel Capsule explodes"}, + {"ssthnk", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, "Chain rattles"}, // SF_X8AWAYSOUND + {"powerd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "UNDESCRIBED POWERD"}, + {"vault", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "UNDESCRIBED VAULT"}, + {"revcym", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "UNDESCRIBED REVCYM"}, + {"ssbmpr", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, "UNDESCRIBED SSBMPR"}, // SF_X4AWAYSOUND + {"chcrun", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "UNDESCRIBED CHCRUN"}, + // Damage sounds {"dmga1", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Damaged"}, {"dmga2", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Damaged"}, diff --git a/src/sounds.h b/src/sounds.h index 42fa246e9..bfbd06887 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -1330,6 +1330,14 @@ typedef enum // Fuel Capsule sfx_lcfuel, + // Sealed Star Chain + sfx_ssthnk, + sfx_powerd, + sfx_vault, + sfx_revcym, + sfx_ssbmpr, + sfx_chcrun, + // Damage sounds sfx_dmga1, sfx_dmga2,