From 93885974438ab57d940f1e7cdfd4495fdf5fe4bc Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Tue, 1 Nov 2016 00:08:16 -0500 Subject: [PATCH 1/9] 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 9a7aa55346..ab1695d3cd 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 52dfd43323..c57af953a9 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 464fb36449..01c03e6d7a 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 760437db99..9c1b5fdb42 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 2/9] 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 01c03e6d7a..45e3044d3a 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 3/9] - 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 c57af953a9..810aa0003c 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 4/9] - 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 f36aaaf69a..d82e6590c4 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 49226ce801..dec81e86fe 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 5/9] - 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 d82e6590c4..9281bfad0e 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 6/9] - 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 765fe66744..dac933af81 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 7/9] - 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 bbb323c7e3..70869b5a2c 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 b0c8775fc5..2c827e6391 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 d3a8c4015a..65e19d4237 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 8/9] - 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 70869b5a2c..22ee4fdb49 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 2c827e6391..ec79d59e60 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 65e19d4237..9e8448879f 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 9/9] 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 9281bfad0e..1a60a0c4fb 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 c6bc8215b0..73cade49a4 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 524b121756..a51a7101be 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 9b917e25c8..d6d2a5403e 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 eecc843d39..71e82f613d 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();