From 2b4e555eae76fa7871d7527086ce55467f8ddba8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" <277429+mackal@users.noreply.github.com> Date: Sat, 3 Sep 2022 10:57:55 -0400 Subject: [PATCH] [Feature] Faction Association (#2408) * Add faction logging category Probably should use this for more things * Add FactionAssociation struct This is simply just a struct that contains an array of faction ids and multiplier. This can hold a maximum of 10 entries (Seru hit is 8, so 2 extra) this can be raised if need be. * Add database changes and other data point changes This is all the database changes and loading changes Included is an optional SQL that will be used as a starting point, there is likely errors or typos, but we will fix those as they are discovered. * Add Client::RewardFaction function This just takes the faction ID and the magnitude of the primary faction hit and calculates the rest. The minimum change will be either 1 or -1. We stop processing after we see an ID of 0 and assume there will be no later entries. The primary faction ID will always receive a hit even if there is no faction association entries * Add users of RewardFaction to NPC death, tasks, and QuestRewards This will only use the new system if the magnitude is set, otherwise we will just use the old system still * Add quest system calls and lua QuestReward support * Add #factionassociation command This just calls RewardFaction, mostly useful for debugging --- common/CMakeLists.txt | 2 + common/database_schema.h | 1 + common/eqemu_logsys.h | 2 + common/eqemu_logsys_log_aliases.h | 16 + common/faction.h | 17 + .../base_faction_association_repository.h | 523 ++++++++++++++++++ .../base/base_npc_types_repository.h | 10 + .../repositories/base/base_tasks_repository.h | 10 + .../faction_association_repository.h | 50 ++ common/shareddb.cpp | 75 +++ common/shareddb.h | 11 + common/tasks.h | 3 +- common/version.h | 2 +- shared_memory/CMakeLists.txt | 2 + shared_memory/faction_association.cpp | 45 ++ shared_memory/faction_association.h | 28 + shared_memory/main.cpp | 30 +- utils/sql/db_update_manifest.txt | 1 + .../2022_09_02_faction_association.sql | 371 +++++++++++++ .../2022_09_02_faction_association.sql | 27 + zone/attack.cpp | 2 +- zone/client.cpp | 44 +- zone/client.h | 3 +- zone/command.cpp | 2 + zone/command.h | 1 + zone/embparser_api.cpp | 6 + zone/gm_commands/faction_association.cpp | 18 + zone/hate_list.cpp | 14 +- zone/hate_list.h | 2 +- zone/lua_client.cpp | 30 +- zone/lua_client.h | 1 + zone/main.cpp | 5 + zone/npc.cpp | 1 + zone/npc.h | 4 + zone/questmgr.cpp | 9 + zone/questmgr.h | 1 + zone/task_client_state.cpp | 10 +- zone/task_manager.cpp | 1 + zone/worldserver.cpp | 5 + zone/zonedb.cpp | 2 +- zone/zonedump.h | 1 + 41 files changed, 1363 insertions(+), 25 deletions(-) create mode 100644 common/repositories/base/base_faction_association_repository.h create mode 100644 common/repositories/faction_association_repository.h create mode 100644 shared_memory/faction_association.cpp create mode 100644 shared_memory/faction_association.h create mode 100644 utils/sql/git/optional/2022_09_02_faction_association.sql create mode 100644 utils/sql/git/required/2022_09_02_faction_association.sql create mode 100644 zone/gm_commands/faction_association.cpp diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index d80db0f9e..6a426cae1 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -197,6 +197,7 @@ SET(repositories repositories/base/base_eventlog_repository.h repositories/base/base_expeditions_repository.h repositories/base/base_expedition_lockouts_repository.h + repositories/base/base_faction_association_repository.h repositories/base/base_faction_base_data_repository.h repositories/base/base_faction_list_repository.h repositories/base/base_faction_list_mod_repository.h @@ -373,6 +374,7 @@ SET(repositories repositories/eventlog_repository.h repositories/expeditions_repository.h repositories/expedition_lockouts_repository.h + repositories/faction_association_repository.h repositories/faction_base_data_repository.h repositories/faction_list_repository.h repositories/faction_list_mod_repository.h diff --git a/common/database_schema.h b/common/database_schema.h index be7c87ba0..a70c31251 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -190,6 +190,7 @@ namespace DatabaseSchema { "damageshieldtypes", "doors", "dynamic_zone_templates", + "faction_association", "faction_base_data", "faction_list", "faction_list_mod", diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index 63e7d1a12..b27ddba3e 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -131,6 +131,7 @@ namespace Logs { CombatRecord, Hate, Discord, + Faction, MaxCategoryID /* Don't Remove this */ }; @@ -220,6 +221,7 @@ namespace Logs { "CombatRecord", "Hate", "Discord", + "Faction", }; } diff --git a/common/eqemu_logsys_log_aliases.h b/common/eqemu_logsys_log_aliases.h index 88c03c98a..db0b463bb 100644 --- a/common/eqemu_logsys_log_aliases.h +++ b/common/eqemu_logsys_log_aliases.h @@ -736,6 +736,16 @@ OutF(LogSys, Logs::Detail, Logs::Discord, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) +#define LogFaction(message, ...) do {\ + if (LogSys.log_settings[Logs::Faction].is_category_enabled == 1)\ + OutF(LogSys, Logs::General, Logs::Faction, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while(0) + +#define LogFactionDetail(message, ...) do {\ + if (LogSys.log_settings[Logs::Faction].is_category_enabled == 1)\ + OutF(LogSys, Logs::Detail, Logs::Faction, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while(0) + #define Log(debug_level, log_category, message, ...) do {\ if (LogSys.log_settings[log_category].is_category_enabled == 1)\ LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ @@ -1180,6 +1190,12 @@ #define LogHateDetail(message, ...) do {\ } while (0) +#define LogFaction(message, ...) do {\ +} while (0) + +#define LogFactionDetail(message, ...) do {\ +} while (0) + #define Log(debug_level, log_category, message, ...) do {\ } while (0) diff --git a/common/faction.h b/common/faction.h index 907e393fc..04b40eb9c 100755 --- a/common/faction.h +++ b/common/faction.h @@ -75,6 +75,23 @@ struct NPCFaction uint8 temp; }; +// Faction Associations give a much more live like faction system +// Basically the primary faction and magnitude of a faction hit will generate the rest of them + +// Largest faction I could find quickly was Lord Inquisitor Seru with 9 total hits (8 associations) so 8 + 2 for max for now +#define MAX_FACTION_ASSOC 10 + +// this is the ID of a faction association and it's multiplier +struct FactionAssociationHit { + int id; + float multiplier; +}; + +struct FactionAssociations { + // maybe there should be more data here, fine for now + FactionAssociationHit hits[MAX_FACTION_ASSOC]; +}; + const char *FactionValueToString(FACTION_VALUE faction_value); FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value); #endif diff --git a/common/repositories/base/base_faction_association_repository.h b/common/repositories/base/base_faction_association_repository.h new file mode 100644 index 000000000..029a355b6 --- /dev/null +++ b/common/repositories/base/base_faction_association_repository.h @@ -0,0 +1,523 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_FACTION_ASSOCIATION_REPOSITORY_H +#define EQEMU_BASE_FACTION_ASSOCIATION_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseFactionAssociationRepository { +public: + struct FactionAssociation { + int32_t id; + int32_t id_1; + float mod_1; + int32_t id_2; + float mod_2; + int32_t id_3; + float mod_3; + int32_t id_4; + float mod_4; + int32_t id_5; + float mod_5; + int32_t id_6; + float mod_6; + int32_t id_7; + float mod_7; + int32_t id_8; + float mod_8; + int32_t id_9; + float mod_9; + int32_t id_10; + float mod_10; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "id_1", + "mod_1", + "id_2", + "mod_2", + "id_3", + "mod_3", + "id_4", + "mod_4", + "id_5", + "mod_5", + "id_6", + "mod_6", + "id_7", + "mod_7", + "id_8", + "mod_8", + "id_9", + "mod_9", + "id_10", + "mod_10", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "id_1", + "mod_1", + "id_2", + "mod_2", + "id_3", + "mod_3", + "id_4", + "mod_4", + "id_5", + "mod_5", + "id_6", + "mod_6", + "id_7", + "mod_7", + "id_8", + "mod_8", + "id_9", + "mod_9", + "id_10", + "mod_10", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("faction_association"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static FactionAssociation NewEntity() + { + FactionAssociation e{}; + + e.id = 0; + e.id_1 = 0; + e.mod_1 = 0; + e.id_2 = 0; + e.mod_2 = 0; + e.id_3 = 0; + e.mod_3 = 0; + e.id_4 = 0; + e.mod_4 = 0; + e.id_5 = 0; + e.mod_5 = 0; + e.id_6 = 0; + e.mod_6 = 0; + e.id_7 = 0; + e.mod_7 = 0; + e.id_8 = 0; + e.mod_8 = 0; + e.id_9 = 0; + e.mod_9 = 0; + e.id_10 = 0; + e.mod_10 = 0; + + return e; + } + + static FactionAssociation GetFactionAssociation( + const std::vector &faction_associations, + int faction_association_id + ) + { + for (auto &faction_association : faction_associations) { + if (faction_association.id == faction_association_id) { + return faction_association; + } + } + + return NewEntity(); + } + + static FactionAssociation FindOne( + Database& db, + int faction_association_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + faction_association_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + FactionAssociation e{}; + + e.id = static_cast(atoi(row[0])); + e.id_1 = static_cast(atoi(row[1])); + e.mod_1 = strtof(row[2], nullptr); + e.id_2 = static_cast(atoi(row[3])); + e.mod_2 = strtof(row[4], nullptr); + e.id_3 = static_cast(atoi(row[5])); + e.mod_3 = strtof(row[6], nullptr); + e.id_4 = static_cast(atoi(row[7])); + e.mod_4 = strtof(row[8], nullptr); + e.id_5 = static_cast(atoi(row[9])); + e.mod_5 = strtof(row[10], nullptr); + e.id_6 = static_cast(atoi(row[11])); + e.mod_6 = strtof(row[12], nullptr); + e.id_7 = static_cast(atoi(row[13])); + e.mod_7 = strtof(row[14], nullptr); + e.id_8 = static_cast(atoi(row[15])); + e.mod_8 = strtof(row[16], nullptr); + e.id_9 = static_cast(atoi(row[17])); + e.mod_9 = strtof(row[18], nullptr); + e.id_10 = static_cast(atoi(row[19])); + e.mod_10 = strtof(row[20], nullptr); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int faction_association_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + faction_association_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const FactionAssociation &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = " + std::to_string(e.id_1)); + v.push_back(columns[2] + " = " + std::to_string(e.mod_1)); + v.push_back(columns[3] + " = " + std::to_string(e.id_2)); + v.push_back(columns[4] + " = " + std::to_string(e.mod_2)); + v.push_back(columns[5] + " = " + std::to_string(e.id_3)); + v.push_back(columns[6] + " = " + std::to_string(e.mod_3)); + v.push_back(columns[7] + " = " + std::to_string(e.id_4)); + v.push_back(columns[8] + " = " + std::to_string(e.mod_4)); + v.push_back(columns[9] + " = " + std::to_string(e.id_5)); + v.push_back(columns[10] + " = " + std::to_string(e.mod_5)); + v.push_back(columns[11] + " = " + std::to_string(e.id_6)); + v.push_back(columns[12] + " = " + std::to_string(e.mod_6)); + v.push_back(columns[13] + " = " + std::to_string(e.id_7)); + v.push_back(columns[14] + " = " + std::to_string(e.mod_7)); + v.push_back(columns[15] + " = " + std::to_string(e.id_8)); + v.push_back(columns[16] + " = " + std::to_string(e.mod_8)); + v.push_back(columns[17] + " = " + std::to_string(e.id_9)); + v.push_back(columns[18] + " = " + std::to_string(e.mod_9)); + v.push_back(columns[19] + " = " + std::to_string(e.id_10)); + v.push_back(columns[20] + " = " + std::to_string(e.mod_10)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static FactionAssociation InsertOne( + Database& db, + FactionAssociation e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.id_1)); + v.push_back(std::to_string(e.mod_1)); + v.push_back(std::to_string(e.id_2)); + v.push_back(std::to_string(e.mod_2)); + v.push_back(std::to_string(e.id_3)); + v.push_back(std::to_string(e.mod_3)); + v.push_back(std::to_string(e.id_4)); + v.push_back(std::to_string(e.mod_4)); + v.push_back(std::to_string(e.id_5)); + v.push_back(std::to_string(e.mod_5)); + v.push_back(std::to_string(e.id_6)); + v.push_back(std::to_string(e.mod_6)); + v.push_back(std::to_string(e.id_7)); + v.push_back(std::to_string(e.mod_7)); + v.push_back(std::to_string(e.id_8)); + v.push_back(std::to_string(e.mod_8)); + v.push_back(std::to_string(e.id_9)); + v.push_back(std::to_string(e.mod_9)); + v.push_back(std::to_string(e.id_10)); + v.push_back(std::to_string(e.mod_10)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.id_1)); + v.push_back(std::to_string(e.mod_1)); + v.push_back(std::to_string(e.id_2)); + v.push_back(std::to_string(e.mod_2)); + v.push_back(std::to_string(e.id_3)); + v.push_back(std::to_string(e.mod_3)); + v.push_back(std::to_string(e.id_4)); + v.push_back(std::to_string(e.mod_4)); + v.push_back(std::to_string(e.id_5)); + v.push_back(std::to_string(e.mod_5)); + v.push_back(std::to_string(e.id_6)); + v.push_back(std::to_string(e.mod_6)); + v.push_back(std::to_string(e.id_7)); + v.push_back(std::to_string(e.mod_7)); + v.push_back(std::to_string(e.id_8)); + v.push_back(std::to_string(e.mod_8)); + v.push_back(std::to_string(e.id_9)); + v.push_back(std::to_string(e.mod_9)); + v.push_back(std::to_string(e.id_10)); + v.push_back(std::to_string(e.mod_10)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + FactionAssociation e{}; + + e.id = static_cast(atoi(row[0])); + e.id_1 = static_cast(atoi(row[1])); + e.mod_1 = strtof(row[2], nullptr); + e.id_2 = static_cast(atoi(row[3])); + e.mod_2 = strtof(row[4], nullptr); + e.id_3 = static_cast(atoi(row[5])); + e.mod_3 = strtof(row[6], nullptr); + e.id_4 = static_cast(atoi(row[7])); + e.mod_4 = strtof(row[8], nullptr); + e.id_5 = static_cast(atoi(row[9])); + e.mod_5 = strtof(row[10], nullptr); + e.id_6 = static_cast(atoi(row[11])); + e.mod_6 = strtof(row[12], nullptr); + e.id_7 = static_cast(atoi(row[13])); + e.mod_7 = strtof(row[14], nullptr); + e.id_8 = static_cast(atoi(row[15])); + e.mod_8 = strtof(row[16], nullptr); + e.id_9 = static_cast(atoi(row[17])); + e.mod_9 = strtof(row[18], nullptr); + e.id_10 = static_cast(atoi(row[19])); + e.mod_10 = strtof(row[20], nullptr); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + FactionAssociation e{}; + + e.id = static_cast(atoi(row[0])); + e.id_1 = static_cast(atoi(row[1])); + e.mod_1 = strtof(row[2], nullptr); + e.id_2 = static_cast(atoi(row[3])); + e.mod_2 = strtof(row[4], nullptr); + e.id_3 = static_cast(atoi(row[5])); + e.mod_3 = strtof(row[6], nullptr); + e.id_4 = static_cast(atoi(row[7])); + e.mod_4 = strtof(row[8], nullptr); + e.id_5 = static_cast(atoi(row[9])); + e.mod_5 = strtof(row[10], nullptr); + e.id_6 = static_cast(atoi(row[11])); + e.mod_6 = strtof(row[12], nullptr); + e.id_7 = static_cast(atoi(row[13])); + e.mod_7 = strtof(row[14], nullptr); + e.id_8 = static_cast(atoi(row[15])); + e.mod_8 = strtof(row[16], nullptr); + e.id_9 = static_cast(atoi(row[17])); + e.mod_9 = strtof(row[18], nullptr); + e.id_10 = static_cast(atoi(row[19])); + e.mod_10 = strtof(row[20], nullptr); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_FACTION_ASSOCIATION_REPOSITORY_H diff --git a/common/repositories/base/base_npc_types_repository.h b/common/repositories/base/base_npc_types_repository.h index 30e259d2a..7d0def72d 100644 --- a/common/repositories/base/base_npc_types_repository.h +++ b/common/repositories/base/base_npc_types_repository.h @@ -144,6 +144,7 @@ public: int8_t always_aggro; int32_t exp_mod; int32_t heroic_strikethrough; + int32_t faction_amount; }; static std::string PrimaryKey() @@ -279,6 +280,7 @@ public: "always_aggro", "exp_mod", "heroic_strikethrough", + "faction_amount", }; } @@ -410,6 +412,7 @@ public: "always_aggro", "exp_mod", "heroic_strikethrough", + "faction_amount", }; } @@ -575,6 +578,7 @@ public: e.always_aggro = 0; e.exp_mod = 100; e.heroic_strikethrough = 0; + e.faction_amount = 0; return e; } @@ -735,6 +739,7 @@ public: e.always_aggro = static_cast(atoi(row[122])); e.exp_mod = static_cast(atoi(row[123])); e.heroic_strikethrough = static_cast(atoi(row[124])); + e.faction_amount = static_cast(atoi(row[125])); return e; } @@ -892,6 +897,7 @@ public: v.push_back(columns[122] + " = " + std::to_string(e.always_aggro)); v.push_back(columns[123] + " = " + std::to_string(e.exp_mod)); v.push_back(columns[124] + " = " + std::to_string(e.heroic_strikethrough)); + v.push_back(columns[125] + " = " + std::to_string(e.faction_amount)); auto results = db.QueryDatabase( fmt::format( @@ -1038,6 +1044,7 @@ public: v.push_back(std::to_string(e.always_aggro)); v.push_back(std::to_string(e.exp_mod)); v.push_back(std::to_string(e.heroic_strikethrough)); + v.push_back(std::to_string(e.faction_amount)); auto results = db.QueryDatabase( fmt::format( @@ -1192,6 +1199,7 @@ public: v.push_back(std::to_string(e.always_aggro)); v.push_back(std::to_string(e.exp_mod)); v.push_back(std::to_string(e.heroic_strikethrough)); + v.push_back(std::to_string(e.faction_amount)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -1350,6 +1358,7 @@ public: e.always_aggro = static_cast(atoi(row[122])); e.exp_mod = static_cast(atoi(row[123])); e.heroic_strikethrough = static_cast(atoi(row[124])); + e.faction_amount = static_cast(atoi(row[125])); all_entries.push_back(e); } @@ -1499,6 +1508,7 @@ public: e.always_aggro = static_cast(atoi(row[122])); e.exp_mod = static_cast(atoi(row[123])); e.heroic_strikethrough = static_cast(atoi(row[124])); + e.faction_amount = static_cast(atoi(row[125])); all_entries.push_back(e); } diff --git a/common/repositories/base/base_tasks_repository.h b/common/repositories/base/base_tasks_repository.h index 592962b78..d5b6d0dc0 100644 --- a/common/repositories/base/base_tasks_repository.h +++ b/common/repositories/base/base_tasks_repository.h @@ -46,6 +46,7 @@ public: uint32_t request_timer_seconds; uint32_t dz_template_id; int32_t lock_activity_id; + int32_t faction_amount; }; static std::string PrimaryKey() @@ -83,6 +84,7 @@ public: "request_timer_seconds", "dz_template_id", "lock_activity_id", + "faction_amount", }; } @@ -116,6 +118,7 @@ public: "request_timer_seconds", "dz_template_id", "lock_activity_id", + "faction_amount", }; } @@ -183,6 +186,7 @@ public: e.request_timer_seconds = 0; e.dz_template_id = 0; e.lock_activity_id = -1; + e.faction_amount = 0; return e; } @@ -245,6 +249,7 @@ public: e.request_timer_seconds = static_cast(strtoul(row[24], nullptr, 10)); e.dz_template_id = static_cast(strtoul(row[25], nullptr, 10)); e.lock_activity_id = static_cast(atoi(row[26])); + e.faction_amount = static_cast(atoi(row[27])); return e; } @@ -305,6 +310,7 @@ public: v.push_back(columns[24] + " = " + std::to_string(e.request_timer_seconds)); v.push_back(columns[25] + " = " + std::to_string(e.dz_template_id)); v.push_back(columns[26] + " = " + std::to_string(e.lock_activity_id)); + v.push_back(columns[27] + " = " + std::to_string(e.faction_amount)); auto results = db.QueryDatabase( fmt::format( @@ -353,6 +359,7 @@ public: v.push_back(std::to_string(e.request_timer_seconds)); v.push_back(std::to_string(e.dz_template_id)); v.push_back(std::to_string(e.lock_activity_id)); + v.push_back(std::to_string(e.faction_amount)); auto results = db.QueryDatabase( fmt::format( @@ -409,6 +416,7 @@ public: v.push_back(std::to_string(e.request_timer_seconds)); v.push_back(std::to_string(e.dz_template_id)); v.push_back(std::to_string(e.lock_activity_id)); + v.push_back(std::to_string(e.faction_amount)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -469,6 +477,7 @@ public: e.request_timer_seconds = static_cast(strtoul(row[24], nullptr, 10)); e.dz_template_id = static_cast(strtoul(row[25], nullptr, 10)); e.lock_activity_id = static_cast(atoi(row[26])); + e.faction_amount = static_cast(atoi(row[27])); all_entries.push_back(e); } @@ -520,6 +529,7 @@ public: e.request_timer_seconds = static_cast(strtoul(row[24], nullptr, 10)); e.dz_template_id = static_cast(strtoul(row[25], nullptr, 10)); e.lock_activity_id = static_cast(atoi(row[26])); + e.faction_amount = static_cast(atoi(row[27])); all_entries.push_back(e); } diff --git a/common/repositories/faction_association_repository.h b/common/repositories/faction_association_repository.h new file mode 100644 index 000000000..18cb67729 --- /dev/null +++ b/common/repositories/faction_association_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_FACTION_ASSOCIATION_REPOSITORY_H +#define EQEMU_FACTION_ASSOCIATION_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_faction_association_repository.h" + +class FactionAssociationRepository: public BaseFactionAssociationRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * FactionAssociationRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * FactionAssociationRepository::GetWhereNeverExpires() + * FactionAssociationRepository::GetWhereXAndY() + * FactionAssociationRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_FACTION_ASSOCIATION_REPOSITORY_H diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 1798cebca..ec7f12c63 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -40,6 +40,7 @@ #include "data_verification.h" #include "repositories/criteria/content_filter_criteria.h" #include "repositories/account_repository.h" +#include "repositories/faction_association_repository.h" namespace ItemField { @@ -1448,6 +1449,80 @@ bool SharedDatabase::LoadNPCFactionLists(const std::string &prefix) { return true; } +void SharedDatabase::GetFactionAssociationInfo(uint32 &list_count, uint32 &max_lists) +{ + list_count = static_cast(FactionAssociationRepository::Count(*this)); + max_lists = static_cast(FactionAssociationRepository::GetMaxId(*this)); +} + +const FactionAssociations *SharedDatabase::GetFactionAssociationHit(int id) +{ + if (!faction_associations_hash) { + return nullptr; + } + + if (faction_associations_hash->exists(id)) { + return &(faction_associations_hash->at(id)); + } + + return nullptr; +} + +void SharedDatabase::LoadFactionAssociation(void *data, uint32 size, uint32 list_count, uint32 max_lists) +{ + EQ::FixedMemoryHashSet hash(reinterpret_cast(data), size, list_count, max_lists); + FactionAssociations faction{}; + + auto results = FactionAssociationRepository::All(*this); + for (auto &row : results) { + faction.hits[0].id = row.id_1; + faction.hits[0].multiplier = row.mod_1; + faction.hits[1].id = row.id_2; + faction.hits[1].multiplier = row.mod_2; + faction.hits[2].id = row.id_3; + faction.hits[2].multiplier = row.mod_3; + faction.hits[3].id = row.id_4; + faction.hits[3].multiplier = row.mod_4; + faction.hits[4].id = row.id_5; + faction.hits[4].multiplier = row.mod_5; + faction.hits[5].id = row.id_6; + faction.hits[5].multiplier = row.mod_6; + faction.hits[6].id = row.id_7; + faction.hits[6].multiplier = row.mod_7; + faction.hits[7].id = row.id_8; + faction.hits[7].multiplier = row.mod_8; + faction.hits[8].id = row.id_9; + faction.hits[8].multiplier = row.mod_9; + faction.hits[9].id = row.id_10; + faction.hits[9].multiplier = row.mod_10; + + hash.insert(row.id, faction); + } +} + +bool SharedDatabase::LoadFactionAssociation(const std::string &prefix) +{ + faction_associations_mmf.reset(nullptr); + faction_associations_hash.reset(nullptr); + + try { + auto Config = EQEmuConfig::get(); + EQ::IPCMutex mutex("factionassociation"); + mutex.Lock(); + std::string file_name = Config->SharedMemDir + prefix + std::string("factionassociations"); + faction_associations_mmf = std::unique_ptr(new EQ::MemoryMappedFile(file_name)); + faction_associations_hash = std::unique_ptr>( + new EQ::FixedMemoryHashSet(reinterpret_cast(faction_associations_mmf->Get()), + faction_associations_mmf->Size())); + mutex.Unlock(); + } catch (std::exception &ex) { + LogError("Error Loading faction associations: {}", ex.what()); + return false; + } + + return true; +} + // Create appropriate EQ::ItemInstance class EQ::ItemInstance* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) { diff --git a/common/shareddb.h b/common/shareddb.h index 49b9837c0..3c71cfd18 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -41,6 +41,7 @@ struct InspectMessage_Struct; struct PlayerProfile_Struct; struct SPDat_Spell_Struct; struct NPCFactionList; +struct FactionAssociations; struct LootTable_Struct; struct LootDrop_Struct; @@ -159,6 +160,14 @@ public: void LoadNPCFactionLists(void *data, uint32 size, uint32 list_count, uint32 max_lists); bool LoadNPCFactionLists(const std::string &prefix); + /** + * faction associations + */ + void GetFactionAssociationInfo(uint32 &list_count, uint32 &max_lists); + const FactionAssociations *GetFactionAssociationHit(int id); + void LoadFactionAssociation(void *data, uint32 size, uint32 list_count, uint32 max_lists); + bool LoadFactionAssociation(const std::string &prefix); + /** * loot */ @@ -212,6 +221,8 @@ protected: std::unique_ptr> items_hash; std::unique_ptr faction_mmf; std::unique_ptr> faction_hash; + std::unique_ptr faction_associations_mmf; + std::unique_ptr> faction_associations_hash; std::unique_ptr loot_table_mmf; std::unique_ptr> loot_table_hash; std::unique_ptr loot_drop_mmf; diff --git a/common/tasks.h b/common/tasks.h index 82eb48ce0..991214349 100644 --- a/common/tasks.h +++ b/common/tasks.h @@ -217,7 +217,8 @@ struct TaskInformation { int reward_id{}; int cash_reward{}; // Expressed in copper int experience_reward{}; - int faction_reward{}; // just a npc_faction_id + int faction_reward{}; // npc_faction_id if amount == 0, otherwise primary faction ID + int faction_amount{}; // faction hit value TaskMethodType reward_method; int reward_points; AltCurrencyType reward_point_type; diff --git a/common/version.h b/common/version.h index a9b4177a4..91de22345 100644 --- a/common/version.h +++ b/common/version.h @@ -34,7 +34,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9203 +#define CURRENT_BINARY_DATABASE_VERSION 9204 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9029 diff --git a/shared_memory/CMakeLists.txt b/shared_memory/CMakeLists.txt index 6902a8b83..407719ea3 100644 --- a/shared_memory/CMakeLists.txt +++ b/shared_memory/CMakeLists.txt @@ -2,6 +2,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.2) SET(shared_memory_sources base_data.cpp + faction_association.cpp items.cpp loot.cpp main.cpp @@ -12,6 +13,7 @@ SET(shared_memory_sources SET(shared_memory_headers base_data.h + faction_association.h items.h loot.h npc_faction.h diff --git a/shared_memory/faction_association.cpp b/shared_memory/faction_association.cpp new file mode 100644 index 000000000..4db6f23c6 --- /dev/null +++ b/shared_memory/faction_association.cpp @@ -0,0 +1,45 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2022 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "faction_association.h" +#include "../common/global_define.h" +#include "../common/shareddb.h" +#include "../common/ipc_mutex.h" +#include "../common/memory_mapped_file.h" +#include "../common/eqemu_exception.h" +#include "../common/faction.h" + +void LoadFactionAssociation(SharedDatabase *database, const std::string &prefix) { + EQ::IPCMutex mutex("factionassociation"); + mutex.Lock(); + + uint32 lists = 0; + uint32 max_list = 0; + database->GetFactionAssociationInfo(lists, max_list); + + uint32 size = static_cast(EQ::FixedMemoryHashSet::estimated_size(lists, max_list)); + + auto Config = EQEmuConfig::get(); + std::string file_name = Config->SharedMemDir + prefix + std::string("factionassociation"); + EQ::MemoryMappedFile mmf(file_name, size); + mmf.ZeroFile(); + + void *ptr = mmf.Get(); + database->LoadFactionAssociation(ptr, size, lists, max_list); + mutex.Unlock(); +} diff --git a/shared_memory/faction_association.h b/shared_memory/faction_association.h new file mode 100644 index 000000000..54d850a08 --- /dev/null +++ b/shared_memory/faction_association.h @@ -0,0 +1,28 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2022 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __EQEMU_SHARED_MEMORY_FACTION_ASSOCIATION_H +#define __EQEMU_SHARED_MEMORY_FACTION_ASSOCIATION_H + +#include +#include "../common/eqemu_config.h" + +class SharedDatabase; +void LoadFactionAssociation(SharedDatabase *database, const std::string &prefix); + +#endif diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index cdbb6cf74..24d6be661 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -27,6 +27,7 @@ #include "../common/rulesys.h" #include "../common/eqemu_exception.h" #include "../common/strings.h" +#include "faction_association.h" #include "items.h" #include "npc_faction.h" #include "loot.h" @@ -181,13 +182,14 @@ int main(int argc, char **argv) std::string hotfix_name = ""; - bool load_all = true; - bool load_items = false; - bool load_factions = false; - bool load_loot = false; - bool load_skill_caps = false; - bool load_spells = false; - bool load_bd = false; + bool load_all = true; + bool load_items = false; + bool load_factions = false; + bool load_faction_assoc = false; + bool load_loot = false; + bool load_skill_caps = false; + bool load_spells = false; + bool load_bd = false; if (argc > 1) { for (int i = 1; i < argc; ++i) { @@ -229,6 +231,10 @@ int main(int argc, char **argv) load_spells = true; load_all = false; } + else if (strcasecmp("faction_assoc", argv[i]) == 0) { + load_faction_assoc = true; + load_all = false; + } break; case '-': { auto split = Strings::Split(argv[i], '='); @@ -300,6 +306,16 @@ int main(int argc, char **argv) } } + if (load_all || load_faction_assoc) { + LogInfo("Loading faction associations"); + try { + LoadFactionAssociation(&content_db, hotfix_name); + } catch(std::exception &ex) { + LogError("{}", ex.what()); + return 1; + } + } + if (load_all || load_bd) { LogInfo("Loading base data"); try { diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 4236cc851..79f668f49 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -457,6 +457,7 @@ 9201|2022_08_22_npc_types_heroic_strikethrough.sql|SHOW COLUMNS FROM `npc_types` LIKE 'heroic_strikethrough'|empty| 9202|2022_08_24_task_activities_step.sql|SHOW COLUMNS FROM `task_activities` LIKE 'step'|contains|unsigned 9203|2022_08_07_replace_task_goals.sql|SHOW COLUMNS FROM `task_activities` LIKE 'item_id'|empty| +9204|2022_09_02_faction_association.sql|SHOW TABLES LIKE 'faction_association'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/optional/2022_09_02_faction_association.sql b/utils/sql/git/optional/2022_09_02_faction_association.sql new file mode 100644 index 000000000..fb17c7357 --- /dev/null +++ b/utils/sql/git/optional/2022_09_02_faction_association.sql @@ -0,0 +1,371 @@ +INSERT INTO `faction_association` VALUES (218,217,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (219,262,1,304,-0.5,273,-1,291,1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (220,281,0.25,296,-0.15,330,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (221,262,-0.15,296,0.1,341,-0.25,230,0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (222,308,-0.1,235,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (223,291,-0.15,230,0.15,262,-0.15,273,0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (225,355,-0.05,263,-0.1,312,-0.05,475,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (226,279,1,335,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (227,274,1,293,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (228,274,-1,261,1,232,1,337,1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (229,281,1,291,0.75,336,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (230,262,-0.15,273,0.15,223,0.1,221,0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (231,266,0.1,265,-0.15,267,0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (232,228,0.15,261,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (233,226,0.1,265,-0.15,267,0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (234,312,-0.05,246,-0.15,270,0,326,-0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (235,222,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (236,334,0.1,370,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (237,308,0.25,251,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (238,245,-0.1,255,-0.1,240,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (239,303,0.15,278,-0.15,275,-0.15,245,-0.15,1522,-2,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (240,288,0.15,255,0.15,238,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (241,223,0.05,292,-0.05,336,0.05,329,0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (242,266,0.15,265,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (244,262,-0.05,320,-0.25,263,-0.1,329,-0.25,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (245,238,-0.15,239,-0.05,255,0.15,333,0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (246,279,0.25,226,0.25,310,0.25,234,-0.25,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (247,318,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (248,326,0.75,312,0.75,441,-0.05,313,-0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (249,323,-0.15,319,0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (254,267,0.15,266,0.1,265,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (255,288,0.25,333,0.25,238,-0.25,1604,-0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (256,313,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (257,441,-0.1,248,-0.1,259,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (258,1732,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (259,451,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (261,228,0.5,312,-0.15,308,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (262,219,0.15,230,-0.15,223,-0.25,291,0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (263,286,0.15,355,0.1,292,0.15,334,-0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (264,268,0.25,444,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (265,242,-1,254,-1,231,-1,233,-1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (266,267,1,265,-1,304,-0.5,277,-0.5,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (267,266,0.15,265,-0.15,289,0.75,277,-0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (269,302,0.15,272,0.15,324,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (270,326,-0.15,311,-0.05,1522,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (271,281,-0.15,296,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (272,302,0.25,343,0.15,324,-0.25,262,0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (274,312,1,304,-0.5,228,-1,285,-0.25,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (275,279,0.25,246,0.15,239,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (276,246,0.1,326,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (278,303,-1,270,0.75,239,-0.75,279,-1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (280,221,-1,341,0.75,262,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (281,271,-0.15,330,-0.15,362,0.2,311,0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (282,323,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (284,281,0.15,262,0.15,304,-0.05,285,-0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (285,279,-0.25,426,1,284,-0.25,304,-0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (286,263,1,292,1,300,1,225,-0.5,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (287,255,-0.75,333,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (289,266,0.75,267,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (290,312,0.2,322,-0.2,293,0.1,274,0.2,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (291,223,-0.2,219,0.15,229,0.1,262,0.2,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (292,241,0.05,263,0.15,286,0.15,336,-0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (293,274,0.75,312,0.75,227,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (296,271,0.25,239,0.25,238,0.25,221,0.25,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (297,274,0.75,227,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (298,226,0.25,265,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (300,286,0.1,263,0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (302,272,0.25,306,-0.15,262,0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (304,284,-0.25,285,-0.15,318,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (306,262,-0.05,309,-0.05,272,-0.05,291,-0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (307,441,-0.05,451,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (308,261,-0.15,222,-0.25,235,0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (309,262,0.15,361,0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (310,279,0.15,246,0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (311,262,0.2,230,-0.15,330,-0.15,281,0.2,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (312,274,0.15,293,0.15,290,0.25,232,-0.25,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (313,248,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (315,441,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (317,251,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (319,249,0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (320,327,0.2,328,0.25,311,0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (321,262,-0.15,306,0.15,345,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (322,223,-0.05,379,-0.05,241,0.05,244,-0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (323,255,0.1,333,0.1,288,0.1,322,0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (324,262,-0.25,272,-0.75,343,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (326,270,-0.15,325,0.1,276,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (327,328,0.15,223,-0.15,336,-0.15,244,-0.2,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (328,320,0.75,327,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (329,336,0.75,304,-0.25,332,1,331,1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (330,336,0.15,281,-0.1,362,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (331,332,1,329,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (332,329,0.15,331,0.15,230,0.05,330,0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (333,245,0.15,255,0.15,238,-0.1,287,-0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (334,236,0.15,270,0.1,370,0.25,326,-0.01,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (336,229,1,329,0.1,230,0.05,330,0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (337,228,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (338,228,0.75,337,0.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (340,278,0.15,362,-0.35,226,341,0,1522,-4,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (341,280,0.3,262,0.5,221,-0.25,219,0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (342,221,-0.25,262,0.15,296,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (343,302,0.2,272,0.2,366,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (345,262,0.25,341,0.15,280,0.3,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (346,330,0.25,281,0.25,362,0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (355,286,0.1,292,0.15,324,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (361,281,0.15,309,0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (362,330,-0.1,281,0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (363,239,-0.15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (364,332,-0.15,269,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (365,263,-0.1,475,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (366,345,-0.1,262,-0.1,332,-0.05,223,-0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (370,236,0.15,270,0.15,1522,-1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (373,332,-0.1,345,-0.4,366,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (375,281,-0.1,263,-0.1,361,-0.1,346,-0.15,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (378,263,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (379,312,-0.05,322,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (398,312,-0.05,326,-0.05,255,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (402,403,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (403,402,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (405,406,1,429,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (406,405,0.25,448,-0.1,419,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (407,460,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (412,312,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (415,416,-0.01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (416,415,-0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (417,418,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (418,417,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (419,448,0.25,406,-0.5,430,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (426,285,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (429,448,1,436,-0.5,405,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (430,436,0.25,448,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (431,432,-0.1,439,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (432,431,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (433,430,0.1,304,0.1,315,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (435,429,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (436,430,1,429,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (438,226,2,310,2,246,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (439,431,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (440,441,0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (441,440,0.25,445,0.25,442,0.25,444,0.25,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (442,441,0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (443,441,0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (444,441,0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (445,441,0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (446,441,-0.2,443,-0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (448,419,0.25,429,0.25,430,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (451,307,1,259,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (454,285,-0.05,318,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (455,304,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (456,459,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (459,456,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (462,464,0.1,463,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (463,464,-0.1,462,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (464,430,-0.1,462,0.1,304,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (467,430,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (469,226,2,310,2,246,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (471,267,-0.1,265,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (473,298,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (474,365,0.1,225,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (475,365,-0.1,225,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1007,1013,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1010,1013,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1013,1007,-0.1,1010,-0.1,1016,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1016,1013,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1020,1021,1,1022,-1,1023,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1021,1020,1,1022,-1,1023,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1022,1023,1,1020,-1,1021,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1023,1022,1,1020,-1,1021,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1024,1025,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1025,1024,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1026,1027,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1027,1026,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1028,1029,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1029,1028,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1030,1031,1,1032,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1031,1030,1,1032,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1032,1030,1,1031,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1033,1035,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1034,1035,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1035,1033,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1048,1051,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1050,1051,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1051,1050,-1,1048,-1,1049,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1052,1058,1,1053,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1053,1052,-1,1058,-1,1059,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1054,1058,-1,1059,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1055,1058,-1,1059,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1056,1055,-1,1058,-1,1059,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1058,1054,-1,1055,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1063,330,1,229,1,281,1,362,1,271,1,311,1,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1068,1078,-1,1080,-1,1072,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1069,1068,-1,1073,-1,1077,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1070,1071,-1,1077,-1,1078,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1071,1070,-1,1077,-1,1078,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1072,1068,-1,1074,-1,1075,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1073,1069,-1,1074,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1074,1072,-1,1073,-1,1075,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1075,1072,-1,1074,-1,1079,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1076,1078,-1,1079,-1,1080,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1077,1069,-1,1070,-1,1071,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1078,1070,-1,1071,-1,1076,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1079,1075,-1,1076,-1,1080,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1080,1068,-1,1076,-1,1079,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1085,1086,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1086,1085,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1088,1085,-1,1089,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1089,1085,-1,1088,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1093,1110,-1,1094,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1094,1093,1,1095,-1,1129,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1095,1094,-1,1129,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1100,1103,-1,1104,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1101,1103,-1,1105,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1107,1108,1,1109,-1,1110,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1108,1107,1,1109,-1,1110,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1109,1107,-1,1108,-1,1110,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1110,1109,1,1111,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1111,1109,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1112,1107,-2,1108,-2,1109,-10,1110,-10,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1113,1107,-1,1108,-1,1109,-1,1110,-1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1114,1109,-1,1110,-5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1115,1107,-1,1108,-1,1109,-1,1110,-1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1116,1109,1,1110,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1120,1121,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1121,1120,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1123,1124,1,1129,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1124,1123,1,1129,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1125,1126,1,1129,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1126,1125,1,1129,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1140,1142,-1,1144,-1.5,1141,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1141,1142,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1142,1141,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1143,1145,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1145,1143,2.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1146,1147,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1147,1146,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1148,1149,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1149,1148,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1166,1244,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1175,1135,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1176,1134,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1181,1183,-0.1,1184,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1186,1623,1,430,-1,436,-1,1188,-1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1192,1183,-0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1193,1184,-0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1194,1189,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1195,1191,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1197,1185,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1198,1185,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1200,1199,0.1,1221,0.1,1222,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1201,1199,-0.1,1200,-0.1,1222,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1202,1203,-0.1,1222,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1204,1223,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1205,1223,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1209,1210,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1210,1209,-1,1226,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1211,1212,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1212,1225,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1213,1225,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1216,1225,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1220,1225,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1221,1224,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1232,1233,-1,1234,1,1235,1,1238,-1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1233,1232,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1234,1235,1,1232,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1235,1234,1,1232,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1237,1232,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1238,1232,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1243,1242,-1,1241,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1244,1166,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1483,1484,1,1485,1,1487,1,1502,-0.1,1503,-0.1,1504,-0.1,1561,-0.1,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1484,1485,-0.1,1486,-0.1,1483,0.05,1541,1,1503,-0.5,1504,-0.1,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1485,1484,-0.1,1486,-0.1,1483,0.05,1542,-0.1,1504,-0.25,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1486,1485,-0.1,1487,-0.1,1483,0.05,1561,-0.5,1505,-0.1,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1487,1486,-0.1,1485,-0.1,1483,0.05,1502,-0.25,1505,-0.25,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1488,1484,-0.1,1486,-0.1,1485,-0.1,1487,-0.1,1542,0.1,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1499,1484,0.1,1486,0.1,1485,0.1,1487,0.1,1502,-0.5,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1500,1501,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1501,1500,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1502,1503,0.1,1504,0.1,1499,-0.5,1483,-0.1,1487,-0.1,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1503,1502,0.1,1504,0.1,1505,-0.1,1506,-0.1,1483,-0.1,1484,-0.5,1485,-0.1,1541,-0.1,0,0,0,0); +INSERT INTO `faction_association` VALUES (1504,1502,0.1,1503,0.1,1483,-0.1,1484,-0.1,1485,-0.25,1541,-0.25,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1505,1503,-0.1,1506,-0.1,1486,-0.1,1487,-0.25,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1506,1503,-0.1,1505,-0.1,1507,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1507,1506,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1508,1510,0.1,1511,0.1,1512,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1509,1510,1,1542,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1510,1509,1,1508,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1511,1508,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1512,1508,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1519,1513,-0.1,1500,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1520,1521,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1521,1520,-0.1,1501,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1524,1502,0.1,1504,0.1,1505,-0.1,1506,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1526,430,0.25,304,0.25,448,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1527,1483,-0.1,1484,-0.1,1485,-0.1,1486,-0.1,1487,-0.1,1499,-0.1,1488,0.1,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1528,1483,-0.1,1484,-0.1,1485,-0.1,1486,-0.1,1487,-0.1,1499,-0.1,1488,0.1,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1535,1536,1,1562,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1536,1535,1,1562,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1538,1505,-0.1,1502,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1541,1484,1,1485,-0.1,1483,0.05,1486,-0.1,1503,-0.25,1504,-0.1,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1542,1559,0.1,1510,-0.5,1511,-0.5,1512,-0.5,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1543,1544,0.1,1545,0.1,1546,0.1,1547,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1544,1543,0.1,1546,0.1,1545,0.1,1547,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1545,1543,0.1,1546,0.1,1544,0.1,1547,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1546,1543,0.1,1545,0.1,1544,0.1,1547,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1548,1549,0.1,1550,0.1,1551,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1549,1548,0.1,1550,0.1,1551,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1550,1548,0.1,1549,0.1,1551,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1551,1550,-0.1,1548,-0.1,1549,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1555,1556,0.1,1483,-1,1484,-1,1487,-1,1486,-1,1541,-1,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1556,1555,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1557,1556,0.1,1555,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1559,1509,-0.1,1542,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1562,1535,0.5,1536,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1563,1563,-0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1570,1506,0.5,1507,0.1,1521,-0.1,1501,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1571,1520,-0.1,1501,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1580,1579,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1597,272,0.5,302,0.5,262,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1599,1597,-1,272,-0.5,302,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1601,1597,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1602,1597,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1604,255,-0.05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1607,1608,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1609,1618,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1610,1614,1,1609,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1611,1615,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1612,1616,1,1609,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1613,1617,1,1609,-0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1620,1597,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1621,1619,-0.2,1609,-0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1622,316,-0.1,326,-0.1,310,-0.1,246,-0.1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1623,430,-0.1,419,0.2,448,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1626,1625,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1627,1628,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1628,1627,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1665,251,-0.25,1593,-0.5,315,1,441,-0.05,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1718,1709,1,1716,1,1717,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1719,1709,1,1716,1,1717,1,1718,1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1720,1709,1,1716,1,1717,1,1718,1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1725,441,1,440,1,445,1,444,1,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1728,451,-1,1729,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1729,451,-0.66,1728,0.33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1732,258,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1763,1761,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1764,1761,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1765,1761,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1766,1761,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1767,1761,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1768,1761,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1770,1771,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1771,1770,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1778,1779,0.5,1780,-0.5,1781,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1779,1778,0.5,1780,-0.5,1781,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1784,1785,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1786,1787,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1787,1786,1,1788,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1788,1786,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1789,1791,-0.6,1795,0.33,1793,-0.33,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1790,1789,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1791,1789,-0.6,1793,0.33,1795,-0.33,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1792,1791,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1793,1795,-0.6,1791,0.33,1789,-0.33,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1794,1793,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1795,1793,-0.6,1789,0.33,1791,-0.33,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1796,1795,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1798,1799,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1799,1775,-1,1788,-1,1799,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1801,1802,-1,1803,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1802,1801,-1,1803,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1803,1801,-1,1802,-0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `faction_association` VALUES (1804,1817,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;0); diff --git a/utils/sql/git/required/2022_09_02_faction_association.sql b/utils/sql/git/required/2022_09_02_faction_association.sql new file mode 100644 index 000000000..333562c74 --- /dev/null +++ b/utils/sql/git/required/2022_09_02_faction_association.sql @@ -0,0 +1,27 @@ +CREATE TABLE `faction_association` ( + `id` INT(10) NOT NULL, + `id_1` INT(10) NOT NULL DEFAULT 0, + `mod_1` FLOAT NOT NULL DEFAULT 0, + `id_2` INT(10) NOT NULL DEFAULT 0, + `mod_2` FLOAT NOT NULL DEFAULT 0, + `id_3` INT(10) NOT NULL DEFAULT 0, + `mod_3` FLOAT NOT NULL DEFAULT 0, + `id_4` INT(10) NOT NULL DEFAULT 0, + `mod_4` FLOAT NOT NULL DEFAULT 0, + `id_5` INT(10) NOT NULL DEFAULT 0, + `mod_5` FLOAT NOT NULL DEFAULT 0, + `id_6` INT(10) NOT NULL DEFAULT 0, + `mod_6` FLOAT NOT NULL DEFAULT 0, + `id_7` INT(10) NOT NULL DEFAULT 0, + `mod_7` FLOAT NOT NULL DEFAULT 0, + `id_8` INT(10) NOT NULL DEFAULT 0, + `mod_8` FLOAT NOT NULL DEFAULT 0, + `id_9` INT(10) NOT NULL DEFAULT 0, + `mod_9` FLOAT NOT NULL DEFAULT 0, + `id_10` INT(10) NOT NULL DEFAULT 0, + `mod_10` FLOAT NOT NULL DEFAULT 0, + PRIMARY KEY(`id`) +); + +ALTER TABLE `npc_types` ADD `faction_amount` INT(10) NOT NULL DEFAULT '0'; +ALTER TABLE `tasks` ADD `faction_amount` INT(10) NOT NULL DEFAULT '0'; diff --git a/zone/attack.cpp b/zone/attack.cpp index 9a2a24b26..3f91a2f52 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2456,7 +2456,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy //do faction hits even if we are a merchant, so long as a player killed us if (!IsCharmed() && give_exp_client && !RuleB(NPC, EnableMeritBasedFaction)) - hate_list.DoFactionHits(GetNPCFactionID()); + hate_list.DoFactionHits(GetNPCFactionID(), GetPrimaryFaction(), GetFactionAmount()); bool IsLdonTreasure = (GetClass() == LDON_TREASURE); diff --git a/zone/client.cpp b/zone/client.cpp index 1a9d8411a..5a62c9e0a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8760,7 +8760,7 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, int32 nfl_id = target->CastToNPC()->GetNPCFactionID(); SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true); qr->faction = target->CastToNPC()->GetPrimaryFaction(); - qr->faction_mod = 1; // Too lazy to get real value, not sure if this is even used by client anyhow. + qr->faction_mod = 1; // Too lazy to get real value, not even used by client anyhow. } } @@ -8780,7 +8780,7 @@ void Client::QuestReward(Mob* target, const QuestReward_Struct &reward, bool fac memcpy(qr, &reward, sizeof(QuestReward_Struct)); // not set in caller because reasons - qr->mob_id = target ? target->GetID() : 0; // Entity ID for the from mob name + qr->mob_id = target ? target->GetID() : 0; // Entity ID for the from mob name, tasks won't set this if (reward.copper > 0 || reward.silver > 0 || reward.gold > 0 || reward.platinum > 0) AddMoneyToPP(reward.copper, reward.silver, reward.gold, reward.platinum); @@ -8789,6 +8789,12 @@ void Client::QuestReward(Mob* target, const QuestReward_Struct &reward, bool fac if (reward.item_id[i] > 0) SummonItem(reward.item_id[i], 0, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor); + // only process if both are valid + // if we don't have a target here, we want to just reward, but if there is a target, need to check charm + if (reward.faction && reward.faction_mod && (target == nullptr || !target->IsCharmed())) + RewardFaction(reward.faction, reward.faction_mod); + + // legacy support if (faction) { if (target && target->IsNPC() && !target->IsCharmed()) @@ -8796,11 +8802,11 @@ void Client::QuestReward(Mob* target, const QuestReward_Struct &reward, bool fac int32 nfl_id = target->CastToNPC()->GetNPCFactionID(); SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true); qr->faction = target->CastToNPC()->GetPrimaryFaction(); - qr->faction_mod = 1; // Too lazy to get real value, not sure if this is even used by client anyhow. + qr->faction_mod = 1; // Too lazy to get real value, not even used by client anyhow. } } - if (reward.exp_reward> 0) + if (reward.exp_reward > 0) AddEXP(reward.exp_reward); QueuePacket(outapp, true, Client::CLIENT_CONNECTED); @@ -8821,6 +8827,36 @@ void Client::CashReward(uint32 copper, uint32 silver, uint32 gold, uint32 platin QueuePacket(outapp.get()); } +void Client::RewardFaction(int id, int amount) +{ + // first we hit the primary faction, even without any associations + SetFactionLevel2(CharacterID(), id, GetClass(), GetBaseRace(), GetDeity(), amount, false); + + auto faction_assoc = content_db.GetFactionAssociationHit(id); + // We could log here, but since it's actually expected for some not to have entries, it would be noisy. + if (!faction_assoc) { + return; + } + + // now hit them in order + for (int i = 0; i < MAX_FACTION_ASSOC; ++i) { + if (faction_assoc->hits[i].id <= 0) // we don't allow later entries + break; + if (faction_assoc->hits[i].multiplier == 0.0f) { + LogFaction("Bad association multiplier for ID {} entry {}", id, i + 1); + continue; + } + + // value is truncated and min clamped to 1 (or -1) + float temp = faction_assoc->hits[i].multiplier * amount; + int sign = temp < 0.0f ? -1 : 1; + int32 new_amount = std::max(1, static_cast(std::abs(temp))) * sign; + + SetFactionLevel2(CharacterID(), faction_assoc->hits[i].id, GetClass(), GetBaseRace(), GetDeity(), + new_amount, false); + } +} + void Client::SendHPUpdateMarquee(){ if (!this || !IsClient() || !current_hp || !max_hp) return; diff --git a/zone/client.h b/zone/client.h index aee1a70a4..f898103c8 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1613,8 +1613,9 @@ public: uint32 GetNextInvSnapshotTime() { return m_epp.next_invsnapshot_time; } void QuestReward(Mob* target, uint32 copper = 0, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0, uint32 itemid = 0, uint32 exp = 0, bool faction = false); - void QuestReward(Mob* target, const QuestReward_Struct &reward, bool faction); // TODO: Fix faction processing + void QuestReward(Mob* target, const QuestReward_Struct &reward, bool faction = false); void CashReward(uint32 copper, uint32 silver, uint32 gold, uint32 platinum); + void RewardFaction(int id, int amount); void ResetHPUpdateTimer() { hpupdate_timer.Start(); } diff --git a/zone/command.cpp b/zone/command.cpp index afefb0f25..12120329d 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -140,6 +140,7 @@ int command_init(void) command_add("endurance", "Restores your or your target's endurance.", AccountStatus::Guide, command_endurance) || command_add("equipitem", "[slotid(0-21)] - Equip the item on your cursor into the specified slot", AccountStatus::Guide, command_equipitem) || command_add("faction", "[Find (criteria | all ) | Review (criteria | all) | Reset (id)] - Resets Player's Faction", AccountStatus::QuestTroupe, command_faction) || + command_add("factionassociation", "[factionid] [amount] - triggers a faction hits via association", AccountStatus::GMLeadAdmin, command_faction_association) || command_add("feature", "Change your or your target's feature's temporarily", AccountStatus::QuestTroupe, command_feature) || command_add("findaliases", "[Search Criteria]- Searches for available command aliases, by alias or command", AccountStatus::Player, command_findaliases) || command_add("findclass", "[Search Criteria] - Search for a class", AccountStatus::Guide, command_findclass) || @@ -1146,6 +1147,7 @@ void command_bot(Client *c, const Seperator *sep) #include "gm_commands/spawnfix.cpp" #include "gm_commands/spawnstatus.cpp" #include "gm_commands/spellinfo.cpp" +#include "gm_commands/faction_association.cpp" #include "gm_commands/stun.cpp" #include "gm_commands/summon.cpp" #include "gm_commands/summonburiedplayercorpse.cpp" diff --git a/zone/command.h b/zone/command.h index fe49b69e3..cbc754562 100644 --- a/zone/command.h +++ b/zone/command.h @@ -77,6 +77,7 @@ void command_enablerecipe(Client *c, const Seperator *sep); void command_endurance(Client *c, const Seperator *sep); void command_equipitem(Client *c, const Seperator *sep); void command_faction(Client *c, const Seperator *sep); +void command_faction_association(Client *c, const Seperator *sep); void command_feature(Client *c, const Seperator *sep); void command_findaliases(Client *c, const Seperator *sep); void command_findclass(Client *c, const Seperator *sep); diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index dae74f55d..735ec7e05 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -689,6 +689,11 @@ void Perl__faction(int faction_id, int value, int temp) quest_manager.faction(faction_id, value, temp); } +void Perl__rewardfaction(int faction_id, int value) +{ + quest_manager.rewardfaction(faction_id, value); +} + void Perl__setsky(uint8 new_sky) { quest_manager.setsky(new_sky); @@ -4171,6 +4176,7 @@ void perl_register_quest() package.add("resettaskactivity", &Perl__resettaskactivity); package.add("respawn", &Perl__respawn); package.add("resume", &Perl__resume); + package.add("rewardfaction", &Perl__rewardfaction); package.add("safemove", &Perl__safemove); package.add("save", &Perl__save); package.add("say", (void(*)(const char*))&Perl__say); diff --git a/zone/gm_commands/faction_association.cpp b/zone/gm_commands/faction_association.cpp new file mode 100644 index 000000000..47410f248 --- /dev/null +++ b/zone/gm_commands/faction_association.cpp @@ -0,0 +1,18 @@ +#include "../client.h" + +void command_faction_association(Client *c, const Seperator *sep) +{ + if (sep->argnum < 2 || !sep->IsNumber(1) || !sep->IsNumber(2)) { + c->Message(Chat::White, "Usage: #factionassociation "); + c->Message(Chat::White, " Defaults to self, unless target is also a client."); + return; + } + + // default to self unless target is also a client + auto target = c; + if (c->GetTarget() && c->GetTarget()->IsClient()) { + target = c->GetTarget()->CastToClient(); + } + + target->RewardFaction(atoi(sep->arg[1]), atoi(sep->arg[2])); +} diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 64be84925..f9d39da45 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -257,8 +257,9 @@ bool HateList::RemoveEntFromHateList(Mob *in_entity) return is_found; } -void HateList::DoFactionHits(int64 npc_faction_level_id) { - if (npc_faction_level_id <= 0) +// so if faction_id and faction_value are set, we do RewardFaction, otherwise old stuff +void HateList::DoFactionHits(int64 npc_faction_level_id, int32 faction_id, int32 faction_value) { + if (npc_faction_level_id <= 0 && faction_id <= 0 && faction_value == 0) return; auto iterator = list.begin(); while (iterator != list.end()) @@ -270,8 +271,13 @@ void HateList::DoFactionHits(int64 npc_faction_level_id) { else client = nullptr; - if (client) - client->SetFactionLevel(client->CharacterID(), npc_faction_level_id, client->GetBaseClass(), client->GetBaseRace(), client->GetDeity()); + if (client) { + if (faction_id != 0 && faction_value != 0) { + client->RewardFaction(faction_id, faction_value); + } else { + client->SetFactionLevel(client->CharacterID(), npc_faction_level_id, client->GetBaseClass(), client->GetBaseRace(), client->GetDeity()); + } + } ++iterator; } } diff --git a/zone/hate_list.h b/zone/hate_list.h index a6a4f93e4..52cb55199 100644 --- a/zone/hate_list.h +++ b/zone/hate_list.h @@ -73,7 +73,7 @@ public: bool in_is_frenzied = false, bool add_to_hate_list_if_not_exist = true ); - void DoFactionHits(int64 npc_faction_level_id); + void DoFactionHits(int64 npc_faction_level_id, int32 faction_id, int32 faction_value); void IsEntityInFrenzyMode(); void PrintHateListToClient(Client *c); void SetHateAmountOnEnt(Mob *other, int64 in_hate, uint64 in_damage); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 9bd79b0f8..a89d41cab 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -436,6 +436,11 @@ void Lua_Client::SetFactionLevel2(uint32 char_id, int faction_id, int char_class self->SetFactionLevel2(char_id, faction_id, char_class, char_race, char_deity, value, temp); } +void Lua_Client::RewardFaction(int id, int amount) { + Lua_Safe_Call_Void(); + self->RewardFaction(id, amount); +} + int Lua_Client::GetRawItemAC() { Lua_Safe_Call_Int(); return self->GetRawItemAC(); @@ -1761,9 +1766,27 @@ void Lua_Client::QuestReward(Lua_Mob target, luabind::adl::object reward) { cur = reward["faction"]; if (luabind::type(cur) != LUA_TNIL) { - try { - faction = luabind::object_cast(cur); - } catch (luabind::cast_failed &) { + // if it's a table it will be {faction, faction_mod} + if (luabind::type(cur) == LUA_TTABLE) { + auto item = cur[1]; + if (luabind::type(item) != LUA_TNIL) { + try { + quest_reward.faction = luabind::object_cast(item); + } catch (luabind::cast_failed &) { + } + } + item = cur[2]; + if (luabind::type(item) != LUA_TNIL) { + try { + quest_reward.faction_mod = luabind::object_cast(item); + } catch (luabind::cast_failed &) { + } + } + } else { + try { + faction = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { + } } } @@ -2922,6 +2945,7 @@ luabind::scope lua_register_client() { .def("ResetCastbarCooldownBySpellID", (void(Lua_Client::*)(uint32))&Lua_Client::ResetCastbarCooldownBySpellID) .def("ResetDisciplineTimer", (void(Lua_Client::*)(uint32))&Lua_Client::ResetDisciplineTimer) .def("ResetTrade", (void(Lua_Client::*)(void))&Lua_Client::ResetTrade) + .def("RewardFaction", (void(Lua_Client::*)(int,int))&Lua_Client::RewardFaction) .def("Save", (void(Lua_Client::*)(int))&Lua_Client::Save) .def("Save", (void(Lua_Client::*)(void))&Lua_Client::Save) .def("SaveBackup", (void(Lua_Client::*)(void))&Lua_Client::SaveBackup) diff --git a/zone/lua_client.h b/zone/lua_client.h index 2c569721e..966c75acd 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -132,6 +132,7 @@ public: int GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 race, uint32 class_, uint32 deity, uint32 faction, Lua_NPC npc); void SetFactionLevel(uint32 char_id, uint32 npc_id, int char_class, int char_race, int char_deity); void SetFactionLevel2(uint32 char_id, int faction_id, int char_class, int char_race, int char_deity, int value, int temp); + void RewardFaction(int id, int amount); int GetRawItemAC(); uint32 AccountID(); const char *AccountName(); diff --git a/zone/main.cpp b/zone/main.cpp index bb74b00e4..471b994af 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -315,6 +315,11 @@ int main(int argc, char** argv) { LogError("Loading npcs faction lists failed!"); return 1; } + LogInfo("Loading faction association hits"); + if (!content_db.LoadFactionAssociation(hotfix_name)) { + LogError("Loading faction association hits failed!"); + return 1; + } LogInfo("Loading loot tables"); if (!database.LoadLoot(hotfix_name)) { LogError("Loading loot failed!"); diff --git a/zone/npc.cpp b/zone/npc.cpp index 96716c96e..c0df84942 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -259,6 +259,7 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi rare_spawn = npc_type_data->rare_spawn; no_target_hotkey = npc_type_data->no_target_hotkey; primary_faction = 0; + faction_amount = npc_type_data->faction_amount; SetNPCFactionID(npc_type_data->npc_faction_id); diff --git a/zone/npc.h b/zone/npc.h index 1417cb2d6..72659db6c 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -278,6 +278,9 @@ public: inline int32 GetPrimaryFaction() const { return primary_faction; } + inline int32 GetFactionAmount() const + { return faction_amount; } + int64 GetNPCHate(Mob *in_ent) { return hate_list.GetEntHateAmount(in_ent); } @@ -561,6 +564,7 @@ protected: int32 npc_faction_id; int32 primary_faction; + int32 faction_amount; Timer attacked_timer; //running while we are being attacked (damaged) Timer swarm_timer; diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 675353d81..c70ec7b3f 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1350,6 +1350,15 @@ void QuestManager::faction(int faction_id, int faction_value, int temp) { } } +void QuestManager::rewardfaction(int faction_id, int faction_value) { + QuestManagerCurrentQuestVars(); + if (initiator && initiator->IsClient()) { + if (faction_id != 0 && faction_value != 0) { + initiator->RewardFaction(faction_id, faction_value); + } + } +} + void QuestManager::setsky(uint8 new_sky) { QuestManagerCurrentQuestVars(); if (zone) diff --git a/zone/questmgr.h b/zone/questmgr.h index d2ec07ee1..f71c1f72c 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -150,6 +150,7 @@ public: void attacknpctype(int npc_type_id); void save(); void faction(int faction_id, int faction_value, int temp); + void rewardfaction(int faction_id, int faction_value); void setsky(uint8 new_sky); void setguild(uint32 new_guild_id, uint8 new_rank); void CreateGuild(const char *guild_name, const char *leader); diff --git a/zone/task_client_state.cpp b/zone/task_client_state.cpp index b984e772f..41647988c 100644 --- a/zone/task_client_state.cpp +++ b/zone/task_client_state.cpp @@ -995,6 +995,9 @@ void ClientTaskState::RewardTask(Client *client, const TaskInformation *task_inf client->Message(Chat::Yellow, task_information->completion_emote.c_str()); } + // TODO: this function should sometimes use QuestReward_Struct and CashReward_Struct + // assumption is they use QuestReward_Struct when there is more than 1 thing getting rewarded + const EQ::ItemData *item_data; std::vector reward_list; @@ -1029,7 +1032,7 @@ void ClientTaskState::RewardTask(Client *client, const TaskInformation *task_inf } // just use normal NPC faction ID stuff - if (task_information->faction_reward) { + if (task_information->faction_reward && task_information->faction_amount == 0) { client->SetFactionLevel( client->CharacterID(), task_information->faction_reward, @@ -1037,6 +1040,11 @@ void ClientTaskState::RewardTask(Client *client, const TaskInformation *task_inf client->GetBaseRace(), client->GetDeity() ); + } else if (task_information->faction_reward != 0 && task_information->faction_amount != 0) { + client->RewardFaction( + task_information->faction_reward, + task_information->faction_amount + ); } if (task_information->cash_reward) { diff --git a/zone/task_manager.cpp b/zone/task_manager.cpp index ae38b666b..bbd4476ab 100644 --- a/zone/task_manager.cpp +++ b/zone/task_manager.cpp @@ -92,6 +92,7 @@ bool TaskManager::LoadTasks(int single_task) task_data.reward_points = task.reward_points; task_data.reward_point_type = static_cast(task.reward_point_type); task_data.faction_reward = task.faction_reward; + task_data.faction_amount = task.faction_amount; task_data.min_level = task.minlevel; task_data.max_level = task.maxlevel; task_data.level_spread = task.level_spread; diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index c89316752..76ada31f8 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -3186,6 +3186,11 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) LogError("Loading npcs faction lists failed!"); } + LogInfo("Loading faction association hits"); + if (!content_db.LoadFactionAssociation(hotfix_name)) { + LogError("Loading faction association hits failed!"); + } + LogInfo("Loading loot tables"); if (!content_db.LoadLoot(hotfix_name)) { LogError("Loading loot failed!"); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index ef4d4598d..2e6d18290 100755 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2385,7 +2385,7 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load t->skip_auto_scale = false; // hardcoded here for now t->hp_regen_per_second = n.hp_regen_per_second; t->heroic_strikethrough = n.heroic_strikethrough; - + t->faction_amount = n.faction_amount; // If NPC with duplicate NPC id already in table, // free item we attempted to add. diff --git a/zone/zonedump.h b/zone/zonedump.h index 55782340d..d5abaf475 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -54,6 +54,7 @@ struct NPCType uint32 npc_spells_id; uint32 npc_spells_effects_id; int32 npc_faction_id; + int32 faction_amount; // faction association magnitude, will use primary faction uint32 merchanttype; uint32 alt_currency_type; uint32 adventure_template;