Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] [CR] Add sneaking/crouchwalking as a new movement mode #22844

Closed
wants to merge 7 commits into from

Conversation

Projects
None yet
@ecroffleps
Copy link
Contributor

commented Feb 1, 2018

The Idea

Adding a new crouched/sneaking movement mode which leads to more possibilities in traversing the wasteland and probably avoiding fights.

Closes #20431

Current state

At the current stage (pretty minor changes) I added a new movement mode "sneak" that simply halves your movement speed, the sound your footsteps make and the distance at witch monsters and NPCs detect you changes the way monsters/NPCs detect you by taking into account your sillhouette, movement speed (if moving), encumbrance and survival skill for all movement modes (see later comment).

I played a few rounds with these changes and it already adds a lot to the gameplay imho, especially during the early game and while looting citys. Balancewise I think it's not even overpowered since a regular zombie will still spot you at around 20 tiles away and being so slow you're not going to walk around in sneak mode the whole game. NPCs being more "alive" and "intelligent" will still notice you at around 40 tiles so no walking up to someone and "stealth killing" them, in the end you're just crouchwalking around on the street in bright daylight.

Further ideas (for new PR or this one)

  • Currently sneaking burns the same amount of stamina as walking (imho it should be more cumbersome?) not required
  • Instead of a flat modifier scale with DEX and/or your survival skill, like suggested in the Issue. I would like to hear your opinion on that matter.
  • Crouching makes aiming guns easier (more stability?)
  • Equipment and/or Load helps/hinders sneaking? (e.g. no sneaking with power armor)
  • Sneaking penalizes dodging (and melee damage?)

Edit by @Leland: reopened related issue and added auto-close keyword

@Mecares

This comment has been minimized.

Copy link
Contributor

commented Feb 1, 2018

  • Crouching makes aiming guns easier (more stability?)

Sounds only good if switching between crouching and walking takes time, to avoid free aim time saving in exchange for added keypresses.

@kevingranade

This comment has been minimized.

Copy link
Member

commented Feb 1, 2018

First of all, cool, I'll want to play with this for a bit, but it looks reasonable.

in the end you're just crouchwalking around on the street in bright daylight.

You are "in broad daylight", but there's a certain value to just moving slowly so that you don't get noticed.
I do wonder if we need to do anything to avoid you running away from a zombie and then dropping to a crouch while in plain sight and losing them. It might not be an issue because the zombie will keep moving toward the last place it saw you, and if you're moving away slower than it moves, it'll just spot you again, but there might be some odd behavior that this triggers.

Currently sneaking burns the same amount of stamina as walking (imho it should be more cumbersome?)

I think this is fine for now, neither of them should be making you "winded", so it doesn't matter much what the exact stamina cost is.

Instead of a flat modifier scale with DEX and/or your survival skill, like suggested in the Issue. I would like to hear your opinion on that matter.

Rather than patching in a stat or a skill, I'd like to have an outline of what the various inputs to stealth are, i.e. silhouette, movement, contrast and lighting; and decide how those are affected by gear and physical ability and environment.

Crouching makes aiming guns easier (more stability?)

Sounds only good if switching between crouching and walking takes time, to avoid free aim time saving in exchange for added keypresses.

Agree with this, but there's a way around it.

  • Toggling move mode is "free".
  • Track "selected move mode" and "current move mode" separately.
  • When taking an action that is impacted by move mode:
    • If "selected move mode" is different from "current move mode":
      • Spend move points to change "current move mode" before acting.

This actually needs to be addressed now, because as long as moving doesn't end your turn, you can toggle between crouching and running and get most of the speed of running, but ALL of the benefit of crouching.

Equipment and/or Load helps/hinders sneaking? (e.g. no sneaking with power armor)

Similar to the skill/dex thing, some gear would make things better, some would make it worse. Power armor is special, and might prevent sneaking entirely.

@Night-Pryanik

This comment has been minimized.

Copy link
Member

commented Feb 2, 2018

Should gear (especially metal armor) affect player-generated sound? Scrap suit, for example, is explicitly states that loose collection of plates jangles and clangs as you walk, attracting the attention of all nearby. I think it's hard to successfully sneak in a gear that sounds like orchestra when you're moving.

@BorkBorkGoesTheCode

This comment has been minimized.

Copy link
Contributor

commented Feb 2, 2018

Don't forget big noisy drum magazines with their loose moving parts.

@ecroffleps

This comment has been minimized.

Copy link
Contributor Author

commented Feb 2, 2018

You are "in broad daylight", but there's a certain value to just moving slowly so that you don't get noticed.
I do wonder if we need to do anything to avoid you running away from a zombie and then dropping to a crouch while in plain sight and losing them. It might not be an issue because the zombie will keep moving toward the last place it saw you, and if you're moving away slower than it moves, it'll just spot you again, but there might be some odd behavior that this triggers.

That was one of my worries when I started, but while playing it seemed fine:

  • If you try to do this in the 20 - 35 tile range the Z will catch up to you and spot you again pretty quick as you mentioned (better of just running away and then start sneaking when you got some distance)
  • In the 35-40 tile range breaking line of sight through sneaking only helps if you can get into a building or forest within a few steps range to completely lose him

I didn't notice any odd behavior yet, but may needs some more testing.

Currently sneaking burns the same amount of stamina as walking (imho it should be more cumbersome?)

I think this is fine for now, neither of them should be making you "winded", so it doesn't matter much what the exact stamina cost is.

Yes I'm with you on that, I was just wondering if reducing the stamina gain while sneaking would add something or if it would be just a gimmick. The range for reducing is only 3 points/turn: stamina gain 10/turn, walking burns 7/turn, running burns 20/turn (without any modifiers). So I'll scrap that idea.

Rather than patching in a stat or a skill, I'd like to have an outline of what the various inputs to stealth are, i.e. silhouette, movement, contrast and lighting; and decide how those are affected by gear and physical ability and environment.

Hm, sounds reasonable. Currently only the lighting affects at what range a creature detects another one.
For the case when a monster/NPC checks if he sees the player I could implement a special calculation
that effects the spotting even when not sneaking (consistency):

  • maybe using the m_size as a easy substitute for a silhouette (every player is medium, but while sneaking small?) -> gear should affect this probably, but of the top of my head I can't think of any good gear related value (encumbrance?, volume?, weight?)
  • movement speed (slower is better) -> affected by stamina, traits, feet encumbrance/hp, ...
  • Lighting is already there
  • I'm not quite sure what contrast in this context would do/mean?

Would be great to give players a reason to wear lighter/less armor if that would mean they're not getting spotted so easily. At the moment more armor is better every time if you can life with the encumbrance.

Sounds only good if switching between crouching and walking takes time, to avoid free aim time saving in exchange for added keypresses.

Agree with this, but there's a way around it. [...]
This actually needs to be addressed now, because as long as moving doesn't end your turn, you can toggle between crouching and running and get most of the speed of running, but ALL of the benefit of crouching.

Didn't even notice that, you're right. And this would also solve another thing I don't think should be there: - sneak into the vision range of a monster

  • press V -> it doesn't see you
  • toggle move mode
  • press V -> you get notified that it will see you if you would continue
  • toggle move mode to sneak again and continue as if nothing happened

How many move points would be appropriate for this? 20?

@ecroffleps

This comment has been minimized.

Copy link
Contributor Author

commented Feb 2, 2018

Should gear (especially metal armor) affect player-generated sound? Scrap suit, for example, is explicitly states that loose collection of plates jangles and clangs as you walk, attracting the attention of all nearby. I think it's hard to successfully sneak in a gear that sounds like orchestra when you're moving.

bool game::walk_move( const tripoint &dest_loc ) {
    ...
    // Sound of footsteps may awaken nearby monsters
    if( !u.has_artifact_with( AEP_STEALTH ) && !u.has_trait( trait_id( "DEBUG_SILENT" ) ) ) {
        if( !u.has_trait( trait_id( "LEG_TENTACLES" ) ) ) {
            int footstep_vol = 6; // 6 being the default volume while walking
            if( u.has_trait( trait_id( "LIGHTSTEP" ) ) || u.is_wearing( "rm13_armor_on" ) ) {
                footstep_vol = 2;
            } else if( u.has_trait( trait_id( "CLUMSY" ) ) ) {
                footstep_vol = 10;
            } else if( u.has_bionic( bionic_id( "bio_ankles" ) ) ) {
                footstep_vol = 12;
            }

            // Footstep volume changes for the different move modes
            if( u.move_mode == "sneak") {
                footstep_vol /= 2;
            } else if( u.move_mode == "run" ) {
                footstep_vol *= 1.5;
            }
           sounds::sound( dest_loc, footstep_vol, "", true, "none" );
           sfx::do_footstep();
        }

        if( one_in( 20 ) && u.has_artifact_with( AEP_MOVEMENT_NOISE ) ) {
            sounds::sound( u.pos(), 40, _( "You emit a rattling sound." ) );
        }
    ...
}

That's the only stuff that affects you're footstep/movement sound (in my version).
Implementing something "better" is probably out of this PRs scope?
Deciding how much noise gear will make only by material is probably not effective. Maybe gear needs a new stat like "sneakiness" (I'm no native speaker 😅) which would factor into sound and this:

maybe using the m_size as a easy substitute for a silhouette (every player is medium, but while sneaking small?) -> gear should affect this probably, but of the top of my head I can't think of any good gear related value (encumbrance?, volume?, weight?)

@@ -188,6 +188,9 @@ bool Creature::sees( const tripoint &t, bool is_player ) const
}
if( is_player ) {
// Special case monster -> player visibility, forcing it to be symmetric with player vision.
if( g->u.move_mode == "sneak" ) { // not symmetric if the player is sneaking

This comment has been minimized.

Copy link
@BevapDin

BevapDin Feb 2, 2018

Contributor

Why are you suddenly referring to g->u?

This comment has been minimized.

Copy link
@ecroffleps

ecroffleps Feb 3, 2018

Author Contributor

The is_player flag is set if the target is the player, so i need to refer to the player like that to check if he is sneaking.
Maybe it would be better to check if the target creature is sneaking in the bool Creature::sees( const Creature &critter ) function and then adding a parameter to this function like: bool Creature::sees( const tripoint &t, bool is_player, bool is_sneaking )
That would also prepare for sneaking enemies (pretty terrifying thought)

This comment has been minimized.

Copy link
@BevapDin

BevapDin Feb 7, 2018

Contributor

A comment explaining the use of the global g->u and a @todo mark should be fine. You could also make a virtual bool Creature::is_sneaking() const function, implemented for the player to check the move_mode.

//~ Movement type: "running". Max string length: one letter.
const auto str_run = pgettext( "movement-type", "R" );
wprintz( w, c_white, " %s", move_mode == "walk" ? str_walk : str_run );
wprintz( w, c_white, " %s", move_mode == "walk" ? str_walk :

This comment has been minimized.

Copy link
@BevapDin

BevapDin Feb 2, 2018

Contributor

Seems like move_mode should be an enumeration.

This comment has been minimized.

Copy link
@ecroffleps

ecroffleps Feb 3, 2018

Author Contributor

Yeah, thought so myself, but changing it would break old savegames?

ecroffleps added some commits Feb 7, 2018

Added: Toggling move-mode is free, changing has a cost. Added: monste…
…r->player visibility is affected by a modifier calculated in player::get_sees_modifier()
@ecroffleps

This comment has been minimized.

Copy link
Contributor Author

commented Feb 13, 2018

New commits implement the suggestion by Kevin where toggling the move-mode is free but if you take an action affected by move-mode changing from running/walking to sneaking and vice versa now costs 20 moves. The selected_move_mode is displayed next to the active move_mode in yellow (for some reason I can't add pictures, I'll try again later)

Sneaking now also affects the output of player::get_size(), it's MS_MEDIUM while walking/running and MS_SMALL while sneaking.

But probably the biggest change is the new way creature::sees() is affected by a modifier with various factors (Only for the creature -> player check) (lower is better):

  • Sillhouete: Supplies the base for the modifier (1.0 if player size is MS_MEDIUM, 0.5 for MS_SMALL)
  • Movement: If the player moved during last action adds 0.125 to 0.5 depending on movecost (slower is better: sneaking~0.125 - walking~0.25 - running~0.5)
  • Skill: Survival skill helps with staying hidden in all circumstances ( removes 0.025 per level)
  • Encumbrance: Encumbrance on all major body parts (head, torso, feet, arms, legs) is bad for staying hidden (adds ~ 0.1 per 20 points of encumbrance)

To make it easier to understand (for you and for me) i made this google-doc which shows you the wanted_range (distance between creature and player) and how it is affected by the modifier:
Example-Sheet

This probably still needs some work but I kind of like that running makes you more visible, it just makes sense that way.

if ( !data.read( "selected_move_mode", selected_move_mode ) ) {
selected_move_mode = move_mode;
}
data.read( "move_mode", moved );

This comment has been minimized.

Copy link
@BevapDin

BevapDin Feb 16, 2018

Contributor

You're reading the same JSON value as above (line 732), is this intentional?

This comment has been minimized.

Copy link
@ecroffleps

ecroffleps Feb 16, 2018

Author Contributor

No not intentional, thank you. Should read the "moved" value.

modifier -= get_skill_level( skill_survival ) * 0.025;

// encumbrance on bodyparts has negative effect (every 20 points = 1%)
modifier += (float) ( encumb( bp_torso ) + encumb( bp_head ) +

This comment has been minimized.

Copy link
@BevapDin

BevapDin Feb 16, 2018

Contributor

That cast is unnecessary, the right side of the division is already a floating point value (2000.0), the left side will be converted to a floating point value automatically.

This comment has been minimized.

Copy link
@ecroffleps

ecroffleps Feb 16, 2018

Author Contributor

Will change that, thank you

@ecroffleps

This comment has been minimized.

Copy link
Contributor Author

commented Feb 16, 2018

I don't understand the issue with the failed build, having astyle regression in files I didn't touch?

11:55:33 #define VERSION "0.C-26296-g3f19a1b"
11:55:34 astyle regressions found.
11:55:34 Formatted src/pimpl.h Formatted src/skill.h
11:55:34 Makefile:979: recipe for target 'astyle-check' failed
11:55:34 make: *** [astyle-check] Error 1
11:55:34 Build step 'Conditional step (single)' marked build as failure
11:55:34 Setting status of edec268 to FAILURE with url http://gorgon.narc.ro:8080/job/Cataclysm-PR-Builder/3338/ and message: 'Build finished. '
11:55:34 Using context: gorgon-ghprb
11:55:35 Finished: FAILURE

Only thing i can think of is: Do I need to merge in changes from upstream/master?

@BorkBorkGoesTheCode

This comment has been minimized.

Copy link
Contributor

commented Feb 17, 2018

@ecroffleps no, then a merge conflicts message would be at bottom of page.

@@ -11168,7 +11199,11 @@ bool player::has_weapon() const

m_size player::get_size() const
{
return MS_MEDIUM;
if ( move_mode == "sneak" ) {
return MS_SMALL;

This comment has been minimized.

Copy link
@Coolthulhu

Coolthulhu Mar 3, 2018

Contributor

This doesn't look good: small size makes one harder to hit, including in melee.
Would be better if you just special cased this in sight-related functions.

This comment has been minimized.

Copy link
@ecroffleps

ecroffleps Mar 13, 2018

Author Contributor

Hm, if it is harder for us to hit smaller targets why not making it harder for them to hit us in this case?
I looked into this and think that penalizing your dodge roll (easy to implement) and the players melee damage/force/strength (can't find a proper place?) while sneaking is a better and more realistic (you're not as mobile and can't put your full body weight into the attack) option for this?

This comment has been minimized.

Copy link
@pipehat

pipehat May 10, 2018

Contributor

I love the small size effect because it could create options for small door (House with dog door... and zdog inside; cramped maintenance tunnels in sewers; small cave passages; etc)


// having moved during last action adds 12.5% to 50% depending on movecost (slower is better)
if ( moved ) {
modifier += ( 0.25 / ( movecounter / 100.0 ) );

This comment has been minimized.

Copy link
@Coolthulhu

Coolthulhu Mar 3, 2018

Contributor

You only seem to use the moved and movecounter for this modifier. You could merge them into one counter that tracks the penalty to stealth.

}

// survival skill helps with staying hidden in all circumstances (2.5% per level)
modifier -= get_skill_level( skill_survival ) * 0.025;

This comment has been minimized.

Copy link
@Coolthulhu

Coolthulhu Mar 3, 2018

Contributor

Survival skill is already way too generalized and does everything at once. From foraging mushrooms, through being an edgy nihilist who feels no guilt for maiming undead humans, to extracting sci-fi gadgets from corpses.
Perception would be good here - if you can't see or hear yourself, you're either amazing at hiding or terrible at perception.


void player::change_move_mode()
{
if ( selected_move_mode != move_mode ) {

This comment has been minimized.

Copy link
@Coolthulhu

Coolthulhu Mar 3, 2018

Contributor

Styling: no space after if. Should look like this: if(

@@ -176,7 +176,8 @@ bool Creature::sees( const tripoint &t, bool is_player ) const
const int range_night = sight_range( 0 );
const int range_max = std::max( range_day, range_night );
const int range_min = std::min( range_cur, range_max );
const int wanted_range = rl_dist( pos(), t );
// If monster sees player is checked wanted range is affected by a modifier
const int wanted_range = rl_dist( pos(), t ) / ( is_player ? g->u.get_sees_modifier() : 1.0f );

This comment has been minimized.

Copy link
@Coolthulhu

Coolthulhu Mar 3, 2018

Contributor

You can pass the sees_modifer as an argument from above - this will make the whole thing much cleaner and allow generalizing stealth to other critters.

@BorkBorkGoesTheCode

This comment has been minimized.

Copy link
Contributor

commented Apr 19, 2018

@ecroffleps are you still coding this?

@FulcrumA

This comment has been minimized.

Copy link
Contributor

commented May 3, 2018

Since it wasn't mentioned in the ticket itself, I think it bears remembering to adjust NPC followers to automatically change their movement type to that of player's. While it may be reasonable to sometimes allow companions to hold position while the player sneaks elsewhere, at times it should be possible for the whole group to move somewhere stealthily.

I also do agree that gear should have some sneaking modifier. I don't think everything needs to have such, but items affecting it the most (like aforementioned rattling, metal armors) should.

@ecroffleps

This comment has been minimized.

Copy link
Contributor Author

commented May 3, 2018

@BorkBorkGoesTheCode Kind of, I'm pretty busy studying right now.

Only made a few minor changes since last commit. I mainly was testing it out with a few characters and playing with the modifiers quite some time. Hitting the sweet spot between being completely useless and totally overpowered is proving to be pretty hard.
If I find the time next week I will try to get the current iteration commitable.

@FulcrumA That's a good point.
Having NPCs (not followers) who are able to sneak would probably be useless since you see them on the overmap anyways?

@Wishbringer

This comment has been minimized.

Copy link
Contributor

commented May 10, 2018

How about having a separate sneak skill and not being able to target hidden creatures, though still visible (to the player) and subject to AOE attacks? I realize this is a major change and may be outside the scope of the current version.

@BorkBorkGoesTheCode

This comment has been minimized.

Copy link
Contributor

commented May 27, 2018

@ecroffleps How's progress?

@ZhilkinSerg

This comment has been minimized.

Copy link
Contributor

commented Jun 16, 2018

Feel free to reopen.

@kevingranade

This comment has been minimized.

Copy link
Member

commented Dec 9, 2018

This pull request has been mentioned on Cataclysm: Dark Days Ahead. There might be relevant details there:

https://discourse.cataclysmdda.org/t/suggestion-for-3-new-skills-and-some-ideas-for-stealth-system-and-what-not/14928/13

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.