Excruciating FOCS doubts
Moderators: Oberlus, Committer
Re: Excruciating FOCS doubts
LienRag, maybe you could google what is a ValueRef (reference to a value), and look at the Eval() function of FreeOrion's C++ code.
You can't expect FreeOrion developers or forum users to teach you programming basics. That's on you, but there are plenty of resources on Internet available to you.
You can't expect FreeOrion developers or forum users to teach you programming basics. That's on you, but there are plenty of resources on Internet available to you.
- Geoff the Medio
- Programming, Design, Admin
- Posts: 13587
- Joined: Wed Oct 08, 2003 1:33 am
- Location: Munich
Re: Excruciating FOCS doubts
Consider:LienRag wrote: ↑Thu May 20, 2021 6:48 pm...this part would probably need more explaining, with examples and probably a diagram (of a few ones).Geoff the Medio wrote: ↑Wed May 19, 2021 10:42 pm Within the script for the condition, you can refer to the RootCandidate object, which is an object that the outer condition is considering matching (ie. one of the ships). You can also refer to the LocalCandidate object, which changes depending where you refer to it. If in the outer condition part of the script, it will be the same as the RootCandidate. Within the inner condition (matching planets) part of the script, it will be the object that the inner condition is considering matching.
Code: Select all
scope = And [
Ship
EmpireHasAdoptedPolicy empire = LocalCandidate.Owner name = "PLC_ALLIED_REPAIR"
WithinStarlaneJumps jumps = RootCandidate.Fuel condition = And [
Planet
OwnedBy empire = Source.Owner
Species name = RootCandidate.Species
Population low = 1 high = LocalCandidate.TargetPopulation - 1
]
]
The "top level" or "outer" condition is and And condition, which matches objects only if the object matches all of its subconditions. The subconditions are tested in order, so in this example, only objects that are ships have their owner's adopted policies checked, and only those that pass that have their jump distances to planets checked.
The WithinStarlaneJumps condition has another layer of an inner or subcondition, which is also an And condition with several parts that are tested in order. But the objects that are tested or match the inner And are not the same objects that are tested or match the outer-most condition or the WithinStarlaneJumps condition.
RootCandidate always refers to an object being tested by the And condition because it is the outermost condition. When the tested root candidate object changes, so will the object that RootCandidate refers to.
LocalCandidate refers to the object being matched by the inner-most condition at the place it is written.
In jumps = RootCandidate.Fuel or empire = LocalCandidate.Owner, the root candidate and the local candidate are the same object, so those object reference could be switched with no change in the results.
Within Species name = RootCandidate.Species, the root candidate and local candidate are different objects. RootCandidate still refers to a ship being tested by the outer And and WithinStarlaneJumps conditions, but in that part of the script, LocalCandidate refers to a planet being tested by the inner And condition. RootCandidate will change for each outer condition candidate that is tested, while LocalCandidate will change for each inner condition candidate that is tested.
In order to evaluate whether the root candidate is matched by the WithinStarlaneJumps condition, a separate test on an independent set of candidate objects is evaluated. When the engine reaches the WithinStarlaneJumps condition, it first evaluates the inner condition, and then uses that result of the inner condition to run the test on the object it is actually matching. In this case, first it has to determine which planets are matched by the inner condition, and then it can check whether the ship it is testing is within some distance of one of those planets.
Based on this and your earlier example of how you thought a Python-scripted condition would be written, you're thinking of these scripts as if they are procedural code, with a series of commands that are executed in order like an interpreted Python program. This is not the right mental model. Rather, these scripts are defining an expression tree or data structure that tells the program what the result should be.Secondly, the first assignment (effects = something) is logically not the same thing than the second (something = value + 40)¹; in a way they're nested assignments if I understand correctly.
It's the difference between "create a condition that matches the terran planets with no population" and
Code: Select all
def TerranUnpopulated(candidates):
matches = []
for candidate in candidates:
if IsPlanet(candidate):
if candidate.population > 0:
matches.append(candidate)
return matches
Code: Select all
a = 5 + 10
Code: Select all
VaribleAssignment name = "a" value = (PerformMathOperation operator = Plus lhs = 5 rhs = 10)
Code: Select all
VaribleAssignment name = "a" value = 5 + 10
Code: Select all
AssignToA value = 5 + 10
But again, a key conceptual problem might be that "value = 5 + 10" is not an assignment. Rather, "AssignToA" creates an assignment effect, and "value = 5 + 10" specifies how to calculate what to assign to A when the effect is executed.
Re: Excruciating FOCS doubts
Yes, agreed. Documentation and IDE support could be a solution here.LienRag wrote: ↑Thu May 20, 2021 7:01 pmif the FreeOrion team wants to have user-generated content, it certainly shouldn't need mastery of C++.Ophiuchus wrote: ↑Thu May 20, 2021 12:09 pm Maybe it helps to remember that conditions, effects, valuerefs (which could look like object properties to you) are evaluated at runtime on the server. This is done as Eval() calls on cpp objects and never via python. If the python scripting will allow more to do than the current FOCS that will still spit out that c structures in the end, subject to the way the server evaluates those - and python has no direct access to runtime object.
Anyway, the point was that you need to understand how evaluation works conceptually in order to grok scripting.
That there are four basic different kinds of things you can actually script, simple values (e.g. buildturns), conditions (e.g. scope), effects (in a effect group), and valuerefs (calculations). These are used to construct the bigger structures (e.g. a type of ship hull). And that the evaluation happens on this structures on the server and never inside the scripting language. The only processing happening before such structures get created is macro expansion (i.e. substituting characters/text snippets), so also a simple calculation of e.g. 1+1 happens later at runtime in c++.
Conditions work similar to select clauses in SQL, not like working on objects on python. At runtime, when a condition is evaluated it gets passed a set of objects (in scope that is usually the whole universe and in combatTargets it is the objects in the combat in that system that turn). You can then filter that set to have only the objects you want to base your effects on. Each candidate which is left in the topmost condition in a scope become the Target for effect evaluation.
Yes, also. More importantly, the result of a condition is a set of such objects (and nothing else). Also Source, Target, *Candidate is such an object.
There is no object for e.g. a ship part. That is why there is an effect changing meters of a part of a given ship instead of an effect changing the meter of a given ship part. Also the way it is done means that all parts of the same part name share the meters (e.g. you cant modify the damage of multiple mass drivers in a ship separately).
The result of a valueref can also be an integer, a float, a string, a PlanetType,.. value and it can be used as input for a condition or an effect.
Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.
Look, ma... four combat bouts!
Look, ma... four combat bouts!
Re: Excruciating FOCS doubts
OK, thanks for your replies.
I will need some time to digest all that...
I will need some time to digest all that...
Re: Excruciating FOCS doubts
Apart from that, I'm not sure to understand the FOCS code of the Ancient Ruins ?
The various possible results of Excavation are, for the first three, coded that way :
Then the two others are coded that way :
Note the lack of "Activation = random probability = 0.n "
And the choice of Extinct Species is coded that way :
So, for Extinct Species, we have a 75% chance of getting any Extinct Species at all.
Then depending on a "dice roll", we have a one on three chance to get Banforo. Then we have a coin toss that decides whether we get Kilandow or Misioria. Since we have a coin toss on the 67% probability left, it means the three Extinct Species are equiprobable.
Also, there are no conditions for these opportunities (except of course Xenoarcheology). Which means that a player can discover many times Banforo remains, for example.
For the other goodies, the choice between them is made differently.
If I understand correctly, the reason why the "if-else" structure is not necessary there is because of the stackinggroup "ANCIENT_RUINS_TECH_UNLOCK" ?
For these goodies, we have 20 % probability to get a Dragon Tooth.
Then a 25 % probability to get a Neutronium Synthetizer.
Then a 50 % probability to get Death Rays.
Then a 100 % probability to get Multi-Spectral Shields.
Then a 100 % probability to get a Krill Spawner.
In the FOCS scripting detail it's written that "Multiple effects scripted into the same item will be evaluated in the order in which they appear. "
So, for the first Ancient Ruin excavation, there is a 20 % chance to get a Dragon Tooth, a 20 % (0,25*0,80) chance to get Neutronium Synthetizer, a 30 % (0,5*0,6) chance to get Death Rays, a 30 % chance to get MSS, and 0% chance to get Krill Spawner.
Am I correct ?
Why allow Krill Spawners only if MSS has already been discovered ?
Also, I don't want to bother calculating the matrix of probabilities for second excavations depending on what has been discovered in the first one, but it's clear that DT chance doesn't change while MSS chances rise with each discovery.
Is that intended ? Why ?
The various possible results of Excavation are, for the first three, coded that way :
Code: Select all
EffectsGroup
scope = Source
activation = And [
Random probability = .2
OwnerHasTech name = "LRN_XENOARCH"
]
stackinggroup = "ANCIENT_RUINS_TECH_UNLOCK"
effects = [
CreateShip designname = "SD_DRAGON_TOOTH" empire = Source.Owner species = Source.Species
GenerateSitRepMessage
message = "EFFECT_ANCIENT_SHIP"
label = "EFFECT_ANCIENT_SHIP_LABEL"
icon = "icons/specials_huge/ancient_ruins_excavated.png"
parameters = [
tag = "planet" data = Source.ID
tag = "predefinedshipdesign" data = "SD_DRAGON_TOOTH"
]
empire = Source.Owner
GenerateSitRepMessage
message = "EFFECT_ANCIENT_SHIP_RUMORS"
label = "EFFECT_ANCIENT_SHIP_RUMORS_LABEL"
icon = "icons/specials_huge/ancient_ruins_excavated.png"
parameters = [
tag = "predefinedshipdesign" data = "SD_DRAGON_TOOTH"
]
]
EffectsGroup
scope = Source
activation = And [
Random probability = 0.25
OwnerHasTech name = "LRN_XENOARCH"
]
stackinggroup = "ANCIENT_RUINS_TECH_UNLOCK"
effects = [
CreateBuilding type = "BLD_NEUTRONIUM_SYNTH"
GenerateSitRepMessage
message = "EFFECT_ANCIENT_BUILDING"
label = "EFFECT_ANCIENT_BUILDING_LABEL"
icon = "icons/specials_huge/ancient_ruins_excavated.png"
parameters = [
tag = "planet" data = Source.ID
tag = "buildingtype" data = "BLD_NEUTRONIUM_SYNTH"
]
empire = Source.Owner
GenerateSitRepMessage
message = "EFFECT_ANCIENT_BUILDING_RUMORS"
label = "EFFECT_ANCIENT_BUILDING_RUMORS_LABEL"
icon = "icons/specials_huge/ancient_ruins_excavated.png"
parameters = [
tag = "buildingtype" data = "BLD_NEUTRONIUM_SYNTH"
]
]
EffectsGroup
scope = Source
activation = And [
Random probability = 0.50
NotOwnerHasTech name = "SHP_WEAPON_4_1"
OwnerHasTech name = "LRN_XENOARCH"
]
stackinggroup = "ANCIENT_RUINS_TECH_UNLOCK"
effects = [
GiveEmpireTech name = "SHP_WEAPON_4_1" empire = Target.Owner
GenerateSitRepMessage
message = "EFFECT_ANCIENT_TECH"
label = "EFFECT_ANCIENT_TECH_LABEL"
icon = "icons/specials_huge/ancient_ruins_excavated.png"
parameters = [
tag = "planet" data = Source.ID
tag = "tech" data = "SHP_WEAPON_4_1"
]
empire = Source.Owner
GenerateSitRepMessage
message = "EFFECT_ANCIENT_TECH_RUMORS"
label = "EFFECT_ANCIENT_TECH_RUMORS_LABEL"
icon = "icons/specials_huge/ancient_ruins_excavated.png"
parameters = [
tag = "tech" data = "SHP_WEAPON_4_1"
]
]
Code: Select all
EffectsGroup
scope = Source
activation = And [
Not OwnerHasTech name = "SHP_MULTISPEC_SHIELD"
OwnerHasTech name = "LRN_XENOARCH"
]
stackinggroup = "ANCIENT_RUINS_TECH_UNLOCK"
effects = [
GiveEmpireTech name = "SHP_MULTISPEC_SHIELD" empire = Target.Owner
GenerateSitRepMessage
message = "EFFECT_ANCIENT_TECH"
label = "EFFECT_ANCIENT_TECH_LABEL"
icon = "icons/specials_huge/ancient_ruins_excavated.png"
parameters = [
tag = "planet" data = Source.ID
tag = "tech" data = "SHP_MULTISPEC_SHIELD"
]
empire = Source.Owner
GenerateSitRepMessage
message = "EFFECT_ANCIENT_TECH_RUMORS"
label = "EFFECT_ANCIENT_TECH_RUMORS_LABEL"
icon = "icons/specials_huge/ancient_ruins_excavated.png"
parameters = [
tag = "tech" data = "SHP_MULTISPEC_SHIELD"
]
]
EffectsGroup
scope = Source
activation = And [
Not OwnerHasTech name = "SHP_KRILL_SPAWN"
OwnerHasTech name = "LRN_XENOARCH"
]
stackinggroup = "ANCIENT_RUINS_TECH_UNLOCK"
effects = [
GiveEmpireTech name = "SHP_KRILL_SPAWN" empire = Target.Owner
GenerateSitRepMessage
message = "EFFECT_ANCIENT_TECH"
label = "EFFECT_ANCIENT_TECH_LABEL"
icon = "icons/specials_huge/ancient_ruins_excavated.png"
parameters = [
tag = "planet" data = Source.ID
tag = "tech" data = "SHP_KRILL_SPAWN"
]
empire = Source.Owner
GenerateSitRepMessage
message = "EFFECT_ANCIENT_TECH_RUMORS"
label = "EFFECT_ANCIENT_TECH_RUMORS_LABEL"
icon = "icons/specials_huge/ancient_ruins_excavated.png"
parameters = [
tag = "tech" data = "SHP_KRILL_SPAWN"
]
]
And the choice of Extinct Species is coded that way :
Code: Select all
// Find extinct species
EffectsGroup
scope = Source
activation = And [
Random probability = 0.75
OwnerHasTech name = "LRN_XENOARCH"
]
effects = [
If condition = Random probability = 0.33
effects = [
AddSpecial name = "EXTINCT_BANFORO_SPECIAL"
GenerateSitRepMessage
message = "EFFECT_ANCIENT_EXTINCT_SPECIES"
label = "EFFECT_ANCIENT_EXTINCT_SPECIES_LABEL"
icon = "icons/specials_huge/extinct_banforo.png"
parameters = [
tag = "planet" data = Source.ID
tag = "species" data = "SP_BANFORO"
]
empire = Source.Owner
GenerateSitRepMessage
message = "EFFECT_ANCIENT_EXTINCT_SPECIES_RUMORS"
label = "EFFECT_ANCIENT_EXTINCT_SPECIES_RUMORS_LABEL"
icon = "icons/specials_huge/extinct_banforo.png"
parameters = [
tag = "species" data = "SP_BANFORO"
]
]
else = If condition = Random probability = 0.5
effects = [
AddSpecial name = "EXTINCT_KILANDOW_SPECIAL"
GenerateSitRepMessage
message = "EFFECT_ANCIENT_EXTINCT_SPECIES"
label = "EFFECT_ANCIENT_EXTINCT_SPECIES_LABEL"
icon = "icons/specials_huge/extinct_kilandow.png"
parameters = [
tag = "planet" data = Source.ID
tag = "species" data = "SP_KILANDOW"
]
empire = Source.Owner
GenerateSitRepMessage
message = "EFFECT_ANCIENT_EXTINCT_SPECIES_RUMORS"
label = "EFFECT_ANCIENT_EXTINCT_SPECIES_RUMORS_LABEL"
icon = "icons/specials_huge/extinct_kilandow.png"
parameters = [
tag = "species" data = "SP_KILANDOW"
]
]
else = [
AddSpecial name = "EXTINCT_MISIORLA_SPECIAL"
GenerateSitRepMessage
message = "EFFECT_ANCIENT_EXTINCT_SPECIES"
label = "EFFECT_ANCIENT_EXTINCT_SPECIES_LABEL"
icon = "icons/specials_huge/extinct_misiorla.png"
parameters = [
tag = "planet" data = Source.ID
tag = "species" data = "SP_MISIORLA"
]
empire = Source.Owner
GenerateSitRepMessage
message = "EFFECT_ANCIENT_EXTINCT_SPECIES_RUMORS"
label = "EFFECT_ANCIENT_EXTINCT_SPECIES_RUMORS_LABEL"
icon = "icons/specials_huge/extinct_misiorla.png"
parameters = [
tag = "species" data = "SP_MISIORLA"
]
]
]
Then depending on a "dice roll", we have a one on three chance to get Banforo. Then we have a coin toss that decides whether we get Kilandow or Misioria. Since we have a coin toss on the 67% probability left, it means the three Extinct Species are equiprobable.
Also, there are no conditions for these opportunities (except of course Xenoarcheology). Which means that a player can discover many times Banforo remains, for example.
For the other goodies, the choice between them is made differently.
If I understand correctly, the reason why the "if-else" structure is not necessary there is because of the stackinggroup "ANCIENT_RUINS_TECH_UNLOCK" ?
For these goodies, we have 20 % probability to get a Dragon Tooth.
Then a 25 % probability to get a Neutronium Synthetizer.
Then a 50 % probability to get Death Rays.
Then a 100 % probability to get Multi-Spectral Shields.
Then a 100 % probability to get a Krill Spawner.
In the FOCS scripting detail it's written that "Multiple effects scripted into the same item will be evaluated in the order in which they appear. "
So, for the first Ancient Ruin excavation, there is a 20 % chance to get a Dragon Tooth, a 20 % (0,25*0,80) chance to get Neutronium Synthetizer, a 30 % (0,5*0,6) chance to get Death Rays, a 30 % chance to get MSS, and 0% chance to get Krill Spawner.
Am I correct ?
Why allow Krill Spawners only if MSS has already been discovered ?
Also, I don't want to bother calculating the matrix of probabilities for second excavations depending on what has been discovered in the first one, but it's clear that DT chance doesn't change while MSS chances rise with each discovery.
Is that intended ? Why ?
Re: Excruciating FOCS doubts
On an unrelated topic, why is the code for the Luxuries macro indicates "Planet = not Source" for the Stability bonus part ?
Also I think that I finally understand this line¹ (partially thanks to previous explanations about SQL anology) : (SpeciesContentOpinion species = LocalCandidate.Species name = ThisSpecial > 0)
But how do you expect such a syntax to be understandable by a laygamer ?
¹ I mean, I don't know what SpeciesContentOpinion is, but that is a problem of documentation, not syntax.
Code: Select all
SPECIAL_INFLUENCE_RESOURCE_EXPORT
'''
// influence specials on a planet set to influence focus generate influence on that planet, regardless of species
EffectsGroup
scope = Source
activation = And [
OwnedBy affiliation = AnyEmpire
Focus type = "FOCUS_INFLUENCE"
]
effects =
SetTargetInfluence value = Value + 3
// stability bonus to connected planets that like this special when running capital markets
EffectsGroup
scope = And [
Planet
Not Source
Population low = 0.001
(SpeciesContentOpinion species = LocalCandidate.Species name = ThisSpecial > 0)
ResourceSupplyConnected empire = Source.Owner condition = Source
// TODO: check for other empires with border checkpoints or free trade or somesuch...
]
activation = And [
OwnedBy affiliation = AnyEmpire
Focus type = "FOCUS_INFLUENCE"
EmpireHasAdoptedPolicy empire = Source.Owner name = "PLC_CAPITAL_MARKETS"
]
stackinggroup = "@1@_STACK"
accountinglabel = "@1@_IMPORTS"
effects = SetTargetHappiness value = Value + 1
'''
But how do you expect such a syntax to be understandable by a laygamer ?
¹ I mean, I don't know what SpeciesContentOpinion is, but that is a problem of documentation, not syntax.
Re: Excruciating FOCS doubts
It's
Code: Select all
Planet
Not Source
Maybe they don't expect such thing.Also I think that I finally understand this line¹ (partially thanks to previous explanations about SQL anology) : (SpeciesContentOpinion species = LocalCandidate.Species name = ThisSpecial > 0)
But how do you expect such a syntax to be understandable by a laygamer ?
- Geoff the Medio
- Programming, Design, Admin
- Posts: 13587
- Joined: Wed Oct 08, 2003 1:33 am
- Location: Munich
Re: Excruciating FOCS doubts
There are several levels of how to answer that...Oberlus wrote: ↑Wed May 26, 2021 6:11 pmMaybe they don't expect such thing.Also I think that I finally understand this line¹ (partially thanks to previous explanations about SQL anology) : (SpeciesContentOpinion species = LocalCandidate.Species name = ThisSpecial > 0)
But how do you expect such a syntax to be understandable by a laygamer ?
1) Regardless of the syntax of how it's specified, be that FOCS or Python or C++, making complicated nested logic for how game content functions is essentially scripting or programming an algorithm. That's something some people can do fairly easily, some people can learn to do with some difficulty, and some people can't or won't do.
2) If you understand how FOCS effects and conditions are structured, the syntax of that line shouldn't be difficult to understand, and from the names of the stuff used in the script, the gameplay relevance should be reasonably clear or easy to guess for most of it.
3) There's a comment right before that in the macro that specifies what this bit of script is doing: // stability bonus to connected planets that like this special when running capital markets. Indeed, that line is checking what the opinion of a species is about the special to which this macro is added. If it's > 0, they like it. If it's < 0, they dislike it.
Re: Excruciating FOCS doubts
Oh, OK, makes sense, thanks.Oberlus wrote: ↑Wed May 26, 2021 6:11 pm It'sThat mean: that is a planet, that is not source. Source already has the bonus from the luxury special in the planet.Code: Select all
Planet Not Source
Re: Excruciating FOCS doubts
As someone with only a little experience coding but some experience code diving and hacking, you search for it. You do a search through the code for where it is used elsewhere. You find things that are similar to what you want to do and work out how to modify it. You watch the commit log to learn how things are done. If I wanted to learn how to add a new meter such as influence/production/etc. that would be hard. However influence was recently added. The code is open source. There's a whole bunch of recent commits adding influence to the game that I can look at, follow and try and learn how a new meter is added to the game. You follow the examples of the more experienced coders working on the game. When you report a bug you watch the commit history and see the fix. You watch, you look, you learn. You modify, you test, you f' up, you correct.LienRag wrote: ↑Wed May 26, 2021 6:06 pm Also I think that I finally understand this line¹ (partially thanks to previous explanations about SQL anology) : (SpeciesContentOpinion species = LocalCandidate.Species name = ThisSpecial > 0)
But how do you expect such a syntax to be understandable by a laygamer ?
¹ I mean, I don't know what SpeciesContentOpinion is, but that is a problem of documentation, not syntax.
Re: Excruciating FOCS doubts
Is there a way in FOCS to query the total anti-planet damage of a set of ships (e.g. owned/allied warships in system)?
If not, can I expect it to be implemented before 0.5?
If not, can I expect it to be implemented before 0.5?
- Geoff the Medio
- Programming, Design, Admin
- Posts: 13587
- Joined: Wed Oct 08, 2003 1:33 am
- Location: Munich
Re: Excruciating FOCS doubts
If you can script a number that calculates the total anti-planet damage of a single ship and a condition that selects the ships of interest, then yes: Use Statistic Sum as specify the single ship calculation as the value = parameter.
Re: Excruciating FOCS doubts
With the master as for all cases to be correct, you need to take targeting manually into account (e.g. exclude flaks, strikers, interceptors), and do something funky for heavy bombers and the monster weapons.Geoff the Medio wrote: ↑Sat Jun 05, 2021 3:34 pmIf you can script a number that calculates the total anti-planet damage of a single ship and a condition that selects the ships of interest, then yes: Use Statistic Sum as specify the single ship calculation as the value = parameter.
You could use XXX.DamageStructurePerBattleMax valueref for getting the correct maximum damage against a ship. Still one would need to filter for only weapon/hangar parts which target planets.
Should we also provide a XXX.DamagePlanetPerBattleMax valueref or a generic one taking an object ID; e.g.
Code: Select all
DamagePerBattleMax ship = Source.ID target = LocalCandidate.ID
Also for your case - what damage model (especially) for heavy bombers would you want to use - is maximum battle damage the right one?
Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.
Look, ma... four combat bouts!
Look, ma... four combat bouts!
Re: Excruciating FOCS doubts
In my case, I was thinking on the Terror Suppression policy, that gives a bonus to stability from each warship in system. Since it gives all importance to #ships, 4 old frigates with 1 MD each would be producing much more stability than a huge Titan with plenty of Death Rays. Both for gameplay and for lore (think about it: "DEATH RAY", that should scare the shit out of people, much more than "mass driver"), I'd like the effect to be based on damage (or cost of the weapon parts) and not on number of ships.
Re: Excruciating FOCS doubts
That would make terror suppression cheaper and cheaper as you upgrade weapon tech. Using old vessels for terror suppression sounds ok to me.Oberlus wrote: ↑Sun Jun 06, 2021 9:50 am In my case, I was thinking on the Terror Suppression policy, that gives a bonus to stability from each warship in system. Since it gives all importance to #ships, 4 old frigates with 1 MD each would be producing much more stability than a huge Titan with plenty of Death Rays. Both for gameplay and for lore (think about it: "DEATH RAY", that should scare the shit out of people, much more than "mass driver"), I'd like the effect to be based on damage (or cost of the weapon parts) and not on number of ships.
Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.
Look, ma... four combat bouts!
Look, ma... four combat bouts!