Jump to content

How Soldiers get assigned a class


Amineri

Recommended Posts

This appears to be one of the great mysteries of the XCOM universe, and one that I noted has been getting a fair number of gripes on the main 2k forums.

 

I've poked around and the most relevant function that determines this is XGFacility_Barracks.PickAClass() -- there is another function called PickRewardSoldierClass that follows different rules.

 

So what are the rules for picking a new class?

 

1) Pick a random class that has never been generated (i.e. no barracks soldier of that class, and no memorial wall soldier of that class)

 

If every class has been generated at least once, then:

1) Pick a random class

a) If there are exactly 2 of this class in the Barracks, and another class has no members in the Barracks, pick the class with no members (if there is more than 1 such class, pick one of them at random)

b) If there are exactly 4 of this class in the Barracks, and another class has zero or one members in the Barracks, pick the class with zero or one members (if there is more than 1such class, pick one of them at random)

c) If (a) and (b) don't apply, the use the original random class

 

That is,

 

A class with 0 members will be picked before a class with 2 members

A class with 0 or 1 members will be picked before a class with 4 members

 

Clearly this has some weaknesses. Once a class has five members alive, there can be no preference for picking a class with fewer members. This is why you sometimes see the same class getting picked over and over. It's basically just bad luck, combined with no restriction to prevent it. And, since reward soldiers follow different rules for selection, it's possible to get a 5th soldier in a class via a reward, and still have none of another! Clearly Firaxis had some intention to prefer classes with fewer members, but the implentation is flawed.

 

It is possible to re-work this function slightly and remove the exact references to having 2 and 4 members. This would generate the following rules for picking a class.

 

A class with 0 members will be picked before a class with 1 member

A class with 1 member will be picked before a class with 2 or 3 members

A class with 2 members will be picked before a class with 4 or 5 members

A class with 3 members will be picked before a class with 6 or 7 members

A class with 4 members will be picked before a class with 8 or 9 members

etc

 

The count of members would be based on current alive members -- healthy, wounded and psi-training.

 

I'm kind of on the fence between implementing it this way, or via

 

A class with 0 members will be picked before a class with 1 or 2 member

A class with 1 member will be picked before a class with 3 or 4 members

A class with 2 members will be picked before a class with 5 or 6 members

A class with 3 members will be picked before a class with 7 or 8 members

A class with 4 members will be picked before a class with 9 or 10 members

etc

 

Maybe it's not really a big deal ... either one is an improvement (I think) over the original.

 

Anyone have any thoughts about this?

Link to comment
Share on other sites

  • Replies 45
  • Created
  • Last Reply

Top Posters In This Topic

Interesting... I think the key point here is, as you've mentioned, make it considers only alive soldier's classes, because sometimes it's harsh if you loose a couple of units of the same class in a row and get stuck without that class for a while. For the rest I think a +/- 2 count margin for classes is ok, so it's not 100% deterministic but it isn't completely random neither. +/- 2 I mean it won't give you the 3rd of a class if you've got none of certain other class, etc. Actualy the difference allowable could increase as soldiers count does, a la (num of soldiers of the less populated class) +1 or +2.

 

I'm not sure I understand option #2, does it mean you can get 2 of each but still have none of certain class? If so I think it's ok, 2*3=6, so at max with 7 units you'll get all classes, it seems ok. But then I wouldn't like to wait that much for the 2nd of that class. Anyway, I think the thing here is ensuring 2 units of each class at short-mid term, and let the rest come as it come, but still allowing some randomness assigning the first classes.

Link to comment
Share on other sites

Shouldn't 'availability for missions' be the tie-breaker before randomness? After all, if all of a particular class was either in the infirmary or Psi Training, I'd want the next recruit to be that class rather than one with the same number of healthy troops.

 

And if you are going to work out how to permit this, why not provide the means to set the assignment priority for those desiring it?

 

-Dubious-

Link to comment
Share on other sites

Shouldn't 'availability for missions' be the tie-breaker before randomness? After all, if all of a particular class was either in the infirmary or Psi Training, I'd want the next recruit to be that class rather than one with the same number of healthy troops.

 

And if you are going to work out how to permit this, why not provide the means to set the assignment priority for those desiring it?

 

-Dubious-

 

It is certainly possible to not count soldiers that are wounded / Psi Training. The current count includes any soldiers that "aren't dead". (At least, after the first one from each class).

 

I wish I could find a hook to allow the player to select the class based in the UI. But UI editting is still our bane. If I were to mess with a UI edit, I'd likely work on the ability to equip more than five items (I believe the behind-the-scenes array allows for up to 22 items to be equipped).

 

I don't see where there is any current weighting information in the generic "PickAClass" function. A class is initially picked via : chosenClass = arrClasses[Rand(arrClasses.Length)]

Then, any other class that is "enough below" that one will get priority. But if you have 8 Snipers, 3 Heavies, and 1 Support, and the game rolls Heavy, you'll get Heavy. Actually, the way the game is coded right now, in that situation if you were to roll Sniper you'd get Sniper.

 

It's a kind of glitchy system -- I suspect that it wasn't a high priority design.

Link to comment
Share on other sites

  • 3 months later...

I've been giving the possibilty for player to select class a bit thought and while I don't see any way to do it properly with a class selection UI, I do belive the second best alternative would be to repurpose the dismiss soldier button to become some sort of change class-button.

 

After doing some UE Explorer "surfing" it seems that what makes soldiers actually being dismissed is this function:

function DismissSoldier(int iSoldier)
{
  local XGStrategySoldier kSoldier;

  kSoldier = m_arrSoldiers[iSoldier];
  // End:0x57
  if(kSoldier.m_kSoldier.iPsiRank == 4)
  {
    return;
  }
  STORAGE().ReleaseLoadout(kSoldier);
  RemoveSoldier(kSoldier);
  kSoldier.Destroy();
  //return;  
}

Does anyone have any suggestions how one would go about modifying that function to do any of the following alternatives?

  • Replace the soldier with a new squaddie of random class
  • Replace the soldier with a rookie with enough XP to be promoted
  • Strip the soldier of all XP, ranks, perks, and gained stats effectively turning him/her into a brand new rookie.

The idea is also to make the button only available to squaddie rank or higher.

 

What the new name of the button would be is open to whatever solution is easiest to implement... Any number of narrative explanations is available. Officer exchange program, back to school, warranty replacement, brainwash, etc.

 

But the general idea is that the player should be able to press the button repeatedly until he/she ends up with a squaddie of the class he wants, thereby making it possible to select class indirectly and remove most of the usefullness of the dismiss button at the same time.

Link to comment
Share on other sites

I just did a test on the following code which work without problem.

function DismissSoldier(int iSoldier)
{
  local XGStrategySoldier kSoldier;
  kSoldier = m_arrSoldiers[iSoldier];
  STORAGE().ReleaseLoadout(kSoldier);
  RemoveSoldier(kSoldier);
  kSoldier.Destroy();
  AddNewSoldiers(1);
  //return;  
}

If I dismiss a soldier I instantly receive a new free rookie :tongue:

 

Adding a call to promote the last soldier in the barracks should be fairly simple... and with some luck not require more than the available 27 storage bytes.

Edited by Bertilsson
Link to comment
Share on other sites

After some additional thinking about I have now decided to attempt the following strategy:

  • Make PickAClass-function unused by replacing any (2) calls to it with rand(4) + 1
    • Makes it 25% chance for any class to be picked always.
  • Dismiss function repurposed
    • if rank > 0 //Save me the effort to disable the DISMISS-button for rookies.
      • Make soldier unique so that it can be found by PickAClass-function
      • Call PickAClass-function (I'll just pretend to be interested in the return value from it)
  • Repurpose PickAClass
    • Identify the unique soldier and assign it to a variable
      • kSoldier.iRank = 0 //In order to level up normally
      • kSoldier.iXP = 0 //Or possibly squaddie requirement
      • ClearPerks //Haven't figured out how to do that yet
      • RandomizeStats(kSoldier);
      • STORAGE().AutoEquip(kSoldier);
      • kSoldier.LevelUp()
    • Return a number that nobody cares about
  • Figure out how the .int files work so that I can rename the DISMISS-button and change the confirmation text, do you really want to change class for this soldier to a random class? Soldier will have all stats removed and lose any rank above squaddie.

Does this seem like a viable strategy in general?

Too powerfull? Would just replacing any soldier with a rookie that arrives in a few days be better?

Something missing?

Any ideas how to wipe all perks from a soldier?

 

Edit: Perphaps limiting the option to only squaddie with no perks is a better and simpler idea? And if there is room left to use dismiss any soldier that has different rank, to not lose any functionality...

Edited by Bertilsson
Link to comment
Share on other sites

This seems too powerful when combined with the NCE and Hidden Potential options (which a lot of players seem to prefer). It basically allows for easy re-rolling of the randomized starting stats for every soldier until you get the "perfect" super-soldier. I feel like you might as well just give every soldier the maximum possible randomized stats if this is added.

 

Even allowing a squadde to be replaced by a rookie wouldn't do too much good as once the OTS auto-promote upgrade is bought it again allows for easy churning of rookies until ones with the "perfect stats" are achieved.

Link to comment
Share on other sites

I guess an easy way to counter stat-milking would be to add a cost of ~ $2 for each use but I'm not very fond of that idea.

 

And since stats are very different between the classes I can't just let the soldier keep the original stats either.

 

And since the OTS auto-promote doesn't allow rookies to exist it also rules out using an item or any other kind of tag to select which class you want a rookie to become pro-actively...

 

I guess a really really convoluted way of doing it would be to make it possible to select in-game which class ALL rookies should be upgraded to... but bringing a bunch of rookies to a mission and returning with all squaddies of a single class before possibilty to change that setting would more or less defeat the purpose.

 

Need to rethink this...

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...