Best way to implement "reverse battery compartment mod" within current code structure?

One thing has been nagging me since forever: you can use car batteries in handheld tools via battery compartment mod ( Battery compartment mod - Cataclysm: Dark Days Ahead ), but you can’t use handheld batteries in vehicles. And there isn’t really a logical reason why you can’t: standard medium battery has the same energy capacity as a “vehicle” motorbike battery, for example.

However, after thinking about the actual implementation for a while, it’s clear that you can’t directly use the code from magazine_battery_mod in reverse (vehicle don’t have “pockets” for batteries the way inventory items do). As such, there are at least 4 ways you can accomplish this “reverse compatibility”:

  • add a separate recipe for each type of handheld battery that directly turns it into vehicle-compatible battery. This will require 7 new recipes (to cover all rechargeable battery types), but is rather straight-forward to implement (for me, anyway) and unlikely case unexpected issues.
  • add a new vehicle part that, when installed into the vehicle, will allow user to install handheld batteries into the same vehicle tile (problem is, I have no practical knowledge of that area of the vehicle code, and it smells heavily of C++, which is not exactly my forte either)
  • create an new item mod that, when installed onto a battery, makes it vehicle-compatible (here I’m not even sure there is a precedent for such thing in the code. Can a simple item mod change how vehicle code sees an item?)
  • create an new item that accepts handheld batteries into it’s pocket, and can be installed into the vehicle thereafter (again, no idea if current vehicle code base even supports two-way interaction with an item inside a pocket of another item)

Right now I’m leaning towards option #1, as I understand the code base for that implementation much better. However, I’d like to hear some other opinions here before I push the PR.

I think your best solution would actually be #2:

  1. create a “handheld battery mount” vehicle part based on the existing “storage_part_mount”
  2. create a bunch of removable battery vehicle parts for handheld batteries
  3. whine at me until I write some code for setting limits on the size of batteries you can install in a BATTERY_MOUNT flagged part. or alternately write it yourself, it’s straightforward C++ IMO but I also know the code pretty well.

However, option #1 is probably the easiest and isn’t unreasonable.

3 Likes

I’m trying to implement #2, it’s going fine, but an obvious problem comes up:

I’ve used two new flags that are not yet defined:
“flags”: [ “HANDHELD_BATTERY_MOUNT” ],
“flags”: [ “NEEDS_HANDHELD_BATTERY_MOUNT” ]

But I don’t actually know where in the code such flags are defined. Any help with that?

1 Like

Flags aren’t defined in the code generally. They’re strings, and stored in a collection of strings that you can search with has_flag( "FLAG_STRING" ). See:
git grep has_flag src/veh*cpp
for more examples than you probably want to read.

There are certain flags that are defined in the vehicle code because they’re referenced multiple times per second and doing a linear search via has_flag() would have performance implications. But an installation flag is not a performance equivalent flag so has_flag() will work fine.

If you search for “BATTERY_MOUNT” in the code:

$ git grep BATTERY_MOUNT src/veh*cpp
src/vehicle.cpp:    remove_dependent_part( "BATTERY_MOUNT", "NEEDS_BATTERY_MOUNT" );

you’ll see that the existing BATTERY_MOUNT flag is only used to make sure that parts get removed in the correct order, and that would all you’d need to do for HANDHELD_BATTERY_MOUNT.

Thanks for taking a swing at this!

1 Like

Shouldn’t they also be checked when Installing the part?
I was under the impression the main use for these flags was to insure you need BATTERY_MOUNT already present in the tile to install anything with NEEDS_BATTERY_MOUNT

My coding is… lets be generous and say elementary at best, but I may have found something useful.

There is the Recharging station in vehicle_parts.json that goes from vehicle battery power to handheld batteries placed in a cargo container. If we made a copy of that using a reversed version of the “recharge” flag than it could drain batteries in a compartment to charge the vehicle.
Does that sound in any way workable?

Unfortunately I haven’t been able to find the code for how the recharge flag works. The file labeled Flags.json just says
“id”: “RECHARGE”,
“type”: “json_flag”,
“context”: [ ]
},

To “charge” a vehicle it needs to have some “internal” batteries in the first place to absorb that charge. I don’t think the current vehicle code will be able to treat an “outside” battery as it’s “primary internal battery” well (if at all).

Ah, yes. I had misread the goal of this. Had assumed they wanted to charge a vehicle off handheld batteries not wholly replace the car’s battery with a handheld one. Clearly I need more coffee before I continue reading.

2 Likes

You’d think you’d need to check BATTERY_MOUNT when you install, but actually it’s a lot simpler: battery mounts provide the on_battery location, and batteries install in the on_battery location. If you don’t have a mount installed, you can’t install a battery because there is no where to install it.

1 Like

So the fact that vehicle batteries are an order of magnitude heavier than comparable (charge-wise) non-vehicle batteries is just ignored? Or those recipes are making them heavier after conversion, somehow?

Medium battery - Cataclysm: Dark Days Ahead is 600g at 500 kJ
Small storage battery - Cataclysm: Dark Days Ahead 2500g at 500kJ
Heavier, but not exactly “order of magnitude”.

The recipe adds extra weight to the vehicle, sure. Plus, handheld batteries are more fragile, too.
But much more to the point: why would a weight difference of less than 2 kg matter on a vehicle?

The frame and whatever-else-is-actually-using-that-battery-in-that-vehicle will most likely weight so much that a kilo or two would be irrelevant.

Ok, but where is that property defined, then? It’s not in their .json definitions, as far as I can see…

I mean, I can see that swappable storage batteries go into
“location”: “on_battery_mount”,

But where is it defined that “swappable storage battery case”, when installed, provides this “on_battery_mount” location?

P.S. Never mind, already found relevant code in vp_flags.json
(It does work via flags, though… Nothing to do with “location”.)

P.P.S. The best part is — flags (as defined in vp_flags.json) already prevent removal of dependent parts. So I have no idea what the hell C++ code even does at this point…

… Provide the support structure and interpret the JSON code?

Nope.
Because similar .json-defined pair of newly-added flags works without the C++ counterpart.

Uh… no. JSON on it’s own can not be executed. It needs C++ (or any other lower programming language) to translate it into machine-readable code.

You can’t just write a game based only on JSON.

I’m specifically talking about the line in C++ code that explicitly mentions the flags.

remove_dependent_part( "BATTERY_MOUNT", "NEEDS_BATTERY_MOUNT" )

Which line?
The part I quoted and answered 8 minutes ago did not mention any line…:

See above, I added the exact line.

Sigh…
So you’re talking about vehicle.cpp?

Sigh…
Yes, I am talking about a line in vehicle.cpp
Always has been. That’s the only line in C++ code directly and explicitly relevant to the flags in question.