How did you manage to get a negative skill value? Perhaps I can poke around and find where the skill is not being properly limited to between 0 and 10.
Just to test I first edited PROGRAM\ITEMS\initItems.c and changed these two swords:
Code:
// Reward for killing Malcolm Hatcher
makeref(itm,Items[n]);
itm.id = "bladeMH";
itm.skiptrade = false; // you can sell the item
itm.skipsell = true; // you can't buy it
itm.skiprand = true; // you can't randomly find it
itm.skipequip = false;
itm.groupID = BLADE_ITEM_TYPE;
itm.name = "itmname_bladeMH";
itm.describe = "itmdescr_bladeMH";
itm.folder = "ammo";
itm.model = "bladeMH";// was "bladeSC"
itm.picIndex = 11;
itm.picTexture = "ITEMS_AS";
itm.price = 2345; //
itm.dmg_min = 30.0;
itm.dmg_max = 44.0;
itm.piercing = 65; //BB (90)
itm.block = 30;
itm.minlevel = 99; //BB+PB
itm.rare = 0.00; // should be unique
itm.param.time = 0.1;
itm.skill.sneak = +2;
itm.param.colorstart = argb(64, 64, 64, 64);
itm.param.colorend = argb(0, 32, 32, 32);
itm.nation = SPAIN;
n++;
// Sword of Bartolomeu (Russian Team)
makeref(itm,Items[n]);
itm.id = "bladeBP";
itm.skiptrade = false; //BB you can sell the item
itm.skipsell = true; // you can't buy it
itm.skiprand = true; // you can't randomly find it
itm.skipequip = false;
//itm.groupID = BLADE_ITEM_TYPE;
itm.name = "itmname_bladeBP";
itm.describe = "itmdescr_bladeBP";
itm.folder = "ammo";
itm.model = "bladeBP";
itm.picIndex = 14;
itm.picTexture = "ITEMS_ccc";
itm.price = 18350; //BB (25000)
itm.dmg_min = 29.0; //BB (20.0)
itm.dmg_max = 46.0; //BB (36.0)
itm.piercing = 75;
itm.block = 80;
itm.minlevel = 99; //BB+PB
itm.rare = 0.00; // should be unique
itm.param.time = 0.1;
itm.skill.sneak = -5;
itm.param.colorstart = argb(64, 64, 64, 64);
itm.param.colorend = argb(0, 32, 32, 32);
itm.nation = PIRATE;
n++;
The first one to give +2 to Luck, the second to give -5 to Luck. Also changed the second to be just an item so I could test the effect of both.
Then edited PROGRAM\Storyline\standard\StartStoryline.c to start the standard storyline with those two swords:
Code:
// PB: Override Character Type -->
PChar.start_weapon.blade = FindCharacterItemByGroup(&PChar, BLADE_ITEM_TYPE);
PChar.start_weapon.gun = FindCharacterItemByGroup(&PChar, GUN_ITEM_TYPE);
TakeItemFromCharacter(Pchar, PChar.start_weapon.blade);
TakeItemFromCharacter(Pchar, PChar.start_weapon.gun);
TakeItemFromCharacter(Pchar, "spyglass2");
GiveItem2Character(Pchar, "bladeMH");
GiveItem2Character(Pchar, "bladeBP");
// PB: Override Character Type <--
Then I started the standard storyline and Luck shows as 0 in red as could be expected. The sword that is now just an item gives the -5 effect. Then I equipped the first sword and Luck still shows as 0 in red. I'm guessing this means the skill is now 1 - 5 + 2 = -2 or -6 depending on how it is calculated but still shows as 0 for some reason. Would be preferable if it could be 0 and any positive effect here of +1 would bring it to 1. Might not be possible.
I'm thinking it could be a problem if a player never raises the skill and gathers enough items to negatively affect it to below 0.
It seems to involve this in PROGRAM\Characters\skills\skill_utils.c:
Code:
// Set skill modifier from items
int CalcSkillModifier(ref character, string skillName)
{
int j, qty;
int mod = 0;
ref itm;
int iChrCabin = FindCharacterShipCabin(character); // KK
for(j = 0; j < SKILLITEMS_QUANTITY; j++)
{
itm = &Items[NativeFindCharacter(&Items, SkillItems[j].id)];
if(!CheckAttribute(itm, "skill." + skillName))
continue;
// KK -->
string itmid = itm.id;
qty = GetCharacterItem(character, itmid);
if (iChrCabin >= 0 && CheckAttribute(&Locations[iChrCabin], "box1.items." + itmid) == true)
qty += sti(Locations[iChrCabin].box1.items.(itmid));
// <-- KK
if( qty >= sti(itm.skill.num)) // *.skill.num = num required for effect. Default = 1
{
if(CheckAttribute(itm, "groupID") && IsCanEquiping(character, itm.groupID) && !IsEquipCharacterByItem(character, itmid))
continue; // if equipable and not equipped, skip // KK
// *.stack = bool indicating if items can be stacked together. Default = false (JRH)
if(sti(itm.skill.stack) == false) qty = 1;
mod += sti(itm.skill.(skillName)) * qty; // PB: Used to end with '/sti(itm.skill.num)'
}
}
// mod = iclamp(-MAX_SKILL_INCREASE, MAX_SKILL_INCREASE, mod); // PB: Single line
mod = iclamp(-100, MAX_SKILL_INCREASE, mod); // JRH: for cursed coins
character.skill.(skillName).modifier = mod;
return mod;
}
Which seems to be based on older code from PROGRAM\Characters\CharacterUtilite.c, here in Build 12.1:
Code:
int GetCharacterSkill(ref _refCharacter, string skillName)
{
if( !CheckAttribute(_refCharacter,"Skill."+skillName) ) return 0;
int skillN = sti(_refCharacter.Skill.(skillName));
// GZ/NK -->
int mod = 0;
string tempattr = "Skill." + skillName + ".mod";
if(CheckAttribute(_refCharacter,tempattr))
{
mod = sti(_refCharacter.(tempattr));
if(skillN + mod > 10) skillN = 10;
else skillN += mod;
}
else
{
int i, qty, lowest;
lowest = 11;
mod = 0;
ref itm;
bool uselow = false;
//uncomment these if you want to disallow stacking different items. See below for more.
//bool canchange = true;
//bool temp = false;
for(i = 0; i < SKILLITEMS_QUANTITY; i++)
{
itm = &Items[NativeFindCharacter(&Items, SkillItems[i].id)];
if(!CheckAttribute(itm,"skill."+skillName)) continue;
qty = GetCharacterItem(_refCharacter, itm.id);
if( qty >= sti(itm.skill.num)) // *.skill.num = num required for effect. Default = 1
{
if(CheckAttribute(itm,"groupID"))
{
string tstr = itm.groupID;
if(!CheckAttribute(_refCharacter,"equip."+tstr)) continue;
if(_refCharacter.equip.(tstr) != itm.id) continue; // if equipable and not equipped, skip
}
//uncomment below lines if you want to disallow stacking different items
//temp = canchange;
//if(CheckAttribute(itm,"skill.diffstack") && sti(itm.skill.diffstack)) temp = true;
//if(temp)
//{
// *.stack = num of item that can be stacked together. Default = 1
if(sti(itm.skill.stack) >= qty/sti(itm.skill.num)) { mod += sti(itm.skill.(skillName)) * qty/sti(itm.skill.num); }
else { mod += sti(itm.skill.(skillName)) * sti(itm.skill.stack) / sti(itm.skill.num); }
if(CheckAttribute(itm,"skill."+skillName+".set"))
{
if(sti(itm.skill.(skillName).set) < lowest) lowest = sti(itm.skill.(skillName).set);
uselow = true;
}
//canchange = false;
//}
}
}
if(uselow)
{
_refCharacter.(tempattr) = lowest + mod - skillN;
if(lowest + mod > 10) skillN = 10;
else skillN = lowest + mod;
}
else
{
if(skillN + mod > 10) skillN = 10;
else skillN += mod;
_refCharacter.(tempattr) = mod;
}
}
// GZ/NK <--
if( skillN<=10 ) return skillN;
trace("Character ID = "+_refCharacter.id + "have skill "+skillName + " = "+skillN);
return 10;
}
With that code it shows blank when it is a negative value. I can get it to show as 0 with this:
Code:
if(skillN + mod < 0)
{
skillN = 0;
}
else
{
if(skillN + mod > 10)
{
skillN = 10;
}
else
{
skillN += mod;
}
}
if(lowest + mod < 0)
{
skillN = 0;
}
else
{
if(lowest + mod > 10)
{
skillN = 10;
}
else
{
skillN = lowest + mod;
}
}
if(skillN + mod < 0)
{
skillN = 0;
}
else
{
if(skillN + mod > 10)
{
skillN = 10;
}
else
{
skillN += mod;
}
}
if(skillN >= 0 && skillN <= 10) return skillN; // Don't know if this change makes a difference.
But that just makes it show as 0 as in Build 14. So, somewhere in B14 it is at least set to not show blank.
If this could be made to work I would appreciate help with also getting it to work with the older code. Some of my projects involve use of older code and so I need to keep compatibility. Or, if a larger rewrite is necessary, details on what needs to be changed so it could also be adapted to an older codebase.
I would prefer if all the item values where added together, and the result of that applied to your current skill. So if you have items giving +5, and items giving -4, they add up to +1, which when added to a skill level of say 5, should give a final result of 6.
Otherwise having items giving +10, and other items giving -10, the final level would always be either 0 or 10 (depending on which you apply first), regardless of original skill.
That's what I'm hoping can be done. Also if a skill that is equally affected by both positive and negative effects could be made to show in for example yellow like positively affected skills are shown in green and negatively affected skills are shown in red that would also be useful. Stuff for that is in PROGRAM\INTERFACE\character.c:
Code:
void SetSkillShow(string skillName, int skillVal)
{
int modval = CalcCharacterSkill(&xi_refCharacter,skillName);
int baseval = GetCharacterBaseSkill(&xi_refCharacter,skillName);
int color = COLOR_NORMAL;
//GameInterface.strings.(skillName) = skillVal + " - " + CalcCharacterSkill(&xi_refCharacter,skillName); // NK
//Levis -->
string stringname = skillName;
GameInterface.strings.(stringname) = skillVal;
if(skillVal < baseval) color = COLOR_RED;
if(skillVal > baseval) color = COLOR_GREEN;
if(skillVal==MAX_CHARACTER_SKILL) color = COLOR_MONEY;
ChangeStringColor(stringname,SetAlphaIntoColor(color,GetAlphaFromSkill(skillVal)));
color = COLOR_NORMAL;
stringname = skillName+"_SEP";
GameInterface.strings.(stringname) = " - ";
ChangeStringColor(stringname,SetAlphaIntoColor(COLOR_MONEY,GetAlphaFromSkill(1)));
stringname = skillName+"_MOD";
GameInterface.strings.(stringname) = modval;
if(modval==MAX_CHARACTER_SKILL) color = COLOR_MONEY;
if(modval > skillVal) color = COLOR_GREEN;
if(modval < skillVal) color = COLOR_RED;
ChangeStringColor(stringname,SetAlphaIntoColor(color,GetAlphaFromSkill(modval)));
//Levis <--
/*int color = COLOR_NORMAL;
if(skillVal==MAX_CHARACTER_SKILL) color = COLOR_MONEY;
ChangeStringColor(skillName,SetAlphaIntoColor(color,GetAlphaFromSkill(skillVal)));*/
}
Here's how I've adapted it to older code:
Code:
void SetSkillShow(string skillName, int skillVal)
{
xi_refCharacter.Skill.(skillName) = skillVal;
int modval = GetCharacterSkill(&xi_refCharacter,skillName);
int color = COLOR_NORMAL;
string stringname = skillName;
GameInterface.strings.(stringname) = skillVal;
if(skillVal == SKILL_MAX) color = COLOR_MONEY;
ChangeStringColor(stringname,SetAlphaIntoColor(color,GetAlphaFromSkill(skillVal)));
//color = COLOR_NORMAL;
stringname = skillName+"_SEP";
GameInterface.strings.(stringname) = "-";
ChangeStringColor(stringname,SetAlphaIntoColor(COLOR_MONEY,GetAlphaFromSkill(modval)));
stringname = skillName+"_MOD";
GameInterface.strings.(stringname) = modval;
if(modval == SKILL_MAX) color = COLOR_MONEY;
if(modval > skillVal) color = COLOR_GREEN;
if(modval < skillVal) color = COLOR_RED;
ChangeStringColor(stringname,SetAlphaIntoColor(color,GetAlphaFromSkill(modval)));
}
It could be said that since I'm not a programmer I should stay out of it, but I'm trying to learn.