From 22b413e84c36f32067e431c0a3ac2d2028dcaf39 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 28 Oct 2019 22:12:47 +0000 Subject: [PATCH 01/14] * Improve the Metal Sonic recording/playback system. * Make the skin to record with Metal rather than Flesh Sonic. (Allowed even if not unlocked!) * Make the object that plays back the recording actually use the Metal skin, rather than just a seperate spriteset. (The boss will still need the spriteset, though.) * Actively record the player's sprite2, frame, and followmobj, just like regular ghosts do. * Disable dashmode while recording, for a fairer race. * Fix a probably long-standing bug where, while recording, being "hurt" would get Metal stuck in pain frames until they physically left the area of hurt. * Always start Metal recording in wait frames for bonus taunting. Other relevant changes: * Increment DEMOVERSION *again*. * Improve the Record Attack ghost followmobj recording to accomodate Metal's jet. * Increase the datatype width of spritenum_t read/write for Record Attack ghosts because SUGOI 4: Back With A Revengance will probably also use more than 255 sprites alone. * Return to standing frames (or prolong them if you're in them, rather than going to wait frames) if the player rotates on the spot with enough force. * This was specifically done *for* Metal recording, but I decided it looked good enough to enable all the time. --- src/d_netcmd.c | 6 +- src/dehacked.c | 20 +--- src/g_game.c | 278 +++++++++++++++++++++++++++++++++++-------------- src/info.c | 22 +--- src/info.h | 20 +--- src/p_inter.c | 3 +- src/p_mobj.c | 9 +- src/p_user.c | 20 +++- src/r_things.c | 1 + 9 files changed, 239 insertions(+), 140 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b14f92b33..5c8c327c8 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1206,9 +1206,9 @@ static void SendNameAndColor(void) players[consoleplayer].mo->color = players[consoleplayer].skincolor; if (metalrecording) - { // Metal Sonic is Sonic, obviously. - SetPlayerSkinByNum(consoleplayer, 0); - CV_StealthSet(&cv_skin, skins[0].name); + { // Starring Metal Sonic as themselves, obviously. + SetPlayerSkinByNum(consoleplayer, 5); + CV_StealthSet(&cv_skin, skins[5].name); } else if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin)) { diff --git a/src/dehacked.c b/src/dehacked.c index 34ee1f170..6369d5d7f 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5260,25 +5260,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_CYBRAKDEMONVILEEXPLOSION3", // Metal Sonic (Race) - // S_PLAY_STND - "S_METALSONIC_STAND", - // S_PLAY_TAP1 - "S_METALSONIC_WAIT1", - "S_METALSONIC_WAIT2", - // S_PLAY_WALK - "S_METALSONIC_WALK1", - "S_METALSONIC_WALK2", - "S_METALSONIC_WALK3", - "S_METALSONIC_WALK4", - "S_METALSONIC_WALK5", - "S_METALSONIC_WALK6", - "S_METALSONIC_WALK7", - "S_METALSONIC_WALK8", - // S_PLAY_SPD1 - "S_METALSONIC_RUN1", - "S_METALSONIC_RUN2", - "S_METALSONIC_RUN3", - "S_METALSONIC_RUN4", + "S_METALSONIC_RACE", // Metal Sonic (Battle) "S_METALSONIC_FLOAT", "S_METALSONIC_VECTOR", diff --git a/src/g_game.c b/src/g_game.c index e2f43e4f2..27cece73d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4044,7 +4044,7 @@ char *G_BuildMapTitle(INT32 mapnum) // DEMO RECORDING // -#define DEMOVERSION 0x000a +#define DEMOVERSION 0x000b #define DEMOHEADER "\xF0" "SRB2Replay" "\x0F" #define DF_GHOST 0x01 // This demo contains ghost data too! @@ -4068,7 +4068,6 @@ static ticcmd_t oldcmd; #define GZT_MOMXY 0x02 #define GZT_MOMZ 0x04 #define GZT_ANGLE 0x08 -// Not used for Metal Sonic #define GZT_FRAME 0x10 // Animation frame #define GZT_SPR2 0x20 // Player animations #define GZT_EXTRA 0x40 @@ -4086,6 +4085,14 @@ static ticcmd_t oldcmd; #define EZT_SPRITE 0x40 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever) // spare EZT slot 0x80 +// GZT_FOLLOW flags +#define FZT_SPAWNED 0x01 // just been spawned +#define FZT_SKIN 0x02 // has skin +#define FZT_LINKDRAW 0x04 // has linkdraw (combine with spawned only) +#define FZT_COLORIZED 0x08 // colorized (ditto) +#define FZT_SCALE 0x10 // different scale to object +// spare FZT slots 0x20 to 0x80 + static mobj_t oldmetal, oldghost; void G_SaveMetal(UINT8 **buffer) @@ -4405,26 +4412,54 @@ void G_WriteGhostTic(mobj_t *ghost) ghostext.hitlist = NULL; } if (ghostext.flags & EZT_SPRITE) - WRITEUINT8(demo_p,oldghost.sprite); + WRITEUINT16(demo_p,oldghost.sprite); ghostext.flags = 0; } if (ghost->player && ghost->player->followmobj) // bloats tails runs but what can ya do { INT16 temp; + UINT8 *followtic_p = demo_p++; + UINT8 followtic = 0; ziptic |= GZT_FOLLOW; + if (ghost->player->followmobj->skin) + followtic |= FZT_SKIN; + + if (!(oldghost.flags2 & MF2_AMBUSH)) + { + followtic |= FZT_SPAWNED; + if (ghost->player->followmobj->flags2 & MF2_LINKDRAW) + followtic |= FZT_LINKDRAW; + if (ghost->player->followmobj->colorized) + followtic |= FZT_COLORIZED; + if (followtic & FZT_SKIN) + WRITEUINT8(demo_p,(UINT8)(((skin_t *)(ghost->player->followmobj->skin))-skins)); + oldghost.flags2 |= MF2_AMBUSH; + } + temp = (INT16)((ghost->player->followmobj->x-ghost->x)>>8); WRITEINT16(demo_p,temp); temp = (INT16)((ghost->player->followmobj->y-ghost->y)>>8); WRITEINT16(demo_p,temp); temp = (INT16)((ghost->player->followmobj->z-ghost->z)>>8); WRITEINT16(demo_p,temp); - WRITEUINT8(demo_p,ghost->player->followmobj->sprite); - WRITEUINT8(demo_p,ghost->player->followmobj->sprite2); + if (followtic & FZT_SKIN) + WRITEUINT8(demo_p,ghost->player->followmobj->sprite2); + WRITEUINT16(demo_p,ghost->player->followmobj->sprite); WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK)); + WRITEUINT8(demo_p,ghost->player->followmobj->color); + if (ghost->player->followmobj->scale != ghost->scale) + { + followtic |= FZT_SCALE; + WRITEFIXED(demo_p,ghost->player->followmobj->scale); + } + + *followtic_p = followtic; } + else + oldghost.flags2 &= ~MF2_AMBUSH; *ziptic_p = ziptic; @@ -4528,17 +4563,24 @@ void G_ConsGhostTic(void) } } if (xziptic & EZT_SPRITE) - demo_p++; + demo_p += sizeof(UINT16); } if (ziptic & GZT_FOLLOW) { // Even more... + UINT8 followtic = READUINT8(demo_p); + if ((followtic & (FZT_SPAWNED|FZT_SKIN)) == (FZT_SPAWNED|FZT_SKIN)) + demo_p++; demo_p += sizeof(INT16); demo_p += sizeof(INT16); demo_p += sizeof(INT16); + if (followtic & FZT_SKIN) + demo_p++; + demo_p += sizeof(UINT16); demo_p++; demo_p++; - demo_p++; + if (followtic & FZT_SCALE) + demo_p += sizeof(fixed_t); } // Re-synchronise @@ -4737,7 +4779,7 @@ void G_GhostTicker(void) } } if (xziptic & EZT_SPRITE) - g->mo->sprite = READUINT8(g->p); + g->mo->sprite = READUINT16(g->p); } // Tick ghost colors (Super and Mario Invincibility flashing) @@ -4763,43 +4805,52 @@ void G_GhostTicker(void) #define follow g->mo->tracer if (ziptic & GZT_FOLLOW) { // Even more... - if (!follow) + UINT8 followtic = READUINT8(g->p); + if (followtic & FZT_SPAWNED) { - mobj_t *newmo = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z, MT_GHOST); - P_SetTarget(&g->mo->tracer, newmo); - P_SetTarget(&newmo->tracer, g->mo); - newmo->skin = g->mo->skin; - newmo->tics = -1; - newmo->flags2 |= MF2_LINKDRAW; + if (follow) + P_RemoveMobj(follow); + P_SetTarget(&follow, P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z, MT_GHOST)); + P_SetTarget(&follow->tracer, g->mo); + follow->tics = -1; + + if (followtic & FZT_LINKDRAW) + follow->flags2 |= MF2_LINKDRAW; + + if (followtic & FZT_COLORIZED) + follow->colorized = true; + + if (followtic & FZT_SKIN) + follow->skin = &skins[READUINT8(g->p)]; follow->eflags = (follow->eflags & ~MFE_VERTICALFLIP)|(g->mo->eflags & MFE_VERTICALFLIP); - follow->destscale = g->mo->destscale; - if (follow->destscale != follow->scale) - P_SetScale(follow, follow->destscale); } - else + if (follow) { - if (xziptic & EZT_FLIP) - g->mo->eflags ^= MFE_VERTICALFLIP; - if (xziptic & EZT_SCALE) + if (!(followtic & FZT_SPAWNED)) { - follow->destscale = g->mo->destscale; - if (follow->destscale != follow->scale) - P_SetScale(follow, follow->destscale); + if (xziptic & EZT_FLIP) + follow->eflags ^= MFE_VERTICALFLIP; } + + P_UnsetThingPosition(follow); + follow->x = g->mo->x + (READINT16(g->p)<<8); + follow->y = g->mo->y + (READINT16(g->p)<<8); + follow->z = g->mo->z + (READINT16(g->p)<<8); + P_SetThingPosition(follow); + if (followtic & FZT_SKIN) + follow->sprite2 = READUINT8(g->p); + else + follow->sprite2 = 0; + follow->sprite = READUINT16(g->p); + follow->frame = (READUINT8(g->p)) | tr_trans30<angle = g->mo->angle; + follow->color = READUINT8(g->p); + if (followtic & FZT_SCALE) + P_SetScale(follow, (follow->destscale = READFIXED(g->p))); + else + P_SetScale(follow, (follow->destscale = g->mo->destscale)); } - - P_UnsetThingPosition(follow); - follow->x = g->mo->x + (READINT16(g->p)<<8); - follow->y = g->mo->y + (READINT16(g->p)<<8); - follow->z = g->mo->z + (READINT16(g->p)<<8); - P_SetThingPosition(follow); - follow->sprite = READUINT8(g->p); - follow->sprite2 = READUINT8(g->p); - follow->frame = (READUINT8(g->p)) | tr_trans30<angle = g->mo->angle; - follow->color = g->mo->color; } else if (follow) { @@ -4826,11 +4877,11 @@ void G_GhostTicker(void) void G_ReadMetalTic(mobj_t *metal) { UINT8 ziptic; - UINT16 speed; - UINT8 statetype; + UINT8 xziptic = 0; if (!metal_p) return; + metal_p++; ziptic = READUINT8(metal_p); // Read changes from the tic @@ -4857,9 +4908,9 @@ void G_ReadMetalTic(mobj_t *metal) if (ziptic & GZT_ANGLE) metal->angle = READUINT8(metal_p)<<24; if (ziptic & GZT_FRAME) - metal_p++; // Currently unused. (Metal Sonic figures out what he's doing his own damn self.) + oldmetal.frame = READUINT32(metal_p); if (ziptic & GZT_SPR2) - metal_p++; + oldmetal.sprite2 = READUINT8(metal_p); // Set movement, position, and angle // oldmetal contains where you're supposed to be. @@ -4871,13 +4922,15 @@ void G_ReadMetalTic(mobj_t *metal) metal->y = oldmetal.y; metal->z = oldmetal.z; P_SetThingPosition(metal); + metal->frame = oldmetal.frame; + metal->sprite2 = oldmetal.sprite2; if (ziptic & GZT_EXTRA) { // But wait, there's more! - ziptic = READUINT8(metal_p); - if (ziptic & EZT_FLIP) + xziptic = READUINT8(metal_p); + if (xziptic & EZT_FLIP) metal->eflags ^= MFE_VERTICALFLIP; - if (ziptic & EZT_SCALE) + if (xziptic & EZT_SCALE) { metal->destscale = READFIXED(metal_p); if (metal->destscale != metal->scale) @@ -4885,36 +4938,52 @@ void G_ReadMetalTic(mobj_t *metal) } } - // Calculates player's speed based on distance-of-a-line formula - speed = FixedDiv(P_AproxDistance(oldmetal.momx, oldmetal.momy), metal->scale)>>FRACBITS; +#define follow metal->tracer + if (ziptic & GZT_FOLLOW) + { // Even more... + UINT8 followtic = READUINT8(metal_p); + if (followtic & FZT_SPAWNED) + { + if (follow) + P_RemoveMobj(follow); + P_SetTarget(&follow, P_SpawnMobj(metal->x, metal->y, metal->z, MT_GHOST)); + P_SetTarget(&follow->tracer, metal); + follow->tics = -1; - // Use speed to decide an appropriate state - if (speed > 28) // default skin runspeed - statetype = 2; - else if (speed > 1) // stopspeed - statetype = 1; - else - statetype = 0; + if (followtic & FZT_COLORIZED) + follow->colorized = true; - // Set state - if (statetype != metal->threshold) - { - switch (statetype) - { - case 2: // run - P_SetMobjState(metal,metal->info->meleestate); - break; - case 1: // walk - P_SetMobjState(metal,metal->info->seestate); - break; - default: // stand - P_SetMobjState(metal,metal->info->spawnstate); - break; + follow->eflags = (follow->eflags & ~MFE_VERTICALFLIP)|(metal->eflags & MFE_VERTICALFLIP); + } + if (follow) + { + if (!(followtic & FZT_SPAWNED)) + { + if (xziptic & EZT_FLIP) + follow->eflags ^= MFE_VERTICALFLIP; + } + + P_UnsetThingPosition(follow); + follow->x = metal->x + (READINT16(metal_p)<<8); + follow->y = metal->y + (READINT16(metal_p)<<8); + follow->z = metal->z + (READINT16(metal_p)<<8); + P_SetThingPosition(follow); + follow->sprite = READUINT16(metal_p); + follow->frame = READUINT32(metal_p); // NOT & FF_FRAMEMASK here, so 32 bits + follow->angle = metal->angle; + follow->color = READUINT8(metal_p); + if (followtic & FZT_SCALE) + P_SetScale(follow, (follow->destscale = READFIXED(metal_p))); + else + P_SetScale(follow, (follow->destscale = metal->destscale)); + } } - metal->threshold = statetype; - } - - // TODO: Modify state durations based on movement speed, similar to players? + else if (follow) + { + P_RemoveMobj(follow); + P_SetTarget(&follow, NULL); + } +#undef follow if (*metal_p == DEMOMARKER) { @@ -4931,7 +5000,7 @@ void G_WriteMetalTic(mobj_t *metal) if (!demo_p) // demo_p will be NULL until the race start linedef executor is triggered! return; - + demo_p++; ziptic_p = demo_p++; // the ziptic, written at the end of this function #define MAXMOM (0xFFFF<<8) @@ -4944,10 +5013,10 @@ void G_WriteMetalTic(mobj_t *metal) oldmetal.x = metal->x; oldmetal.y = metal->y; oldmetal.z = metal->z; + ziptic |= GZT_XYZ; WRITEFIXED(demo_p,oldmetal.x); WRITEFIXED(demo_p,oldmetal.y); WRITEFIXED(demo_p,oldmetal.z); - ziptic |= GZT_XYZ; } else { @@ -4960,16 +5029,16 @@ void G_WriteMetalTic(mobj_t *metal) { oldmetal.momx = momx; oldmetal.momy = momy; + ziptic |= GZT_MOMXY; WRITEINT16(demo_p,momx); WRITEINT16(demo_p,momy); - ziptic |= GZT_MOMXY; } momx = (INT16)((metal->z-oldmetal.z)>>8); if (momx != oldmetal.momz) { oldmetal.momz = momx; - WRITEINT16(demo_p,momx); ziptic |= GZT_MOMZ; + WRITEINT16(demo_p,momx); } // This SHOULD set oldmetal.x/y/z to match metal->x/y/z @@ -4992,8 +5061,21 @@ void G_WriteMetalTic(mobj_t *metal) WRITEUINT8(demo_p,oldmetal.angle); } - // Metal Sonic does not need our state changes. - // ... currently. + // Store the sprite frame. + if ((metal->frame & FF_FRAMEMASK) != oldmetal.frame) + { + oldmetal.frame = metal->frame; // NOT & FF_FRAMEMASK here, so 32 bits + ziptic |= GZT_FRAME; + WRITEUINT32(demo_p,oldmetal.frame); + } + + if (metal->sprite == SPR_PLAY + && metal->sprite2 != oldmetal.sprite2) + { + oldmetal.sprite2 = metal->sprite2; + ziptic |= GZT_SPR2; + WRITEUINT8(demo_p,oldmetal.sprite2); + } { UINT8 *exttic_p = NULL; @@ -5020,6 +5102,48 @@ void G_WriteMetalTic(mobj_t *metal) } } + if (metal->player && metal->player->followmobj) + { + INT16 temp; + UINT8 *followtic_p = demo_p++; + UINT8 followtic = 0; + + ziptic |= GZT_FOLLOW; + + if (!(oldmetal.flags2 & MF2_AMBUSH)) + { + followtic |= FZT_SPAWNED; + /*if (metal->player->followmobj->flags2 & MF2_LINKDRAW) + followtic |= FZT_LINKDRAW;*/ + if (metal->player->followmobj->colorized) + followtic |= FZT_COLORIZED; + /*if (followtic & FZT_SKIN) + WRITEUINT8(demo_p,(UINT8)(((skin_t *)(metal->player->followmobj->skin))-skins));*/ + oldmetal.flags2 |= MF2_AMBUSH; + } + + temp = (INT16)((metal->player->followmobj->x-metal->x)>>8); + WRITEINT16(demo_p,temp); + temp = (INT16)((metal->player->followmobj->y-metal->y)>>8); + WRITEINT16(demo_p,temp); + temp = (INT16)((metal->player->followmobj->z-metal->z)>>8); + WRITEINT16(demo_p,temp); + /*if (followtic & FZT_SKIN) + WRITEUINT8(demo_p,metal->player->followmobj->sprite2);*/ + WRITEUINT16(demo_p,metal->player->followmobj->sprite); + WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits + WRITEUINT8(demo_p,metal->player->followmobj->color); + if (metal->player->followmobj->scale != metal->scale) + { + followtic |= FZT_SCALE; + WRITEFIXED(demo_p,metal->player->followmobj->scale); + } + + *followtic_p = followtic; + } + else + oldmetal.flags2 &= ~MF2_AMBUSH; + *ziptic_p = ziptic; // attention here for the ticcmd size! diff --git a/src/info.c b/src/info.c index cfaad552d..99cd12862 100644 --- a/src/info.c +++ b/src/info.c @@ -1800,21 +1800,7 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, 1, {A_BossScream}, 0, 0, S_CYBRAKDEMONVILEEXPLOSION1}, //S_CYBRAKDEMONVILEEXPLOSION3, // Metal Sonic - {SPR_METL, 0, 35, {NULL}, 0, 0, S_METALSONIC_WAIT1}, // S_METALSONIC_STAND - {SPR_METL, 1, 8, {NULL}, 0, 0, S_METALSONIC_WAIT2}, // S_METALSONIC_WAIT1 - {SPR_METL, 2, 8, {NULL}, 0, 0, S_METALSONIC_WAIT1}, // S_METALSONIC_WAIT2 - {SPR_METL, 3, 4, {NULL}, 0, 0, S_METALSONIC_WALK2}, // S_METALSONIC_WALK1 - {SPR_METL, 4, 4, {NULL}, 0, 0, S_METALSONIC_WALK3}, // S_METALSONIC_WALK2 - {SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_WALK4}, // S_METALSONIC_WALK3 - {SPR_METL, 6, 4, {NULL}, 0, 0, S_METALSONIC_WALK5}, // S_METALSONIC_WALK4 - {SPR_METL, 7, 4, {NULL}, 0, 0, S_METALSONIC_WALK6}, // S_METALSONIC_WALK5 - {SPR_METL, 6, 4, {NULL}, 0, 0, S_METALSONIC_WALK7}, // S_METALSONIC_WALK6 - {SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_WALK8}, // S_METALSONIC_WALK7 - {SPR_METL, 4, 4, {NULL}, 0, 0, S_METALSONIC_WALK1}, // S_METALSONIC_WALK8 - {SPR_METL, 8, 2, {NULL}, 0, 0, S_METALSONIC_RUN2}, // S_METALSONIC_RUN1 - {SPR_METL, 9, 2, {NULL}, 0, 0, S_METALSONIC_RUN3}, // S_METALSONIC_RUN2 - {SPR_METL, 10, 2, {NULL}, 0, 0, S_METALSONIC_RUN4}, // S_METALSONIC_RUN3 - {SPR_METL, 9, 2, {NULL}, 0, 0, S_METALSONIC_RUN1}, // S_METALSONIC_RUN4 + {SPR_PLAY, SPR2_STND, -1, {NULL}, 0, 0, S_METALSONIC_RACE}, // S_METALSONIC_RACE {SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT {SPR_METL, 12|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR @@ -6677,16 +6663,16 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_METALSONIC_RACE 207, // doomednum - S_METALSONIC_STAND, // spawnstate + S_METALSONIC_RACE, // spawnstate 8, // spawnhealth - S_METALSONIC_WALK1, // seestate + S_NULL, // seestate sfx_None, // seesound 0, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound - S_METALSONIC_RUN1, // meleestate + S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate diff --git a/src/info.h b/src/info.h index e7f41f585..bc3626b92 100644 --- a/src/info.h +++ b/src/info.h @@ -1933,25 +1933,7 @@ typedef enum state S_CYBRAKDEMONVILEEXPLOSION3, // Metal Sonic (Race) - // S_PLAY_STND - S_METALSONIC_STAND, - // S_PLAY_TAP1 - S_METALSONIC_WAIT1, - S_METALSONIC_WAIT2, - // S_PLAY_WALK - S_METALSONIC_WALK1, - S_METALSONIC_WALK2, - S_METALSONIC_WALK3, - S_METALSONIC_WALK4, - S_METALSONIC_WALK5, - S_METALSONIC_WALK6, - S_METALSONIC_WALK7, - S_METALSONIC_WALK8, - // S_PLAY_SPD1 - S_METALSONIC_RUN1, - S_METALSONIC_RUN2, - S_METALSONIC_RUN3, - S_METALSONIC_RUN4, + S_METALSONIC_RACE, // Metal Sonic (Battle) S_METALSONIC_FLOAT, S_METALSONIC_VECTOR, diff --git a/src/p_inter.c b/src/p_inter.c index 9017f795d..44215d691 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3615,11 +3615,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } else if (inflictor && inflictor->flags & MF_MISSILE) return false; // Metal Sonic walk through flame !! - else + else if (!player->powers[pw_flashing]) { // Oh no! Metal Sonic is hit !! P_ShieldDamage(player, inflictor, source, damage, damagetype); return true; } + return false; } else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) // ignore bouncing & such in invulnerability { diff --git a/src/p_mobj.c b/src/p_mobj.c index 5735dc27b..b74e08e54 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10399,8 +10399,13 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) if (nummaprings >= 0) nummaprings++; break; - case MT_METALSONIC_BATTLE: case MT_METALSONIC_RACE: + mobj->skin = &skins[5]; + mobj->color = skins[5].prefcolor; + mobj->sprite2 = P_GetSkinSprite2(mobj->skin, mobj->frame & FF_FRAMEMASK, NULL); + mobj->frame &= ~FF_FRAMEMASK; + /* FALLTHRU */ + case MT_METALSONIC_BATTLE: sc = 5; break; case MT_FANG: @@ -11248,6 +11253,8 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) } if (mthing->options & MTF_AMBUSH) P_SetPlayerMobjState(mobj, S_PLAY_FALL); + else if (metalrecording) + P_SetPlayerMobjState(mobj, S_PLAY_WAIT); } else z = floor; diff --git a/src/p_user.c b/src/p_user.c index f81f6d956..a4e500c7c 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11455,7 +11455,7 @@ void P_PlayerThink(player_t *player) // deez New User eXperiences. { - angle_t diff = 0; + angle_t oldang = player->drawangle, diff = 0; UINT8 factor; // Directionchar! // Camera angle stuff. @@ -11573,6 +11573,22 @@ void P_PlayerThink(player_t *player) player->drawangle += diff; } + // reset from waiting to standing when turning on the spot + if (player->panim == PA_IDLE) + { + diff = player->drawangle - oldang; + if (diff > ANGLE_180) + diff = InvAngle(diff); + if (diff > ANG10/2) + { + statenum_t stat = player->mo->state-states; + if (stat == S_PLAY_WAIT) + P_SetPlayerMobjState(player->mo, S_PLAY_STND); + else if (stat == S_PLAY_STND) + player->mo->tics++; + } + } + // Autobrake! check ST_drawInput if you modify this { boolean currentlyonground = P_IsObjectOnGround(player->mo); @@ -11812,7 +11828,7 @@ void P_PlayerThink(player_t *player) #define dashmode player->dashmode // Dash mode - thanks be to Iceman404 - if ((player->charflags & SF_DASHMODE) && !(player->gotflag) && !(maptol & TOL_NIGHTS)) // woo, dashmode! no nights tho. + if ((player->charflags & SF_DASHMODE) && !(player->gotflag) && !(maptol & TOL_NIGHTS) && !metalrecording) // woo, dashmode! no nights tho. { boolean totallyradical = player->speed >= FixedMul(player->runspeed, player->mo->scale); boolean floating = (player->secondjump == 1); diff --git a/src/r_things.c b/src/r_things.c index 00eaae1c2..22f9c5d89 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2692,6 +2692,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) || (modeattacking) // If you have someone else's run you might as well take a look || (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1. || (netgame && (cv_forceskin.value == skinnum)) // Force 2. + || (metalrecording && skinnum == 5) // Force 3. ); } From 2fd47fc70d2420bcb7c93a602905ccd79fc0dae9 Mon Sep 17 00:00:00 2001 From: lachwright Date: Tue, 29 Oct 2019 15:32:03 +0800 Subject: [PATCH 02/14] Implement new states for Buggle, the new Aquabuzz --- src/dehacked.c | 6 +++--- src/info.c | 10 +++++----- src/info.h | 6 +++--- src/p_inter.c | 2 +- src/p_mobj.c | 7 ++++++- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 34ee1f170..534cabb0b 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7253,8 +7253,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_BUMBLEBORE_STUCK2", "S_BUMBLEBORE_DIE", - "S_BBUZZFLY1", - "S_BBUZZFLY2", + "S_BUGGLEIDLE", + "S_BUGGLEFLY", "S_SMASHSPIKE_FLOAT", "S_SMASHSPIKE_EASE1", @@ -8093,7 +8093,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_HIVEELEMENTAL", "MT_BUMBLEBORE", - "MT_BUBBLEBUZZ", + "MT_BUGGLE", "MT_SMASHINGSPIKEBALL", "MT_CACOLANTERN", diff --git a/src/info.c b/src/info.c index cfaad552d..daa2029a6 100644 --- a/src/info.c +++ b/src/info.c @@ -3863,8 +3863,8 @@ state_t states[NUMSTATES] = {SPR_BUMB, 5, 120, {NULL}, 0, 0, S_BUMBLEBORE_DIE}, // S_BUMBLEBORE_STUCK2 {SPR_BUMB, 5, 0, {A_CryingToMomma}, 0, 0, S_XPLD1}, // S_BUMBLEBORE_DIE - {SPR_BBUZ, 0, 2, {NULL}, 0, 0, S_BBUZZFLY2}, // S_BBUZZFLY1 - {SPR_BBUZ, 1, 2, {NULL}, 0, 0, S_BBUZZFLY1}, // S_BBUZZFLY2 + {SPR_BBUZ, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BUGGLEIDLE + {SPR_BBUZ, FF_ANIMATE, -1, {NULL}, 1, 2, S_NULL}, // S_BUGGLEFLY {SPR_FMCE, 0, 20, {NULL}, 0, 0, S_SMASHSPIKE_EASE1}, // S_SMASHSPIKE_FLOAT {SPR_FMCE, 0, 4, {A_ZThrust}, 4, (1<<16)|1, S_SMASHSPIKE_EASE2}, // S_SMASHSPIKE_EASE1 @@ -20128,11 +20128,11 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_BUBBLEBUZZ + { // MT_BUGGLE 124, // doomednum - S_BBUZZFLY1, // spawnstate + S_BUGGLEIDLE, // spawnstate 1, // spawnhealth - S_BBUZZFLY1, // seestate + S_BUGGLEFLY, // seestate sfx_None, // seesound 2, // reactiontime sfx_None, // attacksound diff --git a/src/info.h b/src/info.h index e7f41f585..20b471811 100644 --- a/src/info.h +++ b/src/info.h @@ -3927,8 +3927,8 @@ typedef enum state S_BUMBLEBORE_STUCK2, S_BUMBLEBORE_DIE, - S_BBUZZFLY1, - S_BBUZZFLY2, + S_BUGGLEIDLE, + S_BUGGLEFLY, S_SMASHSPIKE_FLOAT, S_SMASHSPIKE_EASE1, @@ -4789,7 +4789,7 @@ typedef enum mobj_type MT_HIVEELEMENTAL, MT_BUMBLEBORE, - MT_BUBBLEBUZZ, + MT_BUGGLE, MT_SMASHINGSPIKEBALL, MT_CACOLANTERN, diff --git a/src/p_inter.c b/src/p_inter.c index 9017f795d..64a7d2ff8 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2615,7 +2615,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->fuse = target->info->damage; break; - case MT_BUBBLEBUZZ: + case MT_BUGGLE: if (inflictor && inflictor->player // did a player kill you? Spawn relative to the player so they're bound to get it && P_AproxDistance(inflictor->x - target->x, inflictor->y - target->y) <= inflictor->radius + target->radius + FixedMul(8*FRACUNIT, inflictor->scale) // close enough? && inflictor->z <= target->z + target->height + FixedMul(8*FRACUNIT, inflictor->scale) diff --git a/src/p_mobj.c b/src/p_mobj.c index 5735dc27b..93a77bcda 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8406,7 +8406,7 @@ void P_MobjThinker(mobj_t *mobj) } } break; - case MT_BUBBLEBUZZ: + case MT_BUGGLE: mobj->eflags |= MFE_UNDERWATER; //P_MobjCheckWater(mobj); // solely for MFE_UNDERWATER for A_FlickySpawn { if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0 @@ -8420,6 +8420,9 @@ void P_MobjThinker(mobj_t *mobj) if (leveltime % mobj->info->painchance == 0) S_StartSound(mobj, mobj->info->activesound); + + if ((statenum_t)(mobj->state-states) != mobj->info->seestate) + P_SetMobjState(mobj, mobj->info->seestate); } else { @@ -8428,6 +8431,8 @@ void P_MobjThinker(mobj_t *mobj) mobj->momx >>= 1; mobj->momy >>= 1; mobj->momz >>= 1; + if ((statenum_t)(mobj->state-states) != mobj->info->spawnstate) + P_SetMobjState(mobj, mobj->info->spawnstate); } } break; From d7c84c06cb3a3e9c758d485e146e69b0a3924d56 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 29 Oct 2019 15:32:22 +0000 Subject: [PATCH 03/14] * Add thok auras to Metal playback. * Add height changes to demos and Metal playback (to properly place thok aura relative to object). * Fix followmobj recordings in reverse gravity (done via more strenuous flag setting + info height serialisation). * Make RA ghosts fade in from start tic, and go colorized on their final one. * Fix thok auras potentially doing bad things if they're set to MT_NULL. * Add sprite change support to Metal playback. * Re-enable some stuff I previously disabled for Metal recording/playback. * Make ALL objects spawned with skins properly acknowledge that their spawnstate's frame is a sprite2, rather than just specific objects. * Fix placement of Metal Sonic fume in reverse gravity. * Since not backwards compatible with the previous test build, increment DEMOVERSION again. (Don't worry, we've got like 65524 more versions allowed before we run out of possible DEMOVERSIONs...) --- src/g_game.c | 361 ++++++++++++++++++++++++++++++++++++--------------- src/p_mobj.c | 8 +- src/p_user.c | 18 +-- 3 files changed, 270 insertions(+), 117 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 27cece73d..b5e8a9509 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -289,7 +289,7 @@ static struct { // There is no conflict here. typedef struct demoghost { UINT8 checksum[16]; - UINT8 *buffer, *p, color; + UINT8 *buffer, *p, color, fadein; UINT16 version; mobj_t oldmo, *mo; struct demoghost *next; @@ -4044,7 +4044,7 @@ char *G_BuildMapTitle(INT32 mapnum) // DEMO RECORDING // -#define DEMOVERSION 0x000b +#define DEMOVERSION 0x000c #define DEMOHEADER "\xF0" "SRB2Replay" "\x0F" #define DF_GHOST 0x01 // This demo contains ghost data too! @@ -4083,7 +4083,7 @@ static ticcmd_t oldcmd; #define EZT_SCALE 0x10 // Changed size #define EZT_HIT 0x20 // Damaged a mobj #define EZT_SPRITE 0x40 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever) -// spare EZT slot 0x80 +#define EZT_HEIGHT 0x80 // Changed height // GZT_FOLLOW flags #define FZT_SPAWNED 0x01 // just been spawned @@ -4217,28 +4217,28 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum) void G_GhostAddThok(void) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST))) return; ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_THOK; } void G_GhostAddSpin(void) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST))) return; ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_SPIN; } void G_GhostAddRev(void) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST))) return; ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_REV; } void G_GhostAddFlip(void) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST))) return; ghostext.flags |= EZT_FLIP; } @@ -4258,7 +4258,7 @@ void G_GhostAddColor(ghostcolor_t color) void G_GhostAddScale(fixed_t scale) { - if (!demorecording || !(demoflags & DF_GHOST)) + if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST))) return; if (ghostext.lastscale == scale) { @@ -4284,6 +4284,7 @@ void G_WriteGhostTic(mobj_t *ghost) char ziptic = 0; UINT8 *ziptic_p; UINT32 i; + fixed_t height; if (!demo_p) return; @@ -4373,6 +4374,12 @@ void G_WriteGhostTic(mobj_t *ghost) ghostext.flags |= EZT_SPRITE; } + if ((height = FixedDiv(ghost->height, ghost->scale)) != oldghost.height) + { + oldghost.height = height; + ghostext.flags |= EZT_HEIGHT; + } + if (ghostext.flags) { ziptic |= GZT_EXTRA; @@ -4413,10 +4420,15 @@ void G_WriteGhostTic(mobj_t *ghost) } if (ghostext.flags & EZT_SPRITE) WRITEUINT16(demo_p,oldghost.sprite); + if (ghostext.flags & EZT_HEIGHT) + { + height >>= FRACBITS; + WRITEINT16(demo_p, height); + } ghostext.flags = 0; } - if (ghost->player && ghost->player->followmobj) // bloats tails runs but what can ya do + if (ghost->player && ghost->player->followmobj && !(ghost->player->followmobj->sprite == SPR_NULL || (ghost->player->followmobj->flags2 & MF2_DONTDRAW))) // bloats tails runs but what can ya do { INT16 temp; UINT8 *followtic_p = demo_p++; @@ -4430,6 +4442,7 @@ void G_WriteGhostTic(mobj_t *ghost) if (!(oldghost.flags2 & MF2_AMBUSH)) { followtic |= FZT_SPAWNED; + WRITEINT16(demo_p,ghost->player->followmobj->info->height>>FRACBITS); if (ghost->player->followmobj->flags2 & MF2_LINKDRAW) followtic |= FZT_LINKDRAW; if (ghost->player->followmobj->colorized) @@ -4564,13 +4577,21 @@ void G_ConsGhostTic(void) } if (xziptic & EZT_SPRITE) demo_p += sizeof(UINT16); + if (xziptic & EZT_HEIGHT) + demo_p += sizeof(INT16); } if (ziptic & GZT_FOLLOW) { // Even more... UINT8 followtic = READUINT8(demo_p); - if ((followtic & (FZT_SPAWNED|FZT_SKIN)) == (FZT_SPAWNED|FZT_SKIN)) - demo_p++; + if (followtic & FZT_SPAWNED) + { + demo_p += sizeof(INT16); + if (followtic & FZT_SKIN) + demo_p++; + } + if (followtic & FZT_SCALE) + demo_p += sizeof(fixed_t); demo_p += sizeof(INT16); demo_p += sizeof(INT16); demo_p += sizeof(INT16); @@ -4579,8 +4600,6 @@ void G_ConsGhostTic(void) demo_p += sizeof(UINT16); demo_p++; demo_p++; - if (followtic & FZT_SCALE) - demo_p += sizeof(fixed_t); } // Re-synchronise @@ -4666,6 +4685,11 @@ void G_GhostTicker(void) g->mo->z = g->oldmo.z; P_SetThingPosition(g->mo); g->mo->frame = g->oldmo.frame | tr_trans30<fadein) + { + g->mo->frame += (((--g->fadein)/6)<fadein is bad, and it's only set once, so... + g->mo->flags2 &= ~MF2_DONTDRAW; + } g->mo->sprite2 = g->oldmo.sprite2; if (ziptic & GZT_EXTRA) @@ -4723,33 +4747,38 @@ void G_GhostTicker(void) break; } } - if (type == MT_GHOST) + if (type != MT_NULL) { - mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us - mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<mo->x, g->mo->y, g->mo->z - FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK); - mobj->sprite = states[mobjinfo[type].spawnstate].sprite; - mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<tics = -1; // nope. - mobj->color = g->mo->color; - if (g->mo->eflags & MFE_VERTICALFLIP) + if (type == MT_GHOST) { - mobj->flags2 |= MF2_OBJECTFLIP; - mobj->eflags |= MFE_VERTICALFLIP; + mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us + mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<mo->scale); - mobj->destscale = g->mo->scale; + else + { + mobj = P_SpawnMobjFromMobj(g->mo, 0, 0, -FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK); + mobj->sprite = states[mobjinfo[type].spawnstate].sprite; + mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<color = g->mo->color; + mobj->skin = g->mo->skin; + P_SetScale(mobj, (mobj->destscale = g->mo->scale)); + + if (type == MT_THOK) // spintrail-specific modification for MT_THOK + { + mobj->frame = FF_TRANS80; + mobj->fuse = mobj->tics; + } + mobj->tics = -1; // nope. + } + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z+mobj->height; + P_UnsetThingPosition(mobj); + mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up... + P_SetThingPosition(mobj); + if (!mobj->fuse) + mobj->fuse = 8; + P_SetTarget(&mobj->target, g->mo); } - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_UnsetThingPosition(mobj); - mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up... - P_SetThingPosition(mobj); - mobj->fuse = 8; - P_SetTarget(&mobj->target, g->mo); } if (xziptic & EZT_HIT) { // Spawn hit poofs for killing things! @@ -4780,6 +4809,11 @@ void G_GhostTicker(void) } if (xziptic & EZT_SPRITE) g->mo->sprite = READUINT16(g->p); + if (xziptic & EZT_HEIGHT) + { + fixed_t temp = READINT16(g->p)<mo->height = FixedMul(temp, g->mo->scale); + } } // Tick ghost colors (Super and Mario Invincibility flashing) @@ -4806,13 +4840,16 @@ void G_GhostTicker(void) if (ziptic & GZT_FOLLOW) { // Even more... UINT8 followtic = READUINT8(g->p); + fixed_t temp; if (followtic & FZT_SPAWNED) { if (follow) P_RemoveMobj(follow); - P_SetTarget(&follow, P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z, MT_GHOST)); + P_SetTarget(&follow, P_SpawnMobjFromMobj(g->mo, 0, 0, 0, MT_GHOST)); P_SetTarget(&follow->tracer, g->mo); follow->tics = -1; + temp = READINT16(g->p)<height = FixedMul(follow->scale, temp); if (followtic & FZT_LINKDRAW) follow->flags2 |= MF2_LINKDRAW; @@ -4822,34 +4859,41 @@ void G_GhostTicker(void) if (followtic & FZT_SKIN) follow->skin = &skins[READUINT8(g->p)]; - - follow->eflags = (follow->eflags & ~MFE_VERTICALFLIP)|(g->mo->eflags & MFE_VERTICALFLIP); } if (follow) { - if (!(followtic & FZT_SPAWNED)) - { - if (xziptic & EZT_FLIP) - follow->eflags ^= MFE_VERTICALFLIP; - } + if (followtic & FZT_SCALE) + follow->destscale = READFIXED(g->p); + else + follow->destscale = g->mo->destscale; + if (follow->destscale != follow->scale) + P_SetScale(follow, follow->destscale); P_UnsetThingPosition(follow); - follow->x = g->mo->x + (READINT16(g->p)<<8); - follow->y = g->mo->y + (READINT16(g->p)<<8); - follow->z = g->mo->z + (READINT16(g->p)<<8); + temp = READINT16(g->p)<<8; + follow->x = g->mo->x + temp; + temp = READINT16(g->p)<<8; + follow->y = g->mo->y + temp; + temp = READINT16(g->p)<<8; + follow->z = g->mo->z + temp; P_SetThingPosition(follow); if (followtic & FZT_SKIN) follow->sprite2 = READUINT8(g->p); else follow->sprite2 = 0; follow->sprite = READUINT16(g->p); - follow->frame = (READUINT8(g->p)) | tr_trans30<frame = (READUINT8(g->p)) | (g->mo->frame & FF_TRANSMASK); follow->angle = g->mo->angle; follow->color = READUINT8(g->p); - if (followtic & FZT_SCALE) - P_SetScale(follow, (follow->destscale = READFIXED(g->p))); - else - P_SetScale(follow, (follow->destscale = g->mo->destscale)); + + if (!(followtic & FZT_SPAWNED)) + { + if (xziptic & EZT_FLIP) + { + follow->flags2 ^= MF2_OBJECTFLIP; + follow->eflags ^= MFE_VERTICALFLIP; + } + } } } else if (follow) @@ -4857,12 +4901,20 @@ void G_GhostTicker(void) P_RemoveMobj(follow); P_SetTarget(&follow, NULL); } -#undef follow // Demo ends after ghost data. if (*g->p == DEMOMARKER) { g->mo->momx = g->mo->momy = g->mo->momz = 0; +#if 1 // freeze frame (maybe more useful for time attackers) + g->mo->colorized = true; + if (follow) + follow->colorized = true; +#else // dissapearing act + g->mo->fuse = TICRATE; + if (follow) + follow->fuse = TICRATE; +#endif if (p) p->next = g->next; else @@ -4871,6 +4923,7 @@ void G_GhostTicker(void) continue; } p = g; +#undef follow } } @@ -4936,46 +4989,126 @@ void G_ReadMetalTic(mobj_t *metal) if (metal->destscale != metal->scale) P_SetScale(metal, metal->destscale); } + if (xziptic & EZT_THOKMASK) + { // Let's only spawn ONE of these per frame, thanks. + mobj_t *mobj; + INT32 type = -1; + if (metal->skin) + { + skin_t *skin = (skin_t *)metal->skin; + switch (xziptic & EZT_THOKMASK) + { + case EZT_THOK: + type = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem; + break; + case EZT_SPIN: + type = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem; + break; + case EZT_REV: + type = skin->revitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem; + break; + } + } + if (type != MT_NULL) + { + if (type == MT_GHOST) + { + mobj = P_SpawnGhostMobj(metal); // does a large portion of the work for us + } + else + { + mobj = P_SpawnMobjFromMobj(metal, 0, 0, -FixedDiv(FixedMul(metal->info->height, metal->scale) - metal->height,3*FRACUNIT), MT_THOK); + mobj->sprite = states[mobjinfo[type].spawnstate].sprite; + mobj->frame = states[mobjinfo[type].spawnstate].frame; + mobj->angle = metal->angle; + mobj->color = metal->color; + mobj->skin = metal->skin; + P_SetScale(mobj, (mobj->destscale = metal->scale)); + + if (type == MT_THOK) // spintrail-specific modification for MT_THOK + { + mobj->frame = FF_TRANS70; + mobj->fuse = mobj->tics; + } + mobj->tics = -1; // nope. + } + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z+mobj->height; + P_UnsetThingPosition(mobj); + mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up... + P_SetThingPosition(mobj); + if (!mobj->fuse) + mobj->fuse = 8; + P_SetTarget(&mobj->target, metal); + } + } + if (xziptic & EZT_SPRITE) + metal->sprite = READUINT16(metal_p); + if (xziptic & EZT_HEIGHT) + { + fixed_t temp = READINT16(metal_p)<height = FixedMul(temp, metal->scale); + } } #define follow metal->tracer if (ziptic & GZT_FOLLOW) { // Even more... UINT8 followtic = READUINT8(metal_p); + fixed_t temp; if (followtic & FZT_SPAWNED) { if (follow) P_RemoveMobj(follow); - P_SetTarget(&follow, P_SpawnMobj(metal->x, metal->y, metal->z, MT_GHOST)); + P_SetTarget(&follow, P_SpawnMobjFromMobj(metal, 0, 0, 0, MT_GHOST)); P_SetTarget(&follow->tracer, metal); follow->tics = -1; + temp = READINT16(metal_p)<height = FixedMul(follow->scale, temp); + + if (followtic & FZT_LINKDRAW) + follow->flags2 |= MF2_LINKDRAW; if (followtic & FZT_COLORIZED) follow->colorized = true; - follow->eflags = (follow->eflags & ~MFE_VERTICALFLIP)|(metal->eflags & MFE_VERTICALFLIP); + if (followtic & FZT_SKIN) + follow->skin = &skins[READUINT8(metal_p)]; } if (follow) { - if (!(followtic & FZT_SPAWNED)) - { - if (xziptic & EZT_FLIP) - follow->eflags ^= MFE_VERTICALFLIP; - } + if (followtic & FZT_SCALE) + follow->destscale = READFIXED(metal_p); + else + follow->destscale = metal->destscale; + if (follow->destscale != follow->scale) + P_SetScale(follow, follow->destscale); P_UnsetThingPosition(follow); - follow->x = metal->x + (READINT16(metal_p)<<8); - follow->y = metal->y + (READINT16(metal_p)<<8); - follow->z = metal->z + (READINT16(metal_p)<<8); + temp = READINT16(metal_p)<<8; + follow->x = metal->x + temp; + temp = READINT16(metal_p)<<8; + follow->y = metal->y + temp; + temp = READINT16(metal_p)<<8; + follow->z = metal->z + temp; P_SetThingPosition(follow); + if (followtic & FZT_SKIN) + follow->sprite2 = READUINT8(metal_p); + else + follow->sprite2 = 0; follow->sprite = READUINT16(metal_p); follow->frame = READUINT32(metal_p); // NOT & FF_FRAMEMASK here, so 32 bits follow->angle = metal->angle; follow->color = READUINT8(metal_p); - if (followtic & FZT_SCALE) - P_SetScale(follow, (follow->destscale = READFIXED(metal_p))); - else - P_SetScale(follow, (follow->destscale = metal->destscale)); + + if (!(followtic & FZT_SPAWNED)) + { + if (xziptic & EZT_FLIP) + { + follow->flags2 ^= MF2_OBJECTFLIP; + follow->eflags ^= MFE_VERTICALFLIP; + } + } } } else if (follow) @@ -4997,8 +5130,9 @@ void G_WriteMetalTic(mobj_t *metal) { UINT8 ziptic = 0; UINT8 *ziptic_p; + fixed_t height; - if (!demo_p) // demo_p will be NULL until the race start linedef executor is triggered! + if (!demo_p) // demo_p will be NULL until the race start linedef executor is activated! return; demo_p++; ziptic_p = demo_p++; // the ziptic, written at the end of this function @@ -5077,32 +5211,43 @@ void G_WriteMetalTic(mobj_t *metal) WRITEUINT8(demo_p,oldmetal.sprite2); } + // Check for sprite set changes + if (metal->sprite != oldmetal.sprite) { - UINT8 *exttic_p = NULL; - UINT8 exttic = 0; - if ((metal->eflags & MFE_VERTICALFLIP) != (oldmetal.eflags & MFE_VERTICALFLIP)) - { - if (!exttic_p) - exttic_p = demo_p++; - exttic |= EZT_FLIP; - oldmetal.eflags ^= MFE_VERTICALFLIP; - } - if (metal->scale != oldmetal.scale) - { - if (!exttic_p) - exttic_p = demo_p++; - exttic |= EZT_SCALE; - WRITEFIXED(demo_p,metal->scale); - oldmetal.scale = metal->scale; - } - if (exttic_p) - { - *exttic_p = exttic; - ziptic |= GZT_EXTRA; - } + oldmetal.sprite = metal->sprite; + ghostext.flags |= EZT_SPRITE; } - if (metal->player && metal->player->followmobj) + if ((height = FixedDiv(metal->height, metal->scale)) != oldmetal.height) + { + oldmetal.height = height; + ghostext.flags |= EZT_HEIGHT; + } + + if (ghostext.flags & ~(EZT_COLOR|EZT_HIT)) // these two aren't handled by metal ever + { + ziptic |= GZT_EXTRA; + + if (ghostext.scale == ghostext.lastscale) + ghostext.flags &= ~EZT_SCALE; + + WRITEUINT8(demo_p,ghostext.flags); + if (ghostext.flags & EZT_SCALE) + { + WRITEFIXED(demo_p,ghostext.scale); + ghostext.lastscale = ghostext.scale; + } + if (ghostext.flags & EZT_SPRITE) + WRITEUINT16(demo_p,oldmetal.sprite); + if (ghostext.flags & EZT_HEIGHT) + { + height >>= FRACBITS; + WRITEINT16(demo_p, height); + } + ghostext.flags = 0; + } + + if (metal->player && metal->player->followmobj && !(metal->player->followmobj->sprite == SPR_NULL || (metal->player->followmobj->flags2 & MF2_DONTDRAW))) { INT16 temp; UINT8 *followtic_p = demo_p++; @@ -5110,34 +5255,39 @@ void G_WriteMetalTic(mobj_t *metal) ziptic |= GZT_FOLLOW; + if (metal->player->followmobj->skin) + followtic |= FZT_SKIN; + if (!(oldmetal.flags2 & MF2_AMBUSH)) { followtic |= FZT_SPAWNED; - /*if (metal->player->followmobj->flags2 & MF2_LINKDRAW) - followtic |= FZT_LINKDRAW;*/ + WRITEINT16(demo_p,metal->player->followmobj->info->height>>FRACBITS); + if (metal->player->followmobj->flags2 & MF2_LINKDRAW) + followtic |= FZT_LINKDRAW; if (metal->player->followmobj->colorized) followtic |= FZT_COLORIZED; - /*if (followtic & FZT_SKIN) - WRITEUINT8(demo_p,(UINT8)(((skin_t *)(metal->player->followmobj->skin))-skins));*/ + if (followtic & FZT_SKIN) + WRITEUINT8(demo_p,(UINT8)(((skin_t *)(metal->player->followmobj->skin))-skins)); oldmetal.flags2 |= MF2_AMBUSH; } + if (metal->player->followmobj->scale != metal->scale) + { + followtic |= FZT_SCALE; + WRITEFIXED(demo_p,metal->player->followmobj->scale); + } + temp = (INT16)((metal->player->followmobj->x-metal->x)>>8); WRITEINT16(demo_p,temp); temp = (INT16)((metal->player->followmobj->y-metal->y)>>8); WRITEINT16(demo_p,temp); temp = (INT16)((metal->player->followmobj->z-metal->z)>>8); WRITEINT16(demo_p,temp); - /*if (followtic & FZT_SKIN) - WRITEUINT8(demo_p,metal->player->followmobj->sprite2);*/ + if (followtic & FZT_SKIN) + WRITEUINT8(demo_p,metal->player->followmobj->sprite2); WRITEUINT16(demo_p,metal->player->followmobj->sprite); WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits WRITEUINT8(demo_p,metal->player->followmobj->color); - if (metal->player->followmobj->scale != metal->scale) - { - followtic |= FZT_SCALE; - WRITEFIXED(demo_p,metal->player->followmobj->scale); - } *followtic_p = followtic; } @@ -5344,6 +5494,9 @@ void G_BeginMetal(void) M_Memcpy(demo_p, "METL", 4); demo_p += 4; + memset(&ghostext,0,sizeof(ghostext)); + ghostext.lastscale = ghostext.scale = FRACUNIT; + // Set up our memory. memset(&oldmetal,0,sizeof(oldmetal)); oldmetal.x = mo->x; @@ -5992,7 +6145,9 @@ void G_AddGhost(char *defdemoname) gh->mo->state = states+S_PLAY_STND; gh->mo->sprite = gh->mo->state->sprite; gh->mo->sprite2 = (gh->mo->state->frame & FF_FRAMEMASK); - gh->mo->frame = tr_trans20<mo->frame = tr_trans30<mo->flags2 |= MF2_DONTDRAW; + gh->fadein = (9-3)*6; // fade from invisible to trans30 over as close to 35 tics as possible gh->mo->tics = -1; CONS_Printf(M_GetText("Added ghost %s from %s\n"), name, pdemoname); diff --git a/src/p_mobj.c b/src/p_mobj.c index b74e08e54..c87f0bd3c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10402,8 +10402,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_METALSONIC_RACE: mobj->skin = &skins[5]; mobj->color = skins[5].prefcolor; - mobj->sprite2 = P_GetSkinSprite2(mobj->skin, mobj->frame & FF_FRAMEMASK, NULL); - mobj->frame &= ~FF_FRAMEMASK; /* FALLTHRU */ case MT_METALSONIC_BATTLE: sc = 5; @@ -10471,6 +10469,12 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) if (!(mobj->flags & MF_NOTHINK)) P_AddThinker(THINK_MOBJ, &mobj->thinker); + if (mobj->skin) // correct inadequecies above. + { + mobj->sprite2 = P_GetSkinSprite2(mobj->skin, (mobj->frame & FF_FRAMEMASK), NULL); + mobj->frame &= ~FF_FRAMEMASK; + } + // Call action functions when the state is set if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC)) { diff --git a/src/p_user.c b/src/p_user.c index a4e500c7c..7ac9b34ed 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2048,8 +2048,7 @@ void P_SpawnThokMobj(player_t *player) mobj->eflags |= (player->mo->eflags & MFE_VERTICALFLIP); // scale - P_SetScale(mobj, player->mo->scale); - mobj->destscale = player->mo->scale; + P_SetScale(mobj, (mobj->destscale = player->mo->scale)); if (type == MT_THOK) // spintrail-specific modification for MT_THOK { @@ -2059,8 +2058,7 @@ void P_SpawnThokMobj(player_t *player) } P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do - if (demorecording) - G_GhostAddThok(); + G_GhostAddThok(); } // @@ -4574,8 +4572,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (player->revitem && !(leveltime % 5)) // Now spawn the color thok circle. { P_SpawnSpinMobj(player, player->revitem); - if (demorecording) - G_GhostAddRev(); + G_GhostAddRev(); } } @@ -8325,8 +8322,7 @@ static void P_MovePlayer(player_t *player) if (player->pflags & PF_SPINNING && P_AproxDistance(player->speed, player->mo->momz) > FixedMul(15<mo->scale) && !(player->pflags & PF_JUMPED)) { P_SpawnSpinMobj(player, player->spinitem); - if (demorecording) - G_GhostAddSpin(); + G_GhostAddSpin(); } @@ -11052,6 +11048,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) } fume->movecount = dashmode; // keeps track of previous dashmode value so we know whether Metal is entering or leaving it + fume->eflags = (fume->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP); // Make sure to flip in reverse gravity! fume->eflags = (fume->eflags & ~MFE_VERTICALFLIP) | (mo->eflags & MFE_VERTICALFLIP); // Make sure to flip in reverse gravity! // Finally, set its position @@ -11060,10 +11057,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) P_UnsetThingPosition(fume); fume->x = mo->x + P_ReturnThrustX(fume, angle, dist); fume->y = mo->y + P_ReturnThrustY(fume, angle, dist); - if (fume->eflags & MFE_VERTICALFLIP) - fume->z = mo->z + ((mo->height + fume->height) >> 1); - else - fume->z = mo->z + ((mo->height - fume->height) >> 1); + fume->z = mo->z + ((mo->height - fume->height) >> 1); P_SetThingPosition(fume); } From f3ba2c9339435822feb67d0518e4c52f59f44d0c Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 29 Oct 2019 15:59:59 +0000 Subject: [PATCH 04/14] I was right on the money - SendWeaponPref seems to have been delayed compared to earlier in development. Doesn't matter a lick for regular gameplay (net or otherwise), but absolutely mandatory to get it sorted ASAP in Record Attack. --- src/g_game.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index b5e8a9509..52a2d7566 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5434,22 +5434,36 @@ void G_BeginRecording(void) // And mobjtype_t is best with UINT32 too... WRITEUINT32(demo_p, player->followitem); - // Save pflag data + // Save pflag data - see SendWeaponPref() { UINT8 buf = 0; - if (player->pflags & PF_FLIPCAM) + pflags_t pflags = 0; + if (cv_flipcam.value) + { buf |= 0x01; - if (player->pflags & PF_ANALOGMODE) + pflags |= PF_FLIPCAM; + } + if (cv_analog.value) + { buf |= 0x02; - if (player->pflags & PF_DIRECTIONCHAR) + pflags |= PF_ANALOGMODE; + } + if (cv_directionchar.value) + { buf |= 0x04; - if (player->pflags & PF_AUTOBRAKE) + pflags |= PF_DIRECTIONCHAR; + } + if (cv_autobrake.value) + { buf |= 0x08; + pflags |= PF_AUTOBRAKE; + } if (cv_usejoystick.value) buf |= 0x10; CV_SetValue(&cv_showinputjoy, !!(cv_usejoystick.value)); WRITEUINT8(demo_p,buf); + player->pflags = pflags; } // Save netvar data From 91d2beebfa64a4a7285407845018e2ddf566517c Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 29 Oct 2019 17:38:14 +0000 Subject: [PATCH 05/14] * Add a death animation for killing the Metal object, in case somebody wants to Lua up a Sonic CD style race finish for the Metal object, or in case of the following... * Add an alternate DEMOMARKER for ending the Metal Recording on death, which kills the Metal object as well. * Add some more relevant exceptions to the "most objects are removed when touching a deathpit" thing, primarily for the sake of ghosts and Metal playback. --- src/d_clisrv.c | 2 +- src/g_game.c | 50 ++++++++++++++++++++++++++++++--------------- src/g_game.h | 2 +- src/info.c | 4 ++-- src/p_inter.c | 8 +++++++- src/p_mobj.c | 49 +++++++++++++++++++++++++++++++++----------- src/sdl/i_system.c | 4 ++-- src/win32/win_sys.c | 4 ++-- 8 files changed, 85 insertions(+), 38 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 411d847b5..860bde624 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2491,7 +2491,7 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) void CL_Reset(void) { if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); if (metalplayback) G_StopMetalDemo(); if (demorecording) diff --git a/src/g_game.c b/src/g_game.c index 52a2d7566..10e841f64 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3053,7 +3053,7 @@ static void G_DoCompleted(void) if (metalplayback) G_StopMetalDemo(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) @@ -4060,6 +4060,8 @@ char *G_BuildMapTitle(INT32 mapnum) #define ZT_BUTTONS 0x08 #define ZT_AIMING 0x10 #define DEMOMARKER 0x80 // demoend +#define METALDEATH 0x44 +#define METALSNICE 0x69 static ticcmd_t oldcmd; @@ -4901,7 +4903,6 @@ void G_GhostTicker(void) P_RemoveMobj(follow); P_SetTarget(&follow, NULL); } - // Demo ends after ghost data. if (*g->p == DEMOMARKER) { @@ -4934,7 +4935,24 @@ void G_ReadMetalTic(mobj_t *metal) if (!metal_p) return; + + switch (*metal_p) + { + case METALSNICE: + break; + case METALDEATH: + if (metal->tracer) + P_RemoveMobj(metal->tracer); + P_KillMobj(metal, NULL, NULL, 0); + /* FALLTHRU */ + case DEMOMARKER: + default: + // end of demo data stream + G_StopMetalDemo(); + return; + } metal_p++; + ziptic = READUINT8(metal_p); // Read changes from the tic @@ -5117,13 +5135,6 @@ void G_ReadMetalTic(mobj_t *metal) P_SetTarget(&follow, NULL); } #undef follow - - if (*metal_p == DEMOMARKER) - { - // end of demo data stream - G_StopMetalDemo(); - return; - } } void G_WriteMetalTic(mobj_t *metal) @@ -5134,7 +5145,8 @@ void G_WriteMetalTic(mobj_t *metal) if (!demo_p) // demo_p will be NULL until the race start linedef executor is activated! return; - demo_p++; + + WRITEUINT8(demo_p, METALSNICE); ziptic_p = demo_p++; // the ziptic, written at the end of this function #define MAXMOM (0xFFFF<<8) @@ -5300,7 +5312,7 @@ void G_WriteMetalTic(mobj_t *metal) // latest demos with mouse aiming byte in ticcmd if (demo_p >= demoend - 32) { - G_StopMetalRecording(); // no more space + G_StopMetalRecording(false); // no more space return; } } @@ -6282,19 +6294,23 @@ void G_StopMetalDemo(void) } // Stops metal sonic recording. -ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void) +ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill) { boolean saved = false; if (demo_p) { UINT8 *p = demobuffer+16; // checksum position + if (kill) + WRITEUINT8(demo_p, METALDEATH); // add the metal death marker + else + WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker #ifdef NOMD5 - UINT8 i; - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - for (i = 0; i < 16; i++, p++) - *p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. + { + UINT8 i; + for (i = 0; i < 16; i++, p++) + *p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. + } #else - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker md5_buffer((char *)p+16, demo_p - (p+16), (void *)p); // make a checksum of everything after the checksum in the file. #endif saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file. diff --git a/src/g_game.h b/src/g_game.h index 198cbc396..8c775c238 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -174,7 +174,7 @@ void G_AddGhost(char *defdemoname); void G_DoPlayMetal(void); void G_DoneLevelLoad(void); void G_StopMetalDemo(void); -ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void); +ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill); void G_StopDemo(void); boolean G_CheckDemoStatus(void); diff --git a/src/info.c b/src/info.c index 99cd12862..a418b1c51 100644 --- a/src/info.c +++ b/src/info.c @@ -6674,7 +6674,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_NULL, // deathstate + S_PLAY_DEAD, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed @@ -6684,7 +6684,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_SCENERY|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, diff --git a/src/p_inter.c b/src/p_inter.c index 44215d691..e25fb395a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2372,7 +2372,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if (target->player && !target->player->spectator) { if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording! - G_StopMetalRecording(); + G_StopMetalRecording(true); if (gametype == GT_MATCH // note, no team match suicide penalty && ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player))) { // Suicide penalty @@ -2761,6 +2761,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget } } break; + case MT_METALSONIC_RACE: + target->fuse = TICRATE*3; + target->momx = target->momy = target->momz = 0; + P_SetObjectMomZ(target, 14*FRACUNIT, false); + target->flags = (target->flags & ~MF_NOGRAVITY)|(MF_NOCLIP|MF_NOCLIPTHING); + break; default: break; } diff --git a/src/p_mobj.c b/src/p_mobj.c index c87f0bd3c..64c8d61d3 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2570,19 +2570,30 @@ static boolean P_ZMovement(mobj_t *mo) if (!mo->player && P_CheckDeathPitCollide(mo)) { - if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS || mo->type == MT_MINECART) + switch (mo->type) { - // Kill enemies, bosses and minecarts that fall into death pits. - if (mo->health) - { - P_KillMobj(mo, NULL, NULL, 0); - return false; - } - } - else - { - P_RemoveMobj(mo); - return false; + case MT_GHOST: + case MT_METALSONIC_RACE: + case MT_EXPLODE: + case MT_BOSSEXPLODE: + case MT_SONIC3KBOSSEXPLODE: + break; + default: + if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS || mo->type == MT_MINECART) + { + // Kill enemies, bosses and minecarts that fall into death pits. + if (mo->health) + { + P_KillMobj(mo, NULL, NULL, 0); + } + return false; + } + else + { + P_RemoveMobj(mo); + return false; + } + break; } } @@ -8271,6 +8282,20 @@ void P_MobjThinker(mobj_t *mobj) P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true); } break; + case MT_METALSONIC_RACE: + { + if (!(mobj->fuse % 8)) + { + fixed_t r = mobj->radius >> FRACBITS; + mobj_t *explosion = P_SpawnMobj( + mobj->x + (P_RandomRange(r, -r) << FRACBITS), + mobj->y + (P_RandomRange(r, -r) << FRACBITS), + mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), + MT_SONIC3KBOSSEXPLODE); + S_StartSound(explosion, sfx_s3kb4); + } + P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true); + } default: break; } diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index d7926e5b2..e7f8f2e4f 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2181,7 +2181,7 @@ void I_Quit(void) if (demorecording) G_CheckDemoStatus(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); D_QuitNetGame(); I_ShutdownMusic(); @@ -2299,7 +2299,7 @@ void I_Error(const char *error, ...) if (demorecording) G_CheckDemoStatus(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); D_QuitNetGame(); I_ShutdownMusic(); diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index 93b3ff523..c9fdb1c97 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -647,7 +647,7 @@ void I_Error(const char *error, ...) if (demorecording) G_CheckDemoStatus(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); D_QuitNetGame(); @@ -733,7 +733,7 @@ void I_Quit(void) if (demorecording) G_CheckDemoStatus(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); M_SaveConfig(NULL); // save game config, cvars.. #ifndef NONET From 42d380328cd9d256c814373f8e7bc23340af5a32 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 29 Oct 2019 18:17:04 +0000 Subject: [PATCH 06/14] Finish the Metal demo if the Metal playback object is dead. --- src/g_game.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index 10e841f64..569d777ab 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4936,6 +4936,12 @@ void G_ReadMetalTic(mobj_t *metal) if (!metal_p) return; + if (!metal->health) + { + G_StopMetalDemo(); + return; + } + switch (*metal_p) { case METALSNICE: From 297f1ad9a6edf2e4639f6c0c06cbfd27bf70ef21 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 29 Oct 2019 23:11:12 +0000 Subject: [PATCH 07/14] Metal Sonic battle improvements. * Tweaked to use new sprites. * Jet fume behaves much closer to Lach's wonderful work. * Instead of clobbering tracer to spawn powerup overlay, use hprev. * Change timings. One second less to charge up, but two seconds less to spin them out. * Remove terrible pinch overlay in favour of new dashmode-mimic flashing. --- src/info.c | 32 +++++++++--------- src/p_enemy.c | 5 +-- src/p_mobj.c | 91 +++++++++++++++++++++++++++++++++------------------ src/r_draw.c | 4 +++ 4 files changed, 83 insertions(+), 49 deletions(-) diff --git a/src/info.c b/src/info.c index a418b1c51..1064eaf42 100644 --- a/src/info.c +++ b/src/info.c @@ -1803,21 +1803,21 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_STND, -1, {NULL}, 0, 0, S_METALSONIC_RACE}, // S_METALSONIC_RACE {SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT - {SPR_METL, 12|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR - {SPR_METL, 11, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN - {SPR_METL, 13, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE - {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER - {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH - {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE - {SPR_METL, 16, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE - {SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT - {SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN - {SPR_METL, 13, 2, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1 - {SPR_METL, 13, 4, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2 - {SPR_METL, 13, 0, {A_Repeat}, 17, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3 - {SPR_METL, 13, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH4 - {SPR_METL, 11, 1, {A_BossScream}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 - {SPR_METL, 11, 7, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE2 + {SPR_METL, 16|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR + {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN + {SPR_METL, 17, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE + {SPR_METL, 18, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER + {SPR_METL, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH + {SPR_METL, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_NULL}, // S_METALSONIC_BOUNCE + {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE + {SPR_METL, 17, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT + {SPR_METL, 15, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN + {SPR_METL, 17, 2, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1 + {SPR_METL, 17, 4, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2 + {SPR_METL, 17, 0, {A_Repeat}, 17, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3 + {SPR_METL, 17, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH4 + {SPR_METL, 15, 1, {A_BossScream}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 + {SPR_METL, 15, 7, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE2 {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|FF_ANIMATE, -1, {NULL}, 11, 1, S_NULL}, // S_MSSHIELD_F1 {SPR_MSCF, FF_FULLBRIGHT|FF_ANIMATE|12, -1, {NULL}, 8, 2, S_NULL}, // S_MSSHIELD_F2 @@ -6734,7 +6734,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // speed 32*FRACUNIT, // radius 52*FRACUNIT, // height - 0, // display offset + 1, // display offset 0, // mass 0, // damage sfx_None, // activesound diff --git a/src/p_enemy.c b/src/p_enemy.c index cc2d64e8b..9d2a8e95a 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8966,10 +8966,11 @@ void A_BossJetFume(mobj_t *actor) P_SetTarget(&filler->target, actor); filler->fuse = 59; P_SetTarget(&actor->tracer, filler); - filler->destscale = actor->scale/3; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, (filler->destscale = actor->scale/3)); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; + filler->color = SKINCOLOR_ICY; + filler->colorized = true; } else if (locvar1 == 3) // Boss 4 jet flame { diff --git a/src/p_mobj.c b/src/p_mobj.c index 64c8d61d3..b7103ce65 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5595,16 +5595,22 @@ static void P_Boss9Thinker(mobj_t *mobj) if ((!mobj->target || !(mobj->target->flags & MF_SHOOTABLE))) { - if (mobj->tracer) - P_RemoveMobj(mobj->tracer); + if (mobj->hprev) + { + P_RemoveMobj(mobj->hprev); + P_SetTarget(&mobj->hprev, NULL); + } P_BossTargetPlayer(mobj, false); if (mobj->target && (!P_IsObjectOnGround(mobj->target) || mobj->target->player->pflags & PF_SPINNING)) P_SetTarget(&mobj->target, NULL); // Wait for them to hit the ground first if (!mobj->target) // Still no target, aww. { // Reset the boss. - if (mobj->tracer) - P_RemoveMobj(mobj->tracer); + if (mobj->hprev) + { + P_RemoveMobj(mobj->hprev); + P_SetTarget(&mobj->hprev, NULL); + } P_SetMobjState(mobj, mobj->info->spawnstate); mobj->fuse = 0; mobj->momx = FixedDiv(mobj->momx, FRACUNIT + (FRACUNIT>>2)); @@ -5618,7 +5624,7 @@ static void P_Boss9Thinker(mobj_t *mobj) return; } else if (!mobj->fuse) - mobj->fuse = 10*TICRATE; + mobj->fuse = 8*TICRATE; } // AI goes here. @@ -5645,16 +5651,18 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->angle -= InvAngle(angle)/8; // Alter your energy bubble's size/position - if (mobj->health > 3) + if (mobj->health > mobj->info->damage) { - mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); - P_SetScale(mobj->tracer, mobj->tracer->destscale); - } + if (mobj->hprev) + { + mobj->hprev->destscale = FRACUNIT + (2*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); + P_SetScale(mobj->hprev, mobj->hprev->destscale); - P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2); - mobj->tracer->momx = mobj->momx; - mobj->tracer->momy = mobj->momy; - mobj->tracer->momz = mobj->momz; + P_TeleportMove(mobj->hprev, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->hprev->height/2); + mobj->hprev->momx = mobj->momx; + mobj->hprev->momy = mobj->momy; + mobj->hprev->momz = mobj->momz; + } // Firin' mah lazors - INDICATOR if (mobj->fuse > TICRATE/2) @@ -5742,6 +5750,7 @@ static void P_Boss9Thinker(mobj_t *mobj) S_StartSound(mobj, sfx_s3kb3); } } + } // up... mobj->z += mobj->height/2; @@ -5768,12 +5777,12 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->health > mobj->info->damage) { P_SetScale(missile, FRACUNIT/3); - missile->color = SKINCOLOR_GOLD; // sonic cd electric power + missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power } else { P_SetScale(missile, FRACUNIT/5); - missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power + missile->color = SKINCOLOR_SUNSET; // sonic cd electric power } missile->destscale = missile->scale*2; missile->scalespeed = abs(missile->scale - missile->destscale)/missile->fuse; @@ -5885,8 +5894,6 @@ static void P_Boss9Thinker(mobj_t *mobj) return; } - P_SpawnGhostMobj(mobj); - // Pinball attack! if (mobj->movecount == 3 && (mobj->movedir == 0 || mobj->movedir == 2)) { @@ -5901,20 +5908,20 @@ static void P_Boss9Thinker(mobj_t *mobj) if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) { // Hit a wall? Find a direction to bounce mobj->threshold--; - P_SetMobjState(mobj, mobj->state->nextstate); if (!mobj->threshold) { // failed bounce! S_StartSound(mobj, sfx_mspogo); P_BounceMove(mobj); mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0); mobj->momz = 4*FRACUNIT; mobj->flags &= ~MF_PAIN; - mobj->fuse = 10*TICRATE; + mobj->fuse = 8*TICRATE; mobj->movecount = 0; P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION); P_SetMobjState(mobj, mobj->info->meleestate); } else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. + P_SetMobjState(mobj, mobj->state->nextstate); S_StartSound(mobj, sfx_s3k5a); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); mobj->reactiontime = TICRATE - 5*(mobj->info->damage - mobj->health); // targetting time @@ -5931,6 +5938,8 @@ static void P_Boss9Thinker(mobj_t *mobj) return; } + P_SpawnGhostMobj(mobj); + // Vector form dodge! mobj->angle += mobj->movedir; P_InstaThrust(mobj, mobj->angle, -speed); @@ -6027,7 +6036,7 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->health > mobj->info->damage) { // No more bubble if we're broken (pinch phase) mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT); - P_SetTarget(&mobj->tracer, shield); + P_SetTarget(&mobj->hprev, shield); P_SetTarget(&shield->target, mobj); // Attack 2: Energy shot! @@ -6058,14 +6067,15 @@ static void P_Boss9Thinker(mobj_t *mobj) } else { - mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT); + /*mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT); P_SetTarget(&mobj->tracer, shield); P_SetTarget(&shield->target, mobj); shield->height -= 20*FRACUNIT; // different offset... - P_SetMobjState(shield, S_MSSHIELD_F2); + P_SetMobjState(shield, S_MSSHIELD_F2);*/ + P_SetMobjState(mobj, S_METALSONIC_BOUNCE); //P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); -- why does this happen twice? see case 2... } - mobj->fuse = 4*TICRATE; + mobj->fuse = 3*TICRATE; mobj->flags |= MF_PAIN; if (mobj->info->attacksound) S_StartSound(mobj, mobj->info->attacksound); @@ -6076,14 +6086,14 @@ static void P_Boss9Thinker(mobj_t *mobj) case 2: { // We're all charged and ready now! Unleash the fury!! - mobj_t *removemobj = mobj->tracer; S_StopSound(mobj); - P_SetTarget(&mobj->tracer, mobj->hnext); - P_RemoveMobj(removemobj); + if (mobj->hprev) + { + P_RemoveMobj(mobj->hprev); + P_SetTarget(&mobj->hprev, NULL); + } if (mobj->health <= mobj->info->damage) { - mobj_t *whoosh; - // Attack 1: Pinball dash! if (mobj->health == 1) mobj->movedir = 0; @@ -6099,6 +6109,7 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->watertop = mobj->target->floorz + 16*FRACUNIT; P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); +#if 0 whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct whoosh->frame = FF_FULLBRIGHT; whoosh->sprite = SPR_ARMA; @@ -6106,9 +6117,13 @@ static void P_Boss9Thinker(mobj_t *mobj) whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale); whoosh->height = 38*whoosh->scale; whoosh->fuse = 10; - whoosh->color = SKINCOLOR_MAGENTA; + whoosh->color = SKINCOLOR_SUNSET; whoosh->colorized = true; whoosh->flags |= MF_NOCLIPHEIGHT; +#endif + + P_SetMobjState(mobj->tracer, S_JETFUMEFLASH); + P_SetScale(mobj->tracer, mobj->scale << 1); } else { @@ -6123,7 +6138,7 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->watertop = mobj->target->floorz + 32*FRACUNIT; P_SetMobjState(mobj, mobj->info->spawnstate); mobj->flags &= ~MF_PAIN; - mobj->fuse = 10*TICRATE; + mobj->fuse = 8*TICRATE; break; } mobj->movecount++; @@ -8738,11 +8753,17 @@ void P_MobjThinker(mobj_t *mobj) } else if (mobj->fuse == 59) { + boolean dashmod = ((mobj->target->flags & MF_PAIN) && (mobj->target->health <= mobj->target->info->damage)); jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, -mobj->target->radius); jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, -mobj->target->radius); P_UnsetThingPosition(mobj); mobj->x = jetx; mobj->y = jety; + mobj->destscale = mobj->target->scale; + if (!(dashmod && mobj->target->state == states+S_METALSONIC_BOUNCE)) + { + mobj->destscale = (mobj->destscale + FixedDiv(R_PointToDist2(0, 0, mobj->target->momx, mobj->target->momy), 36*mobj->target->scale))/3; + } if (mobj->target->eflags & MFE_VERTICALFLIP) mobj->z = mobj->target->z + mobj->target->height/2 + mobj->height/2; else @@ -8750,6 +8771,14 @@ void P_MobjThinker(mobj_t *mobj) mobj->floorz = mobj->z; mobj->ceilingz = mobj->z+mobj->height; P_SetThingPosition(mobj); + if (dashmod) + { + mobj->color = SKINCOLOR_SUNSET; + if (mobj->target->movecount == 3 && !mobj->target->reactiontime && (mobj->target->movedir == 0 || mobj->target->movedir == 2)) + P_SpawnGhostMobj(mobj); + } + else + mobj->color = SKINCOLOR_ICY; } mobj->fuse++; } @@ -10426,9 +10455,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) break; case MT_METALSONIC_RACE: mobj->skin = &skins[5]; - mobj->color = skins[5].prefcolor; /* FALLTHRU */ case MT_METALSONIC_BATTLE: + mobj->color = skins[5].prefcolor; sc = 5; break; case MT_FANG: diff --git a/src/r_draw.c b/src/r_draw.c index bb70a319f..6fc8d6599 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -567,8 +567,12 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U else if (skinnum == TC_METALSONIC) { for (i = 0; i < 6; i++) + { dest_colormap[Color_Index[SKINCOLOR_BLUE-1][12-i]] = Color_Index[SKINCOLOR_BLUE-1][i]; + } dest_colormap[159] = dest_colormap[253] = dest_colormap[254] = 0; + for (i = 0; i < 16; i++) + dest_colormap[96+i] = dest_colormap[Color_Index[SKINCOLOR_COBALT-1][i]]; } else if (skinnum == TC_DASHMODE) // This is a long one, because MotorRoach basically hand-picked the indices { From ee69551d7b26ee026f37c5a0529d391e526da8ae Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 29 Oct 2019 23:24:00 +0000 Subject: [PATCH 08/14] Give the clone fighter's vectorisation colour, rather than forcing greyscale. --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index b7103ce65..2a8d22b03 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5938,7 +5938,7 @@ static void P_Boss9Thinker(mobj_t *mobj) return; } - P_SpawnGhostMobj(mobj); + P_SpawnGhostMobj(mobj)->colorized = false; // Vector form dodge! mobj->angle += mobj->movedir; From f8d9213fca1cdeb60fac5f86645e230137af741f Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 31 Oct 2019 00:32:19 +0800 Subject: [PATCH 09/14] WIP new states for Glaregoyle --- src/dehacked.c | 58 +++++++++++++++++++++++----------------------- src/info.c | 62 +++++++++++++++++++++++++------------------------- src/info.h | 58 +++++++++++++++++++++++----------------------- src/p_mobj.c | 8 +++---- 4 files changed, 93 insertions(+), 93 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 534cabb0b..a5dc1c4c1 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5662,7 +5662,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_ARROW", "S_ARROWBONK", - // Trapgoyle Demon fire + // Glaregoyle Demon fire "S_DEMONFIRE", // GFZ flowers @@ -6030,29 +6030,29 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_WALLVINE_LONG", "S_WALLVINE_SHORT", - // Trapgoyles - "S_TRAPGOYLE", - "S_TRAPGOYLE_CHECK", - "S_TRAPGOYLE_FIRE1", - "S_TRAPGOYLE_FIRE2", - "S_TRAPGOYLE_FIRE3", - "S_TRAPGOYLEUP", - "S_TRAPGOYLEUP_CHECK", - "S_TRAPGOYLEUP_FIRE1", - "S_TRAPGOYLEUP_FIRE2", - "S_TRAPGOYLEUP_FIRE3", - "S_TRAPGOYLEDOWN", - "S_TRAPGOYLEDOWN_CHECK", - "S_TRAPGOYLEDOWN_FIRE1", - "S_TRAPGOYLEDOWN_FIRE2", - "S_TRAPGOYLEDOWN_FIRE3", - "S_TRAPGOYLELONG", - "S_TRAPGOYLELONG_CHECK", - "S_TRAPGOYLELONG_FIRE1", - "S_TRAPGOYLELONG_FIRE2", - "S_TRAPGOYLELONG_FIRE3", - "S_TRAPGOYLELONG_FIRE4", - "S_TRAPGOYLELONG_FIRE5", + // Glaregoyles + "S_GLAREGOYLE", + "S_GLAREGOYLE_CHECK", + "S_GLAREGOYLE_FIRE1", + "S_GLAREGOYLE_FIRE2", + "S_GLAREGOYLE_FIRE3", + "S_GLAREGOYLEUP", + "S_GLAREGOYLEUP_CHECK", + "S_GLAREGOYLEUP_FIRE1", + "S_GLAREGOYLEUP_FIRE2", + "S_GLAREGOYLEUP_FIRE3", + "S_GLAREGOYLEDOWN", + "S_GLAREGOYLEDOWN_CHECK", + "S_GLAREGOYLEDOWN_FIRE1", + "S_GLAREGOYLEDOWN_FIRE2", + "S_GLAREGOYLEDOWN_FIRE3", + "S_GLAREGOYLELONG", + "S_GLAREGOYLELONG_CHECK", + "S_GLAREGOYLELONG_FIRE1", + "S_GLAREGOYLELONG_FIRE2", + "S_GLAREGOYLELONG_FIRE3", + "S_GLAREGOYLELONG_FIRE4", + "S_GLAREGOYLELONG_FIRE5", // ATZ's Red Crystal/Target "S_TARGET_IDLE", @@ -7650,7 +7650,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_CANNONBALL", // Cannonball "MT_CANNONBALLDECOR", // Decorative/still cannonball "MT_ARROW", // Arrow - "MT_DEMONFIRE", // Trapgoyle fire + "MT_DEMONFIRE", // Glaregoyle fire // Greenflower Scenery "MT_GFZFLOWER1", @@ -7813,10 +7813,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Egg Rock Scenery // Azure Temple Scenery - "MT_TRAPGOYLE", - "MT_TRAPGOYLEUP", - "MT_TRAPGOYLEDOWN", - "MT_TRAPGOYLELONG", + "MT_GLAREGOYLE", + "MT_GLAREGOYLEUP", + "MT_GLAREGOYLEDOWN", + "MT_GLAREGOYLELONG", "MT_TARGET", "MT_GREENFLAME", diff --git a/src/info.c b/src/info.c index daa2029a6..9659c9712 100644 --- a/src/info.c +++ b/src/info.c @@ -2579,32 +2579,32 @@ state_t states[NUMSTATES] = {SPR_WVIN, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_LONG {SPR_WVIN, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_SHORT - // Trapgoyles - {SPR_BGAR, 0, 67, {NULL}, 0, 0, S_TRAPGOYLE_CHECK}, // S_TRAPGOYLE - {SPR_BGAR, 0, 3, {NULL}, 0, 0, S_TRAPGOYLE_FIRE1}, // S_TRAPGOYLE_CHECK - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLE_FIRE2}, // S_TRAPGOYLE_FIRE1 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLE_FIRE3}, // S_TRAPGOYLE_FIRE2 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLE}, // S_TRAPGOYLE_FIRE3 + // Glaregoyles + {SPR_BGAR, FF_ANIMATE|1, 52, {NULL}, 1, 0, S_GLAREGOYLE_WARNING}, // S_GLAREGOYLE + {SPR_BGAR, 2, 6, {NULL}, 1, 2, S_GLAREGOYLE_FIRE}, // S_GLAREGOYLE_WARNING + {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLE_LOOP}, // S_GLAREGOYLE_FIRE + {SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLE_FIRE, S_GLAREGOYLE_COOLDOWN}, // S_GLAREGOYLE_LOOP + {SPR_BGAR, FF_ANIMATE|1, 12, {NULL}, 1, 6, S_GLAREGOYLE}, // S_GLAREGOYLE_COOLDOWN - {SPR_BGAR, 0, 67, {NULL}, 0, 0, S_TRAPGOYLEUP_CHECK}, // S_TRAPGOYLEUP - {SPR_BGAR, 0, 3, {NULL}, 0, 0, S_TRAPGOYLEUP_FIRE1}, // S_TRAPGOYLEUP_CHECK - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_TRAPGOYLEUP_FIRE2}, // S_TRAPGOYLEUP_FIRE1 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_TRAPGOYLEUP_FIRE3}, // S_TRAPGOYLEUP_FIRE2 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_TRAPGOYLEUP}, // S_TRAPGOYLEUP_FIRE3 + {SPR_BGAR, 0, 67, {NULL}, 0, 0, S_GLAREGOYLEUP_CHECK}, // S_GLAREGOYLEUP + {SPR_BGAR, 0, 3, {NULL}, 0, 0, S_GLAREGOYLEUP_FIRE1}, // S_GLAREGOYLEUP_CHECK + {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_GLAREGOYLEUP_FIRE2}, // S_GLAREGOYLEUP_FIRE1 + {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_GLAREGOYLEUP_FIRE3}, // S_GLAREGOYLEUP_FIRE2 + {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_GLAREGOYLEUP}, // S_GLAREGOYLEUP_FIRE3 - {SPR_BGAR, 0, 67, {NULL}, 0, 0, S_TRAPGOYLEDOWN_CHECK}, // S_TRAPGOYLEDOWN - {SPR_BGAR, 0, 3, {NULL}, 0, 0, S_TRAPGOYLEDOWN_FIRE1}, // S_TRAPGOYLEDOWN_CHECK - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_TRAPGOYLEDOWN_FIRE2}, // S_TRAPGOYLEDOWN_FIRE1 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_TRAPGOYLEDOWN_FIRE3}, // S_TRAPGOYLEDOWN_FIRE2 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_TRAPGOYLEDOWN}, // S_TRAPGOYLEDOWN_FIRE3 + {SPR_BGAR, 0, 67, {NULL}, 0, 0, S_GLAREGOYLEDOWN_CHECK}, // S_GLAREGOYLEDOWN + {SPR_BGAR, 0, 3, {NULL}, 0, 0, S_GLAREGOYLEDOWN_FIRE1}, // S_GLAREGOYLEDOWN_CHECK + {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_GLAREGOYLEDOWN_FIRE2}, // S_GLAREGOYLEDOWN_FIRE1 + {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_GLAREGOYLEDOWN_FIRE3}, // S_GLAREGOYLEDOWN_FIRE2 + {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_GLAREGOYLEDOWN}, // S_GLAREGOYLEDOWN_FIRE3 - {SPR_BGAR, 0, 135, {NULL}, 0, 0, S_TRAPGOYLELONG_CHECK}, // S_TRAPGOYLELONG - {SPR_BGAR, 0, 3, {NULL}, 0, 0, S_TRAPGOYLELONG_FIRE1}, // S_TRAPGOYLELONG_CHECK - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG_FIRE2}, // S_TRAPGOYLELONG_FIRE1 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG_FIRE3}, // S_TRAPGOYLELONG_FIRE2 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG_FIRE4}, // S_TRAPGOYLELONG_FIRE3 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG_FIRE5}, // S_TRAPGOYLELONG_FIRE4 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG}, // S_TRAPGOYLELONG_FIRE5 + {SPR_BGAR, 0, 135, {NULL}, 0, 0, S_GLAREGOYLELONG_CHECK}, // S_GLAREGOYLELONG + {SPR_BGAR, 0, 3, {NULL}, 0, 0, S_GLAREGOYLELONG_FIRE1}, // S_GLAREGOYLELONG_CHECK + {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG_FIRE2}, // S_GLAREGOYLELONG_FIRE1 + {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG_FIRE3}, // S_GLAREGOYLELONG_FIRE2 + {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG_FIRE4}, // S_GLAREGOYLELONG_FIRE3 + {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG_FIRE5}, // S_GLAREGOYLELONG_FIRE4 + {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG}, // S_GLAREGOYLELONG_FIRE5 // Target/Red Crystal {SPR_RCRY, 0, -1, {NULL}, 0, 0, S_TARGET_IDLE}, // S_TARGET_IDLE @@ -13581,9 +13581,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_TRAPGOYLE + { // MT_GLAREGOYLE 1500, // doomednum - S_TRAPGOYLE, // spawnstate + S_GLAREGOYLE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -13608,9 +13608,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_TRAPGOYLEUP + { // MT_GLAREGOYLEUP 1501, // doomednum - S_TRAPGOYLEUP, // spawnstate + S_GLAREGOYLEUP, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -13635,9 +13635,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_TRAPGOYLEDOWN + { // MT_GLAREGOYLEDOWN 1502, // doomednum - S_TRAPGOYLEDOWN,// spawnstate + S_GLAREGOYLEDOWN,// spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -13662,9 +13662,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_TRAPGOYLELONG + { // MT_GLAREGOYLELONG 1503, // doomednum - S_TRAPGOYLELONG,// spawnstate + S_GLAREGOYLELONG,// spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound diff --git a/src/info.h b/src/info.h index 20b471811..092b92241 100644 --- a/src/info.h +++ b/src/info.h @@ -2335,7 +2335,7 @@ typedef enum state S_ARROW, S_ARROWBONK, - // Trapgoyle Demon fire + // Glaregoyle Demon fire S_DEMONFIRE, // GFZ flowers @@ -2703,29 +2703,29 @@ typedef enum state S_WALLVINE_LONG, S_WALLVINE_SHORT, - // Trapgoyles - S_TRAPGOYLE, - S_TRAPGOYLE_CHECK, - S_TRAPGOYLE_FIRE1, - S_TRAPGOYLE_FIRE2, - S_TRAPGOYLE_FIRE3, - S_TRAPGOYLEUP, - S_TRAPGOYLEUP_CHECK, - S_TRAPGOYLEUP_FIRE1, - S_TRAPGOYLEUP_FIRE2, - S_TRAPGOYLEUP_FIRE3, - S_TRAPGOYLEDOWN, - S_TRAPGOYLEDOWN_CHECK, - S_TRAPGOYLEDOWN_FIRE1, - S_TRAPGOYLEDOWN_FIRE2, - S_TRAPGOYLEDOWN_FIRE3, - S_TRAPGOYLELONG, - S_TRAPGOYLELONG_CHECK, - S_TRAPGOYLELONG_FIRE1, - S_TRAPGOYLELONG_FIRE2, - S_TRAPGOYLELONG_FIRE3, - S_TRAPGOYLELONG_FIRE4, - S_TRAPGOYLELONG_FIRE5, + // Glaregoyles + S_GLAREGOYLE, + S_GLAREGOYLE_WARNING, + S_GLAREGOYLE_FIRE, + S_GLAREGOYLE_LOOP, + S_GLAREGOYLE_COOLDOWN, + S_GLAREGOYLEUP, + S_GLAREGOYLEUP_CHECK, + S_GLAREGOYLEUP_FIRE1, + S_GLAREGOYLEUP_FIRE2, + S_GLAREGOYLEUP_FIRE3, + S_GLAREGOYLEDOWN, + S_GLAREGOYLEDOWN_CHECK, + S_GLAREGOYLEDOWN_FIRE1, + S_GLAREGOYLEDOWN_FIRE2, + S_GLAREGOYLEDOWN_FIRE3, + S_GLAREGOYLELONG, + S_GLAREGOYLELONG_CHECK, + S_GLAREGOYLELONG_FIRE1, + S_GLAREGOYLELONG_FIRE2, + S_GLAREGOYLELONG_FIRE3, + S_GLAREGOYLELONG_FIRE4, + S_GLAREGOYLELONG_FIRE5, // ATZ's Red Crystal/Target S_TARGET_IDLE, @@ -4346,7 +4346,7 @@ typedef enum mobj_type MT_CANNONBALL, // Cannonball MT_CANNONBALLDECOR, // Decorative/still cannonball MT_ARROW, // Arrow - MT_DEMONFIRE, // Trapgoyle fire + MT_DEMONFIRE, // Glaregoyle fire // Greenflower Scenery MT_GFZFLOWER1, @@ -4509,10 +4509,10 @@ typedef enum mobj_type // Egg Rock Scenery // Azure Temple Scenery - MT_TRAPGOYLE, - MT_TRAPGOYLEUP, - MT_TRAPGOYLEDOWN, - MT_TRAPGOYLELONG, + MT_GLAREGOYLE, + MT_GLAREGOYLEUP, + MT_GLAREGOYLEDOWN, + MT_GLAREGOYLELONG, MT_TARGET, // AKA Red Crystal MT_GREENFLAME, diff --git a/src/p_mobj.c b/src/p_mobj.c index 93a77bcda..73141deae 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12441,10 +12441,10 @@ ML_EFFECT5 : Don't stop thinking when too far away if (mthing->extrainfo) mobj->extravalue1 = mthing->extrainfo; break; - case MT_TRAPGOYLE: - case MT_TRAPGOYLEUP: - case MT_TRAPGOYLEDOWN: - case MT_TRAPGOYLELONG: + case MT_GLAREGOYLE: + case MT_GLAREGOYLEUP: + case MT_GLAREGOYLEDOWN: + case MT_GLAREGOYLELONG: if (mthing->angle >= 360) mobj->tics += 7*(mthing->angle / 360) + 1; // starting delay break; From 3bbb4c3b36a43dbc925b3a5ad17f2569a8099006 Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 31 Oct 2019 19:18:44 +0800 Subject: [PATCH 10/14] Finish Glaregoyle states --- src/dehacked.c | 43 +++++++++++++++++++++++++------------------ src/info.c | 46 ++++++++++++++++++++++++++-------------------- src/info.h | 36 +++++++++++++++++++++--------------- 3 files changed, 72 insertions(+), 53 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index a5dc1c4c1..4b4922aaf 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6030,29 +6030,36 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_WALLVINE_LONG", "S_WALLVINE_SHORT", + // Glaregoyles // Glaregoyles "S_GLAREGOYLE", - "S_GLAREGOYLE_CHECK", - "S_GLAREGOYLE_FIRE1", - "S_GLAREGOYLE_FIRE2", - "S_GLAREGOYLE_FIRE3", + "S_GLAREGOYLE_CHARGE", + "S_GLAREGOYLE_BLINK", + "S_GLAREGOYLE_HOLD", + "S_GLAREGOYLE_FIRE", + "S_GLAREGOYLE_LOOP", + "S_GLAREGOYLE_COOLDOWN", "S_GLAREGOYLEUP", - "S_GLAREGOYLEUP_CHECK", - "S_GLAREGOYLEUP_FIRE1", - "S_GLAREGOYLEUP_FIRE2", - "S_GLAREGOYLEUP_FIRE3", + "S_GLAREGOYLEUP_CHARGE", + "S_GLAREGOYLEUP_BLINK", + "S_GLAREGOYLEUP_HOLD", + "S_GLAREGOYLEUP_FIRE", + "S_GLAREGOYLEUP_LOOP", + "S_GLAREGOYLEUP_COOLDOWN", "S_GLAREGOYLEDOWN", - "S_GLAREGOYLEDOWN_CHECK", - "S_GLAREGOYLEDOWN_FIRE1", - "S_GLAREGOYLEDOWN_FIRE2", - "S_GLAREGOYLEDOWN_FIRE3", + "S_GLAREGOYLEDOWN_CHARGE", + "S_GLAREGOYLEDOWN_BLINK", + "S_GLAREGOYLEDOWN_HOLD", + "S_GLAREGOYLEDOWN_FIRE", + "S_GLAREGOYLEDOWN_LOOP", + "S_GLAREGOYLEDOWN_COOLDOWN", "S_GLAREGOYLELONG", - "S_GLAREGOYLELONG_CHECK", - "S_GLAREGOYLELONG_FIRE1", - "S_GLAREGOYLELONG_FIRE2", - "S_GLAREGOYLELONG_FIRE3", - "S_GLAREGOYLELONG_FIRE4", - "S_GLAREGOYLELONG_FIRE5", + "S_GLAREGOYLELONG_CHARGE", + "S_GLAREGOYLELONG_BLINK", + "S_GLAREGOYLELONG_HOLD", + "S_GLAREGOYLELONG_FIRE", + "S_GLAREGOYLELONG_LOOP", + "S_GLAREGOYLELONG_COOLDOWN", // ATZ's Red Crystal/Target "S_TARGET_IDLE", diff --git a/src/info.c b/src/info.c index 9659c9712..2b1dc6135 100644 --- a/src/info.c +++ b/src/info.c @@ -2580,31 +2580,37 @@ state_t states[NUMSTATES] = {SPR_WVIN, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_SHORT // Glaregoyles - {SPR_BGAR, FF_ANIMATE|1, 52, {NULL}, 1, 0, S_GLAREGOYLE_WARNING}, // S_GLAREGOYLE - {SPR_BGAR, 2, 6, {NULL}, 1, 2, S_GLAREGOYLE_FIRE}, // S_GLAREGOYLE_WARNING + {SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLE_CHARGE}, // S_GLAREGOYLE + {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLE_BLINK}, // S_GLAREGOYLE_CHARGE + {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLE_HOLD}, // S_GLAREGOYLE_BLINK + {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLE_FIRE}, // S_GLAREGOYLE_HOLD {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLE_LOOP}, // S_GLAREGOYLE_FIRE {SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLE_FIRE, S_GLAREGOYLE_COOLDOWN}, // S_GLAREGOYLE_LOOP - {SPR_BGAR, FF_ANIMATE|1, 12, {NULL}, 1, 6, S_GLAREGOYLE}, // S_GLAREGOYLE_COOLDOWN + {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLE}, // S_GLAREGOYLE_COOLDOWN - {SPR_BGAR, 0, 67, {NULL}, 0, 0, S_GLAREGOYLEUP_CHECK}, // S_GLAREGOYLEUP - {SPR_BGAR, 0, 3, {NULL}, 0, 0, S_GLAREGOYLEUP_FIRE1}, // S_GLAREGOYLEUP_CHECK - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_GLAREGOYLEUP_FIRE2}, // S_GLAREGOYLEUP_FIRE1 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_GLAREGOYLEUP_FIRE3}, // S_GLAREGOYLEUP_FIRE2 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_GLAREGOYLEUP}, // S_GLAREGOYLEUP_FIRE3 + {SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLEUP_CHARGE}, // S_GLAREGOYLEUP + {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLEUP_BLINK}, // S_GLAREGOYLEUP_CHARGE + {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLEUP_HOLD}, // S_GLAREGOYLEUP_BLINK + {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLEUP_FIRE}, // S_GLAREGOYLEUP_HOLD + {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_GLAREGOYLEUP_LOOP}, // S_GLAREGOYLEUP_FIRE + {SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLEUP_FIRE, S_GLAREGOYLEUP_COOLDOWN}, // S_GLAREGOYLEUP_LOOP + {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLEUP}, // S_GLAREGOYLEUP_COOLDOWN - {SPR_BGAR, 0, 67, {NULL}, 0, 0, S_GLAREGOYLEDOWN_CHECK}, // S_GLAREGOYLEDOWN - {SPR_BGAR, 0, 3, {NULL}, 0, 0, S_GLAREGOYLEDOWN_FIRE1}, // S_GLAREGOYLEDOWN_CHECK - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_GLAREGOYLEDOWN_FIRE2}, // S_GLAREGOYLEDOWN_FIRE1 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_GLAREGOYLEDOWN_FIRE3}, // S_GLAREGOYLEDOWN_FIRE2 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_GLAREGOYLEDOWN}, // S_GLAREGOYLEDOWN_FIRE3 + {SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLEDOWN_CHARGE}, // S_GLAREGOYLEDOWN + {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLEDOWN_BLINK}, // S_GLAREGOYLEDOWN_CHARGE + {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLEDOWN_HOLD}, // S_GLAREGOYLEDOWN_BLINK + {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLEDOWN_FIRE}, // S_GLAREGOYLEDOWN_HOLD + {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_GLAREGOYLEDOWN_LOOP}, // S_GLAREGOYLEDOWN_FIRE + {SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLEDOWN_FIRE, S_GLAREGOYLEDOWN_COOLDOWN}, // S_GLAREGOYLEDOWN_LOOP + {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLEDOWN}, // S_GLAREGOYLEDOWN_COOLDOWN - {SPR_BGAR, 0, 135, {NULL}, 0, 0, S_GLAREGOYLELONG_CHECK}, // S_GLAREGOYLELONG - {SPR_BGAR, 0, 3, {NULL}, 0, 0, S_GLAREGOYLELONG_FIRE1}, // S_GLAREGOYLELONG_CHECK - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG_FIRE2}, // S_GLAREGOYLELONG_FIRE1 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG_FIRE3}, // S_GLAREGOYLELONG_FIRE2 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG_FIRE4}, // S_GLAREGOYLELONG_FIRE3 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG_FIRE5}, // S_GLAREGOYLELONG_FIRE4 - {SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG}, // S_GLAREGOYLELONG_FIRE5 + {SPR_BGAR, 0, 90, {NULL}, 0, 0, S_GLAREGOYLELONG_CHARGE}, // S_GLAREGOYLELONG + {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLELONG_BLINK}, // S_GLAREGOYLELONG_CHARGE + {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLELONG_HOLD}, // S_GLAREGOYLELONG_BLINK + {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLELONG_FIRE}, // S_GLAREGOYLELONG_HOLD + {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG_LOOP}, // S_GLAREGOYLELONG_FIRE + {SPR_BGAR, 1, 0, {A_Repeat}, 5, S_GLAREGOYLELONG_FIRE, S_GLAREGOYLELONG_COOLDOWN}, // S_GLAREGOYLELONG_LOOP + {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLELONG}, // S_GLAREGOYLELONG_COOLDOWN // Target/Red Crystal {SPR_RCRY, 0, -1, {NULL}, 0, 0, S_TARGET_IDLE}, // S_TARGET_IDLE diff --git a/src/info.h b/src/info.h index 092b92241..612ce0b36 100644 --- a/src/info.h +++ b/src/info.h @@ -2705,27 +2705,33 @@ typedef enum state // Glaregoyles S_GLAREGOYLE, - S_GLAREGOYLE_WARNING, + S_GLAREGOYLE_CHARGE, + S_GLAREGOYLE_BLINK, + S_GLAREGOYLE_HOLD, S_GLAREGOYLE_FIRE, S_GLAREGOYLE_LOOP, S_GLAREGOYLE_COOLDOWN, S_GLAREGOYLEUP, - S_GLAREGOYLEUP_CHECK, - S_GLAREGOYLEUP_FIRE1, - S_GLAREGOYLEUP_FIRE2, - S_GLAREGOYLEUP_FIRE3, + S_GLAREGOYLEUP_CHARGE, + S_GLAREGOYLEUP_BLINK, + S_GLAREGOYLEUP_HOLD, + S_GLAREGOYLEUP_FIRE, + S_GLAREGOYLEUP_LOOP, + S_GLAREGOYLEUP_COOLDOWN, S_GLAREGOYLEDOWN, - S_GLAREGOYLEDOWN_CHECK, - S_GLAREGOYLEDOWN_FIRE1, - S_GLAREGOYLEDOWN_FIRE2, - S_GLAREGOYLEDOWN_FIRE3, + S_GLAREGOYLEDOWN_CHARGE, + S_GLAREGOYLEDOWN_BLINK, + S_GLAREGOYLEDOWN_HOLD, + S_GLAREGOYLEDOWN_FIRE, + S_GLAREGOYLEDOWN_LOOP, + S_GLAREGOYLEDOWN_COOLDOWN, S_GLAREGOYLELONG, - S_GLAREGOYLELONG_CHECK, - S_GLAREGOYLELONG_FIRE1, - S_GLAREGOYLELONG_FIRE2, - S_GLAREGOYLELONG_FIRE3, - S_GLAREGOYLELONG_FIRE4, - S_GLAREGOYLELONG_FIRE5, + S_GLAREGOYLELONG_CHARGE, + S_GLAREGOYLELONG_BLINK, + S_GLAREGOYLELONG_HOLD, + S_GLAREGOYLELONG_FIRE, + S_GLAREGOYLELONG_LOOP, + S_GLAREGOYLELONG_COOLDOWN, // ATZ's Red Crystal/Target S_TARGET_IDLE, From 70a68d3fa90b852aa8f0ab77b0a1a307c22c6ca8 Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 31 Oct 2019 19:38:28 +0800 Subject: [PATCH 11/14] Add static ATZ Gargoyles --- src/dehacked.c | 5 ++++- src/info.c | 30 ++++++++++++++++++++++++++++++ src/info.h | 4 ++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index 4b4922aaf..e1862ef85 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6030,7 +6030,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_WALLVINE_LONG", "S_WALLVINE_SHORT", - // Glaregoyles // Glaregoyles "S_GLAREGOYLE", "S_GLAREGOYLE_CHARGE", @@ -6071,6 +6070,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // ATZ's green flame "S_GREENFLAME", + // ATZ Blue Gargoyle + "S_BLUEGARGOYLE", + // Stalagmites "S_STG0", "S_STG1", @@ -7826,6 +7828,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_GLAREGOYLELONG", "MT_TARGET", "MT_GREENFLAME", + "MT_BLUEGARGOYLE", // Stalagmites "MT_STALAGMITE0", diff --git a/src/info.c b/src/info.c index 2b1dc6135..fa4b556a6 100644 --- a/src/info.c +++ b/src/info.c @@ -2622,6 +2622,9 @@ state_t states[NUMSTATES] = // Green flame {SPR_CFLM, FF_FULLBRIGHT|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 3, S_GREENFLAME}, // S_GREENFLAME + // ATZ Blue Gargoyle + {SPR_BGAR, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEGARGOYLE + // Stalagmites {SPR_STLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_STG0 {SPR_STLG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_STG1 @@ -13749,6 +13752,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_BLUEGARGOYLE + 1506, // doomednum + S_BLUEGARGOYLE, // 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 + 21*FRACUNIT, // speed + 16*FRACUNIT, // radius + 40*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_statu2, // activesound + MF_SLIDEME|MF_SOLID|MF_PUSHABLE, // flags + S_NULL // raisestate + }, + { // MT_STALAGMITE0 1900, // doomednum S_STG0, // spawnstate diff --git a/src/info.h b/src/info.h index 612ce0b36..8d407deb8 100644 --- a/src/info.h +++ b/src/info.h @@ -2743,6 +2743,9 @@ typedef enum state // ATZ's green flame S_GREENFLAME, + // ATZ Blue Gargoyle + S_BLUEGARGOYLE, + // Stalagmites S_STG0, S_STG1, @@ -4521,6 +4524,7 @@ typedef enum mobj_type MT_GLAREGOYLELONG, MT_TARGET, // AKA Red Crystal MT_GREENFLAME, + MT_BLUEGARGOYLE, // Stalagmites MT_STALAGMITE0, From 50b92afc4eabfbc8473af727baffe23ba2f7da92 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 2 Nov 2019 11:56:51 +0000 Subject: [PATCH 12/14] * Restart Metal recording from beginning if retry is used. * Disable lives when Metal recording (and have a big flashing REC instead, because I'm a riot). * Correct some minor directionchar issues (some introduced in this branch, some not). --- src/g_game.c | 6 +++++- src/p_user.c | 16 ++++++++-------- src/st_stuff.c | 8 +++++++- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 569d777ab..44aaf7b12 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2755,6 +2755,8 @@ void G_DoReborn(INT32 playernum) LUAh_MapChange(gamemap); #endif G_DoLoadLevel(true); + if (metalrecording) + G_BeginMetal(); return; } } @@ -2922,7 +2924,7 @@ boolean G_GametypeUsesLives(void) { // Coop, Competitive if ((gametype == GT_COOP || gametype == GT_COMPETITION) - && !modeattacking // No lives in Time Attack + && !(modeattacking || metalrecording) // No lives in Time Attack //&& !G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS)) // No lives in NiGHTS return true; @@ -5510,8 +5512,10 @@ void G_BeginMetal(void) { mobj_t *mo = players[consoleplayer].mo; +#if 0 if (demo_p) return; +#endif demo_p = demobuffer; diff --git a/src/p_user.c b/src/p_user.c index 7ac9b34ed..3849dd199 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11463,6 +11463,13 @@ void P_PlayerThink(player_t *player) player->drawangle = player->mo->angle; else if (P_PlayerInPain(player)) ; + else if (player->powers[pw_justsprung]) // restricted, potentially by lua + { +#ifdef SPRINGSPIN + if (player->powers[pw_justsprung] & (1<<15)) + player->drawangle += (player->powers[pw_justsprung] & ~(1<<15))*(ANG2+ANG1); +#endif + } else if (player->powers[pw_carry] && player->mo->tracer) // carry { switch (player->powers[pw_carry]) @@ -11500,13 +11507,6 @@ void P_PlayerThink(player_t *player) break; } } - else if (player->powers[pw_justsprung]) - { -#ifdef SPRINGSPIN - if (player->powers[pw_justsprung] & (1<<15)) - player->drawangle += (player->powers[pw_justsprung] & ~(1<<15))*(ANG2+ANG1); -#endif - } else if ((player->skidtime > (TICRATE/2 - 2) || ((player->pflags & (PF_SPINNING|PF_STARTDASH)) == PF_SPINNING)) && (abs(player->rmomx) > 5*player->mo->scale || abs(player->rmomy) > 5*player->mo->scale)) // spin/skid force player->drawangle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy); else if (((player->charability2 == CA2_GUNSLINGER || player->charability2 == CA2_MELEE) && player->panim == PA_ABILITY2) || player->pflags & PF_STASIS || player->skidtime) @@ -11578,7 +11578,7 @@ void P_PlayerThink(player_t *player) statenum_t stat = player->mo->state-states; if (stat == S_PLAY_WAIT) P_SetPlayerMobjState(player->mo, S_PLAY_STND); - else if (stat == S_PLAY_STND) + else if (stat == S_PLAY_STND && player->mo->tics != -1) player->mo->tics++; } } diff --git a/src/st_stuff.c b/src/st_stuff.c index 392cb1c03..139303fbb 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -837,7 +837,13 @@ static void ST_drawLivesArea(void) } // Lives number - if (G_GametypeUsesLives() || gametype == GT_RACE) + if (metalrecording) + { + if (((2*leveltime)/TICRATE) & 1) + V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, + hudinfo[HUD_LIVES].f|V_PERPLAYER|V_REDMAP|V_HUDTRANS, "REC"); + } + else if (G_GametypeUsesLives() || gametype == GT_RACE) { // x V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10, From ac196768aa2acecdbb1ed8571fdab1bf716017cb Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 8 Nov 2019 13:58:53 +0000 Subject: [PATCH 13/14] Resolve #283. --- src/p_mobj.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 2a8d22b03..395d434c1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5585,9 +5585,9 @@ static void P_Boss9Thinker(mobj_t *mobj) P_InstaThrust(mobj, mobj->angle, -4*FRACUNIT); P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true); mobj->momz -= gravity; - if (mobj->z < mobj->watertop) + if (mobj->z < mobj->watertop || mobj->z < (mobj->floorz + 16*FRACUNIT)) { - mobj->watertop = mobj->target->floorz + 32*FRACUNIT; + mobj->watertop = mobj->floorz + 32*FRACUNIT; P_SetMobjState(mobj, mobj->info->spawnstate); } return; @@ -5801,8 +5801,10 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->movedir == 0 || mobj->movedir == 2) { // Pausing between bounces in the pinball phase if (mobj->target->player->powers[pw_tailsfly]) // Trying to escape, eh? mobj->watertop = mobj->target->z + mobj->target->momz*6; // Readjust your aim. >:3 - else + else if (mobj->target->floorz > mobj->floorz) mobj->watertop = mobj->target->floorz + 16*FRACUNIT; + else + mobj->watertop = mobj->floorz + 16*FRACUNIT; if (!(mobj->threshold%4)) { mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); @@ -6106,7 +6108,10 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->threshold = 12; // bounce 12 times else mobj->threshold = 24; // bounce 24 times - mobj->watertop = mobj->target->floorz + 16*FRACUNIT; + if (mobj->floorz >= mobj->target->floorz) + mobj->watertop = mobj->floorz + 16*FRACUNIT; + else + mobj->watertop = mobj->target->floorz + 16*FRACUNIT; P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); #if 0 @@ -6135,7 +6140,10 @@ static void P_Boss9Thinker(mobj_t *mobj) } case 3: // Return to idle. - mobj->watertop = mobj->target->floorz + 32*FRACUNIT; + if (mobj->floorz >= mobj->target->floorz) + mobj->watertop = mobj->floorz + 32*FRACUNIT; + else + mobj->watertop = mobj->target->floorz + 32*FRACUNIT; P_SetMobjState(mobj, mobj->info->spawnstate); mobj->flags &= ~MF_PAIN; mobj->fuse = 8*TICRATE; From 0deb13c1ed3a2f7052789a1622e9972a31db173f Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 12 Nov 2019 15:57:23 -0500 Subject: [PATCH 14/14] Update ZB config for Glaregoyle and Buggle object names, and Glaregoyle sprite name. --- extras/conf/SRB2-22.cfg | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index de5b2ea6c..92b072b4d 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -3542,7 +3542,7 @@ thingtypes } 124 { - title = "AquaBuzz"; + title = "Buggle"; sprite = "BBUZA1"; width = 20; height = 24; @@ -5673,8 +5673,8 @@ thingtypes { arrow = 1; blocking = 2; - title = "Trapgoyle"; - sprite = "GARGA1"; + title = "Glaregoyle"; + sprite = "BGARA1"; width = 16; height = 40; flags4text = "[4] Slides when pushed"; @@ -5684,8 +5684,8 @@ thingtypes { arrow = 1; blocking = 2; - title = "Trapgoyle (Up)"; - sprite = "GARGA1"; + title = "Glaregoyle (Up)"; + sprite = "BGARA1"; width = 16; height = 40; flags4text = "[4] Slides when pushed"; @@ -5695,8 +5695,8 @@ thingtypes { arrow = 1; blocking = 2; - title = "Trapgoyle (Down)"; - sprite = "GARGA1"; + title = "Glaregoyle (Down)"; + sprite = "BGARA1"; width = 16; height = 40; flags4text = "[4] Slides when pushed"; @@ -5706,8 +5706,8 @@ thingtypes { arrow = 1; blocking = 2; - title = "Trapgoyle (Long)"; - sprite = "GARGA1"; + title = "Glaregoyle (Long)"; + sprite = "BGARA1"; width = 16; height = 40; flags4text = "[4] Slides when pushed";