diff --git a/zone/client.cpp b/zone/client.cpp index 1e4ba461a..5cc5ae309 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7516,7 +7516,6 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui 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 }; int32 current_value; - bool change = false; // Get the npc faction list if (!database.GetNPCFactionList(npc_id, faction_id, npc_value, temp)) @@ -7525,43 +7524,81 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui { int32 faction_before_hit; int32 faction_to_use_for_messaging; + FactionMods fm; + int32 this_faction_max; + int32 this_faction_min; if (faction_id[i] <= 0) continue; + // Find out starting faction for this faction + // It needs to be used to adj max and min personal + // The range is still the same, 1200-3000(4200), but adjusted for base + database.GetFactionData(&fm, GetClass(), GetRace(), GetDeity(), + faction_id[i]); + + // Adjust the amount you can go up or down so the resulting range + // is PERSONAL_MAX - PERSONAL_MIN + // + // Adjust these values for cases where starting faction is below + // min or above max by not allowing any earn in those directions. + this_faction_min = MIN_PERSONAL_FACTION - fm.base; + this_faction_min = std::min(0, this_faction_min); + this_faction_max = MAX_PERSONAL_FACTION - fm.base; + this_faction_max = std::max(0, this_faction_max); + // Get the characters current value with that faction current_value = GetCharacterFactionLevel(faction_id[i]); faction_before_hit = current_value; - change = UpdatePersonalFaction(char_id, npc_value[i], faction_id[i], ¤t_value, temp[i]); + UpdatePersonalFaction(char_id, npc_value[i], faction_id[i], ¤t_value, temp[i], this_faction_min, this_faction_max); - if (change) - { - SendFactionMessage(npc_value[i], faction_id[i], faction_before_hit, current_value, temp[i]); - } + //Message(14, "Min(%d) Max(%d) Before(%d), After(%d)\n", this_faction_min, this_faction_max, faction_before_hit, current_value); + + SendFactionMessage(npc_value[i], faction_id[i], faction_before_hit, current_value, temp[i], this_faction_min, this_faction_max); } + return; } void Client::SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, int32 value, uint8 temp) { int32 current_value; - bool change=false; //Get the npc faction list if(faction_id > 0 && value != 0) { int32 faction_before_hit; + FactionMods fm; + int32 this_faction_max; + int32 this_faction_min; + + // Find out starting faction for this faction + // It needs to be used to adj max and min personal + // The range is still the same, 1200-3000(4200), but adjusted for base + database.GetFactionData(&fm, GetClass(), GetRace(), GetDeity(), + faction_id); + + // Adjust the amount you can go up or down so the resulting range + // is PERSONAL_MAX - PERSONAL_MIN + // + // Adjust these values for cases where starting faction is below + // min or above max by not allowing any earn/loss in those directions. + // At least one faction starts out way below min, so we don't want + // to allow loses in those cases, just massive gains. + this_faction_min = MIN_PERSONAL_FACTION - fm.base; + this_faction_min = std::min(0, this_faction_min); + this_faction_max = MAX_PERSONAL_FACTION - fm.base; + this_faction_max = std::max(0, this_faction_max); //Get the faction modifiers current_value = GetCharacterFactionLevel(faction_id); faction_before_hit = current_value; - change = UpdatePersonalFaction(char_id, value, faction_id, ¤t_value, temp); + UpdatePersonalFaction(char_id, value, faction_id, ¤t_value, temp, this_faction_min, this_faction_max); - if (change) - { - SendFactionMessage(value, faction_id, faction_before_hit, current_value, temp); - } + //Message(14, "Min(%d) Max(%d) Before(%d), After(%d)\n", this_faction_min, this_faction_max, faction_before_hit, current_value); + + SendFactionMessage(value, faction_id, faction_before_hit, current_value, temp, this_faction_min, this_faction_max); } return; @@ -7583,7 +7620,7 @@ int32 Client::GetCharacterFactionLevel(int32 faction_id) // Checks for bottom out and max faction and old faction db entries // Updates the faction if we are not minned, maxed or we need to repair -bool Client::UpdatePersonalFaction(int32 char_id, int32 npc_value, int32 faction_id, int32 *current_value, int32 temp) +void Client::UpdatePersonalFaction(int32 char_id, int32 npc_value, int32 faction_id, int32 *current_value, int32 temp, int32 this_faction_min, int32 this_faction_max) { bool repair = false; bool change = false; @@ -7601,33 +7638,38 @@ bool Client::UpdatePersonalFaction(int32 char_id, int32 npc_value, int32 faction npc_value *= 2; } } + // Set flag when to update db - if (*current_value > MAX_PERSONAL_FACTION) + // Repair needed, as db changes could modify a base value for a faction + // and we need to auto correct when that happens. + if (*current_value > this_faction_max) { - *current_value = MAX_PERSONAL_FACTION; + *current_value = this_faction_max; repair = true; } - else if (*current_value < MIN_PERSONAL_FACTION) + else if (*current_value < this_faction_min) { - *current_value = MIN_PERSONAL_FACTION; + *current_value = this_faction_min; repair = true; } - else if ((m_pp.gm != 1) && (npc_value != 0) && ((*current_value != MAX_PERSONAL_FACTION) || (*current_value != MIN_PERSONAL_FACTION))) + else if ((m_pp.gm != 1) && (npc_value != 0) && + ((npc_value > 0 && *current_value != this_faction_max) || + ((npc_value < 0 && *current_value != this_faction_min)))) change = true; - *current_value += npc_value; - - if (*current_value > MAX_PERSONAL_FACTION) - *current_value = MAX_PERSONAL_FACTION; - else if (*current_value < MIN_PERSONAL_FACTION) - *current_value = MIN_PERSONAL_FACTION; - if (change || repair) { + *current_value += npc_value; + + if (*current_value > this_faction_max) + *current_value = this_faction_max; + else if (*current_value < this_faction_min) + *current_value = this_faction_min; + database.SetCharacterFactionLevel(char_id, faction_id, *current_value, temp, factionvalues); } -return (repair || change); +return; } // returns the character's faction level, adjusted for racial, class, and deity modifiers @@ -7708,21 +7750,21 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction) //o-------------------------------------------------------------- //| Purpose: Send faction change message to client //o-------------------------------------------------------------- -void Client::SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_before_hit, int32 totalvalue, uint8 temp) +void Client::SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_before_hit, int32 totalvalue, uint8 temp, int32 this_faction_min, int32 this_faction_max) { char name[50]; int32 faction_value; - // If we're dropping from MAX or raising from MIN, we should - // base the message on the new updated value so we don't show + // If we're dropping from MAX or raising from MIN or repairing, + // we should base the message on the new updated value so we don't show // a min MAX message // // If we're changing any other place, we use the value before the // hit. For example, if we go from 1199 to 1200 which is the MAX // we still want to say faction got better this time around. - if ( (faction_before_hit == MAX_PERSONAL_FACTION) || - (faction_before_hit == MIN_PERSONAL_FACTION)) + if ( (faction_before_hit >= this_faction_max) || + (faction_before_hit <= this_faction_min)) faction_value = totalvalue; else faction_value = faction_before_hit; @@ -7733,13 +7775,13 @@ void Client::SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_ if (tmpvalue == 0 || temp == 1 || temp == 2) return; - else if (faction_value >= MAX_PERSONAL_FACTION) + else if (faction_value >= this_faction_max) Message_StringID(15, FACTION_BEST, name); - else if (faction_value <= MIN_PERSONAL_FACTION) + else if (faction_value <= this_faction_min) Message_StringID(15, FACTION_WORST, name); - else if (tmpvalue > 0 && faction_value < MAX_PERSONAL_FACTION && !RuleB(Client, UseLiveFactionMessage)) + else if (tmpvalue > 0 && faction_value < this_faction_max && !RuleB(Client, UseLiveFactionMessage)) Message_StringID(15, FACTION_BETTER, name); - else if (tmpvalue < 0 && faction_value > MIN_PERSONAL_FACTION && !RuleB(Client, UseLiveFactionMessage)) + else if (tmpvalue < 0 && faction_value > this_faction_min && !RuleB(Client, UseLiveFactionMessage)) Message_StringID(15, FACTION_WORSE, name); else if (RuleB(Client, UseLiveFactionMessage)) Message(15, "Your faction standing with %s has been adjusted by %i.", name, tmpvalue); //New Live faction message (14261) diff --git a/zone/client.h b/zone/client.h index fbdcfb676..9248fb742 100644 --- a/zone/client.h +++ b/zone/client.h @@ -607,9 +607,9 @@ public: int32 GetCharacterFactionLevel(int32 faction_id); int32 GetModCharacterFactionLevel(int32 faction_id); void MerchantRejectMessage(Mob *merchant, int primaryfaction); - void SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_before_hit, int32 totalvalue, uint8 temp); + void SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_before_hit, int32 totalvalue, uint8 temp, int32 this_faction_min, int32 this_faction_max); - bool UpdatePersonalFaction(int32 char_id, int32 npc_value, int32 faction_id, int32 *current_value, int32 temp); + void UpdatePersonalFaction(int32 char_id, int32 npc_value, int32 faction_id, int32 *current_value, int32 temp, int32 this_faction_min, int32 this_faction_max); void SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity); void SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, int32 value, uint8 temp); int32 GetRawItemAC(); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 56236f1b8..e90016dfb 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3212,16 +3212,7 @@ bool ZoneDatabase::GetNPCFactionList(uint32 npcfaction_id, int32* faction_id, in bool ZoneDatabase::SetCharacterFactionLevel(uint32 char_id, int32 faction_id, int32 value, uint8 temp, faction_map &val_list) { - std::string query = StringFormat("DELETE FROM faction_values " - "WHERE char_id=%i AND faction_id = %i", - char_id, faction_id); - auto results = QueryDatabase(query); - if (!results.Success()) { - return false; - } - - if(value == 0) - return true; + std::string query; if(temp == 2) temp = 0; @@ -3229,17 +3220,18 @@ bool ZoneDatabase::SetCharacterFactionLevel(uint32 char_id, int32 faction_id, in if(temp == 3) temp = 1; - query = StringFormat("INSERT INTO faction_values (char_id, faction_id, current_value, temp) " - "VALUES (%i, %i, %i, %i)", char_id, faction_id, value, temp); - results = QueryDatabase(query); - if (!results.Success()) { + query = StringFormat("INSERT INTO `faction_values` " + "(`char_id`, `faction_id`, `current_value`, `temp`) " + "VALUES (%i, %i, %i, %i) " + "ON DUPLICATE KEY UPDATE `current_value`=%i,`temp`=%i", + char_id, faction_id, value, temp, value, temp); + auto results = QueryDatabase(query); + + if (!results.Success()) return false; - } + else + val_list[faction_id] = value; - if (results.RowsAffected() == 0) - return false; - - val_list[faction_id] = value; return true; }