diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index d448aa55e847015fa953d5cf6b9401f0bc62eb83..e0548e50d420dbf59457c89c75a8cd31a233a841 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1532,7 +1532,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[3].t += (gl_frontsector->ceilingheight - worldtop) * yscale * grTex->scaleY; wallVerts[2].t += (gl_frontsector->ceilingheight - worldtopslope) * yscale * grTex->scaleY; wallVerts[0].t += (gl_frontsector->floorheight - worldbottom) * yscale * grTex->scaleY; - wallVerts[1].t += (gl_frontsector->floorheight - worldbottomslope) * yscale * yscale; + wallVerts[1].t += (gl_frontsector->floorheight - worldbottomslope) * yscale * grTex->scaleY; } else if (gl_linedef->flags & ML_DONTPEGBOTTOM) { wallVerts[3].t = wallVerts[0].t + ((worldbottom - worldtop) * yscale) * grTex->scaleY; wallVerts[2].t = wallVerts[1].t + ((worldbottomslope - worldtopslope) * yscale) * grTex->scaleY; @@ -1625,12 +1625,17 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom side_t *side = &sides[rover->master->sidenum[0]]; + INT16 lineflags; + if (rover->master->flags & ML_TFERLINE) { size_t linenum = gl_curline->linedef-gl_backsector->lines[0]; newline = rover->master->frontsector->lines[0] + linenum; side = &sides[newline->sidenum[0]]; + lineflags = newline->flags; } + else + lineflags = gl_curline->linedef->flags; texnum = R_GetTextureNum(side->midtexture); @@ -1669,13 +1674,13 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // ...Oh well, anyway, Lower Unpegged now changes pegging of FOFs like in software // -- Monster Iestyn 26/06/18 fixed_t texturevpeg = side->rowoffset + side->offsety_mid; - boolean attachtobottom = !!(rover->master->flags & ML_DONTPEGBOTTOM); + boolean attachtobottom = !!(lineflags & ML_DONTPEGBOTTOM); grTex = HWR_GetTexture(texnum); xscale = FixedToFloat(side->scalex_mid); yscale = FixedToFloat(side->scaley_mid); - if (!(rover->master->flags & ML_SKEWTD)) // no skewing + if (!(lineflags & ML_SKEWTD)) // no skewing { if (attachtobottom) texturevpeg -= (*rover->topheight - *rover->bottomheight) * yscale; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 68b3332e5fc2267b571352e9d176e20dd1d8fb47..46814270078b27d3c6f40387e7297b84901d37ff 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1960,6 +1960,45 @@ static int lib_pMoveOrigin(lua_State *L) return 2; } +static int lib_pLineIsBlocking(lua_State *L) +{ + mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + line_t *line = *((line_t **)luaL_checkudata(L, 2, META_LINE)); + NOHUD + INLEVEL + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + if (!line) + return LUA_ErrInvalid(L, "line_t"); + + // P_LineOpening in P_LineIsBlocking sets these variables. + // We want to keep their old values after so that whatever + // map collision code uses them doesn't get messed up. + fixed_t oldopentop = opentop; + fixed_t oldopenbottom = openbottom; + fixed_t oldopenrange = openrange; + fixed_t oldlowfloor = lowfloor; + fixed_t oldhighceiling = highceiling; + pslope_t *oldopentopslope = opentopslope; + pslope_t *oldopenbottomslope = openbottomslope; + ffloor_t *oldopenfloorrover = openfloorrover; + ffloor_t *oldopenceilingrover = openceilingrover; + + lua_pushboolean(L, P_LineIsBlocking(mo, line)); + + opentop = oldopentop; + openbottom = oldopenbottom; + openrange = oldopenrange; + lowfloor = oldlowfloor; + highceiling = oldhighceiling; + opentopslope = oldopentopslope; + openbottomslope = oldopenbottomslope; + openfloorrover = oldopenfloorrover; + openceilingrover = oldopenceilingrover; + + return 1; +} + static int lib_pSlideMove(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -4454,6 +4493,7 @@ static luaL_Reg lib[] = { {"P_TeleportMove",lib_pTeleportMove}, {"P_SetOrigin",lib_pSetOrigin}, {"P_MoveOrigin",lib_pMoveOrigin}, + {"P_LineIsBlocking",lib_pLineIsBlocking}, {"P_SlideMove",lib_pSlideMove}, {"P_BounceMove",lib_pBounceMove}, {"P_CheckSight", lib_pCheckSight}, diff --git a/src/lua_colorlib.c b/src/lua_colorlib.c index 1e6e82333f18f28421a651728afd42ffc6d387f5..1ef21a41c704b1f3827fc6785fbd7b67c73db252 100644 --- a/src/lua_colorlib.c +++ b/src/lua_colorlib.c @@ -13,10 +13,33 @@ #include "doomdef.h" #include "fastcmp.h" #include "r_data.h" +#include "v_video.h" #include "lua_script.h" #include "lua_libs.h" +#define COLORLIB_USE_LOOKUP + +#ifdef COLORLIB_USE_LOOKUP + static colorlookup_t colormix_lut; + #define GetNearestColor(r, g, b) GetColorLUT(&colormix_lut, r, g, b) +#else + #define GetNearestColor(r, g, b) NearestPaletteColor(r, g, b, pMasterPalette) +#endif + +//////////////// +// Color library +//////////////// + +static int lib_colorPaletteToRgb(lua_State *L) +{ + RGBA_t color = V_GetMasterColor((UINT8)luaL_checkinteger(L, 1)); + lua_pushinteger(L, color.s.red); + lua_pushinteger(L, color.s.green); + lua_pushinteger(L, color.s.blue); + return 3; +} + #define IS_HEX_CHAR(x) ((x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F')) #define ARE_HEX_CHARS(str, i) IS_HEX_CHAR(str[i]) && IS_HEX_CHAR(str[i + 1]) @@ -32,6 +55,13 @@ static UINT32 hex2int(char x) return 0; } +static UINT8 GetHTMLColorLength(const char *str) +{ + if (str[0] == '#') + str++; + return strlen(str) >= 8 ? 4 : 3; +} + static UINT8 ParseHTMLColor(const char *str, UINT8 *rgba, size_t numc) { const char *hex = str; @@ -77,6 +107,302 @@ static UINT8 ParseHTMLColor(const char *str, UINT8 *rgba, size_t numc) return 0; } +static UINT8 GetPackedRGBA(UINT32 colors, UINT8 *rgba) +{ + if (colors > 0xFFFFFF) + { + rgba[0] = (colors >> 24) & 0xFF; + rgba[1] = (colors >> 16) & 0xFF; + rgba[2] = (colors >> 8) & 0xFF; + rgba[3] = colors & 0xFF; + return 4; + } + else + { + rgba[0] = (colors >> 16) & 0xFF; + rgba[1] = (colors >> 8) & 0xFF; + rgba[2] = colors & 0xFF; + rgba[3] = 0xFF; + return 3; + } +} + +static UINT8 GetArgsRGBA(lua_State *L, UINT8 index, INT32 *r, INT32 *g, INT32 *b, INT32 *a) +{ + UINT8 rgba[4] = { 0, 0, 0, 255 }; + UINT8 num = 0; + + if (lua_gettop(L) == 1 && lua_type(L, index) == LUA_TNUMBER) + { + num = GetPackedRGBA(luaL_checkinteger(L, 1), rgba); + + *r = rgba[0]; + *g = rgba[1]; + *b = rgba[2]; + if (a) + *a = rgba[3]; + } + else if (lua_type(L, index) == LUA_TSTRING) + { + const char *str = lua_tostring(L, index); + UINT8 parsed = ParseHTMLColor(str, rgba, GetHTMLColorLength(str)); + if (!parsed) + luaL_error(L, "Malformed HTML color '%s'", str); + + num = parsed == 8 ? 4 : 3; + + *r = rgba[0]; + *g = rgba[1]; + *b = rgba[2]; + if (a) + *a = rgba[3]; + } + else + { + INT32 temp; + +#define CHECKINT(i) luaL_checkinteger(L, i) +#define GETCOLOR(c, i, desc) { \ + temp = CHECKINT(i); \ + if (temp < 0 || temp > 255) \ + luaL_error(L, desc " channel %d out of range (0 - 255)", temp); \ + c = temp; \ + num++; \ + } + + GETCOLOR(*r, index + 0, "red color"); + GETCOLOR(*g, index + 1, "green color"); + GETCOLOR(*b, index + 2, "blue color"); +#undef CHECKINT +#define CHECKINT(i) luaL_optinteger(L, i, 255) + if (a) + GETCOLOR(*a, index + 3, "alpha"); +#undef CHECKINT +#undef GETCOLOR + + num = 3 + (lua_type(L, index + 3) == LUA_TNUMBER); + } + + return num; +} + +static int lib_colorRgbToPalette(lua_State *L) +{ + INT32 r, g, b; + GetArgsRGBA(L, 1, &r, &g, &b, NULL); + +#ifdef COLORLIB_USE_LOOKUP + InitColorLUT(&colormix_lut, pMasterPalette, false); +#endif + + lua_pushinteger(L, GetNearestColor(r, g, b)); + return 1; +} + +#define SCALE_UINT8_TO_FIXED(val) FixedDiv(val * FRACUNIT, 255 * FRACUNIT) +#define SCALE_FIXED_TO_UINT8(val) FixedRound(FixedMul(val, 255 * FRACUNIT)) / FRACUNIT + +static fixed_t hue2rgb(fixed_t p, fixed_t q, fixed_t t) +{ + if (t < 0) + t += FRACUNIT; + if (t > FRACUNIT) + t -= FRACUNIT; + + fixed_t out; + + if (t < FRACUNIT / 6) + out = p + FixedMul(FixedMul(q - p, 6 * FRACUNIT), t); + else if (t < FRACUNIT / 2) + out = q; + else if (t < 2 * FRACUNIT / 3) + out = p + FixedMul(FixedMul(q - p, 2 * FRACUNIT / 3 - t), 6 * FRACUNIT); + else + out = p; + + return out; +} + +static int lib_colorHslToRgb(lua_State *L) +{ + fixed_t h, s, l; + +#define GETHSL(c, i, desc) \ + c = luaL_checkinteger(L, i); \ + if (c < 0 || c > 255) \ + luaL_error(L, desc " %d out of range (0 - 255)", c) + + GETHSL(h, 1, "hue"); + GETHSL(s, 2, "saturation"); + GETHSL(l, 3, "value"); +#undef GETHSL + + if (!s) + { + lua_pushinteger(L, l); + lua_pushinteger(L, l); + lua_pushinteger(L, l); + } + else + { + h = SCALE_UINT8_TO_FIXED(h); + s = SCALE_UINT8_TO_FIXED(s); + l = SCALE_UINT8_TO_FIXED(l); + + fixed_t q, p; + + if (l < FRACUNIT/2) + q = FixedMul(l, FRACUNIT + s); + else + q = l + s - FixedMul(l, s); + + p = l * 2 - q; + + lua_pushinteger(L, SCALE_FIXED_TO_UINT8(hue2rgb(p, q, h + FRACUNIT/3))); + lua_pushinteger(L, SCALE_FIXED_TO_UINT8(hue2rgb(p, q, h))); + lua_pushinteger(L, SCALE_FIXED_TO_UINT8(hue2rgb(p, q, h - FRACUNIT/3))); + } + + return 3; +} + +static int lib_colorRgbToHsl(lua_State *L) +{ + INT32 ir, ig, ib; + GetArgsRGBA(L, 1, &ir, &ig, &ib, NULL); + + fixed_t r = SCALE_UINT8_TO_FIXED(ir); + fixed_t g = SCALE_UINT8_TO_FIXED(ig); + fixed_t b = SCALE_UINT8_TO_FIXED(ib); + + fixed_t cmin = min(min(r, g), b); + fixed_t cmax = max(max(r, g), b); + + fixed_t h, s, l = (cmax + cmin) / 2; + fixed_t delta = cmax - cmin; + + if (!delta) + h = s = 0; + else + { + if (l > FRACUNIT / 2) + s = FixedDiv(delta, (FRACUNIT * 2) - cmax - cmin); + else + s = FixedDiv(delta, cmax + cmin); + + if (r > g && r > b) + { + h = FixedDiv(g - b, delta); + + if (g < b) + h += FRACUNIT * 6; + } + else + { + h = FixedDiv(r - g, delta); + + if (g > b) + h += FRACUNIT * 2; + else + h += FRACUNIT * 4; + } + + h = FixedDiv(h, FRACUNIT * 6); + } + + lua_pushinteger(L, SCALE_FIXED_TO_UINT8(h)); + lua_pushinteger(L, SCALE_FIXED_TO_UINT8(s)); + lua_pushinteger(L, SCALE_FIXED_TO_UINT8(l)); + + return 3; +} + +static int lib_colorHexToRgb(lua_State *L) +{ + UINT8 rgba[4] = { 0, 0, 0, 255 }; + + const char *str = luaL_checkstring(L, 1); + UINT8 parsed = ParseHTMLColor(str, rgba, 4), num = 3; + if (!parsed) + luaL_error(L, "Malformed HTML color '%s'", str); + else if (parsed == 8) + num++; + + lua_pushinteger(L, rgba[0]); + lua_pushinteger(L, rgba[1]); + lua_pushinteger(L, rgba[2]); + if (num == 4) + lua_pushinteger(L, rgba[3]); + + return num; +} + +static int lib_colorRgbToHex(lua_State *L) +{ + INT32 r, g, b, a; + UINT8 num = GetArgsRGBA(L, 1, &r, &g, &b, &a); + + char buffer[10]; + if (num >= 4) + snprintf(buffer, sizeof buffer, "#%02X%02X%02X%02X", r, g, b, a); + else + snprintf(buffer, sizeof buffer, "#%02X%02X%02X", r, g, b); + + lua_pushstring(L, buffer); + return 1; +} + +static int lib_colorPackRgb(lua_State *L) +{ + INT32 r, g, b; + + GetArgsRGBA(L, 1, &r, &g, &b, NULL); + + UINT32 packed = ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF); + + lua_pushinteger(L, packed); + return 1; +} + +static int lib_colorPackRgba(lua_State *L) +{ + INT32 r, g, b, a; + + GetArgsRGBA(L, 1, &r, &g, &b, &a); + + UINT32 packed = ((r & 0xFF) << 24) | ((g & 0xFF) << 16) | ((b & 0xFF) << 8) | (a & 0xFF); + + lua_pushinteger(L, packed); + return 1; +} + +static int lib_colorUnpackRgb(lua_State *L) +{ + UINT8 rgba[4]; + + UINT8 num = GetPackedRGBA(lua_tointeger(L, 1), rgba); + + for (UINT8 i = 0; i < num; i++) + { + lua_pushinteger(L, rgba[i]); + } + + return num; +} + +static luaL_Reg color_lib[] = { + {"paletteToRgb", lib_colorPaletteToRgb}, + {"rgbToPalette", lib_colorRgbToPalette}, + {"hslToRgb", lib_colorHslToRgb}, + {"rgbToHsl", lib_colorRgbToHsl}, + {"hexToRgb", lib_colorHexToRgb}, + {"rgbToHex", lib_colorRgbToHex}, + {"packRgb", lib_colorPackRgb}, + {"packRgba", lib_colorPackRgba}, + {"unpackRgb", lib_colorUnpackRgb}, + {NULL, NULL} +}; + ///////////////////////// // extracolormap userdata ///////////////////////// @@ -180,21 +506,7 @@ static void GetExtraColormapRGBA(lua_State *L, UINT8 *rgba, int arg) } else { - UINT32 colors = lua_tointeger(L, arg); - if (colors > 0xFFFFFF) - { - rgba[0] = (colors >> 24) & 0xFF; - rgba[1] = (colors >> 16) & 0xFF; - rgba[2] = (colors >> 8) & 0xFF; - rgba[3] = colors & 0xFF; - } - else - { - rgba[0] = (colors >> 16) & 0xFF; - rgba[1] = (colors >> 8) & 0xFF; - rgba[2] = colors & 0xFF; - rgba[3] = 0xFF; - } + GetPackedRGBA(lua_tointeger(L, arg), rgba); } } @@ -328,5 +640,7 @@ int LUA_ColorLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + luaL_register(L, "color", color_lib); + return 0; } diff --git a/src/lua_script.c b/src/lua_script.c index 48291410297642234e7f60109367faa6ed062eff..ecd85f11b4427b881ed5a5c43974b759e2ea9597 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -38,6 +38,8 @@ #include "doomstat.h" #include "g_state.h" +#include "hu_stuff.h" + lua_State *gL = NULL; // List of internal libraries to load from SRB2 @@ -432,6 +434,9 @@ int LUA_PushGlobals(lua_State *L, const char *word) return 0; LUA_PushUserdata(L, &camera2, META_CAMERA); return 1; + } else if (fastcmp(word, "chatactive")) { + lua_pushboolean(L, chat_on); + return 1; } return 0; } diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 4ede33f10361980f682daf7d4cd097633db72de3..e183d8dda4a08b4c64dcc2429937cf919d743f67 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -54,7 +54,8 @@ enum skin { skin_contspeed, skin_contangle, skin_soundsid, - skin_sprites + skin_sprites, + skin_natkcolor }; static const char *const skin_opt[] = { @@ -94,6 +95,7 @@ static const char *const skin_opt[] = { "contangle", "soundsid", "sprites", + "natkcolor", NULL}; #define UNIMPLEMENTED luaL_error(L, LUA_QL("skin_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", skin_opt[field]) @@ -218,6 +220,9 @@ static int skin_get(lua_State *L) case skin_sprites: LUA_PushUserdata(L, skin->sprites, META_SKINSPRITES); break; + case skin_natkcolor: + lua_pushinteger(L, skin->natkcolor); + break; } return 1; } diff --git a/src/m_cond.c b/src/m_cond.c index 7fea86c65700126f81134134a3ff3253065b23c8..bfb23e6723482045ed6fb22fe95aa1a464d184fc 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -475,6 +475,9 @@ UINT8 M_MapLocked(INT32 mapnum, gamedata_t *data) // that's better than making dedicated server's lives hell. return false; } + + if (cv_debug || devparm) + return false; // Unlock every level when in devmode. if (!mapheaderinfo[mapnum-1] || mapheaderinfo[mapnum-1]->unlockrequired < 0) { diff --git a/src/m_menu.c b/src/m_menu.c index 48e316cc3581ae179d7e4adc00331555bb26c080..2630dcddf6ccc1fd17bdbfb5223d5ecc5355678a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3651,9 +3651,12 @@ void M_StartControlPanel(void) } else if (!(netgame || multiplayer)) // Single Player { + // Devmode unlocks Pandora's Box in the pause menu + boolean pandora = ((M_SecretUnlocked(SECRET_PANDORA, serverGamedata) || cv_debug || devparm) && !marathonmode); + if (gamestate != GS_LEVEL || ultimatemode) // intermission, so gray out stuff. { - SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA, serverGamedata)) ? (IT_GRAYEDOUT) : (IT_DISABLED); + SPauseMenu[spause_pandora].status = (pandora) ? (IT_GRAYEDOUT) : (IT_DISABLED); SPauseMenu[spause_retry].status = IT_GRAYEDOUT; } else @@ -3662,7 +3665,7 @@ void M_StartControlPanel(void) if (players[consoleplayer].playerstate != PST_LIVE) ++numlives; - SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !marathonmode) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + SPauseMenu[spause_pandora].status = (pandora) ? (IT_STRING | IT_CALL) : (IT_DISABLED); // The list of things that can disable retrying is (was?) a little too complex // for me to want to use the short if statement syntax @@ -3673,7 +3676,11 @@ void M_StartControlPanel(void) } // We can always use level select though. :33 - SPauseMenu[spause_levelselect].status = (maplistoption != 0) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + // Guarantee it if we have either it unlocked or devmode is enabled + if ((maplistoption != 0 || M_SecretUnlocked(SECRET_LEVELSELECT, serverGamedata) || cv_debug || devparm) && !marathonmode) + SPauseMenu[spause_levelselect].status = (IT_STRING | IT_CALL); + else + SPauseMenu[spause_levelselect].status = (IT_DISABLED); // And emblem hints. SPauseMenu[spause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS, clientGamedata) && !marathonmode) ? (IT_STRING | IT_CALL) : (IT_DISABLED); @@ -5141,7 +5148,8 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt) return false; case LLM_LEVELSELECT: - if (!(mapheaderinfo[mapnum]->levelselect & maplistoption)) + if (!(mapheaderinfo[mapnum]->levelselect & maplistoption) + && !(cv_debug || devparm)) //Allow ALL levels in devmode! return false; return true; @@ -5974,16 +5982,6 @@ static void M_DrawNightsAttackBackground(void) if (ntsatkdrawtimer < 0) ntsatkdrawtimer = 0; } -// NiGHTS Attack floating Super Sonic. -static patch_t *ntssupersonic[2]; -static void M_DrawNightsAttackSuperSonic(void) -{ - const UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_YELLOW, GTC_CACHE); - INT32 timer = FixedInt(ntsatkdrawtimer/4) % 2; - angle_t fa = (FixedAngle((FixedInt(ntsatkdrawtimer * 4) % 360)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK; - V_DrawFixedPatch(235<<FRACBITS, (120<<FRACBITS) - (8*FINESINE(fa)), FRACUNIT, 0, ntssupersonic[timer], colormap); -} - static void M_DrawLevelPlatterMenu(void) { UINT8 iter = lsrow, sizeselect = (lswide(lsrow) ? 1 : 0); @@ -7702,9 +7700,12 @@ static void M_PauseLevelSelect(INT32 choice) SP_PauseLevelSelectDef.prevMenu = currentMenu; levellistmode = LLM_LEVELSELECT; - // maplistoption is NOT specified, so that this + // maplistoption is only specified if not set already + // and we have the level select unlocked so that it // transfers the level select list from the menu // used to enter the game to the pause menu. + if (maplistoption == 0 && M_SecretUnlocked(SECRET_LEVELSELECT, serverGamedata)) + maplistoption = 1; if (!M_PrepareLevelPlatter(-1, true)) { @@ -10369,8 +10370,38 @@ void M_DrawNightsAttackMenu(void) V_DrawString(104-72, 180, V_TRANSLUCENT, M_GetText("Press ESC to exit")); } - // Super Sonic - M_DrawNightsAttackSuperSonic(); + // Draw selected character's NiGHTS sprite + patch_t *natksprite; //The patch for the sprite itself + INT32 spritetimer; //Timer for animating NiGHTS sprite + INT32 skinnumber; //Number for skin + UINT16 color; //natkcolor + + if (skins[cv_chooseskin.value-1]->sprites[SPR2_NFLY].numframes == 0) //If we don't have NiGHTS sprites + skinnumber = 0; //Default to Sonic + else + skinnumber = (cv_chooseskin.value-1); + + spritedef_t *sprdef = &skins[skinnumber]->sprites[SPR2_NFLY]; //Make our patch the selected character's NFLY sprite + spritetimer = FixedInt(ntsatkdrawtimer/2) % skins[skinnumber]->sprites[SPR2_NFLY].numframes; //Make the sprite timer cycle though all the frames at 2 tics per frame + spriteframe_t *sprframe = &sprdef->spriteframes[spritetimer]; //Our animation frame is equal to the number on the timer + + natksprite = W_CachePatchNum(sprframe->lumppat[6], PU_PATCH); //Draw the right facing angle + + if (skins[skinnumber]->natkcolor) //If you set natkcolor use it + color = skins[skinnumber]->natkcolor; + else if ((skins[skinnumber]->flags & SF_SUPER) && !(skins[skinnumber]->flags & SF_NONIGHTSSUPER)) //If you go super in NiGHTS, use supercolor + color = skins[skinnumber]->supercolor+4; + else //If you don't go super in NiGHTS or at all, use prefcolor + color = skins[skinnumber]->prefcolor; + + angle_t fa = (FixedAngle(((FixedInt(ntsatkdrawtimer * 4)) % 360)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK; + + V_DrawFixedPatch(270<<FRACBITS, (186<<FRACBITS) - 8*FINESINE(fa), + FixedDiv(skins[skinnumber]->highresscale, skins[skinnumber]->shieldscale), + (sprframe->flip & 1<<6) ? V_FLIP : 0, + natksprite, + R_GetTranslationColormap(TC_BLINK, color, GTC_CACHE)); + //if (P_HasGrades(cv_nextmap.value, 0)) // V_DrawScaledPatch(235 - (((ngradeletters[bestoverall])->width)*3)/2, 135, 0, ngradeletters[bestoverall]); @@ -10462,9 +10493,6 @@ static void M_NightsAttack(INT32 choice) // This is really just to make sure Sonic is the played character, just in case M_PatchSkinNameTable(); - ntssupersonic[0] = W_CachePatchName("NTSSONC1", PU_PATCH); - ntssupersonic[1] = W_CachePatchName("NTSSONC2", PU_PATCH); - G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please M_SetupNextMenu(&SP_NightsAttackDef); diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index 4c11a681f6cad6d8e470449ebea2d1985ff1da91..0c3d519be11c93c12894f52a02d3c3276a38ef20 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -1825,7 +1825,7 @@ static void Command_Map_f(void) return; } - option_force = COM_CheckPartialParm("-f"); + option_force = COM_CheckPartialParm("-f") || (cv_debug || devparm); option_gametype = COM_CheckPartialParm("-g"); newresetplayers = ! COM_CheckParm("-noresetplayers"); diff --git a/src/netcode/i_tcp.c b/src/netcode/i_tcp.c index 3fa2306479bfcaffa576a2e1238e51812967d112..810453f45a9bca49ba22bde81d5e0dd57ddb07c2 100644 --- a/src/netcode/i_tcp.c +++ b/src/netcode/i_tcp.c @@ -424,7 +424,7 @@ static boolean SOCK_cmpipv6(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask) { UINT8 bitmask; I_Assert(mask <= 128); - if (memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, mask / 8) != 0) + if (memcmp(&a->ip6.sin6_addr.s6_addr, &b->ip6.sin6_addr.s6_addr, mask / 8) != 0) return false; if (mask % 8 == 0) return true; @@ -437,6 +437,9 @@ static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask) { UINT32 bitmask = INADDR_NONE; + if (a->any.sa_family != b->any.sa_family) + return false; + if (mask && mask < 32) bitmask = htonl((UINT32)(-1) << (32 - mask)); diff --git a/src/p_local.h b/src/p_local.h index 611e747d25b83df487956676f814ba9a85cadcb3..c412dca5be4293e612c2c3396d8e7d73eabbe8a1 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -424,6 +424,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff); boolean P_Move(mobj_t *actor, fixed_t speed); boolean P_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z); boolean P_MoveOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z); +boolean P_LineIsBlocking(mobj_t *mo, line_t *li); void P_SlideMove(mobj_t *mo); void P_BounceMove(mobj_t *mo); boolean P_CheckSight(mobj_t *t1, mobj_t *t2); diff --git a/src/p_map.c b/src/p_map.c index 1888d92af36b149ccb96065934c6cfe9c8ec65a8..21582bbd74652f554d2431f039b87165029ce39b 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3405,36 +3405,41 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle) return false; } -static boolean PTR_LineIsBlocking(line_t *li) +// +// P_LineIsBlocking +// +// Determines if line would block mo's movement +// +boolean P_LineIsBlocking(mobj_t *mo, line_t *li) { // one-sided linedefs are always solid to sliding movement. if (!li->backsector) - return !P_PointOnLineSide(slidemo->x, slidemo->y, li); + return !P_PointOnLineSide(mo->x, mo->y, li); - if (!(slidemo->flags & MF_MISSILE)) + if (!(mo->flags & MF_MISSILE)) { if (li->flags & ML_IMPASSIBLE) return true; - if ((slidemo->flags & (MF_ENEMY|MF_BOSS)) && li->flags & ML_BLOCKMONSTERS) + if ((mo->flags & (MF_ENEMY|MF_BOSS)) && li->flags & ML_BLOCKMONSTERS) return true; } // set openrange, opentop, openbottom - P_LineOpening(li, slidemo); + P_LineOpening(li, mo); - if (openrange < slidemo->height) + if (openrange < mo->height) return true; // doesn't fit - if (opentop - slidemo->z < slidemo->height) + if (opentop - mo->z < mo->height) return true; // mobj is too high - if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, slidemo->scale)) + if (openbottom - mo->z > FixedMul(MAXSTEPMOVE, mo->scale)) return true; // too big a step up - if (slidemo->player - && openrange < P_GetPlayerHeight(slidemo->player) - && !P_PlayerCanEnterSpinGaps(slidemo->player)) + if (mo->player + && openrange < P_GetPlayerHeight(mo->player) + && !P_PlayerCanEnterSpinGaps(mo->player)) return true; // nonspin character should not take this path return false; @@ -3538,7 +3543,7 @@ static boolean PTR_SlideTraverse(intercept_t *in) li = in->d.line; - if (!PTR_LineIsBlocking(li)) + if (!P_LineIsBlocking(slidemo, li)) return true; // the line blocks movement, diff --git a/src/r_segs.c b/src/r_segs.c index 62fea352fca5d4b3b9b0a39d07b4d562481f5aa2..bd4869bdcc28ed4b4a891bcd8b8288e5e0b37263 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -525,6 +525,9 @@ static boolean R_IsFFloorTranslucent(visffloor_t *pfloor) // // R_RenderThickSideRange // Renders all the thick sides in the given range. + +static fixed_t ffloortexturecolumn[MAXVIDWIDTH]; + void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { size_t pindex; @@ -550,7 +553,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) fixed_t left_top, left_bottom; // needed here for slope skewing pslope_t *skewslope = NULL; boolean do_texture_skew; - UINT32 lineflags; + INT16 lineflags; fixed_t wall_scalex, wall_scaley; void (*colfunc_2s) (column_t *); @@ -575,7 +578,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) lineflags = newline->flags; } else - lineflags = pfloor->master->flags; + lineflags = curline->linedef->flags; texnum = R_GetTextureNum(sidedef->midtexture); @@ -732,10 +735,18 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) wall_scalex = FixedDiv(FRACUNIT, sidedef->scalex_mid); wall_scaley = sidedef->scaley_mid; - thicksidecol = ds->thicksidecol; + thicksidecol = ffloortexturecolumn; - for (INT32 x = x1; x <= x2; x++) - thicksidecol[x] = FixedDiv(thicksidecol[x], wall_scalex) + ds->offsetx; + if (wall_scalex == FRACUNIT) + { + for (INT32 x = x1; x <= x2; x++) + thicksidecol[x] = ds->thicksidecol[x] + ds->offsetx; + } + else + { + for (INT32 x = x1; x <= x2; x++) + thicksidecol[x] = FixedDiv(ds->thicksidecol[x], wall_scalex) + ds->offsetx; + } mfloorclip = ds->sprbottomclip; mceilingclip = ds->sprtopclip; @@ -746,10 +757,12 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) left_bottom = P_GetFFloorBottomZAt(pfloor, ds->leftpos.x, ds->leftpos.y) - viewz; do_texture_skew = lineflags & ML_SKEWTD; - skewslope = *pfloor->t_slope; // skew using top slope by default if (do_texture_skew) + { + skewslope = *pfloor->t_slope; // skew using top slope by default dc_texturemid = FixedMul(left_top, wall_scaley); + } else dc_texturemid = FixedMul(*pfloor->topheight - viewz, wall_scaley); @@ -757,14 +770,16 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (lineflags & ML_DONTPEGBOTTOM) { - skewslope = *pfloor->b_slope; // skew using bottom slope if (do_texture_skew) + { + skewslope = *pfloor->b_slope; // skew using bottom slope dc_texturemid = FixedMul(left_bottom, wall_scaley); + } else offsetvalue -= FixedMul(*pfloor->topheight - *pfloor->bottomheight, wall_scaley); } - if (do_texture_skew && skewslope) + if (skewslope) { angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT)); diff --git a/src/r_skins.c b/src/r_skins.c index 1605ca6c8921364974c9616ed98327c21eca1d59..6b4aeefe1726e46ee3f169540d5e87ad15dc271e 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -144,6 +144,8 @@ static void Sk_SetDefaultValue(skin_t *skin) skin->contspeed = 17; skin->contangle = 0; + skin->natkcolor = SKINCOLOR_NONE; + for (i = 0; i < sfx_skinsoundslot0; i++) if (S_sfx[i].skinsound != -1) skin->soundsid[S_sfx[i].skinsound] = i; @@ -588,7 +590,6 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) UINT16 color = R_GetSuperColorByName(value); skin->supercolor = (color ? color : SKINCOLOR_SUPERGOLD1); } - #define GETFLOAT(field) else if (!stricmp(stoken, #field)) skin->field = FLOAT_TO_FIXED(atof(value)); GETFLOAT(jumpfactor) GETFLOAT(highresscale) @@ -629,6 +630,9 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) GETFLAG(NOSHIELDABILITY) #undef GETFLAG + else if (!stricmp(stoken, "natkcolor")) + skin->natkcolor = R_GetColorByName(value); // SKINCOLOR_NONE is allowed here + else // let's check if it's a sound, otherwise error out { boolean found = false; diff --git a/src/r_skins.h b/src/r_skins.h index a97b24f9657840d99f5e4e4e572bf5da0f6ac0c2..cc3b63cbed2c97de3fc312ad338d6f201edcd65b 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -71,6 +71,7 @@ typedef struct UINT16 prefcolor; UINT16 supercolor; UINT16 prefoppositecolor; // if 0 use tables instead + UINT16 natkcolor; //Color for Nights Attack Menu fixed_t highresscale; // scale of highres, default is 0.5 UINT8 contspeed; // continue screen animation speed