This problem seems to be caused because
SetBaseShipData is called more often than it should be.
First I thought it was Levelling again and it turned out I wasn't 100% wrong there, because it is indeed part of
CheckCharacterSetup :
Code:
void CheckCharacterSetup(ref chref)
{
if (!CheckAttribute(chref,"id")) {chref.id = "without_id"; }
if (!CheckAttribute(chref,"Experience")) {chref.Experience = 1; }
if (!CheckAttribute(chref,"perks.FreePoints")){chref.perks.FreePoints = 1; }
if (!CheckAttribute(chref,"skill.freeskill")){chref.skill.freeskill = 0; }
if (!CheckAttribute(chref,"quest.officertype") || GetAttribute(chref,"quest.officertype") == "combat")
{
if(GetAttribute(chref,"isOfficer") == 1)
{
chref.quest.officertype = GetRandomOfficerType();
}
else
{
if(GetAttribute(chref,"issoldier") == 1)
{
chref.quest.officertype = OFFIC_TYPE_GUARD;
}
else
{
if(GetAttribute(chref,"isMerchant") == 1)
{
chref.quest.officertype = OFFIC_TYPE_SHOPKEEPER;
}
else
{
if(GetAttribute(chref,"isWarrior") == 1)
{
chref.quest.officertype = GetRandomEnemyType();
}
else
{
chref.quest.officerType = GetRandomNPCType();
}
}
}
}
}
if (CharacterHasShip(chref)) chref.quest.officerType = GetCaptainType(chref);
if (!CheckAttribute(chref,"rank")) {chref.rank = 1; }
if (!CheckAttribute(chref,"quest.officerprice") && !IsMainCharacter(chref)) chref.quest.officerprice = 0;
if (!CheckAttribute(chref,"Money")) {
chref.Money = GetRandCharMoney(chref, makeint(Rand(8)+2)); //Levis: Reduced amount of money characters carry
// } else { // PB: Commented out, because zero money may be intentional!
// if (sti(chref.Money) == 0) chref.Money = GetRandCharMoney(chref, makeint(Rand(8)+2));
}
//Checks for leaving officers
if (!CheckAttribute(chref,"loyality")) {chref.loyality = 5+rand(15); }
if (!CheckAttribute(chref,"alignment")) {if(rand(1)==1){chref.alignment = "good";}else{chref.alignment = "bad";}}
if (!CheckAttribute(chref,"homelocation"))
{
int loc = FindLocation(chref.location);
bool set = false;
if(loc > -1)
{
if(GetAttribute(Locations[loc],"type") == "tavern")
{
chref.homelocation = "";
chref.homelocation.group = "";
chref.homelocation.locator = "";
chref.homestate = "";
set = true;
}
}
if(!set)
{
chref.homelocation = chref.location; // PB: was alignment???
chref.homelocation.group = chref.location.group;
chref.homelocation.locator = chref.location.locator;
if(CheckAttribute(chref,"chr_ai.type")) chref.homestate = chref.chr_ai.type;
else chref.homestate = "citizen";
}
}
SetBaseShipData(chref);
}
That is supposed to be called ONCE per character; after that, everything should be set up correctly and it doesn't need doing again.
But when I bypassed Levelling, it STILL happen. After a huge lot of digging, I finally found this:
Code:
// NK make this a separate function 05-05-11
bool Character_PostInit(int n)
{
if(n >= CHARACTERS_QUANTITY) return false;
ref rCharacter = GetCharacter(n);
// NK 05-03-31 check to see if we're overwriting an animation -->
if(!CheckAttribute(rCharacter,"model.animation") || rCharacter.model.animation == "")
{
// changed by MAXIMUS [for AOP models] -->
if(rCharacter.sex == "woman")
{
if(StraifCharacter(rCharacter)) rCharacter.model.animation = "new_woman";
else rCharacter.model.animation = "towngirl";
// KK -->
rCharacter.model.height = WOMAN_HEIGHT;
rCharacter.capacity.max = WOMAN_CAPACITY;
// <-- KK
}
else
{
if(StraifCharacter(rCharacter)) rCharacter.model.animation = "new_man";
else rCharacter.model.animation = "man";
// KK -->
rCharacter.model.height = MAN_HEIGHT;
rCharacter.capacity.max = MAN_CAPACITY;
// <-- KK
}
// changed by MAXIMUS [for AOP models] <--
}
// NK <--
rCharacter.FaceGroup = 0;
// set fellows
if (CheckAttribute(rCharacter,"fellows")) { SetBaseFellows(rCharacter); }
// set base ship data
SetBaseShipData(rCharacter);
But that code has been there FOREVER.
Looks like it is meant to be executed ONLY the first time a character has to be displayed, because it gets triggered by the animations not yet being initialized.
So it sounds like this problem is related to:
1. Quest captains NOT going through the Levelling system properly, so they get correctly initialized (and reset!) only AFTER the sea battle has completed
2. The first time a character has to be displayed as model, the ship gets reset too
For starters, I am getting rid of the
Character_PostInit call to
SetBaseShipData .
Then at least Levelling gets the FULL control over this and it isn't being handled in
two places.
This only leaves the problem of quest captains not being initialized when they need to be for some reason.
That should probably be solved once this is done:
Planned Feature - Use Generic Captain and Ship Generation Functions | PiratesAhoy!
In the end, this is yet another example of too many separate pieces of code existing to do the same thing. This makes debugging stupidly difficult.
So merging multiple functions for the same purpose into ONE is definitely something we should be doing as much as possible!
That does have the risk of temporarily breaking stuff, but having control in one spot makes fixing stuff so much easier than when everything is scattered everywhere.