diff --git a/source/core/gamecvars.cpp b/source/core/gamecvars.cpp index 2dee33550..6167d2716 100644 --- a/source/core/gamecvars.cpp +++ b/source/core/gamecvars.cpp @@ -76,7 +76,7 @@ CVARD(Bool, cl_interpolate, true, CVAR_ARCHIVE, "enable/disable view interpolati CVARD(Bool, cl_slopetilting, false, CVAR_ARCHIVE, "enable/disable slope tilting") // only implemented in Blood CVARD(Int, cl_showweapon, 1, CVAR_ARCHIVE, "enable/disable show weapons") // only implemented in Blood CVARD(Bool, cl_sointerpolation, true, CVAR_ARCHIVE, "enable/disable sector object interpolation") // only implemented in SW -CVARD(Bool, cl_syncinput, false, CVAR_ARCHIVE, "enable/disable synchronized input with game's ticrate") // only implemented in Duke +CVARD(Bool, cl_syncinput, false, CVAR_ARCHIVE, "enable/disable synchronized input with game's tickrate") // only implemented in Duke CVARD(Bool, cl_swsmoothsway, true, CVAR_ARCHIVE, "move SW weapon left and right smoothly while bobbing") CVARD(Bool, cl_showmagamt, false, CVAR_ARCHIVE, "show the amount of rounds left in the magazine of your weapon on the modern HUD") CVARD(Bool, cl_nomeleeblur, false, CVAR_ARCHIVE, "enable/disable blur effect with melee weapons in SW") @@ -84,6 +84,7 @@ CVARD(Bool, cl_exhumedoldturn, false, CVAR_ARCHIVE, "enable/disable legacy turni CVARD(Bool, cl_hudinterpolation, true, CVAR_ARCHIVE, "enable/disable HUD (weapon drawer) interpolation") CVARD(Bool, cl_bloodvanillarun, true, CVAR_ARCHIVE, "enable/disable Blood's vanilla run mode") CVARD(Bool, cl_bloodvanillabobbing, true, CVAR_ARCHIVE, "enable/disable Blood's vanilla bobbing while not using vanilla run mode") +CVARD(Bool, cl_bloodvanillaexplosions, false, CVAR_ARCHIVE, "enable/disable Blood's original explosion behavior") CVARD(Bool, cl_bloodhudinterp, false, CVAR_ARCHIVE, "enable/disable Blood's HUD interpolation") CVARD(Bool, cl_bloodoldweapbalance, false, CVAR_ARCHIVE, "enable/disable legacy 1.0 weapon handling for Blood") diff --git a/source/core/gamecvars.h b/source/core/gamecvars.h index d8d70cd5d..9d6c93fe9 100644 --- a/source/core/gamecvars.h +++ b/source/core/gamecvars.h @@ -29,6 +29,7 @@ EXTERN_CVAR(Bool, cl_exhumedoldturn) EXTERN_CVAR(Bool, cl_hudinterpolation) EXTERN_CVAR(Bool, cl_bloodvanillarun) EXTERN_CVAR(Bool, cl_bloodvanillabobbing) +EXTERN_CVAR(Bool, cl_bloodvanillaexplosions) EXTERN_CVAR(Bool, cl_bloodhudinterp) EXTERN_CVAR(Bool, cl_bloodoldweapbalance) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index dc442e3d3..f9b298559 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -2661,7 +2661,8 @@ void actRadiusDamage(DBloodActor* source, int x, int y, int z, int nSector, int { uint8_t sectmap[(kMaxSectors + 7) >> 3]; auto pOwner = source->GetOwner(); - GetClosestSpriteSectors(nSector, x, y, nDist, sectmap); + const bool newSectCheckMethod = !cl_bloodvanillaexplosions && pOwner && pOwner->IsDudeActor() && !VanillaMode() && !DemoRecordStatus(); // use new sector checking logic + GetClosestSpriteSectors(nSector, x, y, nDist, sectmap, nullptr, newSectCheckMethod); nDist <<= 4; if (flags & 2) { @@ -5011,12 +5012,12 @@ void MoveDude(spritetype *pSprite) } if (pPlayer && zvel[nSprite] > 0x155555 && !pPlayer->fallScream && pXSprite->height > 0) { - const bool playerAlive = (pXSprite->health > 0) || VanillaMode() || DemoRecordStatus(); // only trigger falling scream if player is alive + const bool playerAlive = (pXSprite->health > 0) || VanillaMode() || DemoRecordStatus(); // only trigger falling scream if player is alive or vanilla mode if (playerAlive) - { + { pPlayer->fallScream = 1; sfxPlay3DSound(pSprite, 719, 0, 0); - } + } } vec3_t const oldpos = pSprite->pos; int nLink = CheckLink(pSprite); @@ -5973,7 +5974,7 @@ void actProcessSprites(void) it.Reset(kStatExplosion); while ((nSprite = it.NextIndex()) >= 0) { - uint8_t v24c[(kMaxSectors+7)>>3]; + uint8_t sectmap[(kMaxSectors+7)>>3]; spritetype *pSprite = &sprite[nSprite]; if (pSprite->flags & 32) @@ -5998,9 +5999,13 @@ void actProcessSprites(void) if (gModernMap && pXSprite->data4 > 0) radius = pXSprite->data4; #endif - + + // GetClosestSpriteSectors() has issues checking some sectors due to optimizations + // the new flag newSectCheckMethod for GetClosestSpriteSectors() does rectify these issues, but this may cause unintended side effects for level scripted explosions + // so only allow this new checking method for dude spawned explosions short gAffectedXWalls[kMaxXWalls]; - GetClosestSpriteSectors(nSector, x, y, radius, v24c, gAffectedXWalls); + const bool newSectCheckMethod = !cl_bloodvanillaexplosions && pOwner && pOwner->IsDudeActor() && !VanillaMode() && !DemoRecordStatus(); // use new sector checking logic + GetClosestSpriteSectors(nSector, x, y, radius, sectmap, gAffectedXWalls, newSectCheckMethod); for (int i = 0; i < kMaxXWalls; i++) { @@ -6020,7 +6025,7 @@ void actProcessSprites(void) if (pDude->flags & 32) continue; - if (TestBitString(v24c, pDude->sectnum)) + if (TestBitString(sectmap, pDude->sectnum)) { if (pXSprite->data1 && CheckProximity(pDude, x, y, z, nSector, radius)) { @@ -6051,7 +6056,7 @@ void actProcessSprites(void) if (pThing->flags & 32) continue; - if (TestBitString(v24c, pThing->sectnum)) + if (TestBitString(sectmap, pThing->sectnum)) { if (pXSprite->data1 && CheckProximity(pThing, x, y, z, nSector, radius)) { @@ -6095,7 +6100,7 @@ void actProcessSprites(void) continue; spritetype* pDebris = &sprite[gPhysSpritesList[i]]; - if (!TestBitString(v24c, pDebris->sectnum) || !CheckProximity(pDebris, x, y, z, nSector, radius)) continue; + if (!TestBitString(sectmap, pDebris->sectnum) || !CheckProximity(pDebris, x, y, z, nSector, radius)) continue; else debrisConcuss(nOwner, i, x, y, z, pExplodeInfo->dmgType); } } @@ -6111,7 +6116,7 @@ void actProcessSprites(void) if (pImpact->extra <= 0) continue; XSPRITE* pXImpact = &xsprite[pImpact->extra]; - if (/*pXImpact->state == pXImpact->restState ||*/ !TestBitString(v24c, pImpact->sectnum) || !CheckProximity(pImpact, x, y, z, nSector, radius)) + if (/*pXImpact->state == pXImpact->restState ||*/ !TestBitString(sectmap, pImpact->sectnum) || !CheckProximity(pImpact, x, y, z, nSector, radius)) continue; trTriggerSprite(pImpact->index, pXImpact, kCmdSpriteImpact); diff --git a/source/games/blood/src/ai.cpp b/source/games/blood/src/ai.cpp index c2c6ff532..f93c6d516 100644 --- a/source/games/blood/src/ai.cpp +++ b/source/games/blood/src/ai.cpp @@ -1441,7 +1441,7 @@ void aiThinkTarget(DBloodActor* actor) } } -void sub_5F15C(spritetype *pSprite, XSPRITE *pXSprite) +void aiLookForTarget(spritetype *pSprite, XSPRITE *pXSprite) { assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); @@ -1479,8 +1479,9 @@ void sub_5F15C(spritetype *pSprite, XSPRITE *pXSprite) } if (pXSprite->state) { - uint8_t va4[(kMaxSectors+7)>>3]; - GetClosestSpriteSectors(pSprite->sectnum, pSprite->x, pSprite->y, 400, va4); + uint8_t sectmap[(kMaxSectors+7)>>3]; + const bool newSectCheckMethod = !VanillaMode() && !DemoRecordStatus(); // use new sector checking logic + GetClosestSpriteSectors(pSprite->sectnum, pSprite->x, pSprite->y, 400, sectmap, nullptr, newSectCheckMethod); int nSprite2; StatIterator it(kStatDude); diff --git a/source/games/blood/src/ai.h b/source/games/blood/src/ai.h index ca0eef908..8e68301ca 100644 --- a/source/games/blood/src/ai.h +++ b/source/games/blood/src/ai.h @@ -101,7 +101,7 @@ void aiSetTarget(XSPRITE *pXSprite, int x, int y, int z); void aiSetTarget(XSPRITE *pXSprite, int nTarget); int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType, int nDamage); void aiThinkTarget(DBloodActor* actor); -void sub_5F15C(spritetype *pSprite, XSPRITE *pXSprite); +void aiLookForTarget(spritetype *pSprite, XSPRITE *pXSprite); void aiProcessDudes(void); void aiInit(void); void aiInitSprite(spritetype *pSprite); diff --git a/source/games/blood/src/aibeast.cpp b/source/games/blood/src/aibeast.cpp index 144010a8e..af33c536f 100644 --- a/source/games/blood/src/aibeast.cpp +++ b/source/games/blood/src/aibeast.cpp @@ -82,7 +82,7 @@ void SlashSeqCallback(int, DBloodActor* actor) void StompSeqCallback(int, DBloodActor* actor1) { - uint8_t vb8[(kMaxSectors+7)>>3]; + uint8_t sectmap[(kMaxSectors+7)>>3]; XSPRITE* pXSprite = &actor1->x(); int nSprite = pXSprite->reference; spritetype *pSprite = &actor1->s(); @@ -95,7 +95,8 @@ void StompSeqCallback(int, DBloodActor* actor1) int nSector = pSprite->sectnum; int v1c = 5+2*gGameOptions.nDifficulty; int v10 = 25+30*gGameOptions.nDifficulty; - GetClosestSpriteSectors(nSector, x, y, vc, vb8); + const bool newSectCheckMethod = !VanillaMode() && !DemoRecordStatus(); // use new sector checking logic + GetClosestSpriteSectors(nSector, x, y, vc, sectmap, nullptr, newSectCheckMethod); char v4 = 0; int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); DBloodActor* actor2 = nullptr; @@ -119,7 +120,7 @@ void StompSeqCallback(int, DBloodActor* actor1) continue; if (pSprite2->flags&32) continue; - if (TestBitString(vb8, pSprite2->sectnum) && CheckProximity(pSprite2, x, y, z, nSector, vc)) + if (TestBitString(sectmap, pSprite2->sectnum) && CheckProximity(pSprite2, x, y, z, nSector, vc)) { int top, bottom; GetSpriteExtents(pSprite, &top, &bottom); @@ -150,7 +151,7 @@ void StompSeqCallback(int, DBloodActor* actor1) spritetype *pSprite2 = &sprite[nSprite2]; if (pSprite2->flags&32) continue; - if (TestBitString(vb8, pSprite2->sectnum) && CheckProximity(pSprite2, x, y, z, nSector, vc)) + if (TestBitString(sectmap, pSprite2->sectnum) && CheckProximity(pSprite2, x, y, z, nSector, vc)) { XSPRITE *pXSprite = &xsprite[pSprite2->extra]; if (pXSprite->locked) diff --git a/source/games/blood/src/aicult.cpp b/source/games/blood/src/aicult.cpp index a39c9dc1c..215dacf32 100644 --- a/source/games/blood/src/aicult.cpp +++ b/source/games/blood/src/aicult.cpp @@ -202,7 +202,7 @@ static void cultThinkSearch(DBloodActor* actor) auto pXSprite = &actor->x(); auto pSprite = &actor->s(); aiChooseDirection(pSprite, pXSprite, pXSprite->goalAng); - sub_5F15C(pSprite, pXSprite); + aiLookForTarget(pSprite, pXSprite); } static void cultThinkGoto(DBloodActor* actor) diff --git a/source/games/blood/src/aigarg.cpp b/source/games/blood/src/aigarg.cpp index ac4859aa4..d0ce37bda 100644 --- a/source/games/blood/src/aigarg.cpp +++ b/source/games/blood/src/aigarg.cpp @@ -269,7 +269,7 @@ static void gargThinkSearch(DBloodActor* actor) auto pXSprite = &actor->x(); auto pSprite = &actor->s(); aiChooseDirection(pSprite, pXSprite, pXSprite->goalAng); - sub_5F15C(pSprite, pXSprite); + aiLookForTarget(pSprite, pXSprite); } static void gargThinkGoto(DBloodActor* actor) diff --git a/source/games/blood/src/aiunicult.cpp b/source/games/blood/src/aiunicult.cpp index a249b1935..841e2760f 100644 --- a/source/games/blood/src/aiunicult.cpp +++ b/source/games/blood/src/aiunicult.cpp @@ -382,7 +382,7 @@ static void unicultThinkSearch(DBloodActor* actor) //viewSetSystemMessage("IN SEARCH"); aiChooseDirection(pSprite, pXSprite, pXSprite->goalAng); - sub_5F15C(pSprite, pXSprite); + aiLookForTarget(pSprite, pXSprite); } static void unicultThinkGoto(DBloodActor* actor) diff --git a/source/games/blood/src/aizomba.cpp b/source/games/blood/src/aizomba.cpp index 39544dbd9..89b4f15e0 100644 --- a/source/games/blood/src/aizomba.cpp +++ b/source/games/blood/src/aizomba.cpp @@ -88,7 +88,7 @@ static void zombaThinkSearch(DBloodActor* actor) auto pXSprite = &actor->x(); auto pSprite = &actor->s(); aiChooseDirection(pSprite, pXSprite, pXSprite->goalAng); - sub_5F15C(pSprite, pXSprite); + aiLookForTarget(pSprite, pXSprite); } static void zombaThinkGoto(DBloodActor* actor) diff --git a/source/games/blood/src/gameutil.cpp b/source/games/blood/src/gameutil.cpp index a531f49bf..b964b8a1b 100644 --- a/source/games/blood/src/gameutil.cpp +++ b/source/games/blood/src/gameutil.cpp @@ -172,9 +172,12 @@ bool CheckProximityPoint(int nX1, int nY1, int nZ1, int nX2, int nY2, int nZ2, i int oY = abs(nY2-nY1)>>4; if (oY >= nDist) return 0; - int oZ = abs(nZ2-nZ1)>>4; - if (oZ >= nDist) - return 0; + if (nZ2 != nZ1) + { + int oZ = abs(nZ2-nZ1)>>8; + if (oZ >= nDist) + return 0; + } if (approxDist(oX, oY) >= nDist) return 0; return 1; } @@ -834,8 +837,12 @@ int GetClosestSectors(int nSector, int x, int y, int nDist, short *pSectors, cha return n; } -int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, uint8_t *pSectBit, short *walls) +int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, uint8_t *pSectBit, short *pWalls, bool newSectCheckMethod) { + // by default this function fails with sectors that linked with wide spans, or there was more than one link to the same sector. for example... + // E6M1: throwing TNT on the stone footpath while standing on the brown road will fail due to the start/end points of the span being too far away. it'll only do damage at one end of the road + // E1M2: throwing TNT at the double doors while standing on the train platform + // by setting newSectCheckMethod to true these issues will be resolved static short pSectors[kMaxSectors]; uint8_t sectbits[(kMaxSectors+7)>>3]; memset(sectbits, 0, sizeof(sectbits)); @@ -848,36 +855,76 @@ int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, uint8_t *pSect memset(pSectBit, 0, (kMaxSectors+7)>>3); SetBitString(pSectBit, nSector); } - while (i < n) + while (i < n) // scan through sectors { - int nCurSector = pSectors[i]; - int nStartWall = sector[nCurSector].wallptr; - int nEndWall = nStartWall + sector[nCurSector].wallnum; - walltype *pWall = &wall[nStartWall]; - for (int j = nStartWall; j < nEndWall; j++, pWall++) + const int nCurSector = pSectors[i]; + const int nStartWall = sector[nCurSector].wallptr; + const int nEndWall = nStartWall + sector[nCurSector].wallnum; + for (int j = nStartWall; j < nEndWall; j++) // scan each wall of current sector for new sectors { - int nNextSector = pWall->nextsector; - if (nNextSector < 0) + const walltype *pWall = &wall[j]; + const int nNextSector = pWall->nextsector; + if (nNextSector < 0) // if next wall isn't linked to a sector, skip continue; - if (TestBitString(sectbits, nNextSector)) + if (TestBitString(sectbits, nNextSector)) // if we've already checked this sector, skip continue; - SetBitString(sectbits, nNextSector); - if (CheckProximityWall(wall[j].point2, x, y, nDist)) + bool setSectBit = true; + bool withinRange = CheckProximityWall(pWall->point2, x, y, nDist); + if (newSectCheckMethod && !withinRange) // if range check failed, try comparing midpoints/subdivides of wall span { + for (int k = (j+1); k < nEndWall; k++) // scan through the rest of the sector's walls + { + if (wall[k].nextsector == nNextSector) // if the next walls still reference the sector, then don't flag the sector as checked (yet) + { + setSectBit = false; + break; + } + } + const int nWallA = j; + const int nWallB = wall[nWallA].point2; + int x1 = wall[nWallA].x, y1 = wall[nWallA].y; + int x2 = wall[nWallB].x, y2 = wall[nWallB].y; + int nLength = approxDist(x1-x2, y1-x2); + const int nDist2 = (nDist+(nDist>>1))<<4; + if (nLength > nDist2) // if span is greater than range * 1.5, test midsection + { + nLength = ClipRange(nLength / nDist2, 1, 4); // never split more than 4 times + for (int k = 0; k < nLength; k++) // subdivide span into smaller chunks towards direction + { + const int xcenter = (x1+x2)>>1, ycenter = (y1+y2)>>1; + withinRange = CheckProximityPoint(xcenter, ycenter, 0, x, y, 0, nDist); + if (withinRange) + break; + if ((k+1) == nLength) // reached end, no point in calculating direction/center again + break; + const bool bDir = approxDist(x-x1, y-y1) < approxDist(x-x2, y-y2); + if (bDir) // step closer and check again + x2 = xcenter, y2 = ycenter; + else + x1 = xcenter, y1 = ycenter; + } + } + } + if (withinRange) // if new sector is within range, set to current sector and test walls + { + setSectBit = true; // sector is within range, set as checked if (pSectBit) SetBitString(pSectBit, nNextSector); pSectors[n++] = nNextSector; - if (walls && pWall->extra > 0) + if (pWalls && pWall->extra > 0) { XWALL *pXWall = &xwall[pWall->extra]; if (pXWall->triggerVector && !pXWall->isTriggered && !pXWall->state) - walls[m++] = j; + pWalls[m++] = j; } } + if (setSectBit) + SetBitString(sectbits, nNextSector); } i++; } - if (walls) walls[m] = -1; + pSectors[n] = -1; + if (pWalls) pWalls[m] = -1; return n; } diff --git a/source/games/blood/src/gameutil.h b/source/games/blood/src/gameutil.h index 31a99b255..bfb984b67 100644 --- a/source/games/blood/src/gameutil.h +++ b/source/games/blood/src/gameutil.h @@ -82,7 +82,7 @@ void GetZRangeAtXYZ(int x, int y, int z, int nSector, int *ceilZ, int *ceilHit, int GetDistToLine(int x1, int y1, int x2, int y2, int x3, int y3); unsigned int ClipMove(int *x, int *y, int *z, int *nSector, int xv, int yv, int wd, int cd, int fd, unsigned int nMask); int GetClosestSectors(int nSector, int x, int y, int nDist, short *pSectors, char *pSectBit); -int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, uint8_t *pSectBit, short *affx = nullptr); +int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, uint8_t *pSectBit, short *pWalls = nullptr, bool newSectCheckMethod = false); int picWidth(short nPic, short repeat); int picHeight(short nPic, short repeat); diff --git a/source/games/blood/src/view.cpp b/source/games/blood/src/view.cpp index 99a83feb8..23c6e3952 100644 --- a/source/games/blood/src/view.cpp +++ b/source/games/blood/src/view.cpp @@ -118,7 +118,7 @@ void viewDrawAimedPlayerName(void) if (!cl_idplayers || (gView->aim.dx == 0 && gView->aim.dy == 0)) return; - int hit = HitScan(gView->pSprite, gView->pSprite->z, gView->aim.dx, gView->aim.dy, gView->aim.dz, CLIPMASK0, 512); + int hit = HitScan(gView->pSprite, gView->zView, gView->aim.dx, gView->aim.dy, gView->aim.dz, CLIPMASK0, 512); if (hit == 3) { spritetype* pSprite = &sprite[gHitInfo.hitsprite]; diff --git a/source/games/blood/src/weapon.cpp b/source/games/blood/src/weapon.cpp index a2d5fc950..b2898cba3 100644 --- a/source/games/blood/src/weapon.cpp +++ b/source/games/blood/src/weapon.cpp @@ -2618,14 +2618,15 @@ void WeaponProcess(PLAYER *pPlayer) { void teslaHit(spritetype *pMissile, int a2) { - uint8_t va4[(kMaxSectors+7)>>3]; + uint8_t sectmap[(kMaxSectors+7)>>3]; int x = pMissile->x; int y = pMissile->y; int z = pMissile->z; int nDist = 300; int nSector = pMissile->sectnum; int nOwner = pMissile->owner; - GetClosestSpriteSectors(nSector, x, y, nDist, va4); + const bool newSectCheckMethod = !VanillaMode() && !DemoRecordStatus(); // use new sector checking logic + GetClosestSpriteSectors(nSector, x, y, nDist, sectmap, nullptr, newSectCheckMethod); bool v4 = true; DBloodActor* actor = nullptr; actHitcodeToData(a2, &gHitInfo, &actor); @@ -2640,7 +2641,7 @@ void teslaHit(spritetype *pMissile, int a2) spritetype *pSprite = &sprite[nSprite]; if (pSprite->flags&32) continue; - if (TestBitString(va4, pSprite->sectnum) && CheckProximity(pSprite, x, y, z, nSector, nDist)) + if (TestBitString(sectmap, pSprite->sectnum) && CheckProximity(pSprite, x, y, z, nSector, nDist)) { int dx = pMissile->x-pSprite->x; int dy = pMissile->y-pSprite->y; @@ -2657,7 +2658,7 @@ void teslaHit(spritetype *pMissile, int a2) spritetype *pSprite = &sprite[nSprite]; if (pSprite->flags&32) continue; - if (TestBitString(va4, pSprite->sectnum) && CheckProximity(pSprite, x, y, z, nSector, nDist)) + if (TestBitString(sectmap, pSprite->sectnum) && CheckProximity(pSprite, x, y, z, nSector, nDist)) { XSPRITE *pXSprite = &xsprite[pSprite->extra]; if (!pXSprite->locked) diff --git a/wadsrc/static/language.0 b/wadsrc/static/language.0 index fa866e4fe..0abf938a3 100644 --- a/wadsrc/static/language.0 +++ b/wadsrc/static/language.0 @@ -339,6 +339,7 @@ Touchscreen-like,OPTVAL_TOUCHSCREENLIKE,,,,Jako dotyková obrazovka,Wie auf eine Simple arrow,OPTSTR_SIMPLEARROW,,,,Jednoduchý kurzor,Einfacher Pfeil,,Simpla sago,Flecha simple,,Yksinkertainen nuoli,Flèche simple,Sima nyíl,Freccia semplice,シンプル,기본 커서,Eenvoudige pijl,Prosta strzałka,Flecha simples,Cursor simples,Săgeată simplă,Стрелка,Стрелица System cursor,OPTSTR_SYSTEMCURSOR,,,,Systémový kurzor,Systemcursor,,Sistema kursoro,Cursor del sistema,,Järjestelmän osoitin,Curseur Système,Rendszer egérmutatója,Cursore di sistema,システム,시스템 커서,Systeemcursor,Kursor systemu,Cursor do sistema,,Cursor simplu,Системный курсор,Системска стрелица Default,OPTVAL_DEFAULT,,,,Výchozí,Standard,,Defaŭlta,Por defecto,,Oletus,Défaut,Alapbeállítás,,デフォルト,기본 설정,Standaard,Domyślne,Padrão,,Implicit,По умолчанию,Подраз. +Old,OPTVAL_OLD,,,,Starší,Alt,Παλίο,Malnova,Antíguo,,Vanha,Ancien,Régi,Vecchio,旧,구형,Oud,Stare,Antigo,,Vechiul,Старый,Стари ,,Controller,,,,,,,,,,,,,,,,,,,,, Configure Controller,JOYMNU_TITLE,,,,Konfigurovat ovladač,Controller konfigurieren,,Agordi Ludregilon,Configurar Mando,,Peliohjainasetukset,Configurer Mannette,Kontroller testreszabása,Configura il controller,コントローラー構成:,컨트롤러 구성,Controller configureren,Konfiguruj Kontroler,Configurar controle,Configurar Comando,Configurare controller,Настроить контроллер,Конфигурација контролера Controller Options,JOYMNU_OPTIONS,,,,Nastavení ovladače,Controlleroptionen,,Ludregilo-Agordoj,Opciones del mando,,Peliohjainasetukset,Options Mannette,Kontroller beállításai,Opzioni del controller,コントローラー設定,컨트롤러 설정,Controller opties,Opcje Kontrolera,Opções de controle,Opções do Comando,Setări controller,Настройки контроллера,Подешавања контролера diff --git a/wadsrc/static/language.csv b/wadsrc/static/language.csv index 4905e8632..461324a2b 100644 --- a/wadsrc/static/language.csv +++ b/wadsrc/static/language.csv @@ -119,6 +119,7 @@ Allow Toggle,PLRMNU_TOGGLE,,,,,Umschalten erlauben,,,Permitir Alternado,,Salli v Override Toggle,PLRMNU_OVERRIDE,,,,,Umschalten blockieren,,,Anular Alternado,,Kumoa vaihtokytkeminen,Ignorer On/off,Futás sebesség változtatható,,,,,Nadpisz Przełączenie,Ignorar Ativar/Desativar,,Suprascriere comutare,, If New,PLRMNU_IFNEW,,,,Pokud je nová,Wenn neu,,,Si Nuevo,,Jos uusi,Si nouveau,Ha új,,,,,Jeśli Nowe,Quando Novo,,Dacă e nouă,, Equip Weapon Pickups,PLRMNU_EQUIP,,,,Přepnout na sebranou zbraň,Waffen sofort aktivieren,,,Equipar Armas Recogidas,,Vaihda poimittuun aseeseen,Equiper armes ramassées,Felvett fegyver használata,,,,,Wybierz Broń,Equipar Armas,,Echipează armele ridicate,, +Explosions Behavior,EXPLOS_BEHAVIOR,,,,Chování při výbuchu,Explosionsverhalten,,,Comportamiento de explosiones,,Räjähdykset Käyttäytyminen,Comportement des explosions,Robbanások Viselkedés,,,,,Zachowanie wybuchów,Comportamiento de explosiones,,Comportament cu explozii,, Parental Lock,PLRMNU_PLOCK,,,,Rodičovský zámek,Kindersicherung,,,Bloqueo Parental,,Lapsilukko,Contrôle Parental,Szülői zár,,,,,Blokada Rodzicielska,Bloqueio Parental,,Control Parental,, Only preferred,PLRMNU_PREFERRED,,,,Pouze preferované,Nur bevorzugte,,,Solo preferido,,Vain parempaan,Seulement si Préféré,Csak a preferált,,,,,Tylko wybrane,Somente preferido,,Doar preferate,, Vanilla Keyboard Turning Speed,PLRMNU_EXHUMEDOLDTURN,,,,,,,,Velocidad de Giro del Teclado como en Vanilla,,,,Eredeti billentyűs fordulás sebesség,,,,,Oryginalna prędkość rozglądania się na klawiaturze,,,Viteză Rotire cu Tastatură,, diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 16db5aae7..396cfb04a 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -950,6 +950,12 @@ OptionValue "WeapSwitch" 3, "$PLRMNU_PREFERRED" } +OptionValue "ExplosBehavior" +{ + 0, "$OPTVAL_DEFAULT" + 1, "$OPTVAL_OLD" +} + OptionMenu GameplayOptions protected { @@ -971,6 +977,7 @@ OptionMenu GameplayOptions protected ifgame(Blood) { Option "$PLRMNU_EQUIP", "cl_weaponswitch", "WeapSwitch" + Option "$EXPLOS_BEHAVIOR", "cl_bloodvanillaexplosions", "ExplosBehavior" } ifgame(Exhumed) {