From 587c0079e263b9c404865ce2c22ba9f02e5305f5 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 22 Oct 2016 23:19:24 +0100 Subject: [PATCH 01/10] Started work on FLIPX/FLIPY support for patches. Doesn't do anything yet, but the parser should know how to look for them now Note: I had to create M_UnGetToken in order to avoid problems with looking for patch parameters (marked by { and }) but not finding anything --- src/dehacked.c | 2 +- src/doomdef.h | 1 + src/m_misc.c | 21 ++++++++++++++++++--- src/r_data.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/r_data.h | 1 + 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 20f835981..920e5eec3 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2778,7 +2778,7 @@ static void readpatch(MYFILE *f, const char *name, UINT16 wad) char *word2; char *tmp; INT32 i = 0, j = 0, value; - texpatch_t patch = {0, 0, UINT16_MAX, UINT16_MAX}; + texpatch_t patch = {0, 0, UINT16_MAX, UINT16_MAX, 0}; // Jump to the texture this patch belongs to, which, // coincidentally, is always the last one on the buffer cache. diff --git a/src/doomdef.h b/src/doomdef.h index 410e740fa..d0ac3a676 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -407,6 +407,7 @@ void M_StartupLocale(void); extern void *(*M_Memcpy)(void* dest, const void* src, size_t n) FUNCNONNULL; char *va(const char *format, ...) FUNCPRINTF; char *M_GetToken(const char *inputString); +void M_UnGetToken(void); char *sizeu1(size_t num); char *sizeu2(size_t num); char *sizeu3(size_t num); diff --git a/src/m_misc.c b/src/m_misc.c index cfe73d88f..d6ab40196 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1617,6 +1617,11 @@ INT32 axtoi(const char *hexStg) return intValue; } +// Token parser variables + +static UINT32 oldendPos = 0; // old value of endPos, used by M_UnGetToken +static UINT32 endPos = 0; // now external to M_GetToken, but still static + /** Token parser for TEXTURES, ANIMDEFS, and potentially other lumps later down the line. * Was originally R_GetTexturesToken when I was coding up the TEXTURES parser, until I realized I needed it for ANIMDEFS too. * Parses up to the next whitespace character or comma. When finding the start of the next token, whitespace is skipped. @@ -1631,7 +1636,7 @@ char *M_GetToken(const char *inputString) { static const char *stringToUse = NULL; // Populated if inputString != NULL; used otherwise static UINT32 startPos = 0; - static UINT32 endPos = 0; +// static UINT32 endPos = 0; static UINT32 stringLength = 0; static UINT8 inComment = 0; // 0 = not in comment, 1 = // Single-line, 2 = /* Multi-line */ char *texturesToken = NULL; @@ -1641,12 +1646,12 @@ char *M_GetToken(const char *inputString) { stringToUse = inputString; startPos = 0; - endPos = 0; + oldendPos = endPos = 0; stringLength = strlen(inputString); } else { - startPos = endPos; + startPos = oldendPos = endPos; } if (stringToUse == NULL) return NULL; @@ -1777,6 +1782,16 @@ char *M_GetToken(const char *inputString) return texturesToken; } +/** Undoes the last M_GetToken call + * The current position along the string being parsed is reset to the last saved position. + * This exists mostly because of R_ParseTexture/R_ParsePatch honestly, but could be useful elsewhere? + * -Monster Iestyn (22/10/16) + */ +void M_UnGetToken(void) +{ + endPos = oldendPos; +} + /** Count bits in a number. */ UINT8 M_CountBits(UINT32 num, UINT8 size) diff --git a/src/r_data.c b/src/r_data.c index cb5cf3591..5c3d06649 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -502,6 +502,7 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) char *patchName = NULL; INT16 patchXPos; INT16 patchYPos; + UINT8 flip = 0; texpatch_t *resultPatch = NULL; lumpnum_t patchLumpNum; @@ -598,6 +599,47 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) } Z_Free(texturesToken); + // Patch parameters block (OPTIONAL) + // added by Monster Iestyn (22/10/16) + + // Left Curly Brace + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + ; // move on and ignore, R_ParseTextures will deal with this + else + { + if (strcmp(texturesToken,"{")==0) + { + Z_Free(texturesToken); + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s parameters should be",patchName); + } + while (strcmp(texturesToken,"}")!=0) + { + if (stricmp(texturesToken, "FLIPX")==0) + flip |= 1; + else if (stricmp(texturesToken, "FLIPY")==0) + flip |= 2; + Z_Free(texturesToken); + + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s parameters or right curly brace should be",patchName); + } + } + } + else + { + // this is not what we wanted... + // undo last read so R_ParseTextures can re-get the token for its own purposes + M_UnGetToken(); + } + Z_Free(texturesToken); + } + if (actuallyLoadPatch == true) { // Check lump exists @@ -608,6 +650,7 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) resultPatch->originy = patchYPos; resultPatch->lump = patchLumpNum & 65535; resultPatch->wad = patchLumpNum>>16; + resultPatch->flip = flip; // Clean up a little after ourselves Z_Free(patchName); // Then return it diff --git a/src/r_data.h b/src/r_data.h index 69a2882af..1384ecac0 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -31,6 +31,7 @@ typedef struct // Block origin (always UL), which has already accounted for the internal origin of the patch. INT16 originx, originy; UINT16 wad, lump; + UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both } texpatch_t; // A maptexturedef_t describes a rectangular texture, From ce97c1e98644e660bc77b03b51920099f4cf95dc Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 10 Nov 2016 17:51:10 +0000 Subject: [PATCH 02/10] Added basic spindash dust Also cleaned up some of the code in P_DoSpinAbility while I was at it --- src/dehacked.c | 7 ++ src/info.c | 35 +++++++++ src/info.h | 8 +++ src/p_mobj.c | 5 ++ src/p_user.c | 189 ++++++++++++++++++++++++++++++------------------- 5 files changed, 170 insertions(+), 74 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index c3b606fe0..3ef8b0d29 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5566,6 +5566,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_WATERZAP", + // Spindash dust + "S_SPINDUST1", + "S_SPINDUST2", + "S_SPINDUST3", + "S_SPINDUST4", + "S_FOG1", "S_FOG2", "S_FOG3", @@ -6376,6 +6382,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_MEDIUMBUBBLE", // medium bubble "MT_EXTRALARGEBUBBLE", // extra large bubble "MT_WATERZAP", + "MT_SPINDUST", // Spindash dust "MT_TFOG", "MT_SEED", "MT_PARTICLE", diff --git a/src/info.c b/src/info.c index 9fb442883..459238917 100644 --- a/src/info.c +++ b/src/info.c @@ -274,6 +274,7 @@ char sprnames[NUMSPRITES + 1][5] = "SMOK", "BUBL", // Bubble "WZAP", + "DUST", // Spindash dust "TFOG", // Teleport Fog "SEED", // Sonic CD flower seed "PRTL", // Particle (for fans, etc.) @@ -2279,6 +2280,13 @@ state_t states[NUMSTATES] = {SPR_WZAP, FF_TRANS10|FF_ANIMATE|FF_RANDOMANIM, 4, {NULL}, 3, 2, S_NULL}, // S_WATERZAP + // Spindash dust + // TODO: other spin dust types + {SPR_DUST, 0, 7, {NULL}, 0, 0, S_SPINDUST2}, // S_SPINDUST1 + {SPR_DUST, 1, 6, {NULL}, 0, 0, S_SPINDUST3}, // S_SPINDUST2 + {SPR_DUST, FF_TRANS30|2, 4, {NULL}, 0, 0, S_SPINDUST4}, // S_SPINDUST3 + {SPR_DUST, FF_TRANS60|3, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST4 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50, 2, {NULL}, 0, 0, S_FOG2}, // S_FOG1 {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|1, 2, {NULL}, 0, 0, S_FOG3}, // S_FOG2 {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|2, 2, {NULL}, 0, 0, S_FOG4}, // S_FOG3 @@ -10940,6 +10948,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SPINDUST + -1, // doomednum + S_SPINDUST1, // 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 + 4*FRACUNIT, // speed + 4*FRACUNIT, // radius + 4*FRACUNIT, // height + 0, // display offset + 4, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIP, // flags + S_NULL // raisestate + }, + { // MT_TFOG -1, // doomednum S_FOG1, // spawnstate diff --git a/src/info.h b/src/info.h index b0683c172..fc5012d29 100644 --- a/src/info.h +++ b/src/info.h @@ -466,6 +466,7 @@ typedef enum sprite SPR_SMOK, SPR_BUBL, // Bubble SPR_WZAP, + SPR_DUST, // Spindash dust SPR_TFOG, // Teleport Fog SPR_SEED, // Sonic CD flower seed SPR_PRTL, // Particle (for fans, etc.) @@ -2457,6 +2458,12 @@ typedef enum state S_WATERZAP, + // Spindash dust + S_SPINDUST1, + S_SPINDUST2, + S_SPINDUST3, + S_SPINDUST4, + S_FOG1, S_FOG2, S_FOG3, @@ -3286,6 +3293,7 @@ typedef enum mobj_type MT_MEDIUMBUBBLE, // medium bubble MT_EXTRALARGEBUBBLE, // extra large bubble MT_WATERZAP, + MT_SPINDUST, // Spindash dust MT_TFOG, MT_SEED, MT_PARTICLE, diff --git a/src/p_mobj.c b/src/p_mobj.c index e9bcd193a..abe7849f2 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7537,6 +7537,11 @@ void P_MobjThinker(mobj_t *mobj) mobj->tracer->y, mobj->tracer->floorz, SPLATDRAWMODE_SHADE); #endif break; + case MT_SPINDUST: // Spindash dust + mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000 + mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same + //mobj->momz = mobj->momz+P_MobjFlip(mobj)/3; // no meaningful change in value to be frank + break; case MT_SPINFIRE: if (mobj->eflags & MFE_VERTICALFLIP) mobj->z = mobj->ceilingz - mobj->height; diff --git a/src/p_user.c b/src/p_user.c index 697f42e4d..02ab2044c 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3667,6 +3667,40 @@ void P_DoJump(player_t *player, boolean soundandstate) } } +static void P_DoSpinDashDust(player_t *player) +{ + UINT32 i; + mobj_t *particle; + UINT32 prandom[3]; + for (i = 0; i <= (leveltime%7)/2; i++) { // 1, 2, 3 or 4 particles + particle = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SPINDUST); + + if (player->powers[pw_shield] == SH_ELEMENTAL && !(player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))) { + //P_SetMobjState(particle, S_FIREDUST1); + //particle->bubble = false; + } else if (player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) { + //P_SetMobjState(particle, S_BUBBLEDUST1); + //particle->bubble = true; + } else { + //P_SetMobjState(particle, S_SPINDUST1); + //particle->bubble = false; + } + P_SetTarget(&particle->target, player->mo); + particle->destscale = (2*player->mo->scale)/3; + P_SetScale(particle, particle->destscale); + if (player->mo->eflags & MFE_VERTICALFLIP) // readjust z position if needed + particle->z = player->mo->z + player->mo->height - particle->height; + prandom[0] = P_RandomFixed()<<2; // P_RandomByte()<<10 + prandom[1] = P_RandomRange(-30, 30); // P_RandomRange(-ANG30/FRACUNIT, ANG30/FRACUNIT)*FRACUNIT + prandom[2] = P_RandomFixed()<<3; // P_RandomByte()<<11 + P_SetObjectMomZ(particle, player->dashspeed/50 + prandom[0], false); + P_InstaThrust(particle, + player->mo->angle + (prandom[1]*ANG1), + -FixedMul(player->dashspeed/12 + FRACUNIT + prandom[2], player->mo->scale)); + P_TryMove(particle, particle->x+particle->momx, particle->y+particle->momy, true); + } +} + // // P_DoSpinAbility // @@ -3674,6 +3708,7 @@ void P_DoJump(player_t *player, boolean soundandstate) // static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) { + boolean canstand = true; // can we stand on the ground? (mostly relevant for slopes) if (player->pflags & PF_STASIS) return; @@ -3685,69 +3720,92 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) } #endif - // Spinning and Spindashing - if ((player->charability2 == CA2_SPINDASH) && !(player->pflags & PF_SLIDING) && !player->exiting - && !P_PlayerInPain(player)) // subsequent revs - { - if ((cmd->buttons & BT_USE) && player->speed < FixedMul(5<mo->scale) && !player->mo->momz && onground && !(player->pflags & PF_USEDOWN) && !(player->pflags & PF_SPINNING) #ifdef ESLOPE - && (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2) + canstand = (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2); #endif - ) - { - player->mo->momx = player->cmomx; - player->mo->momy = player->cmomy; - player->pflags |= PF_STARTDASH|PF_SPINNING; - player->dashspeed = player->mindash; - P_SetPlayerMobjState(player->mo, S_PLAY_DASH); - player->pflags |= PF_USEDOWN; - if (!player->spectator) - S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh. - } - else if ((cmd->buttons & BT_USE) && (player->pflags & PF_STARTDASH)) - { - if (player->dashspeed < player->maxdash) - { -#define chargecalculation (6*(player->dashspeed - player->mindash))/(player->maxdash - player->mindash) - fixed_t soundcalculation = chargecalculation; - player->dashspeed += FRACUNIT; - if (!player->spectator && soundcalculation != chargecalculation) - S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh. -#undef chargecalculation - } - if (player->revitem && !(leveltime % 5)) // Now spawn the color thok circle. - { - P_SpawnSpinMobj(player, player->revitem); - if (demorecording) - G_GhostAddRev(); - } - } - // If not moving up or down, and travelling faster than a speed of four while not holding - // down the spin button and not spinning. - // AKA Just go into a spin on the ground, you idiot. ;) - else if ((cmd->buttons & BT_USE || ((twodlevel || (player->mo->flags2 & MF2_TWOD)) && cmd->forwardmove < -20)) - && !player->climbing && !player->mo->momz && onground && (player->speed > FixedMul(5<mo->scale) -#ifdef ESLOPE - || (player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && abs(player->mo->standingslope->zdelta) >= FRACUNIT/2) -#endif - ) && !(player->pflags & PF_USEDOWN) && !(player->pflags & PF_SPINNING)) + /////////////////////////////// + // ability-specific behavior // + /////////////////////////////// + if (!(player->pflags & PF_SLIDING) && !player->exiting && !P_PlayerInPain(player)) + { + switch (player->charability2) { - player->pflags |= PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); - if (!player->spectator) - S_StartSound(player->mo, sfx_spin); - player->pflags |= PF_USEDOWN; + case CA2_SPINDASH: // Spinning and Spindashing + // Start revving + if ((cmd->buttons & BT_USE) && player->speed < FixedMul(5<mo->scale) + && !player->mo->momz && onground && !(player->pflags & (PF_USEDOWN|PF_SPINNING)) + && canstand) + { + player->mo->momx = player->cmomx; + player->mo->momy = player->cmomy; + player->pflags |= PF_STARTDASH|PF_SPINNING; + player->dashspeed = player->mindash; + P_SetPlayerMobjState(player->mo, S_PLAY_DASH); + player->pflags |= PF_USEDOWN; + if (!player->spectator) + S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh. + } + // Revving + else if ((cmd->buttons & BT_USE) && (player->pflags & PF_STARTDASH)) + { + if (player->dashspeed < player->maxdash) + { +#define chargecalculation (6*(player->dashspeed - player->mindash))/(player->maxdash - player->mindash) + fixed_t soundcalculation = chargecalculation; + player->dashspeed += FRACUNIT; + if (!player->spectator && soundcalculation != chargecalculation) + S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh. +#undef chargecalculation + } + if (player->revitem && !(leveltime % 5)) // Now spawn the color thok circle. + { + P_SpawnSpinMobj(player, player->revitem); + if (demorecording) + G_GhostAddRev(); + } + } + + // If not moving up or down, and travelling faster than a speed of four while not holding + // down the spin button and not spinning. + // AKA Just go into a spin on the ground, you idiot. ;) + else if ((cmd->buttons & BT_USE || ((twodlevel || (player->mo->flags2 & MF2_TWOD)) && cmd->forwardmove < -20)) + && !player->climbing && !player->mo->momz && onground && (player->speed > FixedMul(5<mo->scale) + || !canstand) && !(player->pflags & (PF_USEDOWN|PF_SPINNING))) + { + player->pflags |= PF_SPINNING; + P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + if (!player->spectator) + S_StartSound(player->mo, sfx_spin); + player->pflags |= PF_USEDOWN; + } + break; + case CA2_MELEE: // Melee attack + if (!(player->panim == PA_ABILITY2) && (cmd->buttons & BT_USE) && player->speed < FixedMul(10<mo->scale) + && !player->mo->momz && onground && !(player->pflags & PF_USEDOWN) + && canstand) + { + P_ResetPlayer(player); + player->mo->z += P_MobjFlip(player->mo); + player->mo->momx = player->cmomx = 0; + player->mo->momy = player->cmomy = 0; + P_SetObjectMomZ(player->mo, player->mindash, false); + P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->maxdash, player->mo->scale)); + P_SetPlayerMobjState(player->mo, S_PLAY_MELEE); + player->pflags |= PF_USEDOWN; + S_StartSound(player->mo, sfx_s3k8b); + } + break; } } + /////////////////////////////// + // general spinning behavior // + /////////////////////////////// + // Rolling normally if (onground && player->pflags & PF_SPINNING && !(player->pflags & PF_STARTDASH) - && player->speed < FixedMul(5*FRACUNIT,player->mo->scale) -#ifdef ESLOPE - && (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2) -#endif - ) + && player->speed < FixedMul(5*FRACUNIT,player->mo->scale) && canstand) { if (GETSECSPECIAL(player->mo->subsector->sector->special, 4) == 7 || (player->mo->ceilingz - player->mo->floorz < P_GetPlayerHeight(player))) P_InstaThrust(player->mo, player->mo->angle, FixedMul(10*FRACUNIT, player->mo->scale)); @@ -3792,29 +3850,12 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) { if (player->mo->state-states != S_PLAY_DASH) P_SetPlayerMobjState(player->mo, S_PLAY_DASH); + // Spawn spin dash dust + if (!(player->mo->eflags & MFE_GOOWATER)) + P_DoSpinDashDust(player); } else if (onground && player->pflags & PF_SPINNING && !(player->panim == PA_ROLL)) P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); - - // Melee attack - if ((player->charability2 == CA2_MELEE) && !(player->panim == PA_ABILITY2) && !player->exiting - && !P_PlayerInPain(player) && (cmd->buttons & BT_USE) && player->speed < FixedMul(10<mo->scale) - && !player->mo->momz && onground && !(player->pflags & PF_USEDOWN) -#ifdef ESLOPE - && (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2) -#endif - ) - { - P_ResetPlayer(player); - player->mo->z += P_MobjFlip(player->mo); - player->mo->momx = player->cmomx = 0; - player->mo->momy = player->cmomy = 0; - P_SetObjectMomZ(player->mo, player->mindash, false); - P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->maxdash, player->mo->scale)); - P_SetPlayerMobjState(player->mo, S_PLAY_MELEE); - player->pflags |= PF_USEDOWN; - S_StartSound(player->mo, sfx_s3k8b); - } } // From 47c67472ff3ce02ae646c342ec36f5e834ace232 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 10 Nov 2016 21:09:05 +0000 Subject: [PATCH 03/10] Added bubble form of spin dust --- src/dehacked.c | 4 ++++ src/info.c | 5 ++++- src/info.h | 4 ++++ src/p_mobj.c | 7 +++++++ src/p_user.c | 15 +++++---------- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 3ef8b0d29..487ef8cd9 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5571,6 +5571,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SPINDUST2", "S_SPINDUST3", "S_SPINDUST4", + "S_SPINDUST_BUBBLE1", + "S_SPINDUST_BUBBLE2", + "S_SPINDUST_BUBBLE3", + "S_SPINDUST_BUBBLE4", "S_FOG1", "S_FOG2", diff --git a/src/info.c b/src/info.c index 459238917..d9bf9b463 100644 --- a/src/info.c +++ b/src/info.c @@ -2281,11 +2281,14 @@ state_t states[NUMSTATES] = {SPR_WZAP, FF_TRANS10|FF_ANIMATE|FF_RANDOMANIM, 4, {NULL}, 3, 2, S_NULL}, // S_WATERZAP // Spindash dust - // TODO: other spin dust types {SPR_DUST, 0, 7, {NULL}, 0, 0, S_SPINDUST2}, // S_SPINDUST1 {SPR_DUST, 1, 6, {NULL}, 0, 0, S_SPINDUST3}, // S_SPINDUST2 {SPR_DUST, FF_TRANS30|2, 4, {NULL}, 0, 0, S_SPINDUST4}, // S_SPINDUST3 {SPR_DUST, FF_TRANS60|3, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST4 + {SPR_BUBL, 0, 7, {NULL}, 0, 0, S_SPINDUST_BUBBLE2}, // S_SPINDUST_BUBBLE1 + {SPR_BUBL, 0, 6, {NULL}, 0, 0, S_SPINDUST_BUBBLE3}, // S_SPINDUST_BUBBLE2 + {SPR_BUBL, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_BUBBLE4}, // S_SPINDUST_BUBBLE3 + {SPR_BUBL, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_BUBBLE4 {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50, 2, {NULL}, 0, 0, S_FOG2}, // S_FOG1 {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|1, 2, {NULL}, 0, 0, S_FOG3}, // S_FOG2 diff --git a/src/info.h b/src/info.h index fc5012d29..4545bbbd6 100644 --- a/src/info.h +++ b/src/info.h @@ -2463,6 +2463,10 @@ typedef enum state S_SPINDUST2, S_SPINDUST3, S_SPINDUST4, + S_SPINDUST_BUBBLE1, + S_SPINDUST_BUBBLE2, + S_SPINDUST_BUBBLE3, + S_SPINDUST_BUBBLE4, S_FOG1, S_FOG2, diff --git a/src/p_mobj.c b/src/p_mobj.c index abe7849f2..827d24f3c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7541,6 +7541,13 @@ void P_MobjThinker(mobj_t *mobj) mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000 mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same //mobj->momz = mobj->momz+P_MobjFlip(mobj)/3; // no meaningful change in value to be frank + if (mobj->state >= &states[S_SPINDUST_BUBBLE1] && mobj->state <= &states[S_SPINDUST_BUBBLE4]) // bubble dust! + { + P_MobjCheckWater(mobj); + if (mobj->watertop != mobj->subsector->sector->floorheight - 1000*FRACUNIT + && mobj->z+mobj->height >= mobj->watertop - 5*FRACUNIT) + mobj->flags2 |= MF2_DONTDRAW; + } break; case MT_SPINFIRE: if (mobj->eflags & MFE_VERTICALFLIP) diff --git a/src/p_user.c b/src/p_user.c index 02ab2044c..7fe015a39 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3671,19 +3671,14 @@ static void P_DoSpinDashDust(player_t *player) { UINT32 i; mobj_t *particle; - UINT32 prandom[3]; + INT32 prandom[3]; for (i = 0; i <= (leveltime%7)/2; i++) { // 1, 2, 3 or 4 particles particle = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SPINDUST); - if (player->powers[pw_shield] == SH_ELEMENTAL && !(player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))) { - //P_SetMobjState(particle, S_FIREDUST1); - //particle->bubble = false; - } else if (player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) { - //P_SetMobjState(particle, S_BUBBLEDUST1); - //particle->bubble = true; - } else { - //P_SetMobjState(particle, S_SPINDUST1); - //particle->bubble = false; + /*if (player->powers[pw_shield] == SH_ELEMENTAL && !(player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))) { + P_SetMobjState(particle, S_SPINDUST_FIRE; + } else */if (player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) { + P_SetMobjState(particle, S_SPINDUST_BUBBLE1); } P_SetTarget(&particle->target, player->mo); particle->destscale = (2*player->mo->scale)/3; From c81665b9af3b901b449d9e932f0ffa8f452b755b Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 13 Nov 2016 22:02:29 +0000 Subject: [PATCH 04/10] Added flame version --- src/dehacked.c | 4 ++++ src/info.c | 6 ++++++ src/info.h | 5 +++++ src/p_user.c | 8 ++++---- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 487ef8cd9..25429dba3 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5575,6 +5575,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SPINDUST_BUBBLE2", "S_SPINDUST_BUBBLE3", "S_SPINDUST_BUBBLE4", + "S_SPINDUST_FIRE1", + "S_SPINDUST_FIRE2", + "S_SPINDUST_FIRE3", + "S_SPINDUST_FIRE4", "S_FOG1", "S_FOG2", diff --git a/src/info.c b/src/info.c index d9bf9b463..fb8291f4f 100644 --- a/src/info.c +++ b/src/info.c @@ -275,6 +275,7 @@ char sprnames[NUMSPRITES + 1][5] = "BUBL", // Bubble "WZAP", "DUST", // Spindash dust + "FPRT", // Spindash dust (flame) "TFOG", // Teleport Fog "SEED", // Sonic CD flower seed "PRTL", // Particle (for fans, etc.) @@ -2289,6 +2290,11 @@ state_t states[NUMSTATES] = {SPR_BUBL, 0, 6, {NULL}, 0, 0, S_SPINDUST_BUBBLE3}, // S_SPINDUST_BUBBLE2 {SPR_BUBL, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_BUBBLE4}, // S_SPINDUST_BUBBLE3 {SPR_BUBL, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_BUBBLE4 + {SPR_FPRT, 0, 7, {NULL}, 0, 0, S_SPINDUST_FIRE2}, // S_SPINDUST_FIRE1 + {SPR_FPRT, 0, 6, {NULL}, 0, 0, S_SPINDUST_FIRE3}, // S_SPINDUST_FIRE2 + {SPR_FPRT, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_FIRE4}, // S_SPINDUST_FIRE3 + {SPR_FPRT, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_FIRE4 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50, 2, {NULL}, 0, 0, S_FOG2}, // S_FOG1 {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|1, 2, {NULL}, 0, 0, S_FOG3}, // S_FOG2 diff --git a/src/info.h b/src/info.h index 4545bbbd6..d3f4ad55a 100644 --- a/src/info.h +++ b/src/info.h @@ -467,6 +467,7 @@ typedef enum sprite SPR_BUBL, // Bubble SPR_WZAP, SPR_DUST, // Spindash dust + SPR_FPRT, // Spindash dust (flame) SPR_TFOG, // Teleport Fog SPR_SEED, // Sonic CD flower seed SPR_PRTL, // Particle (for fans, etc.) @@ -2467,6 +2468,10 @@ typedef enum state S_SPINDUST_BUBBLE2, S_SPINDUST_BUBBLE3, S_SPINDUST_BUBBLE4, + S_SPINDUST_FIRE1, + S_SPINDUST_FIRE2, + S_SPINDUST_FIRE3, + S_SPINDUST_FIRE4, S_FOG1, S_FOG2, diff --git a/src/p_user.c b/src/p_user.c index 7fe015a39..69fdc56b0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3675,11 +3675,11 @@ static void P_DoSpinDashDust(player_t *player) for (i = 0; i <= (leveltime%7)/2; i++) { // 1, 2, 3 or 4 particles particle = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SPINDUST); - /*if (player->powers[pw_shield] == SH_ELEMENTAL && !(player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))) { - P_SetMobjState(particle, S_SPINDUST_FIRE; - } else */if (player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) { + if (player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) // overrides fire version P_SetMobjState(particle, S_SPINDUST_BUBBLE1); - } + else if (player->powers[pw_shield] == SH_ELEMENTAL) + P_SetMobjState(particle, S_SPINDUST_FIRE1); + P_SetTarget(&particle->target, player->mo); particle->destscale = (2*player->mo->scale)/3; P_SetScale(particle, particle->destscale); From 6e70acc82d60a7551a8e02f8c0315f9bdea572d4 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 13 Nov 2016 22:33:57 +0000 Subject: [PATCH 05/10] Added SF_NOSPINDASHDUST to disable spindash dust --- src/d_player.h | 1 + src/dehacked.c | 1 + src/p_user.c | 2 +- src/r_things.c | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/d_player.h b/src/d_player.h index bd553d9fa..a39b058e2 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -44,6 +44,7 @@ typedef enum SF_STOMPDAMAGE = 1<<9, // Always damage enemies, etc by landing on them, no matter your vunerability? SF_MARIODAMAGE = SF_NOJUMPDAMAGE|SF_STOMPDAMAGE, // The Mario method of being able to damage enemies, etc. SF_MACHINE = 1<<10, // Beep boop. Are you a robot? + SF_NOSPINDASHDUST = 1<<11, // Don't spawn dust particles when charging a spindash // free up to and including 1<<31 } skinflags_t; diff --git a/src/dehacked.c b/src/dehacked.c index 25429dba3..3a8a42129 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7060,6 +7060,7 @@ struct { {"SF_STOMPDAMAGE",SF_STOMPDAMAGE}, {"SF_MARIODAMAGE",SF_MARIODAMAGE}, {"SF_MACHINE",SF_MACHINE}, + {"SF_NOSPINDASHDUST",SF_NOSPINDASHDUST}, // Character abilities! // Primary diff --git a/src/p_user.c b/src/p_user.c index 69fdc56b0..9cab4c2cd 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3846,7 +3846,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (player->mo->state-states != S_PLAY_DASH) P_SetPlayerMobjState(player->mo, S_PLAY_DASH); // Spawn spin dash dust - if (!(player->mo->eflags & MFE_GOOWATER)) + if (!(player->charflags & SF_NOSPINDASHDUST) && !(player->mo->eflags & MFE_GOOWATER)) P_DoSpinDashDust(player); } else if (onground && player->pflags & PF_SPINNING && !(player->panim == PA_ROLL)) diff --git a/src/r_things.c b/src/r_things.c index 9f6cad529..a55bc8582 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2880,6 +2880,7 @@ void R_AddSkins(UINT16 wadnum) GETFLAG(STOMPDAMAGE) GETFLAG(MARIODAMAGE) GETFLAG(MACHINE) + GETFLAG(NOSPINDASHDUST) #undef GETFLAG else // let's check if it's a sound, otherwise error out From 2941521806bdcb09612dab0aaf476ca64e1edbf0 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 16 Nov 2016 18:43:25 +0000 Subject: [PATCH 06/10] Add R_Draw2sMultiPatchTranslucentColumn_8, for columns of multi-patch textures used as midtextures on two-sided linedefs with both transparency AND translucency ...that was a mouthful --- src/r_draw.h | 1 + src/r_draw8.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/r_segs.c | 2 ++ src/screen.c | 2 ++ src/screen.h | 1 + 5 files changed, 103 insertions(+) diff --git a/src/r_draw.h b/src/r_draw.h index 60c3c9db6..4a105b5b0 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -162,6 +162,7 @@ void R_DrawSplat_8(void); void R_DrawTranslucentSplat_8(void); void R_DrawTranslucentSpan_8(void); void R_Draw2sMultiPatchColumn_8(void); +void R_Draw2sMultiPatchTranslucentColumn_8(void); void R_DrawFogSpan_8(void); void R_DrawFogColumn_8(void); void R_DrawColumnShadowed_8(void); diff --git a/src/r_draw8.c b/src/r_draw8.c index c1b7da11b..9340b61c6 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -203,6 +203,103 @@ void R_Draw2sMultiPatchColumn_8(void) } } +void R_Draw2sMultiPatchTranslucentColumn_8(void) +{ + INT32 count; + register UINT8 *dest; + register fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + + if (count < 0) // Zero length, column does not exceed a pixel. + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + return; +#endif + + // Framebuffer destination address. + // Use ylookup LUT to avoid multiply with ScreenWidth. + // Use columnofs LUT for subwindows? + + //dest = ylookup[dc_yl] + columnofs[dc_x]; + dest = &topleft[dc_yl*vid.width + dc_x]; + + count++; + + // Determine scaling, which is the only mapping to be done. + fracstep = dc_iscale; + //frac = dc_texturemid + (dc_yl - centery)*fracstep; + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + + // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. + // This is as fast as it gets. + { + register const UINT8 *source = dc_source; + register const UINT8 *transmap = dc_transmap; + register const lighttable_t *colormap = dc_colormap; + register INT32 heightmask = dc_texheight-1; + register UINT8 val; + if (dc_texheight & heightmask) // not a power of 2 -- killough + { + heightmask++; + heightmask <<= FRACBITS; + + if (frac < 0) + while ((frac += heightmask) < 0); + else + while (frac >= heightmask) + frac -= heightmask; + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + val = source[frac>>FRACBITS]; + + if (val != TRANSPARENTPIXEL) + *dest = colormap[*(transmap + (val<<8) + (*dest))]; + + dest += vid.width; + + // Avoid overflow. + if (fracstep > 0x7FFFFFFF - frac) + frac += fracstep - heightmask; + else + frac += fracstep; + + while (frac >= heightmask) + frac -= heightmask; + } while (--count); + } + else + { + while ((count -= 2) >= 0) // texture height is a power of 2 + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[*(transmap + (val<<8) + (*dest))]; + dest += vid.width; + frac += fracstep; + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[*(transmap + (val<<8) + (*dest))]; + dest += vid.width; + frac += fracstep; + } + if (count & 1) + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[*(transmap + (val<<8) + (*dest))]; + } + } + } +} + /** \brief The R_DrawShadeColumn_8 function Experiment to make software go faster. Taken from the Boom source */ diff --git a/src/r_segs.c b/src/r_segs.c index 257be2989..3bd8b94c1 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -271,6 +271,8 @@ static void R_Render2sidedMultiPatchColumn(column_t *column) if (colfunc == wallcolfunc) twosmultipatchfunc(); + else if (colfunc == fuzzcolfunc) + twosmultipatchtransfunc(); else colfunc(); } diff --git a/src/screen.c b/src/screen.c index d00155785..97c865a97 100644 --- a/src/screen.c +++ b/src/screen.c @@ -49,6 +49,7 @@ void (*splatfunc)(void); // span drawer w/ transparency void (*basespanfunc)(void); // default span func for color mode void (*transtransfunc)(void); // translucent translated column drawer void (*twosmultipatchfunc)(void); // for cols with transparent pixels +void (*twosmultipatchtransfunc)(void); // for cols with transparent pixels AND translucency // ------------------ // global video state @@ -127,6 +128,7 @@ void SCR_SetMode(void) fuzzcolfunc = R_DrawTranslucentColumn_8; walldrawerfunc = R_DrawWallColumn_8; twosmultipatchfunc = R_Draw2sMultiPatchColumn_8; + twosmultipatchtransfunc = R_Draw2sMultiPatchTranslucentColumn_8; #ifdef RUSEASM if (R_ASM) { diff --git a/src/screen.h b/src/screen.h index 2dff4590e..a61de7f92 100644 --- a/src/screen.h +++ b/src/screen.h @@ -136,6 +136,7 @@ extern void (*basespanfunc)(void); extern void (*splatfunc)(void); extern void (*transtransfunc)(void); extern void (*twosmultipatchfunc)(void); +extern void (*twosmultipatchtransfunc)(void); // ----- // CPUID From 410b55ebcd6d8688eba09873ba1f46ec3d150828 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 28 Nov 2016 22:21:54 +0000 Subject: [PATCH 07/10] Work on FLIPX/FLIPX support: *Added FLIPX/FLIPY support for multi-patch textures and single-patch textures without holes *Added FLIPY support for single-patch textures with holes; I'll sort FLIPX support out later --- src/r_data.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++---- src/r_data.h | 1 + src/r_segs.c | 35 +++++++++++++++++++++++++++++-- src/r_things.c | 2 +- src/r_things.h | 1 + 5 files changed, 89 insertions(+), 7 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index b39ede58c..f4910fa00 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -173,6 +173,43 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig } } +static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, INT32 originy, INT32 cacheheight, INT32 patchheight) +{ + INT32 count, position; + UINT8 *source, *dest; + INT32 topdelta, prevdelta = -1; + + while (patch->topdelta != 0xff) + { + topdelta = patch->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + topdelta = patchheight-patch->length-topdelta; + source = (UINT8 *)patch + 2 + patch->length; // patch + 3 + (patch->length-1) + count = patch->length; + position = originy + topdelta; + + if (position < 0) + { + count += position; + position = 0; + } + + if (position + count > cacheheight) + count = cacheheight - position; + + dest = cache + position; + if (count > 0) + { + for (; dest < cache + position + count; --source) + *dest++ = *source; + } + + patch = (column_t *)((UINT8 *)patch + patch->length + 4); + } +} + // // R_GenerateTexture // @@ -191,7 +228,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) texture_t *texture; texpatch_t *patch; patch_t *realpatch; - int x, x1, x2, i; + int x, x1, x2, i, width, height; size_t blocksize; column_t *patchcol; UINT32 *colofs; @@ -239,6 +276,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) if (holey) { texture->holes = true; + texture->flip = patch->flip; blocksize = W_LumpLengthPwad(patch->wad, patch->lump); block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function &texturecache[texnum]); @@ -259,6 +297,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) // multi-patch textures (or 'composite') texture->holes = false; + texture->flip = 0; blocksize = (texture->width * 4) + (texture->width * texture->height); texturememory += blocksize; block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]); @@ -277,7 +316,9 @@ static UINT8 *R_GenerateTexture(size_t texnum) { realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); x1 = patch->originx; - x2 = x1 + SHORT(realpatch->width); + width = SHORT(realpatch->width); + height = SHORT(realpatch->height); + x2 = x1 + width; if (x1 < 0) x = 0; @@ -289,11 +330,17 @@ static UINT8 *R_GenerateTexture(size_t texnum) for (; x < x2; x++) { - patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1])); + if (patch->flip & 1) + patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[(x1+width-1)-x])); + else + patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1])); // generate column ofset lookup colofs[x] = LONG((x * texture->height) + (texture->width*4)); - R_DrawColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height); + if (patch->flip & 2) + R_DrawFlippedColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height, height); + else + R_DrawColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height); } } @@ -469,6 +516,7 @@ void R_LoadTextures(void) texture->height = SHORT(patchlump->height)*patchcount; texture->patchcount = patchcount; texture->holes = false; + texture->flip = 0; // Allocate information for the texture's patches. for (k = 0; k < patchcount; k++) @@ -479,6 +527,7 @@ void R_LoadTextures(void) patch->originy = (INT16)(k*patchlump->height); patch->wad = (UINT16)w; patch->lump = texstart + j; + patch->flip = 0; } Z_Unlock(patchlump); diff --git a/src/r_data.h b/src/r_data.h index 1384ecac0..72054da5d 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -43,6 +43,7 @@ typedef struct char name[8]; INT16 width, height; boolean holes; + UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both // All the patches[patchcount] are drawn back to front into the cached texture. INT16 patchcount; diff --git a/src/r_segs.c b/src/r_segs.c index 257be2989..91fb0e5bd 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -276,6 +276,13 @@ static void R_Render2sidedMultiPatchColumn(column_t *column) } } +// quick wrapper for R_DrawFlippedMaskedColumn so it can be set as a colfunc_2s value +// uses column2s_length for texture->height as above +static void R_DrawFlippedMaskedSegColumn(column_t *column) +{ + R_DrawFlippedMaskedColumn(column, column2s_length); +} + void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { size_t pindex; @@ -347,7 +354,15 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info in SRB2 if (textures[texnum]->holes) - colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture + { + if (textures[texnum]->flip & 2) // vertically flipped? + { + colfunc_2s = R_DrawFlippedMaskedSegColumn; + column2s_length = textures[texnum]->height; + } + else + colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture + } else { colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info) @@ -700,6 +715,14 @@ static void R_DrawRepeatMaskedColumn(column_t *col) } while (sprtopscreen < sprbotscreen); } +static void R_DrawRepeatFlippedMaskedColumn(column_t *col) +{ + do { + R_DrawFlippedMaskedColumn(col, column2s_length); + sprtopscreen += dc_texheight*spryscale; + } while (sprtopscreen < sprbotscreen); +} + // // R_RenderThickSideRange // Renders all the thick sides in the given range. @@ -1027,7 +1050,15 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) //faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info anymore in Doom Legacy if (textures[texnum]->holes) - colfunc_2s = R_DrawRepeatMaskedColumn; //render the usual 2sided single-patch packed texture + { + if (textures[texnum]->flip & 2) // vertically flipped? + { + colfunc_2s = R_DrawRepeatFlippedMaskedColumn; + column2s_length = textures[texnum]->height; + } + else + colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture + } else { colfunc_2s = R_Render2sidedMultiPatchColumn; //render multipatch with no holes (no post_t info) diff --git a/src/r_things.c b/src/r_things.c index 9f6cad529..5d560b53d 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -712,7 +712,7 @@ void R_DrawMaskedColumn(column_t *column) dc_texturemid = basetexturemid; } -static void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) +void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) { INT32 topscreen; INT32 bottomscreen; diff --git a/src/r_things.h b/src/r_things.h index 20dd25abf..572884d21 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -46,6 +46,7 @@ extern fixed_t windowtop; extern fixed_t windowbottom; void R_DrawMaskedColumn(column_t *column); +void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight); void R_SortVisSprites(void); //faB: find sprites in wadfile, replace existing, add new ones From c833497d39ecf9f2b1ae9a869c3c39ba71e5117b Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 1 Dec 2016 14:40:58 +0000 Subject: [PATCH 08/10] Correcting slip-up I made when originally improving zoom tubes. --- src/p_user.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 45a55d76b..524d50fb0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7159,13 +7159,6 @@ static void P_DoZoomTube(player_t *player) P_SetTarget(&player->mo->tracer, waypoint); // calculate MOMX/MOMY/MOMZ for next waypoint - // change angle - player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->tracer->x, player->mo->tracer->y); - - if (player == &players[consoleplayer]) - localangle = player->mo->angle; - else if (player == &players[secondarydisplayplayer]) - localangle2 = player->mo->angle; // change slope dist = P_AproxDistance(P_AproxDistance(player->mo->tracer->x - player->mo->x, player->mo->tracer->y - player->mo->y), player->mo->tracer->z - player->mo->z); @@ -7185,6 +7178,17 @@ static void P_DoZoomTube(player_t *player) CONS_Debug(DBG_GAMELOGIC, "Next waypoint not found, releasing from track...\n"); } } + + // change angle + if (player->mo->tracer) + { + player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->tracer->x, player->mo->tracer->y); + + if (player == &players[consoleplayer]) + localangle = player->mo->angle; + else if (player == &players[secondarydisplayplayer]) + localangle2 = player->mo->angle; + } } // From 52a84cf3091b2bfd26b8e5505f7c39d0fad3941a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 1 Dec 2016 21:43:27 +0000 Subject: [PATCH 09/10] Fix negative y offsets for both normal and y-flipped patches --- src/r_data.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/r_data.c b/src/r_data.c index f4910fa00..3e28b8ca2 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -160,6 +160,7 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig if (position < 0) { count += position; + source -= position; // start further down the column position = 0; } @@ -193,6 +194,7 @@ static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, INT if (position < 0) { count += position; + source += position; // start further UP the column position = 0; } From 84f3102ad08788e4142c9020e0fabb225ea5abcf Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 1 Dec 2016 22:37:33 +0000 Subject: [PATCH 10/10] Added FLIPX support for single patch textures with holes This completes FLIPX/FLIPY support for all textures --- src/r_data.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/r_data.c b/src/r_data.c index 3e28b8ca2..350bd4175 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -289,6 +289,14 @@ static UINT8 *R_GenerateTexture(size_t texnum) colofs = (UINT32 *)(void *)(block + 8); texturecolumnofs[texnum] = colofs; blocktex = block; + if (patch->flip & 1) // flip the patch horizontally + { + UINT32 *realcolofs = (UINT32 *)realpatch->columnofs; + for (x = 0; x < texture->width; x++) + colofs[x] = realcolofs[texture->width-1-x]; // swap with the offset of the other side of the texture + } + // we can't as easily flip the patch vertically sadly though, + // we have wait until the texture itself is drawn to do that for (x = 0; x < texture->width; x++) colofs[x] = LONG(LONG(colofs[x]) + 3); goto done;