View Single Post
  #1  
Old 08-28-2014, 04:37 PM
noudess
Discordant
 
Join Date: Sep 2012
Location: Upstate NY
Posts: 274
Default Modified Faction min/max system

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;
}
Reply With Quote