Over in this
thread I brought up an issue with the current code.
I brought it up ober on peq and got some
input.
I looked at the current code alot, and found some bugs like below, which tries to boundary check, but actually makes the # even smaller if the mod is negative..
Code:
}
else if(tmpValue <= MIN_FACTION)
{
t = MIN_FACTION - mod;
Based on all that I rewrote this one function (currently in client.cpp for you guys, was in faction.cpp in my version), and changed a couple of constants (features.h for me).
The idea of my changes:
- each char has a window from +1200 to -3000 to earn for himself against each faction regardless of mods
- The mods are applied to that value to determine resulting faction.
- Thie means the range is 1200+mods to -3000 + mods
- Now, all characters "deeds" matter equally. This solved my issue where my Erudites min faction was only -500 based on the old code, while others could dig a deeprr hole. Now, if my Erudite kills down to -3000 personal, illusion wiont be enough to not be KOS.
I like the new system. I think it is closer to the old system and makes more sense.
Here's the code, up to you if you want it. Not posting as a diff - your filenames have changed and I reformatted. I couldn't really read/understand until I did. It's just the one func + defines, but the func is close to a rewrite. Alot of logic moved around to make it more straight forward.
Code:
// In features.h on my server
#define MIN_PERSONAL_FACTION (-3000)
#define MAX_PERSONAL_FACTION (1200)
// In faction.cpp on my server, client.cpp in recent code base
void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity)
{
_ZP(Client_SetFactionLevel);
int32 faction_id[MAX_NPC_FACTIONS]={ 0,0,0,0,0,0,0,0,0,0 };
int32 npc_value[MAX_NPC_FACTIONS]={ 0,0,0,0,0,0,0,0,0,0 };
uint8 temp[MAX_NPC_FACTIONS]={ 0,0,0,0,0,0,0,0,0,0 };
int16 mod;
int16 tmpValue;
int16 current_value;
FactionMods fm;
bool change=false;
bool repair=false;
char *msg;
// Get the npc faction list
if(!database.GetNPCFactionList(npc_id, faction_id, npc_value, temp))
return;
for(int i = 0;i<MAX_NPC_FACTIONS;i++)
{
if(faction_id[i] <= 0)
continue;
// Get the faction modifiers
if(database.GetFactionData(&fm,char_class,char_race,char_deity,faction_id[i]))
{
// Get the characters current value with that faction
current_value = GetCharacterFactionLevel(faction_id[i]);
// Modify if we have Heroic Charisma
if(this->itembonuses.HeroicCHA)
{
int faction_mod = itembonuses.HeroicCHA / 5;
// If our result isn't truncated, then just do that
if(npc_value[i] * faction_mod / 100 != 0)
npc_value[i] += npc_value[i] * faction_mod / 100;
// If our result is truncated, then double a mob's value every once
// in a while to equal what they would have got
else
{
if(MakeRandomInt(0, 100) < faction_mod)
npc_value[i] *= 2;
}
}
// Set flag when to update db.
if (current_value > MAX_PERSONAL_FACTION) // db faction out of line (old code saved it wrong)
{
repair=true;
current_value = MAX_PERSONAL_FACTION;
}
else if (current_value < MIN_PERSONAL_FACTION) // db faction out of line (old code saved it wrong)
{
repair=true;
current_value = MIN_PERSONAL_FACTION;
}
// Also update if there's a hit and we're not maxxed or bottomed out or a GM
else if(m_pp.gm != 1 && npc_value[i] != 0 &&
(current_value != MAX_PERSONAL_FACTION || current_value != MIN_PERSONAL_FACTION))
{
change=true;
}
current_value += npc_value[i];
if (current_value < MIN_PERSONAL_FACTION)
{
current_value = MIN_PERSONAL_FACTION;
}
else if (current_value > MAX_PERSONAL_FACTION)
{
current_value = MAX_PERSONAL_FACTION;
}
if (change || repair)
{
database.SetCharacterFactionLevel(char_id, faction_id[i],
current_value, temp[i], factionvalues);
if (change) // Message only if kill modified faction. Repair silently.
{
//figure out their modifierm buildmessage wants final faction
mod = fm.base + fm.class_mod + fm.race_mod + fm.deity_mod;
tmpValue = current_value + mod + npc_value[i];
msg = BuildFactionMessage(npc_value[i],faction_id[i],tmpValue,temp[i]);
if (msg != 0)
Message(0, msg);
safe_delete_array(msg);
}
}
}
}
return;
}
Then I had to change the message function to use the modifier constant names:
Code:
char* BuildFactionMessage(int32 tmpvalue, int32 faction_id, int32 totalvalue, uint8 temp)
{
/*
This should be replaced to send string-ID based messages using:
#define FACTION_WORST 469 //Your faction standing with %1 could not possibly get any worse.
#define FACTION_WORSE 470 //Your faction standing with %1 got worse.
#define FACTION_BEST 471 //Your faction standing with %1 could not possibly get any better.
#define FACTION_BETTER 472 //Your faction standing with %1 got better.
some day.
*/
//tmpvalue is the change as best I can tell.
char *faction_message = 0;
char name[50];
if(database.GetFactionName(faction_id, name, sizeof(name)) == false) {
snprintf(name, sizeof(name),"Faction%i",faction_id);
}
if(tmpvalue == 0 || temp == 1 || temp == 2) {
return 0;
}
else if (totalvalue >= MAX_PERSONAL_FACTION) {
MakeAnyLenString(&faction_message, "Your faction standing with %s could not possibly get any better!", name);
return faction_message;
}
else if(tmpvalue > 0 && totalvalue < MAX_PERSONAL_FACTION) {
MakeAnyLenString(&faction_message, "Your faction standing with %s has gotten better!", name);
return faction_message;
}
else if(tmpvalue < 0 && totalvalue > MIN_PERSONAL_FACTION) {
MakeAnyLenString(&faction_message, "Your faction standing with %s has gotten worse!", name);
return faction_message;
}
else if(totalvalue <= MIN_PERSONAL_FACTION) {
MakeAnyLenString(&faction_message, "Your faction standing with %s could not possibly get any worse!", name);
return faction_message;
}
return 0;
}
And remove the truncation from this function.
Code:
// returns the character's faction level, adjusted for racial, class, and deity modifiers
int32 Client::GetModCharacterFactionLevel(int32 faction_id) {
int32 Modded = GetCharacterFactionLevel(faction_id);
FactionMods fm;
if(database.GetFactionData(&fm,GetClass(),GetRace(),GetDeity(),faction_id))
Modded += fm.base + fm.class_mod + fm.race_mod + fm.deity_mod;
return Modded;
}