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;