Merge branch 'jartha/lightning-flame-shield' into 'master'

New Lightning Shield and Flame Shield graphics

See merge request kart-krew-dev/ring-racers-internal!2554
This commit is contained in:
Oni VelocitOni 2025-05-20 02:53:41 +00:00
commit 1fb70714bb
9 changed files with 353 additions and 66 deletions

View file

@ -1993,6 +1993,12 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
"S_LIGHTNINGSHIELD23",
"S_LIGHTNINGSHIELD24",
// Lightning Shield Visuals
"S_THNC1",
"S_THNA1",
"S_THNC2",
"S_THNB1",
// Bubble Shield
"S_BUBBLESHIELD1",
"S_BUBBLESHIELD2",
@ -2057,6 +2063,11 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
"S_FLAMESHIELD17",
"S_FLAMESHIELD18",
// Flame Shield Visuals
"S_FLMA1",
"S_FLMA2",
"S_FLMB1",
"S_FLAMESHIELDDASH1",
"S_FLAMESHIELDDASH2",
"S_FLAMESHIELDDASH3",
@ -3624,9 +3635,11 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
"MT_MANTARING", // Juicebox for SPB
"MT_LIGHTNINGSHIELD", // Shields
"MT_LIGHTNINGSHIELD_VISUAL",
"MT_BUBBLESHIELD",
"MT_BUBBLESHIELD_VISUAL",
"MT_FLAMESHIELD",
"MT_FLAMESHIELD_VISUAL",
"MT_FLAMESHIELDUNDERLAY",
"MT_FLAMESHIELDPAPER",
"MT_BUBBLESHIELDTRAP",

View file

@ -375,6 +375,9 @@ char sprnames[NUMSPRITES + 1][5] =
"TRIS", // SPB Manta Ring start
"TRNQ", // SPB Manta Ring loop
"THNS", // Lightning Shield
"THNC", // Lightning Shield Top Flash
"THNA", // Lightning Shield Top Swoosh
"THNB", // Lightning Shield Bottom Swoosh
"BUBS", // Bubble Shield (not Bubs)
"BUBA", // Bubble Shield Outline
"BUBB", // Bubble Shield Top Wave
@ -383,6 +386,8 @@ char sprnames[NUMSPRITES + 1][5] =
"BUBE", // Bubble Shield Underline
"BWVE", // Bubble Shield waves
"FLMS", // Flame Shield
"FLMA", // Flame Shield Top Layer
"FLMB", // Flame Shield Bottom Layer
"FLMD", // Flame Shield dash
"FLMP", // Flame Shield paper sprites
"FLML", // Flame Shield speed lines
@ -2534,6 +2539,12 @@ state_t states[NUMSTATES] =
{SPR_THNS, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_LIGHTNINGSHIELD23}, // S_LIGHTNINGSHIELD22
{SPR_THNS, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_LIGHTNINGSHIELD24}, // S_LIGHTNINGSHIELD23
{SPR_THNS, FF_FULLBRIGHT|0, 2, {NULL}, 0, 0, S_LIGHTNINGSHIELD1}, // S_LIGHTNINGSHIELD24
//
// Lightning Shield Visuals
{SPR_THNC, FF_ADD|FF_FULLBRIGHT|FF_ANIMATE, 11, {NULL}, 10, 1, S_THNA1}, // S_THNC1
{SPR_THNA, FF_ADD|FF_FULLBRIGHT|FF_ANIMATE, 44, {NULL}, 43, 1, S_THNC2}, // S_THNA1
{SPR_THNC, FF_ADD|FF_FULLBRIGHT|FF_ANIMATE, 11, {NULL}, 10, 1, S_THNB1}, // S_THNC2
{SPR_THNB, FF_ADD|FF_FULLBRIGHT|FF_ANIMATE, 43, {NULL}, 42, 1, S_THNC1}, // S_THNB1
{SPR_BUBS, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_BUBBLESHIELD2}, // S_BUBBLESHIELD1
{SPR_BUBS, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_BUBBLESHIELD3}, // S_BUBBLESHIELD2
@ -2596,30 +2607,35 @@ state_t states[NUMSTATES] =
{SPR_FLMS, FF_FULLBRIGHT|16, 2, {NULL}, 0, 0, S_FLAMESHIELD17}, // S_FLAMESHIELD16
{SPR_FLMS, FF_FULLBRIGHT|8, 2, {NULL}, 0, 0, S_FLAMESHIELD18}, // S_FLAMESHIELD17
{SPR_FLMS, FF_FULLBRIGHT|17, 2, {NULL}, 0, 0, S_FLAMESHIELD1}, // S_FLAMESHIELD18
//
// Flame Shield Visuals
{SPR_FLMA, FF_ADD|FF_FULLBRIGHT|FF_ANIMATE, 28, {NULL}, 27, 1, S_FLMA2}, // S_FLMA1
{SPR_NULL, 0, 16, {NULL}, 0, 0, S_FLMA1}, // S_FLMA2
{SPR_FLMB, FF_FULLBRIGHT|FF_ANIMATE, 44, {NULL}, 43, 1, S_FLMB1}, // S_FLMB1
{SPR_FLMD, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH2}, // S_FLAMESHIELDDASH1
{SPR_FLMD, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH3}, // S_FLAMESHIELDDASH2
{SPR_FLMD, FF_FULLBRIGHT, 1, {A_FlameShieldPaper}, 0, 2, S_FLAMESHIELDDASH4}, // S_FLAMESHIELDDASH3
{SPR_FLMD, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH5}, // S_FLAMESHIELDDASH4
{SPR_FLMD, FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH6}, // S_FLAMESHIELDDASH5
{SPR_FLMD, FF_FULLBRIGHT, 1, {A_FlameShieldPaper}, 1, 3, S_FLAMESHIELDDASH7}, // S_FLAMESHIELDDASH6
{SPR_FLMD, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH8}, // S_FLAMESHIELDDASH7
{SPR_FLMD, FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH9}, // S_FLAMESHIELDDASH8
{SPR_FLMD, FF_FULLBRIGHT, 1, {A_FlameShieldPaper}, 2, 0, S_FLAMESHIELDDASH10}, // S_FLAMESHIELDDASH9
{SPR_FLMD, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH11}, // S_FLAMESHIELDDASH10
{SPR_FLMD, FF_FULLBRIGHT|8, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH12}, // S_FLAMESHIELDDASH11
{SPR_FLMD, FF_FULLBRIGHT, 1, {A_FlameShieldPaper}, 3, 1, S_FLAMESHIELDDASH1}, // S_FLAMESHIELDDASH12
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH2}, // S_FLAMESHIELDDASH1
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH3}, // S_FLAMESHIELDDASH2
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT, 1, {A_FlameShieldPaper}, 0, 2, S_FLAMESHIELDDASH4}, // S_FLAMESHIELDDASH3
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH5}, // S_FLAMESHIELDDASH4
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH6}, // S_FLAMESHIELDDASH5
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT, 1, {A_FlameShieldPaper}, 1, 3, S_FLAMESHIELDDASH7}, // S_FLAMESHIELDDASH6
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH8}, // S_FLAMESHIELDDASH7
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH9}, // S_FLAMESHIELDDASH8
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT, 1, {A_FlameShieldPaper}, 2, 0, S_FLAMESHIELDDASH10}, // S_FLAMESHIELDDASH9
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH11}, // S_FLAMESHIELDDASH10
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT|8, 1, {NULL}, 0, 0, S_FLAMESHIELDDASH12}, // S_FLAMESHIELDDASH11
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT, 1, {A_FlameShieldPaper}, 3, 1, S_FLAMESHIELDDASH1}, // S_FLAMESHIELDDASH12
{SPR_FLMD, FF_FULLBRIGHT|9, 2, {NULL}, 0, 0, S_NULL}, // S_FLAMESHIELDDASH2_UNDERLAY
{SPR_FLMD, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_NULL}, // S_FLAMESHIELDDASH5_UNDERLAY
{SPR_FLMD, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_NULL}, // S_FLAMESHIELDDASH8_UNDERLAY
{SPR_FLMD, FF_FULLBRIGHT|12, 2, {NULL}, 0, 0, S_NULL}, // S_FLAMESHIELDDASH11_UNDERLAY
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT|9, 2, {NULL}, 0, 0, S_NULL}, // S_FLAMESHIELDDASH2_UNDERLAY
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_NULL}, // S_FLAMESHIELDDASH5_UNDERLAY
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_NULL}, // S_FLAMESHIELDDASH8_UNDERLAY
{SPR_FLMD, FF_ADD|FF_FULLBRIGHT|12, 2, {NULL}, 0, 0, S_NULL}, // S_FLAMESHIELDDASH11_UNDERLAY
{SPR_FLMP, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_NULL}, // S_FLAMESHIELDPAPER
{SPR_FLML, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE, 7, {NULL}, 6, 1, S_NULL}, // S_FLAMESHIELDLINE1
{SPR_FLML, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE|7, 7, {NULL}, 6, 1, S_NULL}, // S_FLAMESHIELDLINE2
{SPR_FLML, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE|14, 7, {NULL}, 6, 1, S_NULL}, // S_FLAMESHIELDLINE3
{SPR_FLMF, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_FLAMESHIELDFLASH
{SPR_FLMP, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_NULL}, // S_FLAMESHIELDPAPER
{SPR_FLML, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE, 7, {NULL}, 6, 1, S_NULL}, // S_FLAMESHIELDLINE1
{SPR_FLML, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE|7, 7, {NULL}, 6, 1, S_NULL}, // S_FLAMESHIELDLINE2
{SPR_FLML, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE|14, 7, {NULL}, 6, 1, S_NULL}, // S_FLAMESHIELDLINE3
{SPR_FLMF, FF_ADD|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_FLAMESHIELDFLASH
{SPR_GTOP, FF_ANIMATE, -1, {NULL}, 5, 1, S_NULL}, // S_GARDENTOP_FLOATING
{SPR_GTOP, 0, 1, {NULL}, 5, 1, S_GARDENTOP_SINKING2}, // S_GARDENTOP_SINKING1
@ -2925,54 +2941,54 @@ state_t states[NUMSTATES] =
// Oh no it's annoying lightning states.......
// Lightning Sparks (it's the ones we'll use for the radius)
{SPR_KSPK, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK2}, // S_KSPARK1
{SPR_NULL, FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK3}, // S_KSPARK2
{SPR_KSPK, FF_FULLBRIGHT|1, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK4}, // S_KSPARK3
{SPR_NULL, FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK5}, // S_KSPARK4
{SPR_KSPK, FF_FULLBRIGHT|2, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK6}, // S_KSPARK5
{SPR_NULL, FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK7}, // S_KSPARK6
{SPR_KSPK, FF_FULLBRIGHT|3, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK8}, // S_KSPARK7
{SPR_NULL, FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK9}, // S_KSPARK8
{SPR_KSPK, FF_TRANS40|FF_FULLBRIGHT|4, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK10}, // S_KSPARK9
{SPR_NULL, FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK11}, // S_KSPARK10
{SPR_KSPK, FF_TRANS50|FF_FULLBRIGHT|5, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK12}, // S_KSPARK11
{SPR_NULL, FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK13}, // S_KSPARK12
{SPR_KSPK, FF_TRANS60|FF_FULLBRIGHT|6, 2, {A_LightningFollowPlayer}, 0, 0, S_NULL}, // S_KSPARK13
{SPR_KSPK, FF_ADD|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK2}, // S_KSPARK1
{SPR_NULL, FF_ADD|FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK3}, // S_KSPARK2
{SPR_KSPK, FF_ADD|FF_FULLBRIGHT|1, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK4}, // S_KSPARK3
{SPR_NULL, FF_ADD|FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK5}, // S_KSPARK4
{SPR_KSPK, FF_ADD|FF_FULLBRIGHT|2, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK6}, // S_KSPARK5
{SPR_NULL, FF_ADD|FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK7}, // S_KSPARK6
{SPR_KSPK, FF_ADD|FF_FULLBRIGHT|3, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK8}, // S_KSPARK7
{SPR_NULL, FF_ADD|FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK9}, // S_KSPARK8
{SPR_KSPK, FF_ADD|FF_TRANS40|FF_FULLBRIGHT|4, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK10}, // S_KSPARK9
{SPR_NULL, FF_ADD|FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK11}, // S_KSPARK10
{SPR_KSPK, FF_ADD|FF_TRANS50|FF_FULLBRIGHT|5, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK12}, // S_KSPARK11
{SPR_NULL, FF_ADD|FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK13}, // S_KSPARK12
{SPR_KSPK, FF_ADD|FF_TRANS60|FF_FULLBRIGHT|6, 2, {A_LightningFollowPlayer}, 0, 0, S_NULL}, // S_KSPARK13
// The straight bolt...
{SPR_LZI1, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO12}, // S_LZIO11
{SPR_NULL, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO13}, // S_LZIO12
{SPR_LZI1, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO14}, // S_LZIO13
{SPR_LZI1, FF_FULLBRIGHT|1, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO15}, // S_LZIO14
{SPR_NULL, FF_FULLBRIGHT, 4, {A_LightningFollowPlayer}, 0, 0, S_LZIO16}, // S_LZIO15
{SPR_LZI1, FF_FULLBRIGHT|1, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO17}, // S_LZIO16
{SPR_LZI1, FF_ADD|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO12}, // S_LZIO11
{SPR_NULL, FF_ADD|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO13}, // S_LZIO12
{SPR_LZI1, FF_ADD|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO14}, // S_LZIO13
{SPR_LZI1, FF_ADD|FF_FULLBRIGHT|1, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO15}, // S_LZIO14
{SPR_NULL, FF_ADD|FF_FULLBRIGHT, 4, {A_LightningFollowPlayer}, 0, 0, S_LZIO16}, // S_LZIO15
{SPR_LZI1, FF_ADD|FF_FULLBRIGHT|1, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO17}, // S_LZIO16
{SPR_NULL, 0, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO18}, // S_LZIO17
{SPR_LZI1, FF_TRANS50|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO19}, // S_LZIO18
{SPR_LZI1, FF_TRANS70|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_NULL}, // S_LZIO19
{SPR_LZI1, FF_ADD|FF_TRANS50|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO19}, // S_LZIO18
{SPR_LZI1, FF_ADD|FF_TRANS70|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_NULL}, // S_LZIO19
{SPR_NULL, FF_FULLBRIGHT, 6, {A_LightningFollowPlayer}, 0, 0, S_LZIO22}, // S_LZIO21
{SPR_LZI2, FF_FULLBRIGHT|1, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO23}, // S_LZIO22
{SPR_LZI2, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO24}, // S_LZIO23
{SPR_NULL, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO25}, // S_LZIO24
{SPR_NULL, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO26}, // S_LZIO25
{SPR_NULL, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO27}, // S_LZIO26
{SPR_LZI2, FF_TRANS30|FF_FULLBRIGHT|2, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO28}, // S_LZIO27
{SPR_NULL, FF_ADD|FF_FULLBRIGHT, 6, {A_LightningFollowPlayer}, 0, 0, S_LZIO22}, // S_LZIO21
{SPR_LZI2, FF_ADD|FF_FULLBRIGHT|1, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO23}, // S_LZIO22
{SPR_LZI2, FF_ADD|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO24}, // S_LZIO23
{SPR_NULL, FF_ADD|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO25}, // S_LZIO24
{SPR_NULL, FF_ADD|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO26}, // S_LZIO25
{SPR_NULL, FF_ADD|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO27}, // S_LZIO26
{SPR_LZI2, FF_ADD|FF_TRANS30|FF_FULLBRIGHT|2, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO28}, // S_LZIO27
{SPR_NULL, 0, 4, {A_LightningFollowPlayer}, 0, 0, S_LZIO29}, // S_LZIO28
{SPR_LZI2, FF_TRANS70|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_NULL}, // S_LZIO29
{SPR_LZI2, FF_ADD|FF_TRANS70|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_NULL}, // S_LZIO29
// The slanted bolt. Man these states are boring as all heck to do.
{SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT2}, // S_KLIT1
{SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT3}, // S_KLIT2
{SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|1, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT4}, // S_KLIT3
{SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT5}, // S_KLIT4
{SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|2, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT6}, // S_KLIT5
{SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT7}, // S_KLIT6
{SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|3, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT8}, // S_KLIT7
{SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT9}, // S_KLIT8
{SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|4, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT10}, // S_KLIT9
{SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT11}, // S_KLIT10
{SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|5, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT12}, // S_KLIT11
{SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT1}, // S_KLIT12
{SPR_KLIT, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT2}, // S_KLIT1
{SPR_NULL, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT3}, // S_KLIT2
{SPR_KLIT, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE|1, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT4}, // S_KLIT3
{SPR_NULL, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT5}, // S_KLIT4
{SPR_KLIT, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE|2, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT6}, // S_KLIT5
{SPR_NULL, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT7}, // S_KLIT6
{SPR_KLIT, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE|3, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT8}, // S_KLIT7
{SPR_NULL, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT9}, // S_KLIT8
{SPR_KLIT, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE|4, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT10}, // S_KLIT9
{SPR_NULL, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT11}, // S_KLIT10
{SPR_KLIT, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE|5, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT12}, // S_KLIT11
{SPR_NULL, FF_ADD|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT1}, // S_KLIT12
{SPR_FZSM, 0, 4, {NULL}, 0, 0, S_FZEROSMOKE2}, // S_FZEROSMOKE1
{SPR_FZSM, 1, 4, {NULL}, 0, 0, S_FZEROSMOKE3}, // S_FZEROSMOKE2
@ -15357,7 +15373,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_LIGHTNINGSHIELD
-1, // doomednum
S_LIGHTNINGSHIELD1, // spawnstate
S_INVISIBLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -15382,6 +15398,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_LIGHTNINGSHIELD_VISUAL
-1, // doomednum
S_THNC1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // 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
8, // speed
28*FRACUNIT, // radius
56*FRACUNIT, // height
1, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_BUBBLESHIELD
-1, // doomednum
S_BUBBLESHIELD1, // spawnstate
@ -15438,7 +15481,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_FLAMESHIELD
-1, // doomednum
S_FLAMESHIELD1, // spawnstate
S_INVISIBLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -15463,6 +15506,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_FLAMESHIELD_VISUAL
-1, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // 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
8, // speed
28*FRACUNIT, // radius
56*FRACUNIT, // height
1, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_FLAMESHIELDUNDERLAY
-1, // doomednum
S_FLAMESHIELDDASH2_UNDERLAY, // spawnstate

View file

@ -914,6 +914,9 @@ typedef enum sprite
SPR_TRIS, // SPB Manta Ring start
SPR_TRNQ, // SPB Manta Ring loop
SPR_THNS, // Thunder Shield
SPR_THNC, // Lightning Shield Top Flash
SPR_THNA, // Lightning Shield Top Swoosh
SPR_THNB, // Lightning Shield Bottom Swoosh
SPR_BUBS, // Bubble Shield (not Bubs)
SPR_BUBA, // Bubble Shield Outline
SPR_BUBB, // Bubble Shield Top Wave
@ -922,6 +925,8 @@ typedef enum sprite
SPR_BUBE, // Bubble Shield Underline
SPR_BWVE, // Bubble Shield waves
SPR_FLMS, // Flame Shield
SPR_FLMA, // Flame Shield Top Layer
SPR_FLMB, // Flame Shield Bottom Layer
SPR_FLMD, // Flame Shield dash
SPR_FLMP, // Flame Shield paper sprites
SPR_FLML, // Flame Shield speed lines
@ -3029,6 +3034,12 @@ typedef enum state
S_LIGHTNINGSHIELD23,
S_LIGHTNINGSHIELD24,
// Lightning Shield Visuals
S_THNC1,
S_THNA1,
S_THNC2,
S_THNB1,
// Bubble Shield
S_BUBBLESHIELD1,
S_BUBBLESHIELD2,
@ -3093,6 +3104,11 @@ typedef enum state
S_FLAMESHIELD17,
S_FLAMESHIELD18,
// Flame Shield Visuals
S_FLMA1,
S_FLMA2,
S_FLMB1,
S_FLAMESHIELDDASH1,
S_FLAMESHIELDDASH2,
S_FLAMESHIELDDASH3,
@ -4687,9 +4703,11 @@ typedef enum mobj_type
MT_MANTARING, // Juicebox for SPB
MT_LIGHTNINGSHIELD, // Shields
MT_LIGHTNINGSHIELD_VISUAL,
MT_BUBBLESHIELD,
MT_BUBBLESHIELD_VISUAL,
MT_FLAMESHIELD,
MT_FLAMESHIELD_VISUAL,
MT_FLAMESHIELDUNDERLAY,
MT_FLAMESHIELDPAPER,
MT_BUBBLESHIELDTRAP,

View file

@ -14059,6 +14059,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
P_SetTarget(&shield->target, player->mo);
S_StartSound(player->mo, sfx_s3k41);
player->curshield = KSHIELD_LIGHTNING;
Obj_SpawnLightningShieldVisuals(shield);
}
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
@ -14191,6 +14193,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
P_SetTarget(&shield->target, player->mo);
S_StartSound(player->mo, sfx_s3k3e);
player->curshield = KSHIELD_FLAME;
Obj_SpawnFlameShieldVisuals(shield);
}
if (!HOLDING_ITEM && NO_HYUDORO)

View file

@ -453,6 +453,14 @@ void K_DoBallhogAttack(player_t *player, UINT8 num_hogs);
void Obj_SpawnBubbleShieldVisuals(mobj_t *source);
boolean Obj_TickBubbleShieldVisual(mobj_t *mobj);
/* Lightning Shield */
void Obj_SpawnLightningShieldVisuals(mobj_t *source);
boolean Obj_TickLightningShieldVisual(mobj_t *mobj);
/* Flame Shield */
void Obj_SpawnFlameShieldVisuals(mobj_t *source);
boolean Obj_TickFlameShieldVisual(mobj_t *mobj);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -62,6 +62,8 @@ target_sources(SRB2SDL2 PRIVATE
ballhog.cpp
bubble-shield.cpp
flybot767.c
lightning-shield.cpp
flame-shield.cpp
)
add_subdirectory(versus)

View file

@ -0,0 +1,82 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2025 by James Robert Roman
// Copyright (C) 2025 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.
//-----------------------------------------------------------------------------
#include "objects.hpp"
#include "../tables.h"
using namespace srb2::objects;
namespace
{
struct Shield : Mobj
{
void target() = delete;
Mobj* follow() const { return Mobj::target(); }
void follow(Mobj* n) { Mobj::target(n); }
player_t* player() const { return follow()->player; }
bool valid() const { return Mobj::valid(follow()) && player(); }
};
struct Visual : Mobj
{
void target() = delete;
Shield* shield() const { return Mobj::target<Shield>(); }
void shield(Shield* n) { Mobj::target(n); }
bool valid() const { return Mobj::valid(shield()) && shield()->valid(); }
static void spawn
( Shield* shield,
statenum_t state,
int offset)
{
if (!shield->valid())
return;
Visual* x = Mobj::spawn<Visual>(shield->pos(), MT_FLAMESHIELD_VISUAL);
x->scale(5 * shield->follow()->scale() / 4);
x->state(state);
x->shield(shield);
x->linkdraw(shield->follow(), offset);
}
bool tick()
{
if (!valid())
{
remove();
return false;
}
move_origin(shield()->pos());
renderflags = (renderflags & ~RF_DONTDRAW) |
(shield()->state()->num() == S_INVISIBLE ? 0 : RF_DONTDRAW);
return true;
}
};
}; // namespace
void Obj_SpawnFlameShieldVisuals(mobj_t *shield)
{
Visual::spawn(static_cast<Shield*>(shield), S_FLMA1, 1);
Visual::spawn(static_cast<Shield*>(shield), S_FLMB1, -1);
}
boolean Obj_TickFlameShieldVisual(mobj_t *mobj)
{
return static_cast<Visual*>(mobj)->tick();
}

View file

@ -0,0 +1,74 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2025 by James Robert Roman
// Copyright (C) 2025 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.
//-----------------------------------------------------------------------------
#include "objects.hpp"
#include "../tables.h"
using namespace srb2::objects;
namespace
{
struct Shield : Mobj
{
void target() = delete;
Mobj* follow() const { return Mobj::target(); }
void follow(Mobj* n) { Mobj::target(n); }
bool valid() const { return Mobj::valid(follow()); }
};
struct Visual : Mobj
{
void target() = delete;
Shield* shield() const { return Mobj::target<Shield>(); }
void shield(Shield* n) { Mobj::target(n); }
bool valid() const { return Mobj::valid(shield()) && shield()->valid(); }
static void spawn(Shield* shield)
{
if (!shield->valid())
return;
Visual* x = Mobj::spawn<Visual>(shield->pos(), MT_LIGHTNINGSHIELD_VISUAL);
x->scale(5 * shield->follow()->scale() / 4);
x->shield(shield);
x->linkdraw(shield->follow());
x->tick();
}
bool tick()
{
if (!valid())
{
remove();
return false;
}
move_origin(shield()->pos());
dispoffset = state()->num() == S_THNB1 ? -1 : 1;
return true;
}
};
}; // namespace
void Obj_SpawnLightningShieldVisuals(mobj_t *shield)
{
Visual::spawn(static_cast<Shield*>(shield));
}
boolean Obj_TickLightningShieldVisual(mobj_t *mobj)
{
return static_cast<Visual*>(mobj)->tick();
}

View file

@ -6666,6 +6666,22 @@ static void P_MobjSceneryThink(mobj_t *mobj)
}
break;
}
case MT_LIGHTNINGSHIELD_VISUAL:
{
if (!Obj_TickLightningShieldVisual(mobj))
{
return;
}
break;
}
case MT_FLAMESHIELD_VISUAL:
{
if (!Obj_TickFlameShieldVisual(mobj))
{
return;
}
break;
}
default:
if (mobj->fuse)
{ // Scenery object fuse! Very basic!
@ -8714,8 +8730,8 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
else
{
if (curstate >= S_FLAMESHIELDDASH1 && curstate <= S_FLAMESHIELDDASH12)
P_SetMobjState(mobj, S_FLAMESHIELD1);
mobj->dispoffset = ((curstate - S_FLAMESHIELD1) & 1) ? -1 : 1;
P_SetMobjState(mobj, S_INVISIBLE);
//mobj->dispoffset = ((curstate - S_FLAMESHIELD1) & 1) ? -1 : 1;
}
mobj->extravalue1 = mobj->target->player->flamedash;