Merge branch 'master' of http://git.magicalgirl.moe/STJr/SRB2Internal.git into shield-actions

This commit is contained in:
toasterbabe 2016-12-13 22:03:59 +00:00
commit d8d5f31898
17 changed files with 478 additions and 92 deletions

View File

@ -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;

View File

@ -2781,7 +2781,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.
@ -5670,6 +5670,20 @@ 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_SPINDUST_BUBBLE1",
"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",
"S_FOG3",
@ -6493,6 +6507,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",
@ -7173,6 +7188,7 @@ struct {
{"SF_STOMPDAMAGE",SF_STOMPDAMAGE},
{"SF_MARIODAMAGE",SF_MARIODAMAGE},
{"SF_MACHINE",SF_MACHINE},
{"SF_NOSPINDASHDUST",SF_NOSPINDASHDUST},
// Character abilities!
// Primary

View File

@ -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);

View File

@ -280,6 +280,8 @@ char sprnames[NUMSPRITES + 1][5] =
"SMOK",
"BUBL", // Bubble
"WZAP",
"DUST", // Spindash dust
"FPRT", // Spindash dust (flame)
"TFOG", // Teleport Fog
"SEED", // Sonic CD flower seed
"PRTL", // Particle (for fans, etc.)
@ -2388,6 +2390,21 @@ state_t states[NUMSTATES] =
{SPR_WZAP, FF_TRANS10|FF_ANIMATE|FF_RANDOMANIM, 4, {NULL}, 3, 2, S_NULL}, // S_WATERZAP
// Spindash dust
{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_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
{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|2, 2, {NULL}, 0, 0, S_FOG4}, // S_FOG3
@ -11400,6 +11417,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

View File

@ -475,6 +475,8 @@ typedef enum sprite
SPR_SMOK,
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.)
@ -2567,6 +2569,20 @@ typedef enum state
S_WATERZAP,
// Spindash dust
S_SPINDUST1,
S_SPINDUST2,
S_SPINDUST3,
S_SPINDUST4,
S_SPINDUST_BUBBLE1,
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,
S_FOG3,
@ -3409,6 +3425,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,

View File

@ -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)

View File

@ -7750,6 +7750,18 @@ 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
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->flags & MF_NOGRAVITY)
{

View File

@ -3731,6 +3731,35 @@ void P_DoJump(player_t *player, boolean soundandstate)
}
}
static void P_DoSpinDashDust(player_t *player)
{
UINT32 i;
mobj_t *particle;
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->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);
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
//
@ -3738,6 +3767,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;
@ -3749,69 +3779,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<<FRACBITS, player->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<<FRACBITS, player->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<<FRACBITS, player->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<<FRACBITS, player->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<<FRACBITS, player->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));
@ -3856,29 +3909,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->charflags & SF_NOSPINDASHDUST) && !(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<<FRACBITS, player->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);
}
}
//
@ -7364,13 +7400,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);
@ -7390,6 +7419,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;
}
}
//

View File

@ -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;
}
@ -173,6 +174,44 @@ 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;
source += position; // start further UP the column
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 +230,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 +278,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]);
@ -249,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;
@ -259,6 +307,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 +326,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 +340,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 +526,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 +537,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);
@ -502,6 +561,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 +658,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 +709,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

View File

@ -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,
@ -42,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;

View File

@ -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);

View File

@ -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
*/

View File

@ -271,11 +271,20 @@ static void R_Render2sidedMultiPatchColumn(column_t *column)
if (colfunc == wallcolfunc)
twosmultipatchfunc();
else if (colfunc == fuzzcolfunc)
twosmultipatchtransfunc();
else
colfunc();
}
}
// 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 +356,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 +717,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 +1052,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)

View File

@ -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;
@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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