aliens

Author Topic: [Suggestion] More granular research roll and foundation for making it moddable  (Read 330 times)

Offline krakp

  • Captain
  • ***
  • Posts: 66
    • View Profile
While working on my research feature I noticed how the initial roll for a project is calculated in https://github.com/OpenXcom/OpenXcom/blob/master/src/Basescape/ResearchInfoState.cpp

Code: [Select]
ResearchInfoState::ResearchInfoState(Base *base, RuleResearch *rule) : _base(base), _project(new ResearchProject(rule, int(rule->getCost() * OpenXcom::RNG::generate(50, 150)/100))), _rule(rule)
{
buildUi();
}

Since we are only choosing from a 100 (or 101 to be exact) random values, the granularity of the roll will be a 100th of the Average cost. So e.g. for the Blaster Launcher project (average 900) you can get a roll of 900 or 909 but you will never get anything in between.

I improved this granularity (so that you can get every integer value from the possible range) by changing this function to this version:

Code: [Select]
ResearchInfoState::ResearchInfoState(Base *base, RuleResearch *rule) : _base(base), _project(nullptr), _rule(rule)
{
int randomizedCost = RNG::generate(rule->getMinCost(), rule->getMaxCost());

_project = new ResearchProject(rule, randomizedCost);

buildUi();
}

For this to work I introduced 2 very simple auxiliary functions in src\Mod\RuleResearch.cpp:

Code: [Select]

/**
 * Gets the minimum cost of this ResearchProject.
 * @return The minimum cost of this ResearchProject (in man/day).
 */
int RuleResearch::getMinCost() const
{
return (getCost() + 1) / 2; /// for integers -  (x+1)/2 is the same as ceiling(x/2).
}

/**
 * Gets the maximum cost of this ResearchProject.
 * @return The maximum cost of this ResearchProject (in man/day).
 */
int RuleResearch::getMaxCost() const
{
return ((getCost()) * 3 + 1) / 2; /// for integers -  (x*3+1)/2 is the same as ceiling(x*3/2).
}

Because of how I calculated the minimum (using a kind of manual ceiling function - see the comment in the code), I also directly address the issue that Meridian fixed in https://github.com/Xilmi/OpenXcom/commit/8d96b4092516399b7c57548a4c1412981d1a1443.

Both these changes are quite cosmetic, so you may think "why bother". What I was thinking though is that moving the Max and Min cost calculation to the ResearchRule (rather than having it around the UI generating code of the Basescape/ResearchInfoState) is first of all cleaner and secondly can enable, with very little effort, to actually modify the standard behaviour of rolling +/- 50%.

Imagine that in a mod you could not only define the average project time but also Max and Min. This way you could have some very well scoped projects (where both Max and Min are near to the Average) and some very random projects allowing for any roll range you can possibly come up with. With my changes, it would take quite little effort to have the getMinCost and getMaxCost actually refence some hardcoded values from the mod, as an option.

Would this be something useful / interesting? Cheers!