The earth object did not include _inherited(...) in the Construction() callback. Thus it was not initialized as a stackable object correctly. Fortunately the other stackable objects did not have this problem.
Nonetheless I added a unit test, so that we can identify similar problems in the future.
The callback happens in every call to MergeWithStacksIn() now, instead of RejectEntrance(). Otherwise the following use case does not work: Liquid enters crew/building and fills the contained barrels. Added a unit test for that use case. Stackable unit tests still pass.
The function RejectEntrance() has two more callbacks to the object it should enter:
- CollectFromStack(object stack): The object can grab items from the stack, before the stack tries to merge with stacks in the object. This is necessary for barrels, so that a large liquid stack can fill an empty barrel.
- RejectStack(object stack): This is called after the stack is merged. Currently, the stack merging counts as handled only if the stack is removed. This callback allows the object to still reject the stack, for example if it accepts only one item, such as the barrel does.
The previous name suggested that the object actually gets put into another object. In fact it merges the stack count with other stacks, and it does not only try to (and reverts the state if it fails), but it actually changes other objects even if the function returns false.
This got removed by accidet (checking if the object was added to another stack seemed logical). However, this whole function does not really make sense. It returns true if the object got removed only. That means that the object would not enter the other object anyway.
Removed the UpdateStackDisplay(), because that happens in TryAddToStack() if the count changes, anyway.
The part where the stack count is reduced behaves the same as DoStackCount(); The stack display is updated in SetStackCount()/DoStackCount() respectively, so that line can be removed.
Added parameter to 'GetFuelAmount' that specified how much fuel is requested from this object. Oil is now fuel and only the needed amount is removed instead of removing the entire stack when a producer requests fuel.
This was used inconsistently and without regard to correctness, so it is better removed altogether. In case of incomplete objects, the incomplete object always returns the reduced amount.
The liquid objects cannot be converted from one to another. The fuel object will be removed again, it does not make sense that "burnt fuel" can be transferred from one object to another.
Previously, sharing the logic made sense, because both objects used variables to store the liquid. Now, the liquid container stores liquid in an object - this is not desirable in the pump because it would create and remove objects for no good reason (only so that it has a virtual liquid storage) every time it pumps. Consequently, liquid objects cannot enter a pump anymore.
Unit test 3 still fails, because the functions are not runtime overloadable. Test 12 fails, because liquid transfer does not work correctly yet. This fill be fixed in the next checkin.
Added debug logging, this has to be removed again later.
The icons currently only show Xbox 360 controller labeling. The icon set
also includes icons for PlayStation controllers, so we could extend this
in the future.
This also removes the controller id from the control definitions,
instead defaulting to 0. This doesn't change anything for now as we only
had definitions for controller 0 anyways.
Unfortunately, now the object is not actually transferred, but removed, and a new one is created or an existing one is filled in the liquid container. The logic could use a rework actually, because everything was more clear when the container stored things in variables.
The special handling of the stackable library was moved from the interaction menu to that library. The reasoning behind this is that the menu should not have to know each and every object, but the objects should tell the menu how they are displayed.
Liquids are displayed by their liquid count now. It would be even better, if the max. capacity would be displayed without having to hover the description field.
The liquid container now stores liquid objects, instead of volume and liquid type. Liquid objects can have be of a specific type, such as Liquid_Water, Liquid_Oil, etc..., but they can also just stay Library_Liquid for other liquids.
The liquid container logic has become more complex now, but still works as before. Transferring liquids to other objects may still need some improvements:
- at the moment, transferring liquids between liquid containers is possible
- maybe liquids objects, such as oil, can enter a liquid container while another liquid is in that container already - will need a unit test for that
- transferring liquid from a liquid container to a structure or crew member should be possible (but is not yet), if the target is not a liquid container but contains liquid containers
The steam engine treats barrels the same as itself when it comes to extracting liquids. This removes the need for the callback OnFuelRemoved() in the barrel, as well as the stupid definition call from the barrel to the steam engine.
The steam engine can burn oil as fuel now. Added test to power system unit test. Still needs support for actually getting oil into the engine.
Fixed a bug in LiquidContainer that would return no liquid if the entire contents are removed. Added unit test for said bug.
Fixed overspilling of connected liquid containers. Pump no longer counts as a liquid container/tank, so that it still spills liquid if no drain is connected.
The steam engine does not remove the barrels, it just empties them. Made power system unit test 19 end if both pumps are pumping, this seems to be the intention of the unit test. Added power system unit test 20: Steam engine fueled by oil barrels.
Made the steam engine interface more modular, removing duplicate code. Added a callback when refilling fuel that allows the objects not to be removed. This is important for barrels, because barrels will just empty their contents, they should not vanish!
The pump actually stores liquid until it can pump. This may not be desired, but it was like that before my changes already. This probably is better than having it drop excess material at the pump.
The pump can transfer liquids to and from liquid containers now. Changed the material storage from material index to material name now, because liquid containers may contain fantasy liquids, too. The pipe cannot output such imaginary liquids though, so only transfer between compatible containers is possible.
The pipe can be connected from the interaction menu now, too. Expanded the disconnection logic, because more problems arise when the pipe can still be connected to other structures - it would be sufficient to remove the line, but that could be annoying:
- if the pipe is connected to a container, then you can disconnect the pipe from that liquid tank and it will still be connected to the pump
- if you disconnect the pipe from the pump, then it will disconnect from the liquid tank as well
Maybe this is confusing to the user, we can still kick that out later again.
Now it is possible to connect lines from a pump to the steam engine. This is achieved by the steam engine being a liquid tank. It did not seem good to allow connection from pumps to all liquid containers (i.e. barrels). A liquid tank is also a liquid container, they share the same interface, but it is also a structure.
It is not yet possible to fill the steam engine with any liquid though, because it is not defined what kind of liquid it accepts. This will be oil in the future. Furthermore, the behaviour when the pump adds incompatible liquid is not defined yet.
Added a new library for liquid containers that is based on the original barrel script.
Library_LiquidContainer
- Extracted the interface from the barrel. The function names and argument types are not final yet.
- Fixed an inconsistency in the script: There were two ways of determining whether a barrel is suited
for a material. Either by name, or material index.
- renamed argument names to "liquid_name" for liquids, "amount" for quantities, so that the code is more easily understandable
- replaced comparison 'fill level > 0' with 'is not empty?'
- moved storage variables to a local proplist, so that names do not clash
- Ordered the methods by application and documented each section
Barrel:
- The original barrel functions delegate to Library_LiquidContainer-functions now, so that the original functionality is not disturbed. Obsolete functions are marked with "TODO: deprecated".
- Moved barrel value change to the update function
- Moved hit sound effect to separate function
- Replaced uses of the magic number '3' with a runtime-overloadable call to GetBarrelIntakeY()
- Replaced comparison 'fill level > 0' with 'is not empty?'
MetalBarrel:
- Adjusted the hit function. The difference between this and the normal barrel is the hit sound and material position. These should be constants or functions, instead of magic numbers
- Moved hit sound effect to separate function
- Removed the Hit()-function, because the hit sound is played in a separate function now
- With this change the y-offset of the barrel checking for other liquids on a hit is now 3 instead of 7. This should be ok, because the barrels have the same dimensions, it seemed strange that they would have different offsets
With the SDL_GameController interface, buttons and axes have actual
names we can refer to. This also allows for advanced mappings using both
sticks (this probably needs script changes) as well as the triggers.
It is possible to set the amount of resources to be extracted with an additional parameter in SetResource() now. The default amount to be extracted is 95 percent, which is the same behaviour as before the changes.
Deciphered what some of the functions are good for, since the original code is kind of cryptic. This should help again when expanding to diggable materials.
The steam engine treats barrels the same as itself when it comes to extracting liquids. This removes the need for the callback OnFuelRemoved() in the barrel, as well as the stupid definition call from the barrel to the steam engine.
This messes up so many things as one could have expected. Instead we do the sensible thing and enable it only in the test scenario. For future reference all sequences involving an elevator and NPC clonks are broken with this feature.
The steam engine can burn oil as fuel now. Added test to power system unit test. Still needs support for actually getting oil into the engine.
Fixed a bug in LiquidContainer that would return no liquid if the entire contents are removed. Added unit test for said bug.
Fixed overspilling of connected liquid containers. Pump no longer counts as a liquid container/tank, so that it still spills liquid if no drain is connected.
The script now just sets visibility per player (VIS_Select) instead of creating one dummy object per player. It also uses the object directly instead of indirecting everything through an effect (the effect couldn't be used on other objects anyway).
The steam engine does not remove the barrels, it just empties them. Made power system unit test 19 end if both pumps are pumping, this seems to be the intention of the unit test. Added power system unit test 20: Steam engine fueled by oil barrels.
Made the steam engine interface more modular, removing duplicate code. Added a callback when refilling fuel that allows the objects not to be removed. This is important for barrels, because barrels will just empty their contents, they should not vanish!
..because the library wasn't actually USING the holding callback at all. And it had/has its own CON_Aim hackery anyway. No need for the control-library internal CON_Aim stuff then (I could imagine this might just lead to issues at some point).
Otherwise the situation could arise where you used a ControlUseStart object (the wallkit) but noholdingcallbacks was still set to true (because e.g. you used a hammer before). Then you would not be able to move the preview.
This is described in a comment to the referenced bug.
The pump actually stores liquid until it can pump. This may not be desired, but it was like that before my changes already. This probably is better than having it drop excess material at the pump.
The pump can transfer liquids to and from liquid containers now. Changed the material storage from material index to material name now, because liquid containers may contain fantasy liquids, too. The pipe cannot output such imaginary liquids though, so only transfer between compatible containers is possible.
The pipe can be connected from the interaction menu now, too. Expanded the disconnection logic, because more problems arise when the pipe can still be connected to other structures - it would be sufficient to remove the line, but that could be annoying:
- if the pipe is connected to a container, then you can disconnect the pipe from that liquid tank and it will still be connected to the pump
- if you disconnect the pipe from the pump, then it will disconnect from the liquid tank as well
Maybe this is confusing to the user, we can still kick that out later again.
Which means that you can
1) Drag around the tree / nest in editor mode
2) Shoot zapnests that were put into a catapult by a scenario designer
3) Can RemoveObject a tree and the nest will fall down (instead of keep floating)
4) Can put zap nests in earth (just like in CR!)
Now it is possible to connect lines from a pump to the steam engine. This is achieved by the steam engine being a liquid tank. It did not seem good to allow connection from pumps to all liquid containers (i.e. barrels). A liquid tank is also a liquid container, they share the same interface, but it is also a structure.
It is not yet possible to fill the steam engine with any liquid though, because it is not defined what kind of liquid it accepts. This will be oil in the future. Furthermore, the behaviour when the pump adds incompatible liquid is not defined yet.