Difference between revisions of "Server:Faction"
(16 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
This article will attempt to explain how faction works server-side to assist with understanding the various modifiers applied to characters between the base values and the ones you experience in-game. | This article is intended for developers and will attempt to explain how faction works server-side to assist with understanding the various modifiers applied to characters between the base values and the ones you experience in-game. This is intended to augment reviewing the actual source code and should help with troubleshooting faction bugs or building tools related to faction calculation. | ||
For a player-focused approach, see [[Faction]]. | |||
In the source code, faction is found in [https://github.com/EQMacEmu/Server/blob/main/common/faction.h /common/faction.h] and [https://github.com/EQMacEmu/Server/blob/main/common/faction.cpp /common/faction.cpp]. | In the source code, faction is found in [https://github.com/EQMacEmu/Server/blob/main/common/faction.h /common/faction.h] and [https://github.com/EQMacEmu/Server/blob/main/common/faction.cpp /common/faction.cpp]. | ||
== How Faction Gets Calculated == | == How Faction Gets Calculated == | ||
Faction | Faction calculation begins in the '''FACTION_VALUE Client::GetFactionLevel(uint32 char_id, uint32 p_race, uint32 p_class, uint32 p_deity, int32 pFaction, Mob* tnpc, bool lua)''' function in [https://github.com/EQMacEmu/Server/blob/main/zone/client.cpp#L4350 /zone/client.cpp]. | ||
'''GetFactionLevel''' follows the following process to determine a player's faction with a target NPC: | '''GetFactionLevel''' follows the following process to determine a player's faction with a target NPC: | ||
# [[# | # [[#Optimizations Prior to Faction Checks]] | ||
# [[# | # [[#Pull NPC's Raw Primary Faction Data from the Database]] | ||
# [[#Pull Raw Character Faction Level]] | |||
# [[#Apply Faction Bonuses]] | # [[#Apply Faction Bonuses]] | ||
# [[#Final Calculation]] | |||
# [[#Check for Special Exceptions]] | # [[#Check for Special Exceptions]] | ||
=== | <hr /> | ||
===Optimizations Prior to Faction Checks=== | |||
==== Indifferent Use Cases ==== | |||
''Note: Faction with an NPC will be '''Indifferent''' if any of the following are true:'' | |||
#the player is currently feign death and the target NPC is not immune to it, | |||
#the zone is marked as no combat, | |||
#if the player is invis to undead and the target npc is undead, | |||
#if the player is invis and the target NPC cannot see invis | |||
==== Pets ==== | |||
Pets will be Amiable to their owner and Indifferent to everyone else. | |||
<hr /> | |||
===Pull NPC's Raw Primary Faction Data from the Database=== | |||
First, the server queries data about the NPC's Primary Faction (stored in an '''int32 pFaction''' variable) from the database (via '''bool GetFactionData(FactionMods* fd, uint32 class_mod, uint32 race_mod, uint32 deity_mod, int32 faction_id, uint8 texture_mod, uint8 gender_mod, uint32 base_race, bool skip_illusions = false);''' in [https://github.com/EQMacEmu/Server/blob/main/zone/zonedb.cpp#L2334 /zone/zonedb.cpp]) and stores the modifiers in a variable called '''fmods''' which is of type [[#Faction Modifiers|FactionMod]]. | First, the server queries data about the NPC's Primary Faction (stored in an '''int32 pFaction''' variable) from the database (via '''bool GetFactionData(FactionMods* fd, uint32 class_mod, uint32 race_mod, uint32 deity_mod, int32 faction_id, uint8 texture_mod, uint8 gender_mod, uint32 base_race, bool skip_illusions = false);''' in [https://github.com/EQMacEmu/Server/blob/main/zone/zonedb.cpp#L2334 /zone/zonedb.cpp]) and stores the modifiers in a variable called '''fmods''' which is of type [[#Faction Modifiers|FactionMod]]. | ||
This function is where all the "special sauce" is found regarding how to interpret the faction data as it appears in the database. | This function is where all the "special sauce" is found regarding how to interpret the faction data as it appears in the database. | ||
=== | ===Pull Raw Character Faction Level=== | ||
Next, the server queries the player's current faction value with the NPC's primary faction by calling '''GetCharacterFactionLevel( | Next, the server queries the player's current faction value with the NPC's primary faction ('''pFaction''') by calling '''int32 GetCharacterFactionLevel(int32 faction_id);''' from [https://github.com/EQMacEmu/Server/blob/main/zone/client.cpp#L4492 /zone/client.cpp] and stores that in a variable, '''int32 tmpFactionValue'''. | ||
'''''GetCharacterFactionLevel''' works by simply iterating over a preloaded list of the character's faction data from the '''character_faction_values''' table in the database. This "list" is of type, '''typedef std::map<uint32, int16> faction_map''', which was populated with the '''faction_id''' and '''current_value''' columns from that table.'' | |||
===Apply Faction Bonuses === | ===Apply Faction Bonuses === | ||
Line 32: | Line 50: | ||
==== Spells ==== | ==== Spells ==== | ||
Faction bonuses from Alliance type spells ('''int32 GetFactionBonus(uint32 pFactionID);''') are checked in [https://github.com/EQMacEmu/Server/blob/main/zone/mob.cpp#L3655 /zone/mob.cpp]. | Faction bonuses from Alliance type spells ('''int32 GetFactionBonus(uint32 pFactionID);''') are checked in [https://github.com/EQMacEmu/Server/blob/main/zone/mob.cpp#L3655 /zone/mob.cpp]. | ||
The mob class has a '''std::map<uint32,int32> faction_bonuses;''' property where each mob keeps positive and negative bonuses applied from spells for each Primary Faction ID, bonus pair. These get added by the mob class's protected '''void AddFactionBonus(uint32 pFactionID,int32 bonus);''' function called in [https://github.com/EQMacEmu/Server/blob/main/zone/spell_effects.cpp#L534 /zone/spell_effects.cpp] for a spell with the '''SE_AddFaction''' effect. | |||
==== Items ==== | ==== Items ==== | ||
Faction bonuses from items ('''int32 GetItemFactionBonus(uint32 pFactionID);''') are checked in [https://github.com/EQMacEmu/Server/blob/main/zone/mob.cpp#L3665 /zone/mob.cpp] as well. | Faction bonuses from items ('''int32 GetItemFactionBonus(uint32 pFactionID);''') are checked in [https://github.com/EQMacEmu/Server/blob/main/zone/mob.cpp#L3665 /zone/mob.cpp] as well. | ||
The mob class has a ''' std::map<uint32,int32> item_faction_bonuses;''' property where each mob keeps positive and negative bonuses applied from items for each Primary Faction ID, bonus pair. These get added by the mob class's protected '''void AddItemFactionBonus(uint32 pFactionID,int32 bonus);''' function called in [https://github.com/EQMacEmu/Server/blob/main/zone/bonuses.cpp#L311 /zone/bonuses.cpp]. | |||
=== Final Calculation === | === Final Calculation === | ||
Now that we have the modifiers from the NPC's Primary Faction and the character's '''tmpFactionValue''' which includes their raw value + item and spell bonuses, faction is ultimately calculated in the '''FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value, bool lua = false);''' function which is defined in [https://github.com/EQMacEmu/Server/blob/main/common/faction.cpp#L55 /common/faction.cpp]. | |||
<code> | <code> | ||
Line 47: | Line 68: | ||
===Check for Special Exceptions=== | ===Check for Special Exceptions=== | ||
==== Merchants ==== | ==== Merchants ==== |
Latest revision as of 14:24, 21 November 2024
This article is intended for developers and will attempt to explain how faction works server-side to assist with understanding the various modifiers applied to characters between the base values and the ones you experience in-game. This is intended to augment reviewing the actual source code and should help with troubleshooting faction bugs or building tools related to faction calculation.
For a player-focused approach, see Faction.
In the source code, faction is found in /common/faction.h and /common/faction.cpp.
How Faction Gets Calculated[edit]
Faction calculation begins in the FACTION_VALUE Client::GetFactionLevel(uint32 char_id, uint32 p_race, uint32 p_class, uint32 p_deity, int32 pFaction, Mob* tnpc, bool lua) function in /zone/client.cpp.
GetFactionLevel follows the following process to determine a player's faction with a target NPC:
- #Optimizations Prior to Faction Checks
- #Pull NPC's Raw Primary Faction Data from the Database
- #Pull Raw Character Faction Level
- #Apply Faction Bonuses
- #Final Calculation
- #Check for Special Exceptions
Optimizations Prior to Faction Checks[edit]
Indifferent Use Cases[edit]
Note: Faction with an NPC will be Indifferent if any of the following are true:
- the player is currently feign death and the target NPC is not immune to it,
- the zone is marked as no combat,
- if the player is invis to undead and the target npc is undead,
- if the player is invis and the target NPC cannot see invis
Pets[edit]
Pets will be Amiable to their owner and Indifferent to everyone else.
Pull NPC's Raw Primary Faction Data from the Database[edit]
First, the server queries data about the NPC's Primary Faction (stored in an int32 pFaction variable) from the database (via bool GetFactionData(FactionMods* fd, uint32 class_mod, uint32 race_mod, uint32 deity_mod, int32 faction_id, uint8 texture_mod, uint8 gender_mod, uint32 base_race, bool skip_illusions = false); in /zone/zonedb.cpp) and stores the modifiers in a variable called fmods which is of type FactionMod.
This function is where all the "special sauce" is found regarding how to interpret the faction data as it appears in the database.
Pull Raw Character Faction Level[edit]
Next, the server queries the player's current faction value with the NPC's primary faction (pFaction) by calling int32 GetCharacterFactionLevel(int32 faction_id); from /zone/client.cpp and stores that in a variable, int32 tmpFactionValue.
GetCharacterFactionLevel works by simply iterating over a preloaded list of the character's faction data from the character_faction_values table in the database. This "list" is of type, typedef std::map<uint32, int16> faction_map, which was populated with the faction_id and current_value columns from that table.
Apply Faction Bonuses[edit]
It then calculates faction bonuses and adds those to tmpFactionValue.
Spells[edit]
Faction bonuses from Alliance type spells (int32 GetFactionBonus(uint32 pFactionID);) are checked in /zone/mob.cpp.
The mob class has a std::map<uint32,int32> faction_bonuses; property where each mob keeps positive and negative bonuses applied from spells for each Primary Faction ID, bonus pair. These get added by the mob class's protected void AddFactionBonus(uint32 pFactionID,int32 bonus); function called in /zone/spell_effects.cpp for a spell with the SE_AddFaction effect.
Items[edit]
Faction bonuses from items (int32 GetItemFactionBonus(uint32 pFactionID);) are checked in /zone/mob.cpp as well.
The mob class has a std::map<uint32,int32> item_faction_bonuses; property where each mob keeps positive and negative bonuses applied from items for each Primary Faction ID, bonus pair. These get added by the mob class's protected void AddItemFactionBonus(uint32 pFactionID,int32 bonus); function called in /zone/bonuses.cpp.
Final Calculation[edit]
Now that we have the modifiers from the NPC's Primary Faction and the character's tmpFactionValue which includes their raw value + item and spell bonuses, faction is ultimately calculated in the FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value, bool lua = false); function which is defined in /common/faction.cpp.
character_value = tmpFactionValue + base + class_mod + race_mod + deity_mod
The result of this formula is then returned as a FactionValue.
Check for Special Exceptions[edit]
Merchants[edit]
If a merchant would otherwise con Threateningly or Scowls to the player based on final faction value, they will instead be set to Dubious.
Combat[edit]
If an NPC would normally have Dubious or higher faction with the player, and that player is on their hate list (i.e. from combat), they will instead con Threateningly.
Faction Properties[edit]
The Faction struct defined in /common/faction.h defines the following members:
Property | Data Type | Description |
---|---|---|
id | int32 | database identifier |
mods | std::map<std::string, int16> | |
base | int16 | The base, unmodified value that players start with for this faction before race, class, and deity modifiers are applied |
name | char array 50 | The name of the faction |
see_illusion | bool | Determines whether the faction will see through racial illusion spells |
min_cap | int16 | Minimum value players can reach with this faction |
max_cap | int16 | Maximum value players can reach with this faction |
Faction Modifiers[edit]
The FactionMod struct defined in /common/faction.h defines the following members:
- int32 base
- int32 class_mod
- int32 race_mod
- int32 deity_mod
Faction Value Ranges[edit]
Min Cap | Max Cap | FACTION_VALUE (Enum) |
---|---|---|
>= 2000 | - | FACTION_MAX_ALLY = 0 |
>= 1100 | - | FACTION_ALLY = 1 |
>= 750 | <= 1099 | FACTION_WARMLY = 2 |
>= 500 | <= 749 | FACTION_KINDLY = 3 |
>= 100 | <= 499 | FACTION_AMIABLY = 4 |
>= 0 | <= 99 | FACTION_INDIFFERENTLY = 5 |
>= -100 | <= -1 | FACTION_APPREHENSIVELY = 6 |
>= -500 | <= -101 | FACTION_DUBIOUSLY = 7 |
>= -750 | <= -501 | FACTION_THREATENINGLY = 8 |
- | <= -751 | FACTION_SCOWLS = 9 |
- | <= -2000 | FACTION_MAX_SCOWLS = 10 |
The range of faction values above which are returned as the enums described in the final column are filtered through the const char *FactionValueToString(FACTION_VALUE faction_value); function to convert them to the corresponding string equivalent before being sent to the client and used for in-game consider or similar messages.
NPC Faction[edit]
The NPCFaction struct defined in /common/faction.h defines the following members:
Property | Data Type | Description |
---|---|---|
factionID | uint32 | |
value_mod | int32 | |
npc_value | int8 | |
temp | uint8 |