diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 00c6404b4..b0ecd161d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,8 @@ +January 25, 2009 (Changes by Graf Zahl) +- fixed: AFastProjectile::Tick must call Effect only 8 times per tic, regardless + of the amount of steps taken. +- fixed: momentum checks in AFastProjectile did not use absolute values. + January 24, 2009 - Restored the rhythm section to fmopl.cpp and made some slight updates from version 0.72 of MAME's fmopl.c. Also refactored CalcVoice so that the diff --git a/src/actor.h b/src/actor.h index b4054c373..e3eeb824a 100644 --- a/src/actor.h +++ b/src/actor.h @@ -261,6 +261,7 @@ enum MF4_LOOKALLAROUND = 0x00010000, // Monster has eyes in the back of its head MF4_STANDSTILL = 0x00020000, // Monster should not chase targets unless attacked? MF4_SPECTRAL = 0x00040000, + MF4_SCROLLMOVE = 0x00080000, // momentum has been applied by a scroller MF4_NOSPLASHALERT = 0x00100000, // Splashes don't alert this monster MF4_SYNCHRONIZED = 0x00200000, // For actors spawned at load-time only: Do not randomize tics MF4_NOTARGETSWITCH = 0x00400000, // monster never switches target until current one is dead diff --git a/src/d_main.cpp b/src/d_main.cpp index 98cb0cd80..cb9db695d 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -510,10 +510,50 @@ CVAR (Flag, sv_noautoaim, dmflags2, DF2_NOAUTOAIM); int i_compatflags; // internal compatflags composed from the compatflags CVAR and MAPINFO settings +EXTERN_CVAR(Int, compatmode) + +static int GetCompatibility(int mask) +{ + if (level.info == NULL) return mask; + else return (mask & ~level.info->compatmask) | (level.info->compatflags & level.info->compatmask); +} + CUSTOM_CVAR (Int, compatflags, 0, CVAR_ARCHIVE|CVAR_SERVERINFO) { - if (level.info == NULL) i_compatflags = self; - else i_compatflags = (self & ~level.info->compatmask) | (level.info->compatflags & level.info->compatmask); + i_compatflags = GetCompatibility(self); +} + +CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_SERVERINFO) +{ + int v; + + switch (self) + { + default: + case 0: + v = 0; + break; + + case 1: // Doom2.exe compatible with a few relaxed settings + v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT| + COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_DEHHEALTH|COMPATF_CROSSDROPOFF; + break; + + case 2: // same as 1 but stricter (NO_PASSMOBJ and INVISIBILITY are also set) + v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT| + COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_NO_PASSMOBJ|COMPATF_LIMITPAIN| + COMPATF_DEHHEALTH|COMPATF_INVISIBILITY; + break; + + case 3: + v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL; + break; + + case 4: + v = COMPATF_SOUNDTARGET; + break; + } + compatflags = v; } CVAR (Flag, compat_shortTex, compatflags, COMPATF_SHORTTEX); @@ -536,6 +576,7 @@ CVAR (Flag, compat_invisibility,compatflags, COMPATF_INVISIBILITY); CVAR (Flag, compat_silentinstantfloors,compatflags, COMPATF_SILENT_INSTANT_FLOORS); CVAR (Flag, compat_sectorsounds,compatflags, COMPATF_SECTORSOUNDS); CVAR (Flag, compat_missileclip, compatflags, COMPATF_MISSILECLIP); +CVAR (Flag, compat_crossdropoff,compatflags, COMPATF_CROSSDROPOFF); //========================================================================== // diff --git a/src/doomdef.h b/src/doomdef.h index addad750a..ce6bc8cfc 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -279,6 +279,7 @@ enum COMPATF_SILENT_INSTANT_FLOORS = 1<<17, // Instantly moving floors are not silent COMPATF_SECTORSOUNDS = 1 << 18, // Sector sounds use original method for sound origin. COMPATF_MISSILECLIP = 1 << 19, // Use original Doom heights for clipping against projectiles + COMPATF_CROSSDROPOFF = 1 << 20, // monsters can't be pushed over dropoffs }; // phares 3/20/98: diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index fa4edefaf..ec92a1eeb 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -33,7 +33,7 @@ void AFastProjectile::Tick () int count = 8; if (radius > 0) { - while ( ((momx >> shift) > radius) || ((momy >> shift) > radius)) + while ( ((abs(momx) >> shift) > radius) || ((abs(momy) >> shift) > radius)) { // we need to take smaller steps. shift++; @@ -56,8 +56,8 @@ void AFastProjectile::Tick () if (--ripcount <= 0) { tm.LastRipped = NULL; // [RH] Do rip damage each step, like Hexen - ripcount = count >> 3; } + if (!P_TryMove (this, x + xfrac,y + yfrac, true, false, tm)) { // Blocked move P_ExplodeMissile (this, BlockingLine, BlockingMobj); @@ -78,7 +78,11 @@ void AFastProjectile::Tick () P_ExplodeMissile (this, NULL, NULL); return; } - if (changexy) Effect(); + if (changexy && ripcount <= 0) + { + ripcount = count >> 3; + Effect(); + } } } // Advance the state diff --git a/src/m_options.cpp b/src/m_options.cpp index 7493a5517..c5a112e46 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -86,6 +86,7 @@ EXTERN_CVAR(Bool, nomonsterinterpolation) EXTERN_CVAR(Int, showendoom) EXTERN_CVAR(Bool, hud_althud) +EXTERN_CVAR(Int, compatmode) // // defaulted values // @@ -140,6 +141,14 @@ value_t OffOn[2] = { { 1.0, "Off" } }; +value_t CompatModes[5] = { + { 0.0, "Default" }, + { 1.0, "Doom" }, + { 2.0, "Doom (strict)" }, + { 3.0, "Boom" }, + { 4.0, "ZDoom 2.0.63" } +}; + menu_t *CurrentMenu; int CurrentItem; static const char *OldMessage; @@ -1092,6 +1101,8 @@ static menu_t DMFlagsMenu = *=======================================*/ static menuitem_t CompatibilityItems[] = { + { discrete, "Compatibility mode", {&compatmode}, {5.0}, {0.0}, {0.0}, {CompatModes} }, + { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, { bitflag, "Find shortest textures like Doom", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_SHORTTEX} }, { bitflag, "Use buggier stair building", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_STAIRINDEX} }, { bitflag, "Limit Pain Elementals' Lost Souls", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_LIMITPAIN} }, @@ -1107,6 +1118,7 @@ static menuitem_t CompatibilityItems[] = { { bitflag, "DEH health settings like Doom2.exe", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_DEHHEALTH} }, { bitflag, "Self ref. sectors don't block shots", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_TRACE} }, { bitflag, "Monsters get stuck over dropoffs", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_DROPOFF} }, + { bitflag, "Monsters cannot cross dropoffs", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_CROSSDROPOFF} }, { bitflag, "Monsters see invisible players", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_INVISIBILITY} }, { bitflag, "Boom scrollers are additive", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_BOOMSCROLL} }, { bitflag, "Inst. moving floors are not silent", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_SILENT_INSTANT_FLOORS} }, diff --git a/src/p_map.cpp b/src/p_map.cpp index 6935022c9..3307c3d6d 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -160,6 +160,45 @@ static bool PIT_FindFloorCeiling (line_t *ld, const FBoundingBox &box, FCheckPos return true; } + +void P_GetFloorCeilingZ(FCheckPosition &tmf) +{ + sector_t *sec = P_PointInSector (tmf.x, tmf.y); + tmf.floorsector = sec; + tmf.ceilingsector = sec; + + tmf.floorz = tmf.dropoffz = sec->floorplane.ZatPoint (tmf.x, tmf.y); + tmf.ceilingz = sec->ceilingplane.ZatPoint (tmf.x, tmf.y); + tmf.floorpic = sec->GetTexture(sector_t::floor); + tmf.ceilingpic = sec->GetTexture(sector_t::ceiling); + +#ifdef _3DFLOORS + for(unsigned int i=0;ie->XFloor.ffloors.Size();i++) + { + F3DFloor* rover = sec->e->XFloor.ffloors[i]; + + if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; + + fixed_t ff_bottom = rover->bottom.plane->ZatPoint(tmf.x, tmf.y); + fixed_t ff_top = rover->top.plane->ZatPoint(tmf.x, tmf.y); + + if (ff_top > tmf.floorz) + { + if (ff_top < tmf.z || (tmf.thing != NULL && ff_bottom < tmf.z && ff_top < tmf.z + tmf.thing->MaxStepHeight)) + { + tmf.dropoffz = tmf.floorz = ff_top; + tmf.floorpic = *rover->top.texture; + } + } + if (ff_bottom < tmf.ceilingz && ff_bottom > tmf.z + tmf.thing->height) + { + tmf.ceilingz = ff_bottom; + tmf.ceilingpic = *rover->bottom.texture; + } + } +#endif +} + //========================================================================== // // P_FindFloorCeiling @@ -168,22 +207,24 @@ static bool PIT_FindFloorCeiling (line_t *ld, const FBoundingBox &box, FCheckPos void P_FindFloorCeiling (AActor *actor, bool onlyspawnpos) { - sector_t *sec; FCheckPosition tmf; + tmf.thing = actor; tmf.x = actor->x; tmf.y = actor->y; + tmf.z = actor->z; + P_GetFloorCeilingZ(tmf); + + actor->floorz = tmf.floorz; + actor->dropoffz = tmf.dropoffz; + actor->ceilingz = tmf.ceilingz; + actor->floorpic = tmf.floorpic; + actor->floorsector = tmf.floorsector; + actor->ceilingpic = tmf.ceilingpic; + actor->ceilingsector = tmf.ceilingsector; FBoundingBox box(tmf.x, tmf.y, actor->radius); - sec = P_PointInSector (tmf.x, tmf.y); - tmf.thing = actor; - tmf.floorz = tmf.dropoffz = sec->floorplane.ZatPoint (tmf.x, tmf.y); - tmf.ceilingz = sec->ceilingplane.ZatPoint (tmf.x, tmf.y); - tmf.floorpic = sec->GetTexture(sector_t::floor); - tmf.floorsector = sec; - tmf.ceilingpic = sec->GetTexture(sector_t::ceiling); - tmf.ceilingsector = sec; tmf.touchmidtex = false; validcount++; @@ -207,25 +248,6 @@ void P_FindFloorCeiling (AActor *actor, bool onlyspawnpos) actor->ceilingpic = tmf.ceilingpic; actor->ceilingsector = tmf.ceilingsector; } - -#ifdef _3DFLOORS - // also check 3D floors at the spawn position if the result from the block lines iterator cannot be used. - if (onlyspawnpos) - { - for(unsigned int i=0;iSector->e->XFloor.ffloors.Size();i++) - { - F3DFloor* rover=actor->Sector->e->XFloor.ffloors[i]; - - if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; - - fixed_t ff_bottom=rover->bottom.plane->ZatPoint(actor->x, actor->y); - fixed_t ff_top=rover->top.plane->ZatPoint(actor->x, actor->y); - - if (ff_top > actor->floorz && ff_top < actor->z) actor->floorz = ff_top; - if (ff_bottom < actor->ceilingz && ff_bottom > actor->z + actor->height) actor->ceilingz = ff_bottom; - } - } -#endif } // @@ -244,11 +266,9 @@ void P_FindFloorCeiling (AActor *actor, bool onlyspawnpos) bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefrag) { FCheckPosition tmf; - sector_t* newsec; // kill anything occupying the position - newsec = P_PointInSector (x,y); // The base floor/ceiling is from the subsector that contains the point. // Any contacted lines the step closer together will adjust them. @@ -256,12 +276,7 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr tmf.x = x; tmf.y = y; tmf.z = z; - tmf.floorz = tmf.dropoffz = newsec->floorplane.ZatPoint (x, y); - tmf.ceilingz = newsec->ceilingplane.ZatPoint (x, y); - tmf.floorpic = newsec->GetTexture(sector_t::floor); - tmf.floorsector = newsec; - tmf.ceilingpic = newsec->GetTexture(sector_t::ceiling); - tmf.ceilingsector = newsec; + P_GetFloorCeilingZ(tmf); spechit.Clear (); @@ -1540,6 +1555,13 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, } } + // compatibility check: Doom originally did not allow monsters to cross dropoffs at all. + // If the compatibility flag is on, only allow this when the momentum comes from a scroller + if ((i_compatflags & COMPATF_CROSSDROPOFF) && !(thing->flags4 & MF4_SCROLLMOVE)) + { + dropoff = false; + } + // killough 3/15/98: Allow certain objects to drop off if ((!dropoff && !(thing->flags & (MF_DROPOFF|MF_FLOAT|MF_MISSILE))) || (thing->flags5&MF5_NODROPOFF)) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 2ffa74e7d..2b6c59798 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1396,15 +1396,18 @@ void P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly) // because BOOM relied on the speed being fast enough to accumulate // despite friction. If the speed is too low, then its movement will get // cancelled, and it won't accumulate to the desired speed. + mo->flags4 &= ~MF4_SCROLLMOVE; if (abs(scrollx) > CARRYSTOPSPEED) { scrollx = FixedMul (scrollx, CARRYFACTOR); mo->momx += scrollx; + mo->flags4 |= MF4_SCROLLMOVE; } if (abs(scrolly) > CARRYSTOPSPEED) { scrolly = FixedMul (scrolly, CARRYFACTOR); mo->momy += scrolly; + mo->flags4 |= MF4_SCROLLMOVE; } xmove += scrollx; ymove += scrolly; @@ -1781,6 +1784,7 @@ explode: } mo->momx = mo->momy = 0; + mo->flags4 &= ~MF4_SCROLLMOVE; // killough 10/98: kill any bobbing momentum too (except in voodoo dolls) if (player && player->mo == mo) @@ -3235,14 +3239,20 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t if (SpawningMapThing || !type->IsDescendantOf (RUNTIME_CLASS(APlayerPawn))) { - actor->floorsector = actor->Sector; - actor->floorpic = actor->floorsector->GetTexture(sector_t::floor); - actor->ceilingsector = actor->Sector; - actor->ceilingpic = actor->ceilingsector->GetTexture(sector_t::ceiling); // Check if there's something solid to stand on between the current position and the // current sector's floor. For map spawns this must be delayed until after setting the // z-coordinate. - if (!SpawningMapThing) P_FindFloorCeiling(actor, true); + if (!SpawningMapThing) + { + P_FindFloorCeiling(actor, true); + } + else + { + actor->floorsector = actor->Sector; + actor->floorpic = actor->floorsector->GetTexture(sector_t::floor); + actor->ceilingsector = actor->Sector; + actor->ceilingpic = actor->ceilingsector->GetTexture(sector_t::ceiling); + } } else if (!(actor->flags5 & MF5_NOINTERACTION)) {