Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.
Sign upInitial cleanup of melee code #18697
Conversation
mugling
force-pushed the
mugling:melee
branch
2 times, most recently
to
b82cf7b
Oct 9, 2016
This comment has been minimized.
This comment has been minimized.
|
I'd also suggest renaming |
codemime
reviewed
Oct 9, 2016
| case DT_BASH: | ||
| if( has_flag( "REDUCED_BASHING" ) ) { | ||
| res *= 0.5; | ||
| } |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Yes, but separate PR (keep line count down for now) |
This comment has been minimized.
This comment has been minimized.
|
Ready |
mugling
added some commits
Oct 9, 2016
This comment has been minimized.
This comment has been minimized.
Coolthulhu
reviewed
Oct 9, 2016
| @@ -97,4 +97,10 @@ constexpr double accuracy_goodhit = 0.5; | |||
| constexpr double accuracy_standard = 0.8; | |||
| constexpr double accuracy_grazing = 1.0; | |||
|
|
|||
| /** Minimum item damage output of relevant type to allow using with relevant weapon skill */ | |||
| #define MELEE_STAT 5 | |||
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
That name is really ambiguous.
The old option - having is_cutting_weapon etc. was better.
Could be combined into is_weapon( damage_type ) - this would be both clear and centralized.
This comment has been minimized.
This comment has been minimized.
mugling
Oct 9, 2016
Author
Contributor
Or is_melee( damage_type ) to combine it with @codemime's suggestion
This comment has been minimized.
This comment has been minimized.
mugling
Oct 9, 2016
Author
Contributor
I've updated that retaining the constant only so that item_factory.cpp assigns the weapon category consistently with the check in is_melee()
Coolthulhu
reviewed
Oct 9, 2016
| @@ -3829,13 +3803,32 @@ std::string item::gun_type() const | |||
|
|
|||
| skill_id item::weap_skill() const | |||
| { | |||
| if( !is_weap() && !is_tool() ) { | |||
| if( is_null() || is_gun() || is_gunmod() || is_food() || is_ammo() || | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
mugling
Oct 9, 2016
Author
Contributor
This makes guns with bayonets lose any scaling.
I'm not sure what you mean about scaling.
Oh and it also makes pure unarmed combat have no weap_skill
The null item shouldn't have a skill but I've added checks for unarmed combat where necessary in 3fa13d4:
player::get_hit_weaponplayer::crit_chance
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
I'm not sure what you mean about scaling.
If you're using a gun with a bayonet as a spear, it should train spears (and vice versa).
The null item shouldn't have a skill
It should - it is treated as the fist in pretty much all cases.
This comment has been minimized.
This comment has been minimized.
mugling
Oct 9, 2016
Author
Contributor
If you're using a gun with a bayonet as a spear, it should train spears (and vice versa).
That would mean both is_gun() and is_melee() could be true at the same time. That isn't necessarily a problem but we would need that so code continues to perform the checks in that order (currently the case for all existing code)
The null item shouldn't have a skill
It should - it is treated as the fist in pretty much all cases.
I'm less sure about this. The only cases where it matters were the two functions above
Coolthulhu
reviewed
Oct 9, 2016
| int melee_dam = 0; // Bonus for melee damage; may be a penalty | ||
| int melee_cut = 0; // Cutting damage in melee | ||
| /** Damage output in melee for zero or more damage types */ | ||
| std::map<damage_type, int> melee; |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
Could just be an array. damage_type is an enum small enough that map will both slow things down and make it occupy more memory.
This comment has been minimized.
This comment has been minimized.
Coolthulhu
reviewed
Oct 9, 2016
| best_bonus = std::max( best_bonus, bashing_skill / 3.0f ); | ||
| // CQB bionic acts as a lower bound providing item uses a weapon skill | ||
| if( bonus < 5 && has_active_bionic( "bio_cqb" ) ) { | ||
| bonus = 5; |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
You declared a constant for this purpose and aren't using it here.
This comment has been minimized.
This comment has been minimized.
Coolthulhu
reviewed
Oct 9, 2016
| ///\EFFECT_MELEE adds to other weapon bonuses | ||
| return int(melee_skill / 2.0f + best_bonus); | ||
| ///\EFFECT_MELEE improves hit chance for all items (including non-weapons) | ||
| return bonus + ( get_skill_level( skill_melee ) / 2.0f ); |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
This block will conflict with #18351, which waited much longer and changes much more.
This PR should probably wait for it.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
mugling
Oct 9, 2016
Author
Contributor
What is the plan with #18351 as I don't want to hold either PR up given I've reviewed #18351 and it's otherwise ready to merge and we are also a long way along with this.
If you have an update ready for test tolerances and standard survivors then I'll wait on that, otherwise one of us can do that in a followup PR.
Coolthulhu
reviewed
Oct 9, 2016
| // Practice melee and relevant weapon skill (if any) except when using CQB bionic | ||
| if( !has_active_bionic( "bio_cqb" ) ) { | ||
| practice( skill_melee, rng( 5, 10 ) ); | ||
| practice( weapon.weap_skill(), rng( 5, 10 ) ); |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
This significantly changes the behavior of training - now you only train the highest (or first of the highest) skill.
Meaning that using a wood axe will only teach you bashing. Same for fire axe which is 20/20.
This comment has been minimized.
This comment has been minimized.
mugling
Oct 9, 2016
Author
Contributor
Eventually I want to move to a system where the player makes either a bashing, cutting or stabbing attack (dependent on what would be most effective). For now we could split 150% of the current XP between skills proportionally?
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
Splitting into different attacks is good, but making them all "typed" is not. We had this earlier in the development for knives and it lead to them always training only one of the types due to it scaling better at low levels.
Splitting training sounds good.
But it shouldn't be 150% - more two practices which sum up to 150%, but each is at most 100%.
This is because low amount practices are inherently worse when repeated a lot. Each practice drains focus regardless of amount.
Alternatively, if training one type only, it could be trained twice instead of for twice the amount.
This comment has been minimized.
This comment has been minimized.
mugling
Oct 9, 2016
Author
Contributor
Can you look at what I wrote (d1438d8) which defacto results in either 1 or 2 weapon skills being trained plus melee.
Coolthulhu
reviewed
Oct 9, 2016
| @@ -483,7 +453,7 @@ void player::reach_attack( const tripoint &p ) | |||
| g->m.has_flag( "THIN_OBSTACLE", p ) && | |||
| x_in_y( skill, 10 ) ) ) { | |||
| ///\EFFECT_STR increases bash effects when reach attacking past something | |||
| g->m.bash( p, str_cur + weapon.type->melee_dam ); | |||
| g->m.bash( p, str_cur + weapon.damage_melee( DT_BASH ) ); | |||
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
The function name here is ambiguous in a very important aspect: is this damage base or modified?
Currently all weapon bashes are done on base power.
This comment has been minimized.
This comment has been minimized.
mugling
Oct 9, 2016
Author
Contributor
Intentional change to use modified values. For example REDUCED_BASHING should reduce the effectiveness
Coolthulhu
reviewed
Oct 9, 2016
| if( weap.type->m_to_hit > 0 ) { | ||
| weapon_crit_chance = std::max( | ||
| weapon_crit_chance, 0.5 + 0.1 * weap.type->m_to_hit ); | ||
| weapon_crit_chance = std::max( weapon_crit_chance, 0.5 + 0.1 * weap.type->m_to_hit ); |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
That's a nerf to proper unarmed (ie. no punch daggers), which is already underpowered.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
Old code allowed max( weap.type->m_to_hit, unarmed / 2 ).
It could be a good idea to allow pure unarmed (!is_armed() as opposed to unarmed_strike(), preferably with a comment explaining it) to benefit from the max, but still require regular unarmed to only use weapon type to hit.
This comment has been minimized.
This comment has been minimized.
mugling
Oct 9, 2016
Author
Contributor
I see. Given I fixed player::unarmed_attack() to actually match its function docs (c9678a3) we could restore that initial check using that?
This comment has been minimized.
This comment has been minimized.
mugling
force-pushed the
mugling:melee
branch
2 times, most recently
Oct 9, 2016
mugling
force-pushed the
mugling:melee
branch
to
72e142b
Oct 9, 2016
mugling
added some commits
Oct 9, 2016
This comment has been minimized.
This comment has been minimized.
|
Everything fixed except waiting for #18351 and the last comment about nerf to unarmed which may not still apply? |
Coolthulhu
reviewed
Oct 9, 2016
| @@ -248,6 +248,25 @@ void player::roll_all_damage( bool crit, damage_instance &di, bool average, cons | |||
| roll_stab_damage( crit, di, average, weap ); | |||
| } | |||
|
|
|||
| static void melee_train( player &p, int lo, int hi ) { | |||
| p.practice( skill_melee, rng( lo, hi ) ); | |||
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
Should probably train for 50%-75% of primary weapon skill. Otherwise it will always be higher than any weapon skill.
This comment has been minimized.
This comment has been minimized.
Coolthulhu
reviewed
Oct 9, 2016
| { | ||
| if( is_null() ) { | ||
| if( is_null() || dt >= NUM_DT ) { |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
This check should not be caught like that. If anything calls for a damage_type outside range, it should either debugmsg, crash or bug out hard to show that something is going wrong.
This comment has been minimized.
This comment has been minimized.
Coolthulhu
reviewed
Oct 9, 2016
| { | ||
| if( is_null() ) | ||
| if( is_null() || is_gun() || is_gunmod() || is_food() || is_ammo() || | ||
| is_food_container() || is_armor() || is_book() || is_bionic() ) { |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
This whole check is needlessly restricting.
Consider the cases:
- Someone grabs an alien leg (
is_food() == true) and bashes stuff with it - Gun is used to bash/stab something
- Someone mods in gasoline as edible, chainsaw suddenly stops being a weapon when loaded
- Bible-thumping with a very large bible
is_null would make sense (but be redundant due to low damage) here if you didn't add the unarmed check below - if unarmed weapons are weapons, then pure unarmed should count too.
This comment has been minimized.
This comment has been minimized.
Coolthulhu
reviewed
Oct 9, 2016
| int melee_dam = 0; // Bonus for melee damage; may be a penalty | ||
| int melee_cut = 0; // Cutting damage in melee | ||
| /** Damage output in melee for zero or more damage types */ | ||
| std::array<int, NUM_DT> melee; |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
Is it zeroed properly somewhere?
I created at least 2 bugs by not explicitly zeroing arrays.
This comment has been minimized.
This comment has been minimized.
mugling
Oct 9, 2016
Author
Contributor
No - I had presumed it would be default initialized - is this not the case?
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
Pretty sure it isn't - otherwise I wouldn't have made those 2 bugs.
It can be compiler dependent.
Coolthulhu
reviewed
Oct 9, 2016
| @@ -77,7 +77,7 @@ bool player::is_armed() const | |||
|
|
|||
| bool player::unarmed_attack() const | |||
| { | |||
| return weapon.has_flag("UNARMED_WEAPON"); | |||
| return !is_armed() || weapon.has_flag( "UNARMED_WEAPON" ); | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
mugling
Oct 9, 2016
•
Author
Contributor
Why? If the player has no weapon they are by default making an unarmed attack?
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
"none" has the flag:
{
"type":"GENERIC",
"id": "null",
"symbol": "$",
"color": "red",
"name": "none",
"name_plural": "none",
"description": "seeing this is a bug",
"price": 0,
"volume": 0,
"flags": ["PSEUDO", "UNARMED_WEAPON", "TRADER_AVOID"], "//" : "Fist is internally represented as 'wielding a none as a weapon'"
}
Coolthulhu
reviewed
Oct 9, 2016
| @@ -13738,13 +13740,17 @@ void player::blossoms() | |||
|
|
|||
| float player::power_rating() const | |||
| { | |||
| int dmg = std::max( { weapon.damage_melee( DT_BASH ), | |||
| weapon.damage_melee( DT_CUT ), | |||
| weapon.damage_melee( DT_STAB ) } ); | |||
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
Side note: sum of damage is a better measure of "weaponiness" than maximum.
This comment has been minimized.
This comment has been minimized.
Coolthulhu
reviewed
Oct 9, 2016
| int cut = thrown.damage_melee( DT_CUT ); | ||
| int stab = thrown.damage_melee( DT_STAB ); | ||
| if( cut || stab ) { | ||
| proj.impact.add_damage( cut > stab ? DT_CUT : DT_STAB, cut > stab ? cut : stab ); |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
Would be significantly more readable as
if( cut > 0 || stab > 0 ) {
proj.impact.add_damage( cut > stab ? DT_CUT : DT_STAB, std::max( cut, stab ) );
}
Or even just by allowing stuff to deal both types separately.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Fixed everything. What is the plan with #18351 as I don't want to hold either PR up given I've reviewed #18351 and it's otherwise ready to merge and we are also a long way along with this. If you have an update ready for test tolerances and standard survivors then I'll wait on that, otherwise one of us can do that in a followup PR. |
Coolthulhu
reviewed
Oct 9, 2016
| @@ -251,7 +251,7 @@ void player::roll_all_damage( bool crit, damage_instance &di, bool average, cons | |||
| static void melee_train( player &p, int lo, int hi ) { | |||
| p.practice( skill_melee, ceil( rng( lo, hi ) / 2.0 ) ); | |||
|
|
|||
| if( p.unarmed_attack() ) { | |||
| if( !p.is_armed() ) { | |||
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Oct 9, 2016
Contributor
Is this special case needed?
It probably doesn't hurt, but looks totally redundant, considering that the check below now covers all sorts of unarmed.
This comment has been minimized.
This comment has been minimized.
mugling
added some commits
Oct 9, 2016
This comment has been minimized.
This comment has been minimized.
|
Includes all fixes from review and merged against Ready |
Coolthulhu
self-assigned this
Oct 9, 2016
This comment has been minimized.
This comment has been minimized.
|
This comment has been minimized.
This comment has been minimized.
|
@Coolthulhu fixed - that entire block had become redundant |
mugling
added some commits
Oct 9, 2016
Coolthulhu
merged commit ff6eed3
into
CleverRaven:master
Oct 9, 2016
1 check passed
This comment has been minimized.
This comment has been minimized.
|
Hint for the future: CQB bionic skill adjustment could easily be handled wholly in |
This comment has been minimized.
This comment has been minimized.
|
Good idea |
This comment has been minimized.
This comment has been minimized.
|
This PR broke the buildbot? |
mugling commentedOct 9, 2016
•
edited
The melee code is amongst the oldest in the code base. It is poorly documented and contains many inconsistencies.
Key changes:
STAB,SPEAR) damage from cutting. In the long-term I'd like to start further differentiating these types.MELEE_STAT (5)damage of the relevant type. Below this threshold only melee skill can provide bonuses.cutting 30, bashing 5sword etcBIO_CQB_LEVELdamage_melee( DT_BASH )as opposed totype->melee_damso that flags such asREDUCED_BASHINGandDIAMONDare always correctly handled