Cataclysm-dda: Reinforced item shows wrong stats, negative damage?

Created on 2 Dec 2016  路  32Comments  路  Source: CleverRaven/Cataclysm-DDA

Got a bit of a weird one for you here. I could even reproduce it.

What I saw the first time: 2 SCAR-H's. One had 90 dispersion, the other had 30! Both appeared to be ++reinforced. I then tried to repair both, which worked on the 30 dispersion gun and put it back at 90.

Anyway.. I loaded an earlier save and picked up the two SCAR-H's. I had to remove a bunch of mods from one of them. They were both at 90 dispersion. Then I saved and reloaded. They're now both at 30, still showing ++. Both able to be repaired. Could this be related to #19575?

http://www.filedropper.com/save_12

(S2 - Confirmed) <Bug> Items / Item Actions / Item Qualities

All 32 comments

After the JSON update, I still find many - if not all - of my previously reinforced guns showing 'better than perfect' stats and able to be repaired down to a standard reinforced state. Is there a way to bring durability in line on old savegames or do I have to fix them all by hand?

For the save I uploaded, you find most of these guns in the very bottom left trunk of the car.

Update: It's actually worse than this. These reinforced guns with faulty durability can be fixed by repairing, but as soon as I save and reload, they're back to their previous state.

Marking as confirmation required - can this be reproduced in a new save?

I'd doubt it. At this point, I'm mostly looking to fix the save I have. A lot of damage values read like..

"damage":1.666667e+000, "damage":1.010000e+000, "damage":3.400000e-001, "damage":3.337143e+000and so on...

Can I fix this by just going through all the map files with a replacer and setting, say, "damage":1.0 everywhere? Or cutting the long values down to one number behind the comma? How do I properly convert it to the new system?

Yes, setting damage 1.0 should work. The bug arises because we output via stringstream but then read in via custom code and the two aren't commutative

Cheers!

Okay.. one last comment. I reset all of the scavenged items (indeed, the whole world present in .map files) back to "damage":0, then reinforced a bunch of weapons. In the file they're all listed as "damage":-1.000000, which I assume is correct.

However, they're still wonky. After a save>reload, a 90 dispersion gun turns once again into 30 dispersion, damage increases etc. And all reinforced guns are able to be repaired to regular reinforced status, which lasts only until you save>reload. I'll try this with a new game tomorrow.

What version?
Please post a save

This is currently on Build 6007. Github won't let me upload zips so once again I'm using that crummy host.. sorry about that. http://www.filedropper.com/save_15

There's an A7 rifle in my inventory. It lists 26 damage, which is beyond what it should be able to do. You can 'reinforce' it down to 24. The other guns are in the trunk, bottom left tile.

I just reproduced it with a new savegame, using a world freshly created in version 6017. Like last time, the only mods used are StatsThroughSkills, Disable NPC Needs, Disable Religious Texts & Prevent Zombie Revivification. Shouldn't matter for this I think.

  • Made a military character
  • Edited a firearm repair kit into his inventory
  • Accurized his starting weapon, an M1 Garand to a reinforced 64 damage, 90 dispersion.
  • After a save>reload, the M1 Garand is at a reinforced 66 damage, 30 dispersion and can be repaired.

Could you re-open this issue please?

the only mods used are StatsThroughSkills, Disable NPC Needs, Disable Religious Texts & Prevent Zombie Revivification. Shouldn't matter for this I think.

Agreed

Could you re-open this issue please?

Sure, can you post the save (preferably just copy-paste the part with the M1 Garand)

The vanilla save without any firearm tampering shows:

{ "typeid": "garand", "item_vars": { "magazine_converted": "1" }, "invlet": 99, "contents": [ { "typeid": "garandclip", "contents": [ { "typeid": "3006", "charges": 8 } ] }, { "typeid": "shoulder_strap" } ] },

And then it doesn't seem to matter if I just accurize once and save, load the game once more so the gun shows faulty stats and save again, or if I 'fix' it and save again.. the save file always (correctly?) shows:

{ "typeid": "garand", "item_vars": { "magazine_converted": "1" }, "invlet": 99, "damage": -1.000000, "contents": [ { "typeid": "garandclip", "contents": [ { "typeid": "3006", "charges": 8 } ] }, { "typeid": "shoulder_strap" } ] },

When the save is damage: -1 what does the display show and what are the item stats (vs what is expected)?

faulty

Shows this after loading the game.

repaired

And this after applying the firearm repair kit.

So the bug is that you can apply the firearm kit despite the item already been reinforced?

Yes, and that the gun shows incredibly good stats. 12 effective range, 62 damage and 90 dispersion are, as I understand it, the correct values for a reinforced Garand. But whenever I load a game with reinforced guns in it, they somehow get these stat buffs and become repairable, which removes the buffs until I reload the game.

What was the rationale for floating point damage values anyway? They're
super fragile in weird ways.

It should be a continuous variable allowing deprecation of if( x_in_y( 1, 10 ) { damage++; } ) constructs which players complained were too 'random'. I can see their point: why does one baseball bat breaks on the first swing but a different one lasts all season. We can now implement a lot better mechanics.

Display to the player remains stepped (to integers) and JSON definitions remain in integers. As an ancillary benefit we did get a lot of cleanup of the JSON loading code (which is scary-bad). Many of the bugs are due to problems in the repair code, many of which exist whether or not the underlying type is floating. Work is underway to correct this in #19663.

On Dec 7, 2016 3:57 AM, "mugling" notifications@github.com wrote:

It should be a continuous variable allowing deprecation of if( x_in_y( 1,
10 ) { damage++; } ) constructs which players complained were too 'random'.
I can see their point: why does one baseball bat breaks on the first swing
but a different one lasts all season. We can now implement a lot better
mechanics.

This is unconvincing, simply rescaling the damage number has the same
effect without invoking the bizarrity that is floating point numbers in
c++. While 1-5 was certainly too restrictive a range, floating point is
overkill.

This bug isn't caused by floating point but a bug in the item repair code allowing double reinforcing

Also we only have 4 damage levels so a rescaling (by 100) would still require the same stepping logic. C++ floating point is well defined - the problem here is a bad conditional.

Hey guys, since mugling's attempt at this was unfortunately rejected (see his PR), is there anything on the horizon in the way of a possible fix? AFAIK old issues are auto-closed and this is I think a fairly prominent one that all players experience when they play the game at one point or another.

It has been a while. Does it still reproduce?

Yep, just tested it. Same thing as was described. I also noticed the M1 Garand seems to be gone from the game. Or my savegame, anyway. I had a couple I tested this on, now they're nowhere to be found. Anyway.... separate issue probably.

Can't reproduce. Did this:

  • Spawn 2 SCAR-Hs
  • Accurize both
  • Save and load
  • Try to accurize either
  • Fail
  • Damage one and re-accurize it
  • Still can't over-accurize it
  • Spawn a fresh one
  • Save+load
  • Can't over-accurize it

It could be just bugged saves. Does it reproduce with fresh items? If not, it only requires some save recovery code, which would be much easier than trying to locate the source of this weird behavior.

untitled

Nope, still does it. Check my short procedure from further up the thread. Get yourself a kit and Mechanics level 10 for this (this was probably why it didn't work for you). After a save-reload you see increased stats on a reinforced gun that you can then 'accurize away' by using the kit another time.

I tested this on a fresh world in 6305 with the sheltered and military scenario.

Confirming this bug still exist.
Tested it with a Quaterstaff. Its almost like cheating, makes weapons that are reinforced stronger after reloading the game.

Additional info:
After the 'reinforced+reloadedGame' Item gets damaged, it show its real state after reloading the game.

Guns can't be fully reinforced right now. This has been a recurring problem.

A SCAR-L found in game with HP |\ has a -8 damage penalty, damage 1.000000 in the save and cannot be fully repaired: repairing gives the repair message but doesn't change visible damage; reinforcing gives it two light green ++

@BorkBorkGoesTheCode #24493 should allow guns to be fully reinforced, but I could not reproduce the bug described in this issue, with or without #24493. @Tharn @ZenZen2 could you please see if this issue still persists?

One issue I still see: Sometimes guns will only reinforce up to bright green ++, which may turn into dark green ++ after a save -> reload.

After #24493 partially-reinforced items (which show as bright green) should not appear again, and existing ones should be reinforce-able to the full condition. I don't see why reloading would cause them to turn into dark green however, somewhere in the save loading code that converts the double damage value into an integer perhaps?

I think it has to do with them being damaged prior to being repaired. Will try to reproduce.

After switching to MinGW-w64 this also happened to me, and I think I have found the cause of this issue: in json.cpp, the method JsonIn::get_float() uses i * std::pow(10.0f, e + mod_e) for float deserialization. This of course, depends heavily on the actual implementation of std::pow(). I could have proposed a fix, but unfortunately c++11 only comes with locale-specific float conversion functions (including `istream::operator>>()') which are slow, and not guaranteed to precisely restore serialized float values. c++17 do have a quick and precise conversion function, but that's out of the question for this project. I tried consecutively dividing/multiplying by 10 and it worked for this specific case, but I doubt that will not become broken under other circumstances or compilers.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Taberone picture Taberone  路  3Comments

ituluwituluwzev picture ituluwituluwzev  路  3Comments

RogueYun picture RogueYun  路  3Comments

Coolthulhu picture Coolthulhu  路  3Comments

tinukedaya picture tinukedaya  路  3Comments