From 837ed7bd8064b7872bd7884b26025ce3dee89709 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 29 Oct 2016 05:35:41 +0200 Subject: [PATCH 01/27] Fix dancing sprites due to texture coordinate calculations not taking pixel centers into account Merge R_DrawMaskedColumn and R_DrawMaskedColumnHoriz into one function to remove code duplication --- src/r_draw.h | 2 +- src/r_drawt.cpp | 113 +++++++---------------------------------------- src/r_segs.cpp | 24 +++++----- src/r_things.cpp | 93 ++++++++++++-------------------------- src/r_things.h | 4 +- src/v_draw.cpp | 6 +-- 6 files changed, 61 insertions(+), 181 deletions(-) diff --git a/src/r_draw.h b/src/r_draw.h index c45700a21..fa84e5ae9 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -116,7 +116,6 @@ extern void (*R_DrawSpanMaskedAddClamp)(void); // [RH] Span blit into an interleaved intermediate buffer extern void (*R_DrawColumnHoriz)(void); -void R_DrawMaskedColumnHoriz (const BYTE *column, const FTexture::Span *spans); // [RH] Initialize the above pointers void R_InitColumnDrawers (); @@ -183,6 +182,7 @@ extern void (*rt_map4cols)(int sx, int yl, int yh); #define rt_addclamp4cols rt_addclamp4cols_c #endif +void rt_flip_posts(); void rt_draw4cols (int sx); // [RH] Preps the temporary horizontal buffer. diff --git a/src/r_drawt.cpp b/src/r_drawt.cpp index e8faff0ce..cb228cce0 100644 --- a/src/r_drawt.cpp +++ b/src/r_drawt.cpp @@ -838,6 +838,21 @@ void rt_tlaterevsubclamp4cols (int sx, int yl, int yh) rt_revsubclamp4cols(sx, yl, yh); } +// Reorder the posts so that they get drawn top-to-bottom instead of bottom-to-top. +void rt_flip_posts() +{ + unsigned int *front = horizspan[dc_x & 3]; + unsigned int *back = dc_ctspan[dc_x & 3] - 2; + + while (front < back) + { + swapvalues(front[0], back[0]); + swapvalues(front[1], back[1]); + front += 2; + back -= 2; + } +} + // Copies all spans in all four columns to the screen starting at sx. // sx should be dword-aligned. void rt_draw4cols (int sx) @@ -1103,101 +1118,3 @@ void R_FillColumnHorizP (void) dest += 8; } while (--count); } - -// Same as R_DrawMaskedColumn() except that it always uses R_DrawColumnHoriz(). - -void R_DrawMaskedColumnHoriz (const BYTE *column, const FTexture::Span *span) -{ - const fixed_t texturemid = FLOAT2FIXED(dc_texturemid); - while (span->Length != 0) - { - const int length = span->Length; - const int top = span->TopOffset; - - // calculate unclipped screen coordinates for post - dc_yl = xs_RoundToInt(sprtopscreen + spryscale * top); - dc_yh = xs_RoundToInt(sprtopscreen + spryscale * (top + length) - 1); - - if (sprflipvert) - { - swapvalues (dc_yl, dc_yh); - } - - if (dc_yh >= mfloorclip[dc_x]) - { - dc_yh = mfloorclip[dc_x] - 1; - } - if (dc_yl < mceilingclip[dc_x]) - { - dc_yl = mceilingclip[dc_x]; - } - - if (dc_yl <= dc_yh) - { - if (sprflipvert) - { - dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS) - - fixed_t(CenterY * dc_iscale) - texturemid; - const fixed_t maxfrac = length << FRACBITS; - while (dc_texturefrac >= maxfrac) - { - if (++dc_yl > dc_yh) - goto nextpost; - dc_texturefrac += dc_iscale; - } - fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale; - while (endfrac < 0) - { - if (--dc_yh < dc_yl) - goto nextpost; - endfrac -= dc_iscale; - } - } - else - { - dc_texturefrac = texturemid - (top << FRACBITS) - + (dc_yl*dc_iscale) - fixed_t((CenterY-1) * dc_iscale); - while (dc_texturefrac < 0) - { - if (++dc_yl > dc_yh) - goto nextpost; - dc_texturefrac += dc_iscale; - } - fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale; - const fixed_t maxfrac = length << FRACBITS; - if (dc_yh < mfloorclip[dc_x]-1 && endfrac < maxfrac - dc_iscale) - { - dc_yh++; - } - else while (endfrac >= maxfrac) - { - if (--dc_yh < dc_yl) - goto nextpost; - endfrac -= dc_iscale; - } - } - dc_source = column + top; - dc_dest = ylookup[dc_yl] + dc_x + dc_destorg; - dc_count = dc_yh - dc_yl + 1; - hcolfunc_pre (); - } -nextpost: - span++; - } - - if (sprflipvert) - { - unsigned int *front = horizspan[dc_x&3]; - unsigned int *back = dc_ctspan[dc_x&3] - 2; - - // Reorder the posts so that they get drawn top-to-bottom - // instead of bottom-to-top. - while (front < back) - { - swapvalues (front[0], back[0]); - swapvalues (front[1], back[1]); - front += 2; - back -= 2; - } - } -} diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 48d8f1651..464fb3644 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -173,7 +173,7 @@ CVAR(Bool, r_drawmirrors, true, 0) float *MaskedSWall; float MaskedScaleY; -static void BlastMaskedColumn (void (*blastfunc)(const BYTE *pixels, const FTexture::Span *spans), FTexture *tex) +static void BlastMaskedColumn (FTexture *tex, bool useRt) { // calculate lighting if (fixedcolormap == NULL && fixedlightlev < 0) @@ -198,7 +198,7 @@ static void BlastMaskedColumn (void (*blastfunc)(const BYTE *pixels, const FText // draw the texture const FTexture::Span *spans; const BYTE *pixels = tex->GetColumn (maskedtexturecol[dc_x] >> FRACBITS, &spans); - blastfunc (pixels, spans); + R_DrawMaskedColumn(pixels, spans, useRt); rw_light += rw_lightstep; spryscale += rw_scalestep; } @@ -441,7 +441,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) { for (dc_x = x1; dc_x < x2; ++dc_x) { - BlastMaskedColumn (R_DrawMaskedColumn, tex); + BlastMaskedColumn (tex, false); } } else @@ -456,24 +456,24 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) while ((dc_x < stop) && (dc_x & 3)) { - BlastMaskedColumn (R_DrawMaskedColumn, tex); + BlastMaskedColumn (tex, false); dc_x++; } while (dc_x < stop) { rt_initcols(); - BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++; - BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++; - BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++; - BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); + BlastMaskedColumn (tex, true); dc_x++; + BlastMaskedColumn (tex, true); dc_x++; + BlastMaskedColumn (tex, true); dc_x++; + BlastMaskedColumn (tex, true); rt_draw4cols (dc_x - 3); dc_x++; } while (dc_x < x2) { - BlastMaskedColumn (R_DrawMaskedColumn, tex); + BlastMaskedColumn (tex, false); dc_x++; } } @@ -3245,7 +3245,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, { // calculate lighting dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); } - R_WallSpriteColumn (R_DrawMaskedColumn); + R_WallSpriteColumn (false); dc_x++; } @@ -3258,7 +3258,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, rt_initcols(); for (int zz = 4; zz; --zz) { - R_WallSpriteColumn (R_DrawMaskedColumnHoriz); + R_WallSpriteColumn (true); dc_x++; } rt_draw4cols (dc_x - 4); @@ -3270,7 +3270,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, { // calculate lighting dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); } - R_WallSpriteColumn (R_DrawMaskedColumn); + R_WallSpriteColumn (false); dc_x++; } } diff --git a/src/r_things.cpp b/src/r_things.cpp index a88624443..523004772 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -250,19 +250,17 @@ double sprtopscreen; bool sprflipvert; -void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span) +void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span, bool useRt) { - const fixed_t centeryfrac = FLOAT2FIXED(CenterY); - const fixed_t texturemid = FLOAT2FIXED(dc_texturemid); while (span->Length != 0) { const int length = span->Length; const int top = span->TopOffset; // calculate unclipped screen coordinates for post - dc_yl = xs_RoundToInt(sprtopscreen + spryscale * top); - dc_yh = xs_RoundToInt(sprtopscreen + spryscale * (top + length)) - 1; - + dc_yl = (int)(sprtopscreen + spryscale * top); + dc_yh = (int)(sprtopscreen + spryscale * (top + length)) - 1; + if (sprflipvert) { swapvalues (dc_yl, dc_yh); @@ -279,56 +277,20 @@ void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span) if (dc_yl <= dc_yh) { - if (sprflipvert) - { - dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS) - - FixedMul (centeryfrac, dc_iscale) - texturemid; - const fixed_t maxfrac = length << FRACBITS; - while (dc_texturefrac >= maxfrac) - { - if (++dc_yl > dc_yh) - goto nextpost; - dc_texturefrac += dc_iscale; - } - fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale; - while (endfrac < 0) - { - if (--dc_yh < dc_yl) - goto nextpost; - endfrac -= dc_iscale; - } - } - else - { - dc_texturefrac = texturemid - (top << FRACBITS) - + (dc_yl*dc_iscale) - FixedMul (centeryfrac-FRACUNIT, dc_iscale); - while (dc_texturefrac < 0) - { - if (++dc_yl > dc_yh) - goto nextpost; - dc_texturefrac += dc_iscale; - } - fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale; - const fixed_t maxfrac = length << FRACBITS; - if (dc_yh < mfloorclip[dc_x]-1 && endfrac < maxfrac - dc_iscale) - { - dc_yh++; - } - else while (endfrac >= maxfrac) - { - if (--dc_yh < dc_yl) - goto nextpost; - endfrac -= dc_iscale; - } - } - dc_source = column + top; - dc_dest = ylookup[dc_yl] + dc_x + dc_destorg; + dc_texturefrac = FLOAT2FIXED((dc_yl + 0.5 - sprtopscreen) / spryscale); + dc_source = column; + dc_dest = (ylookup[dc_yl] + dc_x) + dc_destorg; dc_count = dc_yh - dc_yl + 1; - colfunc (); + if (useRt) + hcolfunc_pre(); + else + colfunc (); } -nextpost: span++; } + + if (sprflipvert && useRt) + rt_flip_posts(); } // [ZZ] @@ -470,7 +432,7 @@ void R_DrawVisSprite (vissprite_t *vis) { pixels = tex->GetColumn (frac >> FRACBITS, &spans); if (ispsprite || !R_ClipSpriteColumnWithPortals(vis)) - R_DrawMaskedColumn (pixels, spans); + R_DrawMaskedColumn (pixels, spans, false); dc_x++; frac += xiscale; } @@ -482,7 +444,7 @@ void R_DrawVisSprite (vissprite_t *vis) { pixels = tex->GetColumn (frac >> FRACBITS, &spans); if (ispsprite || !R_ClipSpriteColumnWithPortals(vis)) - R_DrawMaskedColumnHoriz (pixels, spans); + R_DrawMaskedColumn (pixels, spans, true); dc_x++; frac += xiscale; } @@ -493,7 +455,7 @@ void R_DrawVisSprite (vissprite_t *vis) { pixels = tex->GetColumn (frac >> FRACBITS, &spans); if (ispsprite || !R_ClipSpriteColumnWithPortals(vis)) - R_DrawMaskedColumn (pixels, spans); + R_DrawMaskedColumn (pixels, spans, false); dc_x++; frac += xiscale; } @@ -603,7 +565,7 @@ void R_DrawWallSprite(vissprite_t *spr) dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT); } if (!R_ClipSpriteColumnWithPortals(spr)) - R_WallSpriteColumn(R_DrawMaskedColumn); + R_WallSpriteColumn(false); dc_x++; } @@ -617,7 +579,7 @@ void R_DrawWallSprite(vissprite_t *spr) for (int zz = 4; zz; --zz) { if (!R_ClipSpriteColumnWithPortals(spr)) - R_WallSpriteColumn(R_DrawMaskedColumnHoriz); + R_WallSpriteColumn(true); dc_x++; } rt_draw4cols(dc_x - 4); @@ -630,14 +592,14 @@ void R_DrawWallSprite(vissprite_t *spr) dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT); } if (!R_ClipSpriteColumnWithPortals(spr)) - R_WallSpriteColumn(R_DrawMaskedColumn); + R_WallSpriteColumn(false); dc_x++; } } R_FinishSetPatchStyle(); } -void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)) +void R_WallSpriteColumn (bool useRt) { float iscale = swall[dc_x] * MaskedScaleY; dc_iscale = FLOAT2FIXED(iscale); @@ -651,7 +613,7 @@ void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Sp const FTexture::Span *spans; column = WallSpriteTile->GetColumn (lwall[dc_x] >> FRACBITS, &spans); dc_texturefrac = 0; - drawfunc (column, spans); + R_DrawMaskedColumn(column, spans, useRt); rw_light += rw_lightstep; } @@ -984,21 +946,23 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor const double thingxscalemul = spriteScale.X / tex->Scale.X; tx -= ((renderflags & RF_XFLIP) ? (tex->GetWidth() - tex->LeftOffset - 1) : tex->LeftOffset) * thingxscalemul; - x1 = centerx + xs_RoundToInt(tx * xscale); + double dtx1 = tx * xscale; + x1 = centerx + xs_RoundToInt(dtx1); // off the right side? if (x1 >= WindowRight) return; tx += tex->GetWidth() * thingxscalemul; - x2 = centerx + xs_RoundToInt(tx * xscale); + double dtx2 = tx * xscale; + x2 = centerx + xs_RoundToInt(dtx2); // off the left side or too small? if ((x2 < WindowLeft || x2 <= x1)) return; xscale = spriteScale.X * xscale / tex->Scale.X; - iscale = (tex->GetWidth() << FRACBITS) / (x2 - x1); + iscale = (fixed_t)(tex->GetWidth() / (dtx2 - dtx1) * FRACUNIT); double yscale = spriteScale.Y / tex->Scale.Y; @@ -1026,8 +990,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor vis->xiscale = iscale; } - if (vis->x1 > x1) - vis->startfrac += vis->xiscale * (vis->x1 - x1); + vis->startfrac += (fixed_t)(vis->xiscale * (vis->x1 - centerx - dtx1 + 0.5 * thingxscalemul)); } else { diff --git a/src/r_things.h b/src/r_things.h index 29e69d3a5..53b887b18 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -124,8 +124,8 @@ extern double pspriteyscale; extern FTexture *WallSpriteTile; -void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *spans); -void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)); +void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *spans, bool useRt); +void R_WallSpriteColumn (bool useRt); void R_CacheSprite (spritedef_t *sprite); void R_SortVisSprites (int (*compare)(const void *, const void *), size_t first); diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 4677c4b08..20e5311cd 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -299,7 +299,7 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) while ((dc_x < stop4) && (dc_x & 3)) { pixels = img->GetColumn(frac >> FRACBITS, spanptr); - R_DrawMaskedColumn(pixels, spans); + R_DrawMaskedColumn(pixels, spans, false); dc_x++; frac += xiscale_i; } @@ -310,7 +310,7 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) for (int zz = 4; zz; --zz) { pixels = img->GetColumn(frac >> FRACBITS, spanptr); - R_DrawMaskedColumnHoriz(pixels, spans); + R_DrawMaskedColumn(pixels, spans, true); dc_x++; frac += xiscale_i; } @@ -320,7 +320,7 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) while (dc_x < x2_i) { pixels = img->GetColumn(frac >> FRACBITS, spanptr); - R_DrawMaskedColumn(pixels, spans); + R_DrawMaskedColumn(pixels, spans, false); dc_x++; frac += xiscale_i; } From 87ea75169e1b521d991b203484a44d56f5131eeb Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 29 Oct 2016 08:11:12 +0200 Subject: [PATCH 02/27] Fix texturefrac out of bounds bug --- src/r_things.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index 523004772..a15921cba 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -258,9 +258,9 @@ void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span, bool us const int top = span->TopOffset; // calculate unclipped screen coordinates for post - dc_yl = (int)(sprtopscreen + spryscale * top); - dc_yh = (int)(sprtopscreen + spryscale * (top + length)) - 1; - + dc_yl = (int)(sprtopscreen + spryscale * top + 0.5); + dc_yh = (int)(sprtopscreen + spryscale * (top + length) + 0.5) - 1; + if (sprflipvert) { swapvalues (dc_yl, dc_yh); From b1880964faad779a8f31656e63ebf10668517841 Mon Sep 17 00:00:00 2001 From: FishyClockwork Date: Fri, 28 Oct 2016 13:42:37 +0200 Subject: [PATCH 03/27] Added two new sub-blocks for Choice blocks Added two new sub-blocks for Choice blocks: Require and Exclude. The syntax for both is the same as Cost blocks. Require defines what item must be present in your inventory in order to show this choice/reply. Exclude defines what item must not be present in your inventory in order to show this choice/reply. If any Require/Exclude blocks are defined then this choice/reply will be hidden until all blocks of both types are satisfied. --- src/namedef.h | 2 ++ src/p_conversation.cpp | 65 ++++++++++++++++++++++++++++++++++++++---- src/p_conversation.h | 2 ++ src/p_usdf.cpp | 15 +++++++--- 4 files changed, 75 insertions(+), 9 deletions(-) diff --git a/src/namedef.h b/src/namedef.h index eab87c503..8def090fa 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -585,6 +585,8 @@ xx(Ifitem) xx(Choice) xx(Link) xx(Goodbye) +xx(Require) +xx(Exclude) // Special menus xx(Mainmenu) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index f216d9d78..0bc2b98a8 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -516,6 +516,8 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses) reply->ItemCheck[k].Item = dyn_cast(GetStrifeType(rsp->Item[k])); reply->ItemCheck[k].Amount = rsp->Count[k]; } + reply->ItemCheckRequire.Clear(); + reply->ItemCheckExclude.Clear(); // If the first item check has a positive amount required, then // add that to the reply string. Otherwise, use the reply as-is. @@ -656,6 +658,38 @@ CUSTOM_CVAR(Float, dlg_musicvolume, 1.0f, CVAR_ARCHIVE) else if (self > 1.f) self = 1.f; } +//============================================================================ +// +// ShouldSkipReply +// +// Determines whether this reply should be skipped or not. +// +//============================================================================ + +static bool ShouldSkipReply(FStrifeDialogueReply *reply, player_t *player) +{ + if (reply->Reply == nullptr) + return true; + + int i; + for (i = 0; i < (int)reply->ItemCheckRequire.Size(); ++i) + { + if (!CheckStrifeItem(player, reply->ItemCheckRequire[i].Item, reply->ItemCheckRequire[i].Amount)) + { + return true; + } + } + + for (i = 0; i < (int)reply->ItemCheckExclude.Size(); ++i) + { + if (CheckStrifeItem(player, reply->ItemCheckExclude[i].Item, reply->ItemCheckExclude[i].Amount)) + { + return true; + } + } + return false; +} + //============================================================================ // // The conversation menu @@ -673,6 +707,7 @@ class DConversationMenu : public DMenu bool mShowGold; FStrifeDialogueNode *mCurNode; int mYpos; + player_t *mPlayer; public: static int mSelection; @@ -683,9 +718,10 @@ public: // //============================================================================= - DConversationMenu(FStrifeDialogueNode *CurNode) + DConversationMenu(FStrifeDialogueNode *CurNode, player_t *player) { mCurNode = CurNode; + mPlayer = player; mDialogueLines = NULL; mShowGold = false; @@ -720,7 +756,7 @@ public: int i,j; for (reply = CurNode->Children, i = 1; reply != NULL; reply = reply->Next) { - if (reply->Reply == NULL) + if (ShouldSkipReply(reply, mPlayer)) { continue; } @@ -778,6 +814,13 @@ public: } ConversationMenuY = mYpos; //ConversationMenu.indent = 50; + + // Because replies can be selectively hidden mResponses.Size() won't be consistent. + // So make sure mSelection doesn't exceed mResponses.Size(). [FishyClockwork] + if (mSelection >= (int)mResponses.Size()) + { + mSelection = mResponses.Size() - 1; + } } //============================================================================= @@ -839,12 +882,24 @@ public: } else { - // Send dialogue and reply numbers across the wire. assert((unsigned)mCurNode->ThisNodeNum < StrifeDialogues.Size()); assert(StrifeDialogues[mCurNode->ThisNodeNum] == mCurNode); + + // This is needed because mSelection represents the replies currently being displayed which will + // not match up with what's supposed to be selected if there are any hidden/skipped replies. [FishyClockwork] + FStrifeDialogueReply *reply = mCurNode->Children; + int replynum = mSelection; + for (int i = 0; i <= mSelection && reply != nullptr; reply = reply->Next) + { + if (ShouldSkipReply(reply, mPlayer)) + replynum++; + else + i++; + } + // Send dialogue and reply numbers across the wire. Net_WriteByte(DEM_CONVREPLY); Net_WriteWord(mCurNode->ThisNodeNum); - Net_WriteByte(mSelection); + Net_WriteByte(replynum); } Close(); return true; @@ -1169,7 +1224,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang S_Sound (npc, CHAN_VOICE|CHAN_NOPAUSE, CurNode->SpeakerVoice, 1, ATTN_NORM); } - DConversationMenu *cmenu = new DConversationMenu(CurNode); + DConversationMenu *cmenu = new DConversationMenu(CurNode, pc->player); if (CurNode != PrevNode) diff --git a/src/p_conversation.h b/src/p_conversation.h index 5b068fb04..bd674aa10 100644 --- a/src/p_conversation.h +++ b/src/p_conversation.h @@ -45,6 +45,8 @@ struct FStrifeDialogueReply int ActionSpecial; int Args[5]; TArray ItemCheck; + TArray ItemCheckRequire; + TArray ItemCheckExclude; char *Reply; char *QuickYes; int NextNode; // index into StrifeDialogues diff --git a/src/p_usdf.cpp b/src/p_usdf.cpp index dccec7c21..245240273 100644 --- a/src/p_usdf.cpp +++ b/src/p_usdf.cpp @@ -76,11 +76,11 @@ class USDFParser : public UDMFParserBase //=========================================================================== // - // Parse a cost block + // Parse a cost/require/exclude block // //=========================================================================== - bool ParseCost(FStrifeDialogueReply *response) + bool ParseCostRequireExclude(FStrifeDialogueReply *response, FName type) { FStrifeDialogueItemCheck check; check.Item = NULL; @@ -101,7 +101,12 @@ class USDFParser : public UDMFParserBase } } - response->ItemCheck.Push(check); + switch (type) + { + case NAME_Cost: response->ItemCheck.Push(check); break; + case NAME_Require: response->ItemCheckRequire.Push(check); break; + case NAME_Exclude: response->ItemCheckExclude.Push(check); break; + } return true; } @@ -206,7 +211,9 @@ class USDFParser : public UDMFParserBase switch(key) { case NAME_Cost: - ParseCost(reply); + case NAME_Require: + case NAME_Exclude: + ParseCostRequireExclude(reply, key); break; default: From f1a80770e1f18af2b3d55700d0edbfdd89f7edf5 Mon Sep 17 00:00:00 2001 From: FishyClockwork Date: Fri, 28 Oct 2016 13:43:46 +0200 Subject: [PATCH 04/27] Updated the USDF specs Updated the USDF specs about 'require' and 'exclude'. --- specs/usdf.txt | 20 ++++++++++++++++++++ specs/usdf_zdoom.txt | 10 ++++++++++ 2 files changed, 30 insertions(+) diff --git a/specs/usdf.txt b/specs/usdf.txt index 093c9e7d7..2c65f25d0 100644 --- a/specs/usdf.txt +++ b/specs/usdf.txt @@ -122,6 +122,26 @@ conversation // Starts a dialog. amount = ; // Minimum amount of the item needed. } + // The amount of an item needed for this option to become available. + // You can have as many as needed. All require blocks must be satisfied + // to show this option. + require + { + item = ; // Item that is required to show this option. + amount = ; // Minimum amount of the item needed. + } + + // The undesired amount of an item. This option will become available + // if you have less than the specified amount. You can have as many + // as needed. All exclude blocks must be satisfied to show this option. + // Note: if both require and exclude are defined then all require + // and all exclude blocks must be satisfied to show this option. + exclude + { + item = ; // Item that is unwanted to show this option. + amount = ; // Unwanted minimum amount of the item. + } + displaycost = ; // Whether the cost should be // displayed with the option. // If no cost is specified this should diff --git a/specs/usdf_zdoom.txt b/specs/usdf_zdoom.txt index c106cdd1a..8a324c088 100644 --- a/specs/usdf_zdoom.txt +++ b/specs/usdf_zdoom.txt @@ -50,6 +50,16 @@ conversation item = ; } + require + { + item = ; + } + + exclude + { + item = ; + } + giveitem = ; } } From c341bc0d3c127cc0a03c2130b1c2ab2e01071a07 Mon Sep 17 00:00:00 2001 From: FishyClockwork Date: Sat, 29 Oct 2016 15:52:29 +0200 Subject: [PATCH 05/27] Added restriction of Require/Exclude to ZSDF Added restriction of Require/Exclude to ZSDF (namespace = "ZDoom";). A warning will be printed if a Require/Exclude block is detected in USDF (namespace = "Strife";). --- src/p_usdf.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/p_usdf.cpp b/src/p_usdf.cpp index 245240273..e8ce5ca50 100644 --- a/src/p_usdf.cpp +++ b/src/p_usdf.cpp @@ -210,9 +210,17 @@ class USDFParser : public UDMFParserBase { switch(key) { - case NAME_Cost: case NAME_Require: case NAME_Exclude: + // Print a warning if the namespace is not ZDoom otherwise fall-through. [FishyClockwork] + if (namespace_bits != Zd) + { + sc.ScriptMessage("Detected \"%s\" block, ignoring. Require/Exclude are exclusive to namespace ZDoom.", key == NAME_Require ? "Require" : "Exclude"); + while (!sc.CheckToken('}')) sc.MustGetAnyToken(); // Skip this block + break; + } + + case NAME_Cost: ParseCostRequireExclude(reply, key); break; From f450a60f6630ff823c46b8ed151ec85f4ed5f7af Mon Sep 17 00:00:00 2001 From: FishyClockwork Date: Sat, 29 Oct 2016 15:54:45 +0200 Subject: [PATCH 06/27] Undone changes to usdf.txt, updated usdf_zdoom.txt Undone changes to usdf.txt, updated usdf_zdoom.txt --- specs/usdf.txt | 20 -------------------- specs/usdf_zdoom.txt | 14 ++++++++++++-- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/specs/usdf.txt b/specs/usdf.txt index 2c65f25d0..093c9e7d7 100644 --- a/specs/usdf.txt +++ b/specs/usdf.txt @@ -122,26 +122,6 @@ conversation // Starts a dialog. amount = ; // Minimum amount of the item needed. } - // The amount of an item needed for this option to become available. - // You can have as many as needed. All require blocks must be satisfied - // to show this option. - require - { - item = ; // Item that is required to show this option. - amount = ; // Minimum amount of the item needed. - } - - // The undesired amount of an item. This option will become available - // if you have less than the specified amount. You can have as many - // as needed. All exclude blocks must be satisfied to show this option. - // Note: if both require and exclude are defined then all require - // and all exclude blocks must be satisfied to show this option. - exclude - { - item = ; // Item that is unwanted to show this option. - amount = ; // Unwanted minimum amount of the item. - } - displaycost = ; // Whether the cost should be // displayed with the option. // If no cost is specified this should diff --git a/specs/usdf_zdoom.txt b/specs/usdf_zdoom.txt index 8a324c088..588ae6cda 100644 --- a/specs/usdf_zdoom.txt +++ b/specs/usdf_zdoom.txt @@ -50,14 +50,24 @@ conversation item = ; } + // The amount of an item needed for this option to become available. + // You can have as many as needed. All require blocks must be satisfied + // to show this option. require { - item = ; + item = ; // Item that is required to show this option. + amount = ; // Minimum amount of the item needed. } + // The undesired amount of an item. This option will become available + // if you have less than the specified amount. You can have as many + // as needed. All exclude blocks must be satisfied to show this option. + // Note: if both require and exclude are defined then all require + // and all exclude blocks must be satisfied to show this option. exclude { - item = ; + item = ; // Item that is unwanted to show this option. + amount = ; // Unwanted minimum amount of the item. } giveitem = ; From 42be7bee935b7509a5979a77f91b6b8983a9284e Mon Sep 17 00:00:00 2001 From: FishyClockwork Date: Sat, 29 Oct 2016 17:05:59 +0200 Subject: [PATCH 07/27] For USDF treat Require/Exclude as unknown For USDF treat Require/Exclude as an unknown keyword. --- src/p_usdf.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/p_usdf.cpp b/src/p_usdf.cpp index e8ce5ca50..a64dc932f 100644 --- a/src/p_usdf.cpp +++ b/src/p_usdf.cpp @@ -210,19 +210,16 @@ class USDFParser : public UDMFParserBase { switch(key) { + case NAME_Cost: case NAME_Require: case NAME_Exclude: - // Print a warning if the namespace is not ZDoom otherwise fall-through. [FishyClockwork] - if (namespace_bits != Zd) + // Require and Exclude are exclusive to namespace ZDoom. [FishyClockwork] + if (key == NAME_Cost || namespace_bits == Zd) { - sc.ScriptMessage("Detected \"%s\" block, ignoring. Require/Exclude are exclusive to namespace ZDoom.", key == NAME_Require ? "Require" : "Exclude"); - while (!sc.CheckToken('}')) sc.MustGetAnyToken(); // Skip this block + ParseCostRequireExclude(reply, key); break; } - - case NAME_Cost: - ParseCostRequireExclude(reply, key); - break; + // Intentional fall-through default: sc.UnGet(); From 4a56d426c3aedc4dc0593923f3880adcbf98f1f5 Mon Sep 17 00:00:00 2001 From: FishyClockwork Date: Sat, 29 Oct 2016 17:33:34 +0200 Subject: [PATCH 08/27] Actually put the new info in the proper section Actually put the new info in the proper section in usdf_zdoom.txt --- specs/usdf_zdoom.txt | 46 +++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/specs/usdf_zdoom.txt b/specs/usdf_zdoom.txt index 588ae6cda..8fe1bd758 100644 --- a/specs/usdf_zdoom.txt +++ b/specs/usdf_zdoom.txt @@ -50,26 +50,6 @@ conversation item = ; } - // The amount of an item needed for this option to become available. - // You can have as many as needed. All require blocks must be satisfied - // to show this option. - require - { - item = ; // Item that is required to show this option. - amount = ; // Minimum amount of the item needed. - } - - // The undesired amount of an item. This option will become available - // if you have less than the specified amount. You can have as many - // as needed. All exclude blocks must be satisfied to show this option. - // Note: if both require and exclude are defined then all require - // and all exclude blocks must be satisfied to show this option. - exclude - { - item = ; // Item that is unwanted to show this option. - amount = ; // Unwanted minimum amount of the item. - } - giveitem = ; } } @@ -106,6 +86,32 @@ conversation // Starts a dialog. // the standard conversation ID ('actor' property) is used instead // for this purpose but since 'ZDoom' namespace requires the actor // to be a class name it needs a separate field for this. + + page + { + choice + { + // The amount of an item needed for this option to become available. + // You can have as many as needed. All require blocks must be satisfied + // to show this option. + require + { + item = ; // Item that is required to show this option. + amount = ; // Minimum amount of the item needed. + } + + // The undesired amount of an item. This option will become available + // if you have less than the specified amount. You can have as many + // as needed. All exclude blocks must be satisfied to show this option. + // Note: if both require and exclude are defined then all require + // and all exclude blocks must be satisfied to show this option. + exclude + { + item = ; // Item that is unwanted to show this option. + amount = ; // Unwanted minimum amount of the item. + } + } + } } =============================================================================== From 8f2e9be70c30ddd3a5c4e70bd843b27afad15f16 Mon Sep 17 00:00:00 2001 From: FishyClockwork Date: Sat, 29 Oct 2016 17:43:20 +0200 Subject: [PATCH 09/27] Changed a description in usdf_zdoom.txt Changed a description in usdf_zdoom.txt to be more truthful. It's not just one new field anymore. (I really should learn to read these things before changing them.) --- specs/usdf_zdoom.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/usdf_zdoom.txt b/specs/usdf_zdoom.txt index 8fe1bd758..2b2e6f6da 100644 --- a/specs/usdf_zdoom.txt +++ b/specs/usdf_zdoom.txt @@ -76,8 +76,8 @@ namespace = "ZDoom"; III.A : Conversations --------------------- -This block only lists the newly added fields. Currently ZDoom only adds one -field to the specification: +This block only lists the newly added fields. Currently ZDoom only adds a few +fields to the specification: conversation // Starts a dialog. { From 1502eae2ac47c85b0e2c95b8aad60e6de435c449 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sat, 29 Oct 2016 21:08:11 -0500 Subject: [PATCH 10/27] Add XPM (X PixMap) version of ZDoom icon --- src/posix/zdoom.xpm | 83 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/posix/zdoom.xpm diff --git a/src/posix/zdoom.xpm b/src/posix/zdoom.xpm new file mode 100644 index 000000000..eae49eb77 --- /dev/null +++ b/src/posix/zdoom.xpm @@ -0,0 +1,83 @@ +/* XPM */ +static char * zdoom_xpm[] = { +"48 48 32 1", +" c None", +". c #ADA990", +"+ c #999966", +"@ c #666666", +"# c #393939", +"$ c #555555", +"% c #996666", +"& c #777777", +"* c #5F5F5F", +"= c #333333", +"- c #4D4D4D", +"; c #868686", +"> c #969696", +", c #1C1C1C", +"' c #339933", +") c #336633", +"! c #66CC66", +"~ c #66FF66", +"{ c #66CC33", +"] c #222222", +"^ c #333300", +"/ c #292929", +"( c #040404", +"_ c #0C0C0C", +": c #663333", +"< c #996633", +"[ c #CC9966", +"} c #CC6633", +"| c #CC9999", +"1 c #FFCC99", +"2 c #FF9966", +"3 c #FFCCCC", +" ... ", +" ++@##$+ ", +" +...+%&+ ", +" %*=-*&;$=&* ", +" %**=$@;>@=&*% ", +" &**@$*@@$-.+& ", +" %$%@*..$@.. ", +" ,#@+++@@#& ", +" $,#$$@@$#=$'' ", +" )!!!~!{=],,,,]^)'!{') =/, ", +" )){'~!!'')=],=))'{)'')) /=],( ", +" )'!!'!)~'{'),)''''''')) @@/==](( ", +" ^)''')'{{''')'''''),))) $$@$/,( ", +" ,^))),))''''))'')^,__/$$$-#-(( ", +" :<[}<,_)))))))),___,]#@@-/]] ", +" :<|12<:_,,,,,_,#$$-#/,^^=^}}< ", +" :<[1}::,^,,__,#$-==/,,::^:<<< ", +" ::&+@#^,,__/)#-=/,,,,-::^<::= ", +" :*+12[:==_,$-=/,,,,/,#::::=^ ", +" #*}331}-$]-==/,,,,// ##:=^ ", +" /]<13[---],,,,,,,]_] ", +" ,:--/,___]]]]:^___/ ", +" _______,^^,^,__/# ", +" ______:::::/$,,/# ", +" ____^:::=,^^^^,^^ ", +" __,,:=^,,)))^,,= ", +" _,,),,,,,^)^^^,, ", +" ,^,,),__,^))),,^ ", +" ,,,^^,,,,,)))),, ", +" ,,,,,,,)^))))^ ", +" ,,^,,,^^)))))^ ", +" ,^^,,,,)))))), ", +" ,^,,,,))^))), ", +" ],,,,,$&&&*$# ", +" ],,,]#****$# ", +" ]]]]]^####, ", +" ]]]]*,,,,#* ", +" ,_,#@&&@*/ ", +" __$####=# ", +" ,_/$$$$$# ", +" ,,,$*$$$ ", +" ],,,$**$# ", +" ],,,@&&@# ", +" ],,,$**#= ", +" ,,=+++%$ ", +" *%%%*$ ", +" /$*$#/ ", +" ],,]] "}; From 7c1f7aa81cb152e25f672ccb1d4bb109b65729b2 Mon Sep 17 00:00:00 2001 From: FishyClockwork Date: Sun, 30 Oct 2016 20:27:07 +0100 Subject: [PATCH 11/27] Restricted custom goodbyes to ZSDF --- src/p_usdf.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/p_usdf.cpp b/src/p_usdf.cpp index a64dc932f..d40c542a1 100644 --- a/src/p_usdf.cpp +++ b/src/p_usdf.cpp @@ -345,7 +345,11 @@ class USDFParser : public UDMFParserBase break; case NAME_Goodbye: - Goodbye = CheckString(key); + // Custom goodbyes are exclusive to namespace ZDoom. [FishyClockwork] + if (namespace_bits == Zd) + { + Goodbye = CheckString(key); + } break; } } From 4fc5d527c6951584dad900cbf14194193c9e53f4 Mon Sep 17 00:00:00 2001 From: FishyClockwork Date: Sun, 30 Oct 2016 20:30:32 +0100 Subject: [PATCH 12/27] Moved 'goodbye' from usdf.txt to usdf_zdoom.txt I have undone all my changes to usdf.txt. It should look like how it did before commit 0df6ba6 --- specs/usdf.txt | 18 ++++++++---------- specs/usdf_zdoom.txt | 3 +++ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/specs/usdf.txt b/specs/usdf.txt index 093c9e7d7..4d1d01c1b 100644 --- a/specs/usdf.txt +++ b/specs/usdf.txt @@ -87,16 +87,14 @@ conversation // Starts a dialog. page // Starts a new page. Pages are automatically numbered starting at 1. { - name = ; // Name that goes in the upper left hand corner - panel = ; // Name of lump to render as the background. - voice = ; // Narration sound lump. - dialog = ; // Dialog of the page. - goodbye = ; // Custom goodbye message. If omitted then the - // generic goodbyes will be displayed instead. - drop = ; // mobj for the object to drop if the actor is - // killed. - link = ; // Page to jump to if all ifitem conditions are - // satisified. + name = ; // Name that goes in the upper left hand corner + panel = ; // Name of lump to render as the background. + voice = ; // Narration sound lump. + dialog = ; // Dialog of the page. + drop = ; // mobj for the object to drop if the actor is + // killed. + link = ; // Page to jump to if all ifitem conditions are + // satisified. // jumps to the specified page if the player has the specified amount // or more of item in their inventory. This can be repeated as many diff --git a/specs/usdf_zdoom.txt b/specs/usdf_zdoom.txt index 2b2e6f6da..f800b5ae7 100644 --- a/specs/usdf_zdoom.txt +++ b/specs/usdf_zdoom.txt @@ -89,6 +89,9 @@ conversation // Starts a dialog. page { + goodbye = ; // Custom goodbye message. If omitted then the + // generic goodbyes will be displayed instead. + choice { // The amount of an item needed for this option to become available. From ede350ba3672c07907ebee319c015f7a365dbc7d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 30 Oct 2016 23:44:55 +0100 Subject: [PATCH 13/27] - there seem to be some problems with the line endings... --- specs/usdf.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/specs/usdf.txt b/specs/usdf.txt index 4d1d01c1b..1367ccfbf 100644 --- a/specs/usdf.txt +++ b/specs/usdf.txt @@ -87,13 +87,13 @@ conversation // Starts a dialog. page // Starts a new page. Pages are automatically numbered starting at 1. { - name = ; // Name that goes in the upper left hand corner - panel = ; // Name of lump to render as the background. - voice = ; // Narration sound lump. - dialog = ; // Dialog of the page. - drop = ; // mobj for the object to drop if the actor is - // killed. - link = ; // Page to jump to if all ifitem conditions are + name = ; // Name that goes in the upper left hand corner + panel = ; // Name of lump to render as the background. + voice = ; // Narration sound lump. + dialog = ; // Dialog of the page. + drop = ; // mobj for the object to drop if the actor is + // killed. + link = ; // Page to jump to if all ifitem conditions are // satisified. // jumps to the specified page if the player has the specified amount From 43b2584f79ba62fbff6e1cb2b69c862dcbd09dd4 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sun, 30 Oct 2016 23:27:29 -0400 Subject: [PATCH 14/27] - Fixed: Reference to freed stack object in R_FindPlane. This caused a massive slowdown (90% drop in total performance) in R_FindPlane when built with optimizations on in GCC6. Although I don't really understand why since the comparison should have been O(1) regardless of memory contents and even if the check failed every plane it would still be pretty fast, this is what they mean when they say that anything can happen when undefined behavior is triggered. --- src/r_plane.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 07efb84b4..52dfd4332 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -595,9 +595,10 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl fixed_t alpha = FLOAT2FIXED(Alpha); //angle_t angle = (xform.Angle + xform.baseAngle).BAMs(); + FTransform nulltransform; + if (picnum == skyflatnum) // killough 10/98 { // most skies map together - FTransform nulltransform; lightlevel = 0; xform = &nulltransform; nulltransform.xOffs = nulltransform.yOffs = nulltransform.baseyOffs = 0; From 6e6249f896d4beda1b172eb0234fe1e98561cf9d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 31 Oct 2016 18:51:58 +0100 Subject: [PATCH 15/27] - reverted WEAPONTOP to its original value of 32 and made the added fudging bit part of the render side. This is needed so that 'offset(0,32)' does what it is supposed to do. --- src/g_shared/a_weapons.cpp | 1 + src/p_pspr.cpp | 3 +-- src/p_pspr.h | 8 +++----- src/r_things.cpp | 4 ++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index edd250deb..b1ede0187 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -640,6 +640,7 @@ void AWeapon::PostMorphWeapon () pspr = Owner->player->GetPSprite(PSP_WEAPON); pspr->y = WEAPONBOTTOM; + pspr->ResetInterpolation(); pspr->SetState(GetUpState()); } diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index abbd2284e..2e591e20d 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -262,8 +262,7 @@ void DPSprite::NewTick() while (pspr) { pspr->processPending = true; - pspr->oldx = pspr->x; - pspr->oldy = pspr->y; + pspr->ResetInterpolation(); pspr = pspr->Next; } diff --git a/src/p_pspr.h b/src/p_pspr.h index ea03e109f..64a2702a3 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -29,11 +29,8 @@ #define WEAPONBOTTOM 128. -// [RH] +0x6000 helps it meet the screen bottom -// at higher resolutions while still being in -// the right spot at 320x200. -#define WEAPONTOP (32+6./16) - +#define WEAPONTOP 32. +#define WEAPON_FUDGE_Y 0.375 class AInventory; // @@ -77,6 +74,7 @@ public: DPSprite* GetNext() { return Next; } AActor* GetCaller() { return Caller; } void SetCaller(AActor *newcaller) { Caller = newcaller; } + void ResetInterpolation() { oldx = x; oldy = y; } double x, y; double oldx, oldy; diff --git a/src/r_things.cpp b/src/r_things.cpp index a15921cba..cad434fa5 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1302,7 +1302,7 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double } sx = pspr->oldx + (pspr->x - pspr->oldx) * ticfrac; - sy = pspr->oldy + (pspr->y - pspr->oldy) * ticfrac; + sy = pspr->oldy + (pspr->y - pspr->oldy) * ticfrac + WEAPON_FUDGE_Y; if (pspr->Flags & PSPF_ADDBOB) { @@ -1610,7 +1610,7 @@ void R_DrawPlayerSprites () else { wx = weapon->oldx + (weapon->x - weapon->oldx) * r_TicFracF; - wy = weapon->oldy + (weapon->y - weapon->oldy) * r_TicFracF; + wy = weapon->oldy + (weapon->y - weapon->oldy) * r_TicFracF + WEAPON_FUDGE_Y; } } else From 8d7e400f8eaa964f359849df34306ade247cf850 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Mon, 31 Oct 2016 22:34:46 -0500 Subject: [PATCH 16/27] Fixed: DCanvas::FillSimplePoly must set dc_destorg - dc_destorg is normally set to the upper-left corner of the view window. If there is a border, then this won't coincide with the upper-left corner of the screen, and DCanvas::FillSimplePoly would merrily write off the end of the screen buffer. --- src/v_draw.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 20e5311cd..bef732894 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -1330,6 +1330,13 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints, return; } + BYTE *destorgsave = dc_destorg; + dc_destorg = screen->GetBuffer(); + if (dc_destorg == NULL) + { + I_FatalError("Attempt to write to buffer of hardware canvas"); + } + scalex /= tex->Scale.X; scaley /= tex->Scale.Y; @@ -1432,6 +1439,7 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints, pt1 = pt2; pt2--; if (pt2 < 0) pt2 = npoints; } while (pt1 != botpt); + dc_destorg = destorgsave; #endif } From 93885974438ab57d940f1e7cdfd4495fdf5fe4bc Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Tue, 1 Nov 2016 00:08:16 -0500 Subject: [PATCH 17/27] Add 1 pixel tall and wide texture support to the renderer - These require manual detection and overriding of the scaling factors to 0, because a right shift of (32-0) bits wraps around to 0 and results in no shift at all rather than leaving the register zeroed out. --- src/asm_ia32/tmap2.asm | 3 +++ src/r_plane.cpp | 45 +++++++++++++++++++++++++++++++--------- src/r_segs.cpp | 18 ++++++++++++++++ src/textures/texture.cpp | 5 +++-- 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/asm_ia32/tmap2.asm b/src/asm_ia32/tmap2.asm index 9a7aa5534..ab1695d3c 100644 --- a/src/asm_ia32/tmap2.asm +++ b/src/asm_ia32/tmap2.asm @@ -198,7 +198,10 @@ SetTiltedSpanSize: mov [y8+2],cl mov [y9+2],cl mov [y10+2],cl + cmp eax,0 ; if x bits is 0, mask must be 0 too. + jz .notted not eax +.notted: pop ecx mov [m1+2],eax diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 52dfd4332..c57af953a 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -221,10 +221,26 @@ void R_MapPlane (int y, int x1) distance = planeheight * yslope[y]; - ds_xstep = xs_ToFixed(32-ds_xbits, distance * xstepscale); - ds_ystep = xs_ToFixed(32-ds_ybits, distance * ystepscale); - ds_xfrac = xs_ToFixed(32-ds_xbits, distance * basexfrac) + pviewx; - ds_yfrac = xs_ToFixed(32-ds_ybits, distance * baseyfrac) + pviewy; + if (ds_xbits != 0) + { + ds_xstep = xs_ToFixed(32 - ds_xbits, distance * xstepscale); + ds_xfrac = xs_ToFixed(32 - ds_xbits, distance * basexfrac) + pviewx; + } + else + { + ds_xstep = 0; + ds_xfrac = 0; + } + if (ds_ybits != 0) + { + ds_ystep = xs_ToFixed(32 - ds_ybits, distance * ystepscale); + ds_yfrac = xs_ToFixed(32 - ds_ybits, distance * baseyfrac) + pviewy; + } + else + { + ds_ystep = 0; + ds_yfrac = 0; + } if (plane_shade) { @@ -357,7 +373,7 @@ void R_CalcTiltedLighting (double lval, double lend, int width) // //========================================================================== -void R_MapTiltedPlane (int y, int x1) +void R_MapTiltedPlane(int y, int x1) { int x2 = spanend[y]; int width = x2 - x1; @@ -366,18 +382,18 @@ void R_MapTiltedPlane (int y, int x1) DWORD u, v; int i; - iz = plane_sz[2] + plane_sz[1]*(centery-y) + plane_sz[0]*(x1-centerx); + iz = plane_sz[2] + plane_sz[1] * (centery - y) + plane_sz[0] * (x1 - centerx); // Lighting is simple. It's just linear interpolation from start to end if (plane_shade) { - uz = (iz + plane_sz[0]*width) * planelightfloat; + uz = (iz + plane_sz[0] * width) * planelightfloat; vz = iz * planelightfloat; - R_CalcTiltedLighting (vz, uz, width); + R_CalcTiltedLighting(vz, uz, width); } - uz = plane_su[2] + plane_su[1]*(centery-y) + plane_su[0]*(x1-centerx); - vz = plane_sv[2] + plane_sv[1]*(centery-y) + plane_sv[0]*(x1-centerx); + uz = plane_su[2] + plane_su[1] * (centery - y) + plane_su[0] * (x1 - centerx); + vz = plane_sv[2] + plane_sv[1] * (centery - y) + plane_sv[0] * (x1 - centerx); fb = ylookup[y] + x1 + dc_destorg; @@ -1888,6 +1904,15 @@ void R_DrawTiltedPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t } } + // Hack in support for 1 x Z and Z x 1 texture sizes + if (ds_ybits == 0) + { + plane_sv[2] = plane_sv[1] = plane_sv[0] = 0; + } + if (ds_xbits = 0) + { + plane_su[2] = plane_su[1] = plane_su[0] = 0; + } #if defined(X86_ASM) if (ds_source != ds_curtiltedsource) R_SetTiltedSpanSource_ASM (ds_source); diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 464fb3644..01c03e6d7 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -1104,6 +1104,12 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *l rw_pic->GetHeight(); // Make sure texture size is loaded fracbits = 32 - rw_pic->HeightBits; + if (fracbits == 32) + { // Hack for one pixel tall textures + fracbits = 0; + yrepeat = 0; + dc_texturemid = 0; + } setupvline(fracbits); xoffset = rw_offset; basecolormapdata = basecolormap->Maps; @@ -1456,6 +1462,12 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_ rw_pic->GetHeight(); // Make sure texture size is loaded fracbits = 32- rw_pic->HeightBits; + if (fracbits == 32) + { // Hack for one pixel tall textures + fracbits = 0; + yrepeat = 0; + dc_texturemid = 0; + } setupmvline(fracbits); xoffset = rw_offset; basecolormapdata = basecolormap->Maps; @@ -1631,6 +1643,12 @@ void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, f rw_pic->GetHeight(); // Make sure texture size is loaded fracbits = 32 - rw_pic->HeightBits; + if (fracbits == 32) + { // Hack for one pixel tall textures + fracbits = 0; + yrepeat = 0; + dc_texturemid = 0; + } setuptmvline(fracbits); xoffset = rw_offset; basecolormapdata = basecolormap->Maps; diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 760437db9..9c1b5fdb4 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -210,8 +210,9 @@ void FTexture::CalcBitSize () } WidthMask = (1 << WidthBits) - 1; - // The minimum height is 2, because we cannot shift right 32 bits. - for (i = 1; (1 << i) < Height; ++i) + //
The minimum height is 2, because we cannot shift right 32 bits. + // Scratch that. Somebody actually made a 1x1 texture, so now we have to handle it. + for (i = 0; (1 << i) < Height; ++i) { } HeightBits = i; From 5df21fda6814431e2dae8955add6ae9587fabf72 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Tue, 1 Nov 2016 00:18:56 -0500 Subject: [PATCH 18/27] Fixed: Masked midtexture yscale incorrectly used the texture's X scale --- src/r_segs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 01c03e6d7..45e3044d3 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2539,7 +2539,7 @@ void R_StoreWallRange (int start, int stop) lwal = (fixed_t *)(openings + ds_p->maskedtexturecol); swal = (float *)(openings + ds_p->swall); FTexture *pic = TexMan(sidedef->GetTexture(side_t::mid), true); - double yscale = pic->Scale.X * sidedef->GetTextureYScale(side_t::mid); + double yscale = pic->Scale.Y * sidedef->GetTextureYScale(side_t::mid); fixed_t xoffset = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::mid)); if (pic->bWorldPanning) From 46a311b23c7c09ab7e6701d62a5e8c2c331f43c3 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Tue, 1 Nov 2016 09:59:59 +0100 Subject: [PATCH 19/27] - Fixed a typo in 1 pixel tall support addition. Found by Clang -Wparentheses warning. --- src/r_plane.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index c57af953a..810aa0003 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -1909,7 +1909,7 @@ void R_DrawTiltedPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t { plane_sv[2] = plane_sv[1] = plane_sv[0] = 0; } - if (ds_xbits = 0) + if (ds_xbits == 0) { plane_su[2] = plane_su[1] = plane_su[0] = 0; } From 4cf0d76e8cd759bcca5adb27a1b8007ea186937f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 1 Nov 2016 13:33:18 +0100 Subject: [PATCH 20/27] - fixed: RapidJSON in ASCII mode cannot handle extended 8 bit character sets and will produce broken data if the input contains some. This means we need to perform the conversion to UTF-8 on ZDoom's side and run RapidJSON in UTF-8 mode. Daedalus triggers this with a 0x85 character which in Windows CP 1252 is the ellipsis (...) The converter will assume ISO-8859-1, though, but cannot do anything with these characters because they map to the font being used here. --- src/p_acs.cpp | 4 ++ src/serializer.cpp | 173 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 160 insertions(+), 17 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index f36aaaf69..d82e6590c 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -791,6 +791,10 @@ void ACSStringPool::WriteStrings(FSerializer &file, const char *key) const { if (file.BeginObject(nullptr)) { + if (i == 430) + { + int a = 0; + } file("index", i) ("string", entry->Str) ("lockcount", entry->LockCount) diff --git a/src/serializer.cpp b/src/serializer.cpp index 49226ce80..dec81e86f 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -67,6 +67,143 @@ char nulspace[1024 * 1024 * 4]; bool save_full = false; // for testing. Should be removed afterward. +int utf8_encode(int32_t codepoint, char *buffer, int *size) +{ + if (codepoint < 0) + return -1; + else if (codepoint < 0x80) + { + buffer[0] = (char)codepoint; + *size = 1; + } + else if (codepoint < 0x800) + { + buffer[0] = 0xC0 + ((codepoint & 0x7C0) >> 6); + buffer[1] = 0x80 + ((codepoint & 0x03F)); + *size = 2; + } + else if (codepoint < 0x10000) + { + buffer[0] = 0xE0 + ((codepoint & 0xF000) >> 12); + buffer[1] = 0x80 + ((codepoint & 0x0FC0) >> 6); + buffer[2] = 0x80 + ((codepoint & 0x003F)); + *size = 3; + } + else if (codepoint <= 0x10FFFF) + { + buffer[0] = 0xF0 + ((codepoint & 0x1C0000) >> 18); + buffer[1] = 0x80 + ((codepoint & 0x03F000) >> 12); + buffer[2] = 0x80 + ((codepoint & 0x000FC0) >> 6); + buffer[3] = 0x80 + ((codepoint & 0x00003F)); + *size = 4; + } + else + return -1; + + return 0; +} + +int utf8_decode(const char *src, int *size) +{ + int c = src[0] & 255; + int r; + + *size = 1; + if ((c & 0x80) == 0) + { + return c; + } + + int c1 = src[1] & 255; + + if ((c & 0xE0) == 0xC0) + { + r = ((c & 0x1F) << 6) | c1; + if (r >= 128) + { + *size = 2; + return r; + } + return -1; + } + + int c2 = src[2] & 255; + + if ((c & 0xF0) == 0xE0) + { + r = ((c & 0x0F) << 12) | (c1 << 6) | c2; + if (r >= 2048 && (r < 55296 || r > 57343)) + { + *size = 3; + return r; + } + return -1; + } + + int c3 = src[3] & 255; + + if ((c & 0xF8) == 0xF0) + { + r = ((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; + if (r >= 65536 && r <= 1114111) + { + *size = 4; + return r; + } + } + return -1; +} + +static TArray out; +static const char *StringToUnicode(const char *cc, int size = -1) +{ + int ch; + const char *c = cc; + int count = 0; + int count1 = 0; + out.Clear(); + while (ch = (*c++) & 255) + { + count1++; + if (ch >= 128) + { + if (ch < 0x800) count += 2; + else count += 3; + // The source cannot contain 4-byte chars. + } + else count++; + if (count1 == size && size > 0) break; + } + if (count == count1) return cc; // string is pure ASCII. + // we need to convert + out.Resize(count + 1); + out.Last() = 0; + c = cc; + int i = 0; + while (ch = (*c++) & 255) + { + utf8_encode(ch, &out[i], &count1); + i += count1; + } + return &out[0]; +} + +static const char *UnicodeToString(const char *cc) +{ + out.Resize((unsigned)strlen(cc) + 1); + int ndx = 0; + while (*cc != 0) + { + int size; + int c = utf8_decode(cc, &size); + if (c < 0 || c > 255) c = '?'; + out[ndx++] = c; + cc += size; + } + out[ndx] = 0; + return &out[0]; +} + //========================================================================== // // @@ -99,8 +236,8 @@ struct FJSONObject struct FWriter { - typedef rapidjson::Writer > Writer; - typedef rapidjson::PrettyWriter > PrettyWriter; + typedef rapidjson::Writer > Writer; + typedef rapidjson::PrettyWriter > PrettyWriter; Writer *mWriter1; PrettyWriter *mWriter2; @@ -173,14 +310,16 @@ struct FWriter void String(const char *k) { + k = StringToUnicode(k); if (mWriter1) mWriter1->String(k); else if (mWriter2) mWriter2->String(k); } void String(const char *k, int size) { - if (mWriter1) mWriter1->String(k, size); - else if (mWriter2) mWriter2->String(k, size); + k = StringToUnicode(k, size); + if (mWriter1) mWriter1->String(k); + else if (mWriter2) mWriter2->String(k); } void Bool(bool k) @@ -602,7 +741,7 @@ FSerializer &FSerializer::Args(const char *key, int *args, int *defargs, int spe } else if (i == 0 && aval.IsString()) { - args[i] = -FName(aval.GetString()); + args[i] = -FName(UnicodeToString(aval.GetString())); } else { @@ -654,7 +793,7 @@ FSerializer &FSerializer::ScriptNum(const char *key, int &num) } else if (val->IsString()) { - num = -FName(val->GetString()); + num = -FName(UnicodeToString(val->GetString())); } else { @@ -709,7 +848,7 @@ FSerializer &FSerializer::Sprite(const char *key, int32_t &spritenum, int32_t *d { if (val->IsString()) { - uint32_t name = *reinterpret_cast(val->GetString()); + uint32_t name = *reinterpret_cast(UnicodeToString(val->GetString())); for (auto hint = NumStdSprites; hint-- != 0; ) { if (sprites[hint].dwName == name) @@ -747,7 +886,7 @@ FSerializer &FSerializer::StringPtr(const char *key, const char *&charptr) { if (val->IsString()) { - charptr = val->GetString(); + charptr = UnicodeToString(val->GetString()); } else { @@ -1403,7 +1542,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe assert(nameval.IsString() && typeval.IsInt()); if (nameval.IsString() && typeval.IsInt()) { - value = TexMan.GetTexture(nameval.GetString(), typeval.GetInt()); + value = TexMan.GetTexture(UnicodeToString(nameval.GetString()), typeval.GetInt()); } else { @@ -1553,7 +1692,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FName &value, FName *d assert(val->IsString()); if (val->IsString()) { - value = val->GetString(); + value = UnicodeToString(val->GetString()); } else { @@ -1638,7 +1777,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FSoundID &sid, FSoundI assert(val->IsString() || val->IsNull()); if (val->IsString()) { - sid = val->GetString(); + sid = UnicodeToString(val->GetString()); } else if (val->IsNull()) { @@ -1687,7 +1826,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, PClassActor assert(val->IsString() || val->IsNull()); if (val->IsString()) { - clst = PClass::FindActor(val->GetString()); + clst = PClass::FindActor(UnicodeToString(val->GetString())); } else if (val->IsNull()) { @@ -1735,7 +1874,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, PClass *&cl { if (val->IsString()) { - clst = PClass::FindClass(val->GetString()); + clst = PClass::FindClass(UnicodeToString(val->GetString())); } else if (val->IsNull()) { @@ -1810,7 +1949,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FState *&state, FState assert(cls.IsString() && ndx.IsUint()); if (cls.IsString() && ndx.IsUint()) { - PClassActor *clas = PClass::FindActor(cls.GetString()); + PClassActor *clas = PClass::FindActor(UnicodeToString(cls.GetString())); if (clas && ndx.GetUint() < (unsigned)clas->NumOwnedStates) { state = clas->OwnedStates + ndx.GetUint(); @@ -1932,7 +2071,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FString *&p } else if (val->IsString()) { - pstr = AActor::mStringPropertyData.Alloc(val->GetString()); + pstr = AActor::mStringPropertyData.Alloc(UnicodeToString(val->GetString())); } else { @@ -1974,7 +2113,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FString &pstr, FString } else if (val->IsString()) { - pstr = val->GetString(); + pstr = UnicodeToString(val->GetString()); } else { @@ -2023,7 +2162,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, char *&pstr } else if (val->IsString()) { - pstr = copystring(val->GetString()); + pstr = copystring(UnicodeToString(val->GetString())); } else { From 3f57269a8b806d0c775381ef766364b9a18e4bb5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 1 Nov 2016 13:36:33 +0100 Subject: [PATCH 21/27] - fixed: ACSStringPool::AddString did not check for NULL pointers as input. Let's just map them to the empty string, that's a lot better than crashing. --- src/p_acs.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index d82e6590c..9281bfad0 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -375,6 +375,7 @@ void ACSStringPool::Clear() int ACSStringPool::AddString(const char *str) { + if (str == nullptr) str = ""; size_t len = strlen(str); unsigned int h = SuperFastHash(str, len); unsigned int bucketnum = h % NUM_BUCKETS; From 6e0defdc695f9b8e18fe6c730f63e5218245728b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 1 Nov 2016 13:48:56 +0100 Subject: [PATCH 22/27] - fixed numeric output precision for a few sliders. --- wadsrc/static/menudef.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 765fe6674..dac933af8 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -667,8 +667,8 @@ OptionMenu "VideoOptions" Slider "$DSPLYMNU_BRIGHTNESS", "Gamma", 0.75, 3.0, 0.05, 2 Option "$DSPLYMNU_VSYNC", "vid_vsync", "OnOff" Option "$DSPLYMNU_CAPFPS", "cl_capfps", "OffOn" - Slider "$DSPLYMNU_BLOODFADE", "blood_fade_scalar", 0.0, 1.0, 0.05, 1 - Slider "$DSPLYMNU_PICKUPFADE", "pickup_fade_scalar", 0.0, 1.0, 0.05, 1 + Slider "$DSPLYMNU_BLOODFADE", "blood_fade_scalar", 0.0, 1.0, 0.05, 2 + Slider "$DSPLYMNU_PICKUPFADE", "pickup_fade_scalar", 0.0, 1.0, 0.05, 2 Option "$DSPLYMNU_COLUMNMETHOD", "r_columnmethod", "ColumnMethods" StaticText " " @@ -700,7 +700,7 @@ OptionMenu "VideoOptions" ColorPicker "$DSPLYMNU_DIMCOLOR", "dimcolor" Slider "$DSPLYMNU_MOVEBOB", "movebob", 0, 1.0, 0.05, 2 Slider "$DSPLYMNU_STILLBOB", "stillbob", 0, 1.0, 0.05, 2 - Slider "$DSPLYMNU_BOBSPEED", "wbobspeed", 0, 2.0, 0.1, 2 + Slider "$DSPLYMNU_BOBSPEED", "wbobspeed", 0, 2.0, 0.1 } @@ -1242,7 +1242,7 @@ OptionMenu GameplayOptions Title "$GMPLYMNU_TITLE" //Indent 222 Option "$GMPLYMNU_TEAMPLAY", "teamplay", "OnOff" - Slider "$GMPLYMNU_TEAMDAMAGE", "teamdamage", 0, 1, 0.05 + Slider "$GMPLYMNU_TEAMDAMAGE", "teamdamage", 0, 1, 0.05,2 StaticText " " Option "$GMPLYMNU_SMARTAUTOAIM", "sv_smartaim", "SmartAim" StaticText " " @@ -1792,7 +1792,7 @@ OptionMenu NetworkOptions StaticText "$NETMNU_LOCALOPTIONS", 1 Option "$NETMNU_MOVEPREDICTION", "cl_noprediction", "OffOn" Option "$NETMNU_LINESPECIALPREDICTION", "cl_predict_specials", "OnOff" - Slider "$NETMNU_PREDICTIONLERPSCALE", "cl_predict_lerpscale", 0.0, 0.5, 0.05 + Slider "$NETMNU_PREDICTIONLERPSCALE", "cl_predict_lerpscale", 0.0, 0.5, 0.05, 2 Slider "$NETMNU_LERPTHRESHOLD", "cl_predict_lerpthreshold", 0.1, 16.0, 0.1 StaticText " " StaticText "$NETMNU_HOSTOPTIONS", 1 From f72ebe67689c6babe991b9b805eef419e3a186ce Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 1 Nov 2016 03:30:59 -0400 Subject: [PATCH 23/27] - Extended map, recordmap, and open commands to accept "dm/coop" as an extra parameter - to open maps in multiplayer mode with the requested ruleset. --- src/doomstat.h | 3 +++ src/g_game.cpp | 1 + src/g_level.cpp | 41 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index bbb323c7e..70869b5a2 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -71,6 +71,9 @@ extern bool netgame; // Bot game? Like netgame, but doesn't involve network communication. extern bool multiplayer; +// [SP] MPMap implementation - invokes fake multiplayer without bots +extern bool multiplayernext; + // Flag: true only if started as net deathmatch. EXTERN_CVAR (Int, deathmatch) diff --git a/src/g_game.cpp b/src/g_game.cpp index b0c8775fc..2c827e639 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -164,6 +164,7 @@ bool viewactive; bool netgame; // only true if packets are broadcast bool multiplayer; +bool multiplayernext = false; // [SP] MPMap implementation player_t players[MAXPLAYERS]; bool playeringame[MAXPLAYERS]; diff --git a/src/g_level.cpp b/src/g_level.cpp index d3a8c4015..65e19d423 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -90,6 +90,8 @@ #include "g_hub.h" +#include + void STAT_StartNewGame(const char *lev); void STAT_ChangeLevel(const char *newl); @@ -181,6 +183,16 @@ CCMD (map) } else { + if (argv.argc() > 2 && strcmp(argv[2], "coop") == 0) + { + deathmatch = false; + multiplayernext = true; + } + else if (argv.argc() > 2 && strcmp(argv[2], "dm") == 0) + { + deathmatch = true; + multiplayernext = true; + } G_DeferedInitNew (argv[1]); } } @@ -192,7 +204,7 @@ CCMD (map) } else { - Printf ("Usage: map \n"); + Printf ("Usage: map [coop|dm]\n"); } } @@ -218,6 +230,16 @@ CCMD(recordmap) } else { + if (argv.argc() > 3 && strcmp(argv[3], "coop") == 0) + { + deathmatch = false; + multiplayernext = true; + } + else if (argv.argc() > 3 && strcmp(argv[3], "dm") == 0) + { + deathmatch = true; + multiplayernext = true; + } G_DeferedInitNew(argv[2]); gameaction = ga_recordgame; newdemoname = argv[1]; @@ -232,7 +254,7 @@ CCMD(recordmap) } else { - Printf("Usage: recordmap \n"); + Printf("Usage: recordmap [coop|dm]\n"); } } @@ -258,13 +280,23 @@ CCMD (open) } else { + if (argv.argc() > 2 && strcmp(argv[2], "coop") == 0) + { + deathmatch = false; + multiplayernext = true; + } + else if (argv.argc() > 2 && strcmp(argv[2], "dm") == 0) + { + deathmatch = true; + multiplayernext = true; + } gameaction = ga_newgame2; d_skill = -1; } } else { - Printf ("Usage: open \n"); + Printf ("Usage: open [coop|dm]\n"); } } @@ -293,7 +325,8 @@ void G_NewInit () G_ClearSnapshots (); ST_SetNeedRefresh(); netgame = false; - multiplayer = false; + multiplayer = multiplayernext; + multiplayernext = false; if (demoplayback) { C_RestoreCVars (); From 6755373f464a709041ff77277a24bc808256e2a1 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 1 Nov 2016 09:47:01 -0400 Subject: [PATCH 24/27] - fixed: map commands will now take capslock DM/COOP as arguments --- src/doomstat.h | 2 +- src/g_game.cpp | 2 +- src/g_level.cpp | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 70869b5a2..22ee4fdb4 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -71,7 +71,7 @@ extern bool netgame; // Bot game? Like netgame, but doesn't involve network communication. extern bool multiplayer; -// [SP] MPMap implementation - invokes fake multiplayer without bots +// [SP] Map dm/coop implementation - invokes fake multiplayer without bots extern bool multiplayernext; // Flag: true only if started as net deathmatch. diff --git a/src/g_game.cpp b/src/g_game.cpp index 2c827e639..ec79d59e6 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -164,7 +164,7 @@ bool viewactive; bool netgame; // only true if packets are broadcast bool multiplayer; -bool multiplayernext = false; // [SP] MPMap implementation +bool multiplayernext = false; // [SP] Map coop/dm implementation player_t players[MAXPLAYERS]; bool playeringame[MAXPLAYERS]; diff --git a/src/g_level.cpp b/src/g_level.cpp index 65e19d423..9e8448879 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -183,12 +183,12 @@ CCMD (map) } else { - if (argv.argc() > 2 && strcmp(argv[2], "coop") == 0) + if (argv.argc() > 2 && stricmp(argv[2], "coop") == 0) { deathmatch = false; multiplayernext = true; } - else if (argv.argc() > 2 && strcmp(argv[2], "dm") == 0) + else if (argv.argc() > 2 && stricmp(argv[2], "dm") == 0) { deathmatch = true; multiplayernext = true; @@ -230,12 +230,12 @@ CCMD(recordmap) } else { - if (argv.argc() > 3 && strcmp(argv[3], "coop") == 0) + if (argv.argc() > 3 && stricmp(argv[3], "coop") == 0) { deathmatch = false; multiplayernext = true; } - else if (argv.argc() > 3 && strcmp(argv[3], "dm") == 0) + else if (argv.argc() > 3 && stricmp(argv[3], "dm") == 0) { deathmatch = true; multiplayernext = true; @@ -280,12 +280,12 @@ CCMD (open) } else { - if (argv.argc() > 2 && strcmp(argv[2], "coop") == 0) + if (argv.argc() > 2 && stricmp(argv[2], "coop") == 0) { deathmatch = false; multiplayernext = true; } - else if (argv.argc() > 2 && strcmp(argv[2], "dm") == 0) + else if (argv.argc() > 2 && stricmp(argv[2], "dm") == 0) { deathmatch = true; multiplayernext = true; From b420347babeb632497298b9a3e0f0f04e38a6aa9 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Sun, 16 Oct 2016 02:50:21 +0800 Subject: [PATCH 25/27] Added "local" parameters to A_PlaySound and ACS PlaySound --- src/p_acs.cpp | 7 ++++--- src/p_actionfunctions.cpp | 5 +++-- src/s_sound.cpp | 26 ++++++++++++++++++++++++++ src/s_sound.h | 3 +++ wadsrc/static/actors/actor.txt | 2 +- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 9281bfad0..1a60a0c4f 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -5350,7 +5350,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) case ACSF_PlaySound: case ACSF_PlayActorSound: - // PlaySound(tid, "SoundName", channel, volume, looping, attenuation) + // PlaySound(tid, "SoundName", channel, volume, looping, attenuation, local) { FSoundID sid; @@ -5371,6 +5371,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) float vol = argCount > 3 ? ACSToFloat(args[3]) : 1.f; INTBOOL looping = argCount > 4 ? args[4] : false; float atten = argCount > 5 ? ACSToFloat(args[5]) : ATTN_NORM; + INTBOOL local = argCount > 6 ? args[6] : false; if (args[0] == 0) { @@ -5387,11 +5388,11 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) { if (!looping) { - S_Sound(spot, chan, sid, vol, atten); + S_PlaySound(spot, chan, sid, vol, atten, local); } else if (!S_IsActorPlayingSomething(spot, chan & 7, sid)) { - S_Sound(spot, chan | CHAN_LOOP, sid, vol, atten); + S_PlaySound(spot, chan | CHAN_LOOP, sid, vol, atten, local); } } } diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index c6bc8215b..73cade49a 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -1032,16 +1032,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySound) PARAM_FLOAT_OPT (volume) { volume = 1; } PARAM_BOOL_OPT (looping) { looping = false; } PARAM_FLOAT_OPT (attenuation) { attenuation = ATTN_NORM; } + PARAM_BOOL_OPT (local) { local = false; } if (!looping) { - S_Sound (self, channel, soundid, (float)volume, (float)attenuation); + S_PlaySound(self, channel, soundid, (float)volume, (float)attenuation, local); } else { if (!S_IsActorPlayingSomething (self, channel&7, soundid)) { - S_Sound (self, channel | CHAN_LOOP, soundid, (float)volume, (float)attenuation); + S_PlaySound(self, channel | CHAN_LOOP, soundid, (float)volume, (float)attenuation, local); } } return 0; diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 524b12175..a51a7101b 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1301,6 +1301,32 @@ void S_Sound (const sector_t *sec, int channel, FSoundID sfxid, float volume, fl S_StartSound (NULL, sec, NULL, NULL, channel, sfxid, volume, attenuation); } +//========================================================================== +// +// S_PlaySound - Subfunction used by ACS and DECORATE +// +// Has a local parameter to make the sound audible only to the source +// +//========================================================================== + +void S_PlaySound(AActor *a, int chan, FSoundID sid, float vol, float atten, bool local) +{ + if (a == nullptr) + return; + + if (!local) + { + S_Sound(a, chan, sid, vol, atten); + } + else + { + if (a->CheckLocalView(consoleplayer)) + { + S_Sound(chan, sid, vol, ATTN_NONE); + } + } +} + //========================================================================== // // S_LoadSound diff --git a/src/s_sound.h b/src/s_sound.h index 9b917e25c..d6d2a5403 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -241,6 +241,9 @@ void S_Sound (const FPolyObj *poly, int channel, FSoundID sfxid, float volume, f void S_Sound (const sector_t *sec, int channel, FSoundID sfxid, float volume, float attenuation); void S_Sound(const DVector3 &pos, int channel, FSoundID sfxid, float volume, float attenuation); +// [Nash] Used by ACS and DECORATE +void S_PlaySound(AActor *a, int chan, FSoundID sid, float vol, float atten, bool local); + // sound channels // channel 0 never willingly overrides // other channels (1-7) always override a playing sound on that channel diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index eecc843d3..71e82f613 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -191,7 +191,7 @@ ACTOR Actor native //: Thinker action native A_ComboAttack(); action native A_BulletAttack(); action native A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", float snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, float runspeed = 160.0, class pufftype = "BulletPuff"); - action native A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, float volume = 1.0, bool looping = false, float attenuation = ATTN_NORM); + action native A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, float volume = 1.0, bool looping = false, float attenuation = ATTN_NORM, bool local = false); native void A_PlayWeaponSound(sound whattoplay); action native A_FLoopActiveSound(); action native A_LoopActiveSound(); From 3f32ccada6cf3533ab1f4aeb4a66df9cdc37bd2b Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Tue, 1 Nov 2016 22:54:27 -0500 Subject: [PATCH 26/27] Zero In2D before calling Flip() - Fixes an assert when resizing the window in windowed mode. Flip() can call V_OutputResized() in windowed mode. --- src/win32/fb_d3d9.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 06bfa0569..8bb680dbd 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -1092,6 +1092,7 @@ void D3DFB::Update () DrawRateStuff(); DrawPackedTextures(d3d_showpacks); EndBatch(); // Make sure all batched primitives are drawn. + In2D = 0; Flip(); } In2D = 0; From f8641c0ffb65402598bd7c51906cba3e2b6f03dc Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Wed, 2 Nov 2016 00:07:57 -0500 Subject: [PATCH 27/27] Fixed: MaxVisForFloor was broken by the switch to floats - TODO: See if these visibility limits are even needed anymore. --- src/r_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 4252f4155..c69c22c7b 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -355,7 +355,7 @@ void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, MaxVisForWall = (InvZtoScale * (SCREENWIDTH*r_Yaspect) / (viewwidth*SCREENHEIGHT * FocalTangent)); MaxVisForWall = 32767.0 / MaxVisForWall; - MaxVisForFloor = 32767.0 / (viewheight * FocalLengthY / 160); + MaxVisForFloor = 32767.0 / (viewheight >> 2) * FocalLengthY / 160; // Reset r_*Visibility vars R_SetVisibility(R_GetVisibility());