Page 1 of 2

How to add a variable to ships/parts?

Posted: Sat Jan 12, 2019 2:46 am
by Telos
I've been fiddling around with trying to script some of the organic ship changes I'd suggested in this old thread: https://freeorion.org/forum/viewtopic.p ... 69&p=87512

Currently, a ship's max structure is recalculated each turn from scratch, starting with hull structure, adding on effects of armor, reinforced hull tech, and, in the case of living organics, an organic growth bonus that is calculated by multiplying age by growth rate. Unfortunately, this doesn't allow much flexibility regarding how a ship's history might affect its growth, e.g., allowing higher structure for ships produced in a system with an appropriate building or star-color, faster growth for time spent near appropriately colored stars, or permanent injuries from heavy damage. It'd also be nice to have fairly similar functionality on a regenerative carapace ship-part, which ideally would gradually grow from scratch, be reduced by heavy ship damage, and would aid in rapid structure-regeneration just for damage to the carapace, but not to the rest of the ship.

The best way I can imagine to let a ship's history affect its max-structure in these ways is to store some information (e.g., a number representing the net impact of history on max-structure) with each ship, and/or with some part of it, as a variable that can be read and set. I've read through the scripting details guide, but haven't seen a way, within FOCS, to create arbitrary new variables or meters to have be stored with a ship or one of its parts. Is that possible?

In the case of parts, I could maybe kluge something that stores information in one of the part variables that is available to scripting, perhaps the "Capacity" variable used by armors. Am I right in thinking that armors' Capacity is *programmatically* added to max-structure? I can't find anywhere in the scripting files where this is explicitly added, in the way that Reinforced Hull and organic growth are both explicitly scripted to add to max-structure. To get this kluge to work, I'd need some variable whose value is retained from turn to turn (like a meter), and not some variable that reverts back to its default value every turn (like I fear Capacity may be).

In the case of ships, there is a readable variable Age. If this variable is modifiable, you could indirectly make a ship's history affect its max-structure by having it affect its Age: e.g., spending time around a yellow star might make an organic ship mature faster, or getting grievously injured could have the same effect as removing years of growth from its life. Is it possible to change a ship's "Age" in this way? (Probably not if Age is computed on demand by subtracting construction-turn from current-turn, unless construction-turn itself is over-writable.) And would overriding Age (or construction-turn) interfere with anything else that cares about it?

If I can't manually override a ship's Age, do ships have some other persisting variable that I could use to store relevant information instead?

Of course, if we can get this to work with parts, but not ships, then another kluge might be to force ships to have relevant parts, either by scripting addition of the relevant "part" to the ship (is that possible?) or else by practically forcing users to build some relevant part, e.g., an "organic heart" into relevant ships, so that part can then keep track of the fortunes and misfortunes that should cause lasting effects in a ship's size.

Re: How to add a variable to ships/parts?

Posted: Sat Jan 12, 2019 1:44 pm
by Ophiuchus
From the top of my head i think you can add specials to a ship. And that one can have a capacity.

Also ship parts have two capacities which are used for the standard effects (armor +hp, weapons +shots/damage, bay launch capacity, hangar capacity, troop count). Maybe there is now even a third capacity.

Re: How to add a variable to ships/parts?

Posted: Sat Jan 12, 2019 5:18 pm
by Geoff the Medio
As Ophiuchus suggests, it sounds like what you want to do could be accomplished by adding a special to the ship object, and tracking relevant info with the capacity of the special, and basing depending effects on that capacity. You'll need the SpecialCapacity complex-double-value-ref ( https://github.com/freeorion/freeorion/ ... r.cpp#L125 ) and the SetSpecialCapacity effect ( https://github.com/freeorion/freeorion/ ... 3.cpp#L107 ).

Capacity in various parts is used to generate effects that implement the basic function of that part type, unless NoDefaultCapacityEffect is specified in the part definition, eg. ( https://github.com/freeorion/freeorion/ ... ocs.txt#L6 ). The code that creates these effects is that is not specified is ( https://github.com/freeorion/freeorion/ ... n.cpp#L334 )

There is no SetAge effect.

Effects can't add parts to a design. Something weird with costs being calculated with a test for a part being in the design might work, but are not recommended.

Re: How to add a variable to ships/parts?

Posted: Sat Jan 12, 2019 8:49 pm
by Telos
Wow, I had no idea that ships even could have specials, nor that specials could have capacities. I don't think I've encountered either of those in-game. Is there an example of scripts doing this that I could look at?

When specials have capacities, are their values preserved from turn to turn, or do they reset to some default value each turn?

Lacking a good model to look at, I guess I'd need roughly the following steps to make organic ships grow more quickly in certain conditions?
  1. Add an effect to the relevant hulls that creates an "organic growth" special on the hull if it doesn't already have one, and sets the capacity of that special to 0.
  2. Add effects to the relevant hulls to detect various events that should make a ship grow more or less quickly (like being stationary near a yellow star), and make those cause changes in the special's capacity.
  3. Add an effect to the relevant hulls to add the special's capacity to the ship's max-structure in the recalculation of that max-structure each turn

Re: How to add a variable to ships/parts?

Posted: Sat Jan 12, 2019 11:32 pm
by Geoff the Medio
Telos wrote: Sat Jan 12, 2019 8:49 pmIs there an example of scripts doing this that I could look at?
I don't think so.
When specials have capacities, are their values preserved from turn to turn, or do they reset to some default value each turn?
If it's working as intended, yes. Might be buggy as the functionality isn't used much.
Add effects to the relevant hulls to detect various events
Or the special, depending how you want to organize things.

Re: How to add a variable to ships/parts?

Posted: Sun Jan 13, 2019 3:31 pm
by Jaumito
Something simple (I think) you might want to try to add flavor to the organic line: double their stealth rating (or add a flat bonus) when under 'Hide' orders.

Re: How to add a variable to ships/parts?

Posted: Sun Jan 13, 2019 4:08 pm
by Ophiuchus
Also note that there is a PartCapacity condition to query the capacity of a part "design" (note this value is not ship dependent) - this allows for variants of parts with similar effect. E.g. in https://github.com/agrrr3/freeorion/blo ... S.focs.txt

Re: How to add a variable to ships/parts?

Posted: Sun Jan 13, 2019 4:20 pm
by Ophiuchus
Jaumito wrote: Sun Jan 13, 2019 3:31 pm Something simple (I think) you might want to try to add flavor to the organic line: double their stealth rating (or add a flat bonus) when under 'Hide' orders.
I am not sure if that is so easy to balance, but I definitly would like to have a variant of that for (at least some of) the monsters

Re: How to add a variable to ships/parts?

Posted: Wed Jan 16, 2019 2:15 am
by Telos
Ophiuchus wrote: Sun Jan 13, 2019 4:08 pm Also note that there is a PartCapacity condition to query the capacity of a part "design" (note this value is not ship dependent)
Yes, the non-ship-dependence is a problem I've been running into. I can (I think) change the capacity of a part I put on the ship, but I don't seem to be able to read the new value of that part's capacity the next turn, which I need to do. Is there a ship-specific way to query the capacity of a part *on*this*ship*?

Re: How to add a variable to ships/parts?

Posted: Wed Jan 16, 2019 8:43 am
by Ophiuchus
Telos wrote: Wed Jan 16, 2019 2:15 am
Ophiuchus wrote: Sun Jan 13, 2019 4:08 pm Also note that there is a PartCapacity condition to query the capacity of a part "design" (note this value is not ship dependent)
Yes, the non-ship-dependence is a problem I've been running into. I can (I think) change the capacity of a part I put on the ship, but I don't seem to be able to read the new value of that part's capacity the next turn, which I need to do. Is there a ship-specific way to query the capacity of a part *on*this*ship*?
There is no such thing as a capacity of a part *on*this*ship*. The PartCapacity belongs to the parts design not to the ship.

But like in my example you can make variants of a part with different capacities. This only makes sense if there is a small number of different fixed capacities.
In the example i linked i had supply parts in two different sizes.

PartCapacity is a constant for a part.

For variables on ships use specials.

Re: How to add a variable to ships/parts?

Posted: Wed Jan 16, 2019 5:37 pm
by Telos
Ophiuchus wrote: Wed Jan 16, 2019 8:43 am There is no such thing as a capacity of a part *on*this*ship*. The PartCapacity belongs to the parts design not to the ship.
Well, it certainly *seems* like there is such a thing as a capacity for a part (or at least a part-type) on a particular ship. E.g., if you look in the FOCS for Solar Concentrator, it includes effects like the following:

Code: Select all

            effects = [
                SetMaxCapacity partname = "SR_WEAPON_2_1" value = Value + [[SOLAR_CONCENTRATOR_EFFECT]]
                SetCapacity partname = "SR_WEAPON_2_1" value = Value + [[SOLAR_CONCENTRATOR_EFFECT]]
            ]
This doesn't make sense if you read it as changing the Capacity for *all* lasers -- Solar Concentrators don't help every laser in existence! Instead it only makes sense if it affects the capacity of just the lasers on this one particular ship.

Re: How to add a variable to ships/parts?

Posted: Thu Jan 17, 2019 9:57 am
by Geoff the Medio
Ships have meters for (unique) part types in their design. There are effects to set those meters, such capacity and max capacity (which are actually the same meters as damage and max damage), and secondary stat and max secondary stat.

https://github.com/freeorion/freeorion/ ... cs.txt#L54
https://github.com/freeorion/freeorion/ ... cs.txt#L45
https://github.com/freeorion/freeorion/ ... cs.txt#L26

Which meters a ship will have for a particular part depend on the type of that part... so weapons get a capacity/damage and secondary stat (shots per round of combat). Most other parts have nothing, or just have a capacity and max capacity meter. You can see what meters a ship has by right-clicking it in the objects list, and running the debug data dump, and then looking in the chat. At the end should be something like:

Code: Select all

part meters: SR_WEAPON_1_1 METER_MAX_CAPACITY: 4  SR_WEAPON_1_1 METER_MAX_SECONDARY_STAT: 1  SR_WEAPON_1_1 METER_CAPACITY: 4  SR_WEAPON_1_1 METER_SECONDARY_STAT: 1
The values of these meters are (more or less) determined by effects that set them, some of which originate in the corresponding ship part, based on the scripted part stats like capacity:
https://github.com/freeorion/freeorion/ ... n.cpp#L352

These meters generally already have a purpose related to the function of the corresponding part, though, so for a custom scripting situation that isn't consistent with standard part function for that class of part, using a special capacity might be a better approach.

Re: How to add a variable to ships/parts?

Posted: Thu Jan 17, 2019 11:54 pm
by Telos
It feels inefficient and needlessly convoluted to create a separate special to keep track of a changing capacity for a (type of) ship part on a particular ship, when (types of) ship parts already do have capacities and max-capacities for each ship. We can already use NoDefaultCapacityEffect to override the default effect, so there shouldn't need to be a problem with having a part that doesn't quite fit a standard function. It seems like most of this is there already. As far as I can tell, the biggest hurdle blocking scripters from making flexible use of part capacities is just that we don't have a ship-specific way of querying the current capacity of a part on that ship -- instead we just get whatever is defined as the default capacity for that part for all ships -- so if you use NoDefaultCapacityEffect, then there's no way to query the changing capacity to actually make it *do* anything. It would be awesome if there was something like CurrentCapacity partname = "FOO" ship = ID (where the optional ship parameter would default to either Target or to Source, if Target is not a ship).

If I do do the work-around with adding specials, what are the best practices for where I would script the specials? Do they need to be defined in their own file(s) in the Specials directory? Or could (and if so *should*) they be scripted in the very same file as the shippart for which they serve as a capacity?

Re: How to add a variable to ships/parts?

Posted: Fri Jan 18, 2019 11:02 am
by Geoff the Medio
Telos wrote: Thu Jan 17, 2019 11:54 pmAs far as I can tell, the biggest hurdle blocking scripters from making flexible use of part capacities is just that we don't have a ship-specific way of querying the current capacity of a part on that ship...
The (apparent) lack of a way to access ship part meter values in FOCS is an oversight / unimplemented feature.

Re: How to add a variable to ships/parts?

Posted: Fri Jan 18, 2019 11:25 am
by Oberlus
Geoff the Medio wrote: Fri Jan 18, 2019 11:02 amThe (apparent) lack of a way to access ship part meter values in FOCS is an oversight / unimplemented feature.
I think that is more than understandable. Designs are never (can't be) perfect from the beginning.
Telos wrote: Thu Jan 17, 2019 11:54 pmAs far as I can tell, the biggest hurdle blocking scripters from making flexible use of part capacities is just that we don't have a ship-specific way of querying the current capacity of a part on that ship...
I think that is worth the effort to make a new step forward and make a complete design of this and other possible features that FOCS could benefit from and (at least) open a properly documented issue with the corresponding request on github, so that this can be tackled in the future by someone with the skills and time to improve the C++ code that would make it possible.
But we can't expect that current developers do it (the design and documentation) because they are already swamped in work, with many features still lacking that are more important/urgent/relevant to get to a version of FreeOrion closer to its intended final form (for example, improving the AI and implementing Government and Influence).