diff --git a/doomsday/apps/plugins/common/include/config.h b/doomsday/apps/plugins/common/include/config.h index c044e36764..632f365c2e 100644 --- a/doomsday/apps/plugins/common/include/config.h +++ b/doomsday/apps/plugins/common/include/config.h @@ -54,6 +54,7 @@ typedef struct libcommon_config_s { // Gameplay: byte switchSoundOrigin; byte defaultRuleFastMonsters; + byte pushableMomentumLimitedToPusher; // Weapons: byte weaponCycleSequential; // if true multiple next/prev weapon impulses can be chained to allow the user to "count-click-switch". diff --git a/doomsday/apps/plugins/common/src/common.cpp b/doomsday/apps/plugins/common/src/common.cpp index 576d2ad383..9ed7ff73c0 100644 --- a/doomsday/apps/plugins/common/src/common.cpp +++ b/doomsday/apps/plugins/common/src/common.cpp @@ -115,4 +115,5 @@ void Common_Register() #ifdef __JDOOM__ C_VAR_BYTE2("game-monsters-fast", &cfg.common.defaultRuleFastMonsters, 0, 0, 1, fastMonstersChanged); #endif + C_VAR_BYTE ("game-objects-pushable-limit", &cfg.common.pushableMomentumLimitedToPusher, 0, 0, 1); } diff --git a/doomsday/apps/plugins/common/src/game/g_game.cpp b/doomsday/apps/plugins/common/src/game/g_game.cpp index 1ae5db908f..df66f204b2 100644 --- a/doomsday/apps/plugins/common/src/game/g_game.cpp +++ b/doomsday/apps/plugins/common/src/game/g_game.cpp @@ -314,6 +314,7 @@ void G_CommonPreInit() ::quitInProgress = false; // Apply the default game rules. + cfg.common.pushableMomentumLimitedToPusher = true; gfw_Session()->applyNewRules(gfw_DefaultGameRules() = GameRules()); // Register hooks. diff --git a/doomsday/apps/plugins/common/src/hu_menu.cpp b/doomsday/apps/plugins/common/src/hu_menu.cpp index 73c2b24e67..29122c1183 100644 --- a/doomsday/apps/plugins/common/src/hu_menu.cpp +++ b/doomsday/apps/plugins/common/src/hu_menu.cpp @@ -1150,6 +1150,14 @@ void Hu_MenuInitGameplayOptionsPage() .setGroup(1) .setShortcut('w'); + page->addWidget(new LabelWidget("Pushable Speed Limit")) + .setLeft() + .setGroup(1); + page->addWidget(new CVarToggleWidget("game-objects-pushable-limit")) + .setRight() + .setGroup(1) + .setShortcut('p'); + # if __JDOOM__ || __JDOOM64__ page->addWidget(new LabelWidget("Zombie Players Can\n Exit Maps")).setLeft() diff --git a/doomsday/apps/plugins/common/src/world/p_map.cpp b/doomsday/apps/plugins/common/src/world/p_map.cpp index 4e80563031..03858c7377 100644 --- a/doomsday/apps/plugins/common/src/world/p_map.cpp +++ b/doomsday/apps/plugins/common/src/world/p_map.cpp @@ -850,10 +850,32 @@ static int PIT_CheckThing(mobj_t *thing, void * /*context*/) if((thing->flags2 & MF2_PUSHABLE) && !(tmThing->flags2 & MF2_CANNOTPUSH)) { - // Push thing - thing->mom[MX] += tmThing->mom[MX] / 4; - thing->mom[MY] += tmThing->mom[MY] / 4; - NetSv_PlayerMobjImpulse(thing, tmThing->mom[MX]/4, tmThing->mom[MY]/4, 0); + // Push thing. + coord_t pushImpulse[2] = {tmThing->mom[MX] / 4, tmThing->mom[MY] / 4}; + + for (int axis = 0; axis < 2; ++axis) + { + // Do not exceed the momentum of the thing doing the pushing. + if (cfg.common.pushableMomentumLimitedToPusher) + { + coord_t maxIncrement = tmThing->mom[axis] - thing->mom[axis]; + if (thing->mom[axis] > 0 && pushImpulse[axis] > 0) + { + pushImpulse[axis] = de::max(0.0, de::min(pushImpulse[axis], maxIncrement)); + } + else if (thing->mom[axis] < 0 && pushImpulse[axis] < 0) + { + pushImpulse[axis] = de::min(0.0, de::max(pushImpulse[axis], maxIncrement)); + } + } + + thing->mom[axis] += pushImpulse[axis]; + } + + if (!de::fequal(pushImpulse[MX], 0) || !de::fequal(pushImpulse[MY], 0)) + { + NetSv_PlayerMobjImpulse(thing, float(pushImpulse[MX]), float(pushImpulse[MY]), 0); + } } // @fixme Kludge: Always treat blood as a solid.