Type-Enhancement
What steps will reproduce the problem?
1. Create human character.
2. Change classes.
3. Advance beyond old class level.
What is the expected output? What do you see instead?
In AD&D 1st Ed the Dual class is implicitly meant for maximum two classes.
In AD&D 2nd Ed this restriction is lifted.
In Curse, the Human Change Classes does not appear if you have an old class
already. In Secret and POD the menu item is there but says the character
"does not qualify".
There are two possible enhancements here:
A) Make the menu item appear and provide appropriate message if the
character does not qualify (e.g. not human, already changed class, level
insufficient, primary attributes insufficient, etc... don't know if there
are more).
B) Make the game behave like AD&D 2Ed in this aspect, i.e. allow multiple
changes.
What version of the product are you using? On what operating system?
1.0.20 on Win XP
Please provide any additional information below.
References are from SVN dated 11 Sep 2009.
Notes marked with //S:
A) seems like transferring condition checks from here:
ovr018.cs, line 89:
if ((gbl.area2_ptr.training_class_mask > 0 ||
Cheats.free_training == true) &&
ovr026.IsHuman(gbl.player_ptr) &&
ovr026.HumanFirstOldClass_Unknown(gbl.player_ptr) == ClassId.unknown)
{
menuFlags[allow_multiclass] = true;
}
else
{
menuFlags[allow_multiclass] = false;
}
//S: menuFlags[allow_multiclass] should always be true.
to here:
ovr018.cs, line 197:
case 'H':
if (menuFlags[allow_multiclass] == true)
{
ovr026.multiclass(gbl.player_ptr);
}
break;
//S: the condition checking should be made here. e.g.
case 'H':
if (gbl.area2_ptr.training_class_mask <= 0 &&
Cheats.free_training == false)
{
seg041.DisplayStatusText(0, 14,
"???");
}
else if (!ovr026.IsHuman(gbl.player_ptr))
{
seg041.DisplayStatusText(0, 14,
"Not Human");
}
else if
(ovr026.HumanFirstOldClass_Unknown(gbl.player_ptr) != ClassId.unknown)
{
seg041.DisplayStatusText(0, 14,
"Already dual-class");
}
else if (menuFlags[allow_multiclass] == true)
{
ovr026.multiclass(gbl.player_ptr);
}
break;
B) is actually the elimination of the "Already dual-class" condition.
As far as I could see it needs to be fixed in 3 places.
B1) the menu itself, like above. If A) is implemented simply remove the
condition.
B2) the recalculation of menu:
ovr018.cs, line 145:
bool var_11 = (ovr026.IsHuman(gbl.player_ptr) &&
ovr026.HumanFirstOldClass_Unknown(gbl.player_ptr) == ClassId.unknown);
...
if (ovr026.IsHuman(gbl.player_ptr) == false ||
ovr026.HumanFirstOldClass_Unknown(gbl.player_ptr) != ClassId.unknown)
//S: remove old class condition
bool var_11 = (ovr026.IsHuman(gbl.player_ptr));
...
if (ovr026.IsHuman(gbl.player_ptr) == false)
If A) is implemented the whole section can be ignored: replace lines 145-160:
bool var_11 = ...
...
reclac_menus = var_11 &&
gbl.area2_ptr.training_class_mask > 0;
with this single line:
reclac_menus = gbl.area2_ptr.training_class_mask > 0;
By the way I have a feeling that a cheat condition is missing here so it
should definitely look like:
reclac_menus = (gbl.area2_ptr.training_class_mask
<= 0 && Cheats.free_training == false)
B3) Recalculation of HP on CON change:
This is the hardest part.
ovr024.cs, line 1057:
byte var_B = player.ClassLevelsOld[var_C];
if (var_B > 0)
{
sub_647BE(var_B, var_C, stat_a, ref var_A, player);
}
This is within a for loop, therefore the Con bonus will be calculated and
summed for all old classes. I made a try with:
Fighter 9 / Ranger 11
For Con 19 the bonus is 10x5 = 50
However, your version calculates 90 with Con 19 and 72 with Con 18 (i.e. 18
x bonus, where 18 = 9 + min(9,11)).
This is definitely a defect and will open a separate issue for it.
Then modified saved game to:
Fighter 9/Paladin 8/Ranger 11/Magic-User 7/Thief 6
The Con bonus should be:
6x2 for Thief
1x2 for Magic-User
1x5 for Paladin
1x5 for Fighter
1x5 for Ranger (no Con bonus on 11th level)
For a total of 29. Instead, I think the bonus is calculated as:
6x2 + 7x2 + 8x5 + 9x5 + 5 (note: it is properly calculated for the current
class) = 116. However, for some reason, the DOS version calculated 121 (I
have no explanation).
Your version calculates 130/156, depending on Con 18/19.
Nevertheless, either the calls to the sub or the sub itself should be
rewritten to be conscious about multiple dual classes.
I'm still thinking about an effective (linear) algorithm like filling a
vector and summing it up at the end.